diff --git a/Detector/DetCEPCv4/compact/Beampipe_o1_v01_01.xml b/Detector/DetCEPCv4/compact/Beampipe_o1_v01_01.xml index fdc6a5014fb2ea369b02bd41d27d097b79bfdc8e..33dbea275ee6d4d70f2956d7cb88d1f2cead6fd3 100644 --- a/Detector/DetCEPCv4/compact/Beampipe_o1_v01_01.xml +++ b/Detector/DetCEPCv4/compact/Beampipe_o1_v01_01.xml @@ -25,21 +25,21 @@ start="TUBE_firstCone_zStart" end="TUBE_firstCone_zEnd" rMin1="TUBE_firstCone_rInnerStart" rMin2="TUBE_firstCone_rInnerEnd" rMax1="TUBE_firstCone_rInnerStart+TUBE_firstCone_RadThickness" rMax2="TUBE_firstCone_rInnerEnd+TUBE_firstCone_RadThickness" - material="G4_Cu" name="IPInnerBulge" /> + material="G4_Be" name="IPInnerBulge" /> <!-- second cylinder --> - <section type ="Center" + <!--section type ="Center" start="TUBE_secondCylinder_zStart" end="TUBE_secondCylinder_zEnd" rMin1="TUBE_secondCylinder_rInner" rMin2="TUBE_secondCylinder_rInner" rMax1="TUBE_secondCylinder_rInner+TUBE_secondCylinder_thickness" rMax2="TUBE_secondCylinder_rInner+TUBE_secondCylinder_thickness" - material="G4_Cu" name="IPOuterTube" /> + material="G4_Cu" name="IPOuterTube" /--> <!-- second cone, split into parts --> - <section type ="Center" + <!--section type ="Center" start="TUBE_secondCone_part1_zStart" end="TUBE_secondCone_part4_zEnd" rMin1="TUBE_secondCone_part1_rInnerStart" rMin2="TUBE_secondCone_part4_rInnerEnd" rMax1="TUBE_secondCone_part1_rInnerStart+TUBE_secondCone_part1_RadThickness" rMax2="TUBE_secondCone_part4_rInnerEnd+TUBE_secondCone_part4_RadThickness" - material="BeampipeBeCableMix" name="IPOuterTube" /> + material="BeampipeBeCableMix" name="IPOuterTube" /--> <!--section type ="Center" start="TUBE_secondCone_part2_zStart" end="TUBE_secondCone_part2_zEnd" diff --git a/Detector/DetCEPCv4/compact/top_defs.xml b/Detector/DetCEPCv4/compact/top_defs.xml index c774b8c438307c4bbe4aeeea0bd412e1146adafe..49208899381cc8e4cd7fae1115ac2bf50e8e2506 100644 --- a/Detector/DetCEPCv4/compact/top_defs.xml +++ b/Detector/DetCEPCv4/compact/top_defs.xml @@ -112,14 +112,14 @@ <constant name="BCal_rOuter" value="140*mm"/> <!-- the beam tube --> - <constant name="TUBE_IPInnerTube_end_z" value="200*mm"/> + <constant name="TUBE_IPInnerTube_end_z" value="500*mm"/> <constant name="TUBE_central_inner_radius" value="14*mm"/> <constant name="TUBE_central_thickness" value="0.5*mm"/> - <constant name="TUBE_IPInnerBulge_end_z" value="500*mm"/> - <constant name="TUBE_IPInnerBulge_end_innerradius" value="19.5*mm"/> + <constant name="TUBE_IPInnerBulge_end_z" value="700*mm"/> + <constant name="TUBE_IPInnerBulge_end_innerradius" value="17.5*mm"/> - <constant name="TUBE_IPOuterTube_start_z" value="500*mm"/> + <constant name="TUBE_IPOuterTube_start_z" value="700*mm"/> <constant name="TUBE_IPOuterTube_end_z" value="700*mm"/> <constant name="TUBE_Lcal_clearance" value="20*mm"/> diff --git a/Detector/DetCEPCv4/compact/tube_defs.xml b/Detector/DetCEPCv4/compact/tube_defs.xml index b700986ac4f333b7b3333f4e0599605892de8018..a446b1e85fff66abe73f654fb7a0a08314feddb0 100644 --- a/Detector/DetCEPCv4/compact/tube_defs.xml +++ b/Detector/DetCEPCv4/compact/tube_defs.xml @@ -8,7 +8,7 @@ <constant name="TUBE_firstCone_zEnd" value="TUBE_IPInnerBulge_end_z"/> <constant name="TUBE_firstCone_rInnerStart" value="TUBE_innerCylinder_rInner"/> <constant name="TUBE_firstCone_rInnerEnd" value="TUBE_IPInnerBulge_end_innerradius"/> - <constant name="TUBE_firstCone_thickness" value="3*mm"/> + <constant name="TUBE_firstCone_thickness" value="0.5*mm"/> <!-- D. Jeans, update april 2017 in this driver, we have to define the what I call the radial thickness @@ -19,8 +19,8 @@ <constant name="TUBE_firstCone_dz" value="TUBE_firstCone_zEnd-TUBE_firstCone_zStart"/> <constant name="TUBE_firstCone_dr" value="TUBE_firstCone_rInnerEnd-TUBE_firstCone_rInnerStart"/> <constant name="TUBE_firstCone_costh" value="TUBE_firstCone_dz/sqrt( TUBE_firstCone_dz**2. + TUBE_firstCone_dr**2. )"/> - <constant name="TUBE_firstCone_RadThickness" value="TUBE_firstCone_thickness/TUBE_firstCone_costh"/> - + <!--constant name="TUBE_firstCone_RadThickness" value="TUBE_firstCone_thickness/TUBE_firstCone_costh"/--> + <constant name="TUBE_firstCone_RadThickness" value="TUBE_firstCone_thickness"/> <constant name="TUBE_secondCylinder_zStart" value="TUBE_firstCone_zEnd"/> <constant name="TUBE_secondCylinder_zEnd" value="TUBE_IPOuterTube_end_z"/> diff --git a/Detector/DetCEPCv4/src/tracker/VXD04_geo.cpp b/Detector/DetCEPCv4/src/tracker/VXD04_geo.cpp index 9b13b09a490026901fabc8d868c3109f849afb4d..bec4117d8d72721a2c93c1bb9e5087a2d7847f54 100644 --- a/Detector/DetCEPCv4/src/tracker/VXD04_geo.cpp +++ b/Detector/DetCEPCv4/src/tracker/VXD04_geo.cpp @@ -323,7 +323,8 @@ static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector se phirot = (2*M_PI)/nb_ladder; - double ladder_clothest_approch = beryllium_ladder_block_thickness*2 +0.1; + //Notice: length unit in here is cm, by fucd + double ladder_clothest_approch = beryllium_ladder_block_thickness*2 +0.01; // calculate optimal offset, such that there is 0.1mm space between to the edge and the surface of two adjacent ladders. // in the case of ladders overlapped per superlayer @@ -333,11 +334,16 @@ static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector se +(ladder_clothest_approch+cos(phirot)*2*(foam_spacer_thickness+active_silicon_thickness+flex_cable_thickness+metal_traces_thickness))/sin(phirot)); */ // in the case of ladders overlapped per layer - + /* double offset_phi=(1-cos(phirot))/sin(phirot)*layer_radius -((ladder_width+(side_band_electronics_option*side_band_electronics_width/2.)) +(ladder_clothest_approch+cos(phirot)*2*(active_silicon_thickness+flex_cable_thickness+metal_traces_thickness-foam_spacer_thickness/2.0))/sin(phirot)); - + */ + // by fucd: same as CEPC_v4 in MokkaC + double offset_phi=(1-cos(phirot))/sin(phirot)*layer_radius + -((ladder_width+(side_band_electronics_option*side_band_electronics_width/2.)) + +(ladder_clothest_approch+cos(phirot)*2*(active_silicon_thickness+flex_cable_thickness+metal_traces_thickness))/sin(phirot)); + if (LayerId==0||LayerId==2||LayerId==4) { //------------------------------------------------------------------------ for (double ladder_loop=0;ladder_loop<nb_ladder;ladder_loop++) { @@ -581,7 +587,6 @@ static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector se beryllium_ladder_block_length2 = beryllium_ladder_block_length + (shell_half_z - (end_electronics_half_z *3.* end_ladd_electronics_option)-ladder_length); for (double AnnulusBlock_loop=0;AnnulusBlock_loop<nb_ladder;AnnulusBlock_loop++) { - Box BerylliumAnnulusBlockSolid( ladder_width, beryllium_ladder_block_length2/2., beryllium_ladder_block_thickness); //**fg: need to create unique string name per Volume object @@ -1200,7 +1205,9 @@ static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector se } //Adjusted by Thorben Quast to provide consistency with CLIC while drawing for CED //Please check as the prefactor is simply chosen for the geometry to match the hits - thisLayer.offsetSensitive = 0.5*active_offset_phi ; + //thisLayer.offsetSensitive = 0.5*active_offset_phi ; + //without CED as first step @CepC, by fucd + thisLayer.offsetSensitive = active_offset_phi ; thisLayer.thicknessSensitive = active_silicon_thickness ; thisLayer.zHalfSensitive = ladder_length ; diff --git a/Detector/DetInterface/DetInterface/IGeoSvc.h b/Detector/DetInterface/DetInterface/IGeoSvc.h index 2925d7a2dec6ce96ffbe3f26779fadd1fa742c57..75f6f5aa8b6302c59554b4e173cdeb3e2dc0b591 100644 --- a/Detector/DetInterface/DetInterface/IGeoSvc.h +++ b/Detector/DetInterface/DetInterface/IGeoSvc.h @@ -11,6 +11,8 @@ #define IGEOSVC_H #include "GaudiKernel/IService.h" +#include "DDRec/DetectorData.h" +#include <map> namespace dd4hep { class Detector; @@ -18,8 +20,18 @@ namespace dd4hep { namespace DDSegmentation { class BitFieldCoder; } + class Detector; + class DetElement; + } +class StructExtension; + +namespace gear{ + class ZPlanarParametersImpl; + class GearParametersImpl; +} +class TMaterial; // class G4VUserDetectorConstruction; class GAUDI_API IGeoSvc : virtual public IService { @@ -37,6 +49,16 @@ public: // short cut to retrieve the Decoder according to the Readout name virtual Decoder* getDecoder(const std::string& readout_name) = 0; + // obsolete parameter format, will remove once StructExtension<> validated + virtual const gear::ZPlanarParametersImpl* getVXDParameters() = 0; + + virtual const dd4hep::rec::ZPlanarData* getVXDData() = 0; + virtual const dd4hep::rec::ConicalSupportData* getBeamPipeData() =0; + + virtual const std::map<std::string,double>& getDetParameters(std::string s) = 0; + virtual const double getDetParameter(std::string set_name, std::string par_name) = 0; + virtual TMaterial* getMaterial(std::string s) = 0; + virtual ~IGeoSvc() {} }; diff --git a/Detector/GeoSvc/CMakeLists.txt b/Detector/GeoSvc/CMakeLists.txt index 2a5b97ded1389cd0a45a5f41ba8d5c562580a031..c4b767e60920da0c3420d5a84afe58ddbf68ae2c 100644 --- a/Detector/GeoSvc/CMakeLists.txt +++ b/Detector/GeoSvc/CMakeLists.txt @@ -11,9 +11,9 @@ gaudi_depends_on_subdirs( Detector/DetInterface ) - find_package(ROOT COMPONENTS MathCore GenVector Geom Tree) find_package(DD4hep COMPONENTS DDG4 DDRec REQUIRED) +find_package(GEAR REQUIRED) gaudi_add_module(GeoSvc src/GeoSvc.cpp @@ -26,5 +26,6 @@ gaudi_add_module(GeoSvc DD4hep ${DD4hep_COMPONENT_LIBRARIES} GaudiKernel + $ENV{GEAR}/lib/libgear.so # ROOT -) \ No newline at end of file +) diff --git a/Detector/GeoSvc/src/GeoSvc.cpp b/Detector/GeoSvc/src/GeoSvc.cpp index 1739aa8a68e3996ea56d37849ffefa8dcd0b2f71..61671acfa8140087fdcdfa15ba3a40404cceaf72 100644 --- a/Detector/GeoSvc/src/GeoSvc.cpp +++ b/Detector/GeoSvc/src/GeoSvc.cpp @@ -1,14 +1,28 @@ #include "GeoSvc.h" +#include "gearimpl/GearParametersImpl.h" +#include "TMath.h" +#include "TMaterial.h" +#include "CLHEP/Units/SystemOfUnits.h" + +#include "G4Box.hh" +#include "G4Tubs.hh" +#include "G4LogicalVolume.hh" +#include "G4PVPlacement.hh" +#include "G4NistManager.hh" #include "DD4hep/Detector.h" #include "DD4hep/Plugins.h" #include "DDG4/Geant4Converter.h" #include "DDG4/Geant4Mapping.h" +#include "DDRec/DetectorData.h" + +#include <iomanip> +#include <iostream> DECLARE_COMPONENT(GeoSvc) GeoSvc::GeoSvc(const std::string& name, ISvcLocator* svc) -: base_class(name, svc), m_dd4hep_geo(nullptr) { +: base_class(name, svc), m_dd4hep_geo(nullptr), m_vxdData(nullptr), m_beamPipeData(nullptr){ } @@ -18,20 +32,46 @@ GeoSvc::~GeoSvc() { StatusCode GeoSvc::initialize() { - StatusCode sc = Service::initialize(); - - m_dd4hep_geo = &(dd4hep::Detector::getInstance()); - // if failed to load the compact, a runtime error will be thrown. - m_dd4hep_geo->fromCompact(m_dd4hep_xmls.value()); + StatusCode sc = Service::initialize(); - return sc; + m_dd4hep_geo = &(dd4hep::Detector::getInstance()); + // if failed to load the compact, a runtime error will be thrown. + m_dd4hep_geo->fromCompact(m_dd4hep_xmls.value()); + + dd4hep::DetElement world = m_dd4hep_geo->world(); + //info() << world.type() << " " << world.path() << " " << world.placementPath() << endmsg; + const std::map<std::string, dd4hep::DetElement>& subs = world.children(); + for(std::map<std::string, dd4hep::DetElement>::const_iterator it=subs.begin();it!=subs.end();it++){ + dd4hep::DetElement sub = it->second; + info() << it->first << " " << sub.path() << " " << sub.placementPath() << endmsg; + if(it->first=="Tube"){ + dd4hep::Volume vol = sub.volume(); + dd4hep::Solid solid = vol.solid(); + //info() << " " << solid.type() << " " << solid.name() << endmsg; + const std::map<std::string, dd4hep::DetElement>& pipes = sub.children(); + for(std::map<std::string, dd4hep::DetElement>::const_iterator it=pipes.begin();it!=pipes.end();it++){ + dd4hep::DetElement pipe = it->second; + //info() << " " << it->first << " " << pipe.id() << " " << pipe.path() << " " << pipe.placementPath() << endmsg; + } + try{ + m_beamPipeData = sub.extension<dd4hep::rec::ConicalSupportData>(); + } + catch(std::runtime_error& e){ + info() << e.what() << " " << m_beamPipeData << endmsg; + } + } + if(it->first=="VXD"){ + sc = convertVXD(sub); + } + } + return sc; } StatusCode GeoSvc::finalize() { - StatusCode sc; - - return sc; + StatusCode sc; + if(m_vxdParameters) delete m_vxdParameters; + return sc; } dd4hep::DetElement @@ -47,6 +87,7 @@ GeoSvc::lcdd() { return m_dd4hep_geo; } + IGeoSvc::Decoder* GeoSvc::getDecoder(const std::string& readout_name) { @@ -76,4 +117,486 @@ GeoSvc::getDecoder(const std::string& readout_name) { } return decoder; + +} + + +const std::map<std::string,double>& GeoSvc::getDetParameters(std::string name){ + if(m_detParameters.find(name)!=m_detParameters.end()) return m_detParameters[name]; + else{ + char message[200]; + sprintf(message,"GeoSvc has not the parameter set named %s", name); + throw std::runtime_error(message); + } +} + +const double GeoSvc::getDetParameter(std::string set_name, std::string par_name){ + std::map<std::string, std::map<std::string,double> >::iterator it=m_detParameters.find(set_name); + if(it!=m_detParameters.end()){ + if(it->second.find(par_name)!=it->second.end()) return it->second[par_name]; + } + char message[200]; + sprintf(message,"GeoSvc has not the parameter named %s in set %s", par_name, set_name); + throw std::runtime_error(message); +} + +StatusCode GeoSvc::convertVXD(dd4hep::DetElement& vxd){ + StatusCode sc; + //fucd: another method to obtain parameters, but not fully for KalDet + bool extensionDataValid = true; + try{ + m_vxdData = vxd.extension<dd4hep::rec::ZPlanarData>(); + } + catch(std::runtime_error& e){ + extensionDataValid = false; + info() << e.what() << " " << m_vxdData << endmsg; + } + + std::vector<helpLayer> helpSensitives; + std::vector<helpLayer> helpLadders; + std::vector<int> helpNumberLadders; + std::vector<double> helpPhi0; + int helpCount=0; + int type=0; + double shellInnerRadius, shellOuterRadius, shellHalfLength, gap, shellRadLength; + int nLadders=0; + double phi0=0; + helpLayer thisLadder; + double beryllium_ladder_block_length=0,end_electronics_half_z=0,side_band_electronics_width=0; + double rAlu, drAlu, rSty, drSty, dzSty, rInner, aluEndcapZ, aluHalfZ, alu_RadLen, Cryostat_dEdx; + double VXDSupportDensity, VXDSupportZeff, VXDSupportAeff, VXDSupportRadLen; + dd4hep::Volume vxd_vol = vxd.volume(); + for(int i=0;i<vxd_vol->GetNdaughters();i++){ + TGeoNode* daughter = vxd_vol->GetNode(i); + std::string nodeName = daughter->GetName(); + //info() << daughter->GetName() << endmsg; + if(nodeName=="VXD_support_assembly_0"){ + TGeoNode* shell = FindNode(daughter, "SupportShell"); + if(shell){ + const TGeoShape* shape_shell = shell->GetVolume()->GetShape(); + //fucd: IsA() method does not always work for TGeoTube, sometimes, strange? + //if(shape_shell->IsA()==TGeoTube::Class()){ + if(shape_shell->TestShapeBit(TGeoTube::kGeoTube)){ + const TGeoTube* tube = (const TGeoTube*) shape_shell; + shellInnerRadius = tube->GetRmin()*CLHEP::cm; + shellOuterRadius = tube->GetRmax()*CLHEP::cm; + shellHalfLength = tube->GetDz()*CLHEP::cm; + } + else{ + error() << shell->GetName() << " is not a TGeoTube! Shape bits = " << shape_shell->TestShapeBits(0xFFFFFFFF) << endmsg; + } + TGeoMaterial* mat = shell->GetMedium()->GetMaterial(); + shellRadLength = mat->GetRadLen()*CLHEP::cm; + } + TGeoNode* block = FindNode(daughter, "BerylliumAnnulusBlock"); + if(block){ + const TGeoShape* shape_block = block->GetVolume()->GetShape(); + if(shape_block->IsA()==TGeoBBox::Class()){ + const TGeoBBox* box = (const TGeoBBox*) shape_block; + beryllium_ladder_block_length = box->GetDY()*CLHEP::cm; + } + else{ + error() << block->GetName() << " is not a TGeoTube! Shape bits = " << shape_block->TestShapeBits(0xFFFFFFFF) << endmsg; + } + } + TGeoNode* skin = FindNode(daughter, "CryostatAluSkinBarrel"); + if(skin){ + const TGeoShape* shape_skin = skin->GetVolume()->GetShape(); + if(shape_skin->TestShapeBit(TGeoTube::kGeoTube)){ + const TGeoTube* tube = (const TGeoTube*) shape_skin; + rAlu = tube->GetRmin()*CLHEP::cm; + drAlu = tube->GetRmax()*CLHEP::cm - rAlu; + aluHalfZ = tube->GetDz()*CLHEP::cm; + //info() << rmin << "," << rmax << "," << zhalf << endmsg; + } + else{ + error() << skin->GetName() << " is not a TGeoTube! Shape bits = " << shape_skin->TestShapeBits(0xFFFFFFFF) << endmsg; + } + } + TGeoNode* foam = FindNode(daughter, "CryostatFoamBarrel"); + if(foam){ + const TGeoShape* shape_foam = foam->GetVolume()->GetShape(); + if(shape_foam->TestShapeBit(TGeoTube::kGeoTube)){ + const TGeoTube* tube = (const TGeoTube*) shape_foam; + rSty = tube->GetRmin()*CLHEP::cm; + drSty = tube->GetRmax()*CLHEP::cm - rSty; + dzSty = tube->GetDz()*CLHEP::cm; + //info() << rmin << "," << rmax << "," << zhalf << endmsg; + } + else{ + error() << foam->GetName() << " is not a TGeoTube! Shape bits = " << shape_foam->TestShapeBits(0xFFFFFFFF) << endmsg; + } + } + TGeoNode* skinEnd = FindNode(daughter, "CryostatAluSkinEndPlateInner"); + if(skinEnd){ + const TGeoShape* shape_skinEnd = skinEnd->GetVolume()->GetShape(); + if(shape_skinEnd->TestShapeBit(TGeoTube::kGeoTube)){ + const TGeoTube* tube = (const TGeoTube*) shape_skinEnd; + rInner = tube->GetRmin()*CLHEP::cm; + double rmax = tube->GetRmax()*CLHEP::cm; + drAlu = tube->GetDz()*CLHEP::cm*2; + //info() << rmin << "," << rmax << "," << zhalf << endmsg; + } + else{ + error() << skinEnd->GetName() << " is not a TGeoTube! Shape bits = " << shape_skinEnd->TestShapeBits(0xFFFFFFFF) << endmsg; + } + } + TGeoNode* shellEnd = FindNode(daughter, "EndPlateShell_outer"); + if(shellEnd){ + const TGeoShape* shape_shellEnd = shellEnd->GetVolume()->GetShape(); + if(shape_shellEnd->TestShapeBit(TGeoTube::kGeoTube)){ + const TGeoTube* tube = (const TGeoTube*) shape_shellEnd; + double rmin = tube->GetRmin()*CLHEP::cm; + double rmax = tube->GetRmax()*CLHEP::cm; + double zhalf = tube->GetDz()*CLHEP::cm; + //info() << rmin << "," << rmax << "," << zhalf << endmsg; + } + else{ + error() << shellEnd->GetName() << " is not a TGeoTube! Shape bits = " << shape_shellEnd->TestShapeBits(0xFFFFFFFF) << endmsg; + } + } + + } + else if(nodeName=="layer_assembly_0_1"){ + if(TGeoNode* side_band = FindNode(daughter, "ElectronicsBand")){ + const TGeoShape* shape_band = side_band->GetVolume()->GetShape(); + if(shape_band->IsA()==TGeoBBox::Class()){ + const TGeoBBox* box = (const TGeoBBox*) shape_band; + side_band_electronics_width = box->GetDX()*CLHEP::cm*2; + //info() << "fucd: "<< box->GetDX() << " " << box->GetDY() << " " << box->GetDZ() <<endmsg; + } + else{ + error() << "ElectronicsBand is not a TGeoBBox!!!"<< endmsg; + } + } + if(TGeoNode* end = FindNode(daughter, "ElectronicsEnd")){ + const TGeoShape* shape_end = end->GetVolume()->GetShape(); + if(shape_end->IsA()==TGeoBBox::Class()){ + const TGeoBBox* box = (const TGeoBBox*) shape_end; + end_electronics_half_z = box->GetDY()*CLHEP::cm; + //info() << "fucd: " << box->GetDX() << " " << box->GetDY() << " " << box->GetDZ() << endmsg; + } + else{ + error() << "ElectronicsEnd is not a TGeoBBox!!!"<< endmsg; + } + } + } + + /* + for(int j=0;j<daughter->GetNdaughters();j++){ + TGeoNode* next = daughter->GetDaughter(j); + info() << "fucd: " << next->GetName() << endmsg; + } + */ + } + + const std::map<std::string, dd4hep::DetElement>& components = vxd.children(); + for(std::map<std::string, dd4hep::DetElement>::const_iterator it=components.begin();it!=components.end();it++){ + dd4hep::DetElement component = it->second; + dd4hep::Volume vol = component.volume(); + dd4hep::PlacedVolume phys = component.placement(); + TGeoMaterial* mat = vol->GetMaterial(); + const TGeoShape* shape = vol->GetShape(); + const dd4hep::PlacedVolumeExtension::VolIDs& ids = phys.volIDs(); + //info() << " " << it->first << " " << vol->GetName() << " " << component.id() << " " << component.path() << " " << component.placementPath() << endmsg; + //info() << " " << shape->GetName() << " " << vol.solid().name() << endmsg; + //info() << " " << mat->GetName() << " " << mat->GetRadLen() << endmsg; + //info() << " " << ids.str() << endmsg; + //info() << " " << vol->GetNdaughters() << endmsg; + //double radL = mat->GetRadLen(); + //dd4hep::Solid solid = vol.solid(); + //info() << " " << sh->TestShapeBit(TGeoShape::kGeoBox) << " " << sh->GetName() << " " << phys.material().radLength() << endmsg; + if(vol.isSensitive()&&shape->IsA()==TGeoBBox::Class()){ + int iLayer = ids.find("layer")->second; + int iModule = ids.find("module")->second; + int iSide = ids.find("side")->second; + //info() << " layer=" << iLayer << " module=" << iModule << mat->GetName() << endmsg; + if(iModule==0&&iLayer==helpCount+1){ + helpCount++; + helpSensitives.push_back(thisLadder); + helpLadders.push_back(thisLadder); + helpNumberLadders.push_back(nLadders); + helpPhi0.push_back(phi0); + nLadders = 0; + thisLadder.length = 0; + } + if(iLayer == helpCount){ + if(iModule == 0){ + const TGeoBBox* box = (const TGeoBBox*) shape; + double width = box->GetDX()*CLHEP::cm; + double length = box->GetDY()*CLHEP::cm; + double thickness = box->GetDZ()*CLHEP::cm; + TGeoMatrix* matrix = phys->GetMatrix(); + const double* pos = matrix->GetTranslation(); + const double* rot_data = matrix->GetRotationMatrix(); + TGeoRotation rot; + rot.SetMatrix(rot_data); + double theta,phi,psi; + rot.GetAngles(phi,theta,psi); + phi *= TMath::DegToRad(); + theta *= TMath::DegToRad(); + psi *= TMath::DegToRad(); + phi0 = -TMath::PiOver2()+phi; + double distance = fabs(cos(phi0)*sin(theta)*pos[0]+sin(phi0)*sin(theta)*pos[1]+cos(theta)*pos[2]); + double offset = sqrt(pos[0]*pos[0]+pos[1]*pos[1]-distance*distance)*pos[0]/fabs(pos[0])*CLHEP::cm; + distance *= CLHEP::cm; + distance -= thickness; + double radL = mat->GetRadLen()*CLHEP::cm; + //info() << " -> " << helpCount << ": " << distance << " " << cos(atan2(pos[1],pos[0])-phi)*sqrt(pos[0]*pos[0]+pos[1]*pos[1]) << endmsg; + thisLadder.distance = distance; + thisLadder.offset = offset; + thisLadder.thickness = thickness; + thisLadder.length += length; + thisLadder.width = width; + thisLadder.radLength = radL; + thisLadder.z = pos[2]*CLHEP::cm; + } + if(iModule==nLadders) nLadders++; + } + } + //info() << " " << vol.solid().type() << " " << vol.solid().name() << " " << vol->GetNdaughters() << endmsg; + else if(it->first=="VXD_support"){ + helpCount++; + helpSensitives.push_back(thisLadder); + helpLadders.push_back(thisLadder); + helpNumberLadders.push_back(nLadders); + helpPhi0.push_back(phi0); + nLadders = 0; + if(vol->GetNdaughters()==0) error() << "!!!!!!!!!" << endmsg; + + int nFlexCable = 0, nFoamSpacer=0, nMetalTraces=0; + int currentLayer = -1; + double tFlexCable, tFoamSpacer, tMetalTraces; + double radLFlexCable, radLFoamSpacer, radLMetalTraces; + double intLFlexCable, intLFoamSpacer, intLMetalTraces; + double dFlexCable, dFoamSpacer, dMetalTraces; + double metalZeff, metalZAeff, foamZeff, foamZAeff, flexZeff, flexZAeff; + for(int i=0;i<vol->GetNdaughters();i++){ + TGeoNode* daughter = vol->GetNode(i); + TGeoMaterial* matDaughter = daughter->GetMedium()->GetMaterial(); + const TGeoShape* shape_sup = daughter->GetVolume()->GetShape(); + TGeoMatrix* matrix = daughter->GetMatrix(); + const double* pos = matrix->GetTranslation(); + const double* rot_data = matrix->GetRotationMatrix(); + TGeoRotation rot; + rot.SetMatrix(rot_data); + double theta,phi,psi; + rot.GetAngles(phi,theta,psi); + phi *= TMath::DegToRad(); + theta *= TMath::DegToRad(); + psi *= TMath::DegToRad(); + phi0 = -TMath::PiOver2()+phi; + std::string phy_name = daughter->GetName(); + if(phy_name.find("FoamSpacer")==-1&&phy_name.find("FlexCable")==-1&&phy_name.find("MetalTraces")==-1){ + //info() << phy_name <<endmsg; + continue; + } + int iLayer = atoi(phy_name.substr(phy_name.find("_")+1,2).c_str()); + if(iLayer!=currentLayer){ + //info() << tFoamSpacer << "," << tFlexCable << "," << tMetalTraces << endmsg; + helpLadders[currentLayer].thickness = tFoamSpacer+tFlexCable+tMetalTraces; + helpLadders[currentLayer].radLength = helpLadders[currentLayer].thickness / (tFoamSpacer/radLFoamSpacer+tFlexCable/radLFlexCable+tMetalTraces/radLMetalTraces); + nFlexCable = 0; + nFoamSpacer=0; + nMetalTraces=0; + currentLayer=iLayer; + } + //info() << "ss pos=" << pos[0] << "," << pos[1] << "," << pos[2] << " distance=" << sqrt(pos[0]*pos[0]+pos[1]*pos[1]) << endmsg; + //info() << "ss rot=" << phi << "," << theta << "," << psi << endmsg; + //info() << "ss " << daughter->GetName() << " " << daughter->GetVolume()->GetName() << " " << endmsg; + if(shape_sup->IsA()==TGeoBBox::Class()&&(nFoamSpacer==0||nFlexCable==0||nMetalTraces==0)){ + const TGeoBBox* box = (const TGeoBBox*) shape_sup; + //info() << phy_name.substr(phy_name.find("_")+1,2) << " " << iLayer << " " << box->GetDX() << "," << box->GetDY() << "," << box->GetDZ() << endmsg; + //info() << "fucd: pos " << pos[0] << " " << pos[1] << " " << pos[2] << endmsg; + double distance = fabs(cos(phi0)*sin(theta)*pos[0]+sin(phi0)*sin(theta)*pos[1]+cos(theta)*pos[2]); + double offset = sqrt(pos[0]*pos[0]+pos[1]*pos[1]-distance*distance)*pos[0]/fabs(pos[0])*CLHEP::cm; + distance -= box->GetDZ(); + distance *= CLHEP::cm; + if(helpLadders[iLayer].distance == helpSensitives[iLayer].distance) helpLadders[iLayer].distance = distance; + else helpLadders[iLayer].distance = TMath::Min(helpLadders[iLayer].distance, distance); + //info() << phy_name << " " << distance << " " << offset << endmsg; + if(phy_name.find("FoamSpacer")!=-1&&nFoamSpacer==0){ + helpLadders[iLayer].offset = offset; + tFoamSpacer = box->GetDZ()*CLHEP::cm; + radLFoamSpacer = matDaughter->GetRadLen()*CLHEP::cm; + intLFoamSpacer = matDaughter->GetIntLen()*CLHEP::cm; + dFoamSpacer = matDaughter->GetDensity()*CLHEP::g/CLHEP::cm3; + //fucd: A calculated by TGeoMaterial class is not equal to Zeff/ZAeff, Zeff = sum(Zi*Ai/sumA), ZAeff = sum(Zi/Ai*A/totalA) + // use Zeff and ZAeff to keep same with Mokka case + //foamZ = matDaughter->GetZ(); + //foamA = matDaughter->GetA(); + double totalA = 0, Zeff = 0, ZAeff = 0; + for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){ + totalA += matDaughter->GetElement(iEle)->A(); + } + for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){ + double A, Z, w; + // by fucd: w!=A/totalA, strange! to fix + matDaughter->GetElementProp(A,Z,w,iEle); + Zeff += Z*w; + ZAeff += Z/A*w; + //info() << std::setprecision(16) << Z << " " << A << " " << A/totalA << " " << w << endmsg; + } + foamZeff = Zeff; + foamZAeff = ZAeff; + nFoamSpacer++; + } + if(phy_name.find("FlexCable")!=-1&&nFlexCable==0){ + helpLadders[iLayer].width = box->GetDX()*CLHEP::cm; + helpLadders[iLayer].length = box->GetDY()*CLHEP::cm-beryllium_ladder_block_length*2-end_electronics_half_z*2; + tFlexCable = box->GetDZ()*CLHEP::cm; + radLFlexCable = matDaughter->GetRadLen()*CLHEP::cm; + intLFlexCable = matDaughter->GetIntLen()*CLHEP::cm; + dFlexCable = matDaughter->GetDensity()*CLHEP::g/CLHEP::cm3; + double Zeff = 0, ZAeff = 0; + for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){ + double A, Z, w; + matDaughter->GetElementProp(A,Z,w,iEle); + Zeff += Z*w; + ZAeff += Z/A*w; + //std::cout << std::setprecision(16) << Z << " " << A << " " << w << std::endl; + } + flexZeff = Zeff; + flexZAeff = ZAeff; + nFlexCable++; + } + if(phy_name.find("MetalTraces")!=-1&&nMetalTraces==0){ + tMetalTraces = box->GetDZ()*CLHEP::cm; + radLMetalTraces = matDaughter->GetRadLen()*CLHEP::cm; + intLMetalTraces = matDaughter->GetIntLen()*CLHEP::cm; + dMetalTraces = matDaughter->GetDensity()*CLHEP::g/CLHEP::cm3; + double totalA = 0, Zeff = 0, ZAeff = 0; + for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){ + totalA += matDaughter->GetElement(iEle)->A(); + } + for(int iEle = 0; iEle<matDaughter->GetNelements(); iEle++){ + double A, Z, w; + matDaughter->GetElementProp(A,Z,w,iEle); + Zeff += Z*w; + ZAeff += Z/A*w; + //info() << Z << " " << A << " " << w << endmsg; + } + metalZeff = Zeff; + metalZAeff = ZAeff; + nMetalTraces++; + } + } + } + { + //info() << tFoamSpacer << "," << tFlexCable << "," << tMetalTraces << endmsg; + double tSupport = tMetalTraces + tFoamSpacer + tFlexCable; + helpLadders[currentLayer].thickness = tSupport; + helpLadders[currentLayer].radLength = helpLadders[currentLayer].thickness / (tFoamSpacer/radLFoamSpacer+tFlexCable/radLFlexCable+tMetalTraces/radLMetalTraces); + nFlexCable = 0; + nFoamSpacer=0; + nMetalTraces=0; + + //calculations of thickness fractions of each layer of the support + double metalTF = tMetalTraces / tSupport; + double foamTF = tFoamSpacer / tSupport; + double flexTF = tFlexCable / tSupport; + //info() << foamTF << "," << flexTF << "," << metalTF << endmsg; + //info() << dFoamSpacer/(CLHEP::kg/CLHEP::cm3) << "," << dFlexCable/(CLHEP::kg/CLHEP::cm3) << "," << dMetalTraces/(CLHEP::kg/CLHEP::cm3) << endmsg; + //info() << foamZeff << " " << flexZeff << " " << metalZeff << endmsg; + //info() << foamZAeff << " " << flexZAeff << " " << metalZAeff << endmsg; + G4double elemVol = 1*CLHEP::cm3; + G4double VXDSupportMass = (foamTF*dFoamSpacer + flexTF*dFlexCable + metalTF*dMetalTraces)*elemVol; + VXDSupportDensity = VXDSupportMass/elemVol; + + G4double foamFM = 100. * ((foamTF*(elemVol)*dFoamSpacer) / VXDSupportMass) ; + G4double kaptonFM = 100. * ((flexTF*(elemVol)*dFlexCable) / VXDSupportMass) ; + G4double metalFM = 100. * ((metalTF*(elemVol)*dMetalTraces) / VXDSupportMass) ; + + VXDSupportRadLen = helpLadders[currentLayer].radLength; + + VXDSupportZeff = (metalFM/100.)*metalZeff + (kaptonFM/100.)*flexZeff + (foamFM/100.)*foamZeff; + G4double VXDSupportZAeff = (metalFM/100.)*metalZAeff + (kaptonFM/100.)*flexZAeff + (foamFM/100.)*foamZAeff; + VXDSupportAeff = VXDSupportZeff / VXDSupportZAeff; + G4double VXDSupportIntLength = 1. / ((metalTF/intLMetalTraces) + (flexTF/intLFlexCable) + (foamTF/intLFoamSpacer)); + VXDSupportDensity = 1000*VXDSupportDensity/(CLHEP::g/CLHEP::cm3); + //info() << "fucd: " << VXDSupportZeff << " " << VXDSupportAeff << " " << VXDSupportRadLen << " " << VXDSupportIntLength << " " << VXDSupportDensity << endmsg; + //info() << intLMetalTraces << " " << intLFlexCable << " " << intLFoamSpacer <<endmsg; + } + } + //info() << it->first << endmsg; + } + if(end_electronics_half_z>0 && side_band_electronics_width==0) type = gear::ZPlanarParametersImpl::CCD ; + if(side_band_electronics_width>0 && end_electronics_half_z==0 ) type = gear::ZPlanarParametersImpl::CMOS ; + if(side_band_electronics_width>0 && end_electronics_half_z>0) type = gear::ZPlanarParametersImpl::HYBRID ; + + m_vxdParameters = new gear::ZPlanarParametersImpl(type, shellInnerRadius, shellOuterRadius, shellHalfLength, gap, shellRadLength ); + // by fucd: debug info, if validated enough, merge them in future + info() << "=====================from convertor==============================" << endmsg; + info() << type << " " << shellInnerRadius << " " << shellOuterRadius << " " << shellHalfLength << " " << gap << " " << shellRadLength << endmsg; + for(int i=0;i<helpCount;i++){ + m_vxdParameters->addLayer(helpNumberLadders[i] , helpPhi0[i] , + helpLadders[i].distance , helpLadders[i].offset, helpLadders[i].thickness*2 , + helpLadders[i].length , helpLadders[i].width*2 , helpLadders[i].radLength , + helpSensitives[i].distance, helpSensitives[i].offset , helpSensitives[i].thickness*2 , + helpSensitives[i].length , helpSensitives[i].width*2 , helpSensitives[i].radLength ) ; + info() << "fucd " << i << ": " << helpNumberLadders[i] << ", " << helpPhi0[i] << ", " + << helpLadders[i].distance << ", " << helpLadders[i].offset << ", " << helpLadders[i].thickness*2 << ", " << helpLadders[i].length << ", " + << helpLadders[i].width*2 << ", " << helpLadders[i].radLength << ", " << helpSensitives[i].distance << ", " << helpSensitives[i].offset << ", " + << helpSensitives[i].thickness*2 << ", " << helpSensitives[i].length << ", " << helpSensitives[i].width*2 << ", " << helpSensitives[i].radLength << endmsg; + } + //m_vxdInfra = new gear::GearParametersImpl; + //CryostatAlRadius, CryostatAlThickness, CryostatAlInnerR, CryostatAlZEndCap, CryostatAlHalfZ + //m_vxdInfra->setDoubleVal("CryostatAlRadius",rAlu); + //m_vxdInfra->setDoubleVal("CryostatAlThickness",drAlu); + //m_vxdInfra->setDoubleVal("CryostatAlInnerR",rInner); + //m_vxdInfra->setDoubleVal("CryostatAlZEndCap",aluEndcapZ=dzSty + drSty + drAlu / 2); + //m_vxdInfra->setDoubleVal("CryostatAlHalfZ",aluHalfZ= dzSty + drSty); + // change GearParametersImpl to map + std::map<std::string,double> vxdInfra; + vxdInfra["CryostatAlRadius"] = rAlu; + vxdInfra["CryostatAlThickness"] = drAlu; + vxdInfra["CryostatAlInnerR"] = rInner; + vxdInfra["CryostatAlZEndCap"] = dzSty+drSty+drAlu/2; + vxdInfra["CryostatAlHalfZ"] = dzSty+drSty; + m_detParameters["VXDInfra"] = vxdInfra; + //effective A different with what in Mokka, fix them as Mokka's + //m_materials["VXDSupportMaterial"] = new TMaterial("VXDSupportMaterial", "", VXDSupportAeff, VXDSupportZeff, VXDSupportDensity, VXDSupportRadLen, 0.); + m_materials["VXDSupportMaterial"] = new TMaterial("VXDSupportMaterial", "", 2.075865162e+01, 1.039383117e+01, 2.765900000e+02/1000, 1.014262421e+02, 0.); + + info() << "=====================from ZPlanarData==============================" << endmsg; + if(m_vxdData){ + info() << m_vxdData->rInnerShell << " " << m_vxdData->rOuterShell << " " << m_vxdData->zHalfShell << " " << m_vxdData->gapShell << endmsg; + const std::vector<dd4hep::rec::ZPlanarData::LayerLayout>& layers = m_vxdData->layers; + for(int i=0;i<layers.size();i++){ + const dd4hep::rec::ZPlanarData::LayerLayout& thisLayer = layers[i]; + info() << i << ": " << thisLayer.ladderNumber << "," << thisLayer.phi0 << "," << thisLayer.distanceSupport << "," << thisLayer.offsetSupport << "," + << thisLayer.thicknessSupport << "," << thisLayer.zHalfSupport << "," << thisLayer.widthSupport << "," << "NULL," + << thisLayer.distanceSensitive << "," << thisLayer.offsetSensitive << "," << thisLayer.thicknessSensitive << "," << thisLayer.zHalfSensitive << "," + << thisLayer.widthSensitive << ",NULL" << endmsg; + } + } + info() << rAlu << " " << drAlu << " " << rInner << " " << aluEndcapZ << " " << aluHalfZ << endmsg; + //info() << m_materials["VXDSupportMaterial"] << endmsg; + return sc; +} + +TGeoNode* GeoSvc::FindNode(TGeoNode* mother, char* name){ + TGeoNode* next = 0; + if(mother->GetNdaughters()!=0){ + for(int i=0;i<mother->GetNdaughters();i++){ + TGeoNode* daughter = mother->GetDaughter(i); + std::string s = daughter->GetName(); + //info() << "current: " << s << " search for" << name << endmsg; + if(s.find(name)!=-1){ + next = daughter; + break; + } + else{ + next = FindNode(daughter, name); + } + } + } + return next; +} + +TMaterial* GeoSvc::getMaterial(std::string name){ + std::map<std::string, TMaterial*>::const_iterator it = m_materials.find(name); + if(it!=m_materials.end()) return it->second; + else return 0; + } diff --git a/Detector/GeoSvc/src/GeoSvc.h b/Detector/GeoSvc/src/GeoSvc.h index 1be2b4ff4e0d4a504e216cc9b9a302dec001f5f6..b90060cfa5adc65a00fb013089bff8412c826e37 100644 --- a/Detector/GeoSvc/src/GeoSvc.h +++ b/Detector/GeoSvc/src/GeoSvc.h @@ -15,29 +15,65 @@ // DD4Hep #include "DD4hep/Detector.h" -class GeoSvc: public extends<Service, IGeoSvc> { -public: - GeoSvc(const std::string& name, ISvcLocator* svc); - ~GeoSvc(); +#include <gear/GEAR.h> +#include <gearimpl/ZPlanarParametersImpl.h> +#include <gearimpl/GearParametersImpl.h> + +class dd4hep::DetElement; +class TGeoNode; - // Service - StatusCode initialize() override; - StatusCode finalize() override; +class GeoSvc: public extends<Service, IGeoSvc> { + public: + GeoSvc(const std::string& name, ISvcLocator* svc); + ~GeoSvc(); + + // Service + StatusCode initialize() override; + StatusCode finalize() override; + + // IGeoSvc + dd4hep::DetElement getDD4HepGeo() override; + dd4hep::Detector* lcdd() override; + + const gear::ZPlanarParametersImpl* getVXDParameters() override {return m_vxdParameters;}; + const dd4hep::rec::ZPlanarData* getVXDData() override {return m_vxdData;}; + const dd4hep::rec::ConicalSupportData* getBeamPipeData() override {return m_beamPipeData;}; - // IGeoSvc - dd4hep::DetElement getDD4HepGeo() override; - dd4hep::Detector* lcdd() override; + const std::map<std::string,double>& getDetParameters(std::string name) override; + const double getDetParameter(std::string set_name, std::string par_name) override; + TMaterial* getMaterial(std::string name); + + private: + StatusCode convertVXD(dd4hep::DetElement& sub); Decoder* getDecoder(const std::string& readout_name) override; private: + TGeoNode* FindNode(TGeoNode* mother, char* name); + // DD4hep XML compact file path + Gaudi::Property<std::string> m_dd4hep_xmls{this, "compact"}; + + // + dd4hep::Detector* m_dd4hep_geo; - // DD4hep XML compact file path - Gaudi::Property<std::string> m_dd4hep_xmls{this, "compact"}; - // - dd4hep::Detector* m_dd4hep_geo; -}; + gear::ZPlanarParametersImpl* m_vxdParameters; + dd4hep::rec::ZPlanarData* m_vxdData; + dd4hep::rec::ConicalSupportData* m_beamPipeData; + //gear::GearParametersImpl* m_vxdInfra; + std::map<std::string, std::map<std::string,double> > m_detParameters; + std::map<std::string, TMaterial*> m_materials; + struct helpLayer { + double distance =0; + double offset =0; + double thickness =0; + double length =0; + double width =0; + double radLength =0; + double z =0; + double foam_spacer_radLength =0; + }; +}; #endif // GeoSvc_h diff --git a/Digitisers/SimpleDigi/CMakeLists.txt b/Digitisers/SimpleDigi/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..90246e681c2ba41d66ff8c916e4a8d451a8c8503 --- /dev/null +++ b/Digitisers/SimpleDigi/CMakeLists.txt @@ -0,0 +1,23 @@ +gaudi_subdir(SimpleDigi v0r0) + +find_package(CLHEP REQUIRED) +find_package(GEAR REQUIRED) +find_package(GSL REQUIRED ) +find_package(LCIO REQUIRED ) +find_package(podio REQUIRED ) +find_package(K4FWCore REQUIRED) +find_package(EDM4HEP REQUIRED) + +gaudi_depends_on_subdirs( + Service/GearSvc + Service/EventSeeder + Service/TrackSystemSvc +) + +set(SimpleDigi_srcs src/*.cpp) + +# Modules +gaudi_add_module(SimpleDigi ${SimpleDigi_srcs} + INCLUDE_DIRS K4FWCore GaudiKernel GaudiAlgLib CLHEP gear ${GSL_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} + LINK_LIBRARIES K4FWCore GaudiKernel GaudiAlgLib CLHEP $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} ${LCIO_LIBRARIES} EDM4HEP::edm4hep EDM4HEP::edm4hepDict +) diff --git a/Reconstruction/Digitisers/src/PlanarDigiAlg.cpp b/Digitisers/SimpleDigi/src/PlanarDigiAlg.cpp similarity index 76% rename from Reconstruction/Digitisers/src/PlanarDigiAlg.cpp rename to Digitisers/SimpleDigi/src/PlanarDigiAlg.cpp index 203fec53b1e5c9da461da41df7718ee15d8ae3fb..7cb4830dc2d9c6b6665d31416f6ab38a49784c20 100644 --- a/Reconstruction/Digitisers/src/PlanarDigiAlg.cpp +++ b/Digitisers/SimpleDigi/src/PlanarDigiAlg.cpp @@ -2,8 +2,9 @@ #include "PlanarDigiAlg.h" #include "GearSvc/IGearSvc.h" #include "EventSeeder/IEventSeeder.h" -#include "plcio/MCParticleConst.h" - +#include "TrackSystemSvc/ITrackSystemSvc.h" +#include "edm4hep/MCParticleConst.h" +#include "edm4hep/Vector3d.h" /* #include <EVENT/LCCollection.h> #include <EVENT/SimTrackerHit.h> @@ -47,7 +48,7 @@ PlanarDigiAlg::PlanarDigiAlg(const std::string& name, ISvcLocator* svcLoc) // Output collections declareProperty("TrackerHitCollection", _outColHdl, "Handle of the TrackerHit output collection"); - declareProperty("SimTrkHitRelCollection", _outRelColHdl, "Handle of TrackerHit SimTrackHit relation collection"); + declareProperty("TrackerHitAssociationCollection", _outRelColHdl, "Handle of TrackerHit SimTrackHit relation collection"); } StatusCode PlanarDigiAlg::initialize() @@ -83,25 +84,46 @@ StatusCode PlanarDigiAlg::initialize() //TODO:trksystem->init() ; //FIXME:SJA gear surface store has now been filled so we can dispose of the MarlinTrkSystem //TODO:delete trksystem; - + + auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc"); + if ( !_trackSystemSvc ) { + error() << "Failed to find TrackSystemSvc ..." << endmsg; + return StatusCode::FAILURE; + } + + MarlinTrk::IMarlinTrkSystem* _trksystem = _trackSystemSvc->getTrackSystem(); + _trksystem->init(); + + _trackSystemSvc->removeTrackSystem(); + return GaudiAlgorithm::initialize(); } StatusCode PlanarDigiAlg::execute() { - auto header = _headerCol.get()->at(0); - int evtNo = header.getEventNumber(); - int runNo = header.getRunNumber(); - debug() << "Processing Run[" << runNo << "]::Event[" << evtNo << "]" << endmsg; + //auto header = _headerCol.get()->at(0); + //int evtNo = header.getEventNumber(); + //int runNo = header.getRunNumber(); + //debug() << "Processing Run[" << runNo << "]::Event[" << evtNo << "]" << endmsg; - unsigned int thisSeed = _SEEDER->getSeed(this, evtNo, runNo); + //unsigned int thisSeed = _SEEDER->getSeed(this, evtNo, runNo); + unsigned int thisSeed = _SEEDER->getSeed(this, _nEvt, 0); gsl_rng_set( _rng, thisSeed ) ; debug() << "seed set to " << thisSeed << endmsg; - auto STHcol = _inColHdl.get(); - if ( STHcol == nullptr ) { + //auto STHcol = _inColHdl.get(); + //if ( STHcol == nullptr ) { + // debug() << "Collection " << _inColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + // return StatusCode::SUCCESS; // or FAILURE ? + //} + + const edm4hep::SimTrackerHitCollection* STHcol = nullptr; + try { + STHcol = _inColHdl.get(); + } + catch ( GaudiException &e ) { debug() << "Collection " << _inColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; - return StatusCode::SUCCESS; // or FAILURE ? + return StatusCode::SUCCESS; } // ** @@ -123,30 +145,29 @@ StatusCode PlanarDigiAlg::execute() if ( nSimHits>0 ) { auto SimTHit = STHcol->at( 0 ) ; - encoder.setValue(SimTHit.getCellID0()) ; + encoder.setValue(SimTHit.getCellID()) ; det_id = encoder[lcio::ILDCellID0::subdet] ; - } - - if ( det_id == lcio::ILDDetID::VXD ){} - else if( det_id == lcio::ILDDetID::SIT ){} - else if( det_id == lcio::ILDDetID::SET ){} - else if( det_id == lcio::ILDDetID::FTD ){} - else { - fatal() << "unsupported detector ID = " << det_id - << ": file " << __FILE__ << " line " << __LINE__ - << endmsg; - return StatusCode::FAILURE; + + if ( det_id == lcio::ILDDetID::VXD ){} + else if( det_id == lcio::ILDDetID::SIT ){} + else if( det_id == lcio::ILDDetID::SET ){} + else if( det_id == lcio::ILDDetID::FTD ){} + else { + fatal() << "unsupported detector ID = " << det_id << " CellID = " << SimTHit.getCellID() + << ": file " << __FILE__ << " line " << __LINE__ + << endmsg; + return StatusCode::FAILURE; + } } //smearing debug() << " processing collection " << _inColHdl.fullKey() << " with " << nSimHits << " hits ... " << endmsg ; - int i = 0; for( auto SimTHit : *STHcol ) { - const int celId = SimTHit->getCellID0() ; + const int celId = SimTHit.getCellID() ; encoder.setValue(celId) ; int side = encoder[lcio::ILDCellID0::side]; @@ -191,19 +212,19 @@ StatusCode PlanarDigiAlg::execute() debug() << " --- will smear hit with resU = " << resU << " and resV = " << resV << endmsg; - auto& pos = SimTHit->getPosition() ; - - double smearedPos[3]; + auto& pos = SimTHit.getPosition() ; - // GearSurfaces::MeasurementSurface* ms = _GEAR->getMeasurementSurfaceStore().GetMeasurementSurface( SimTHit->getCellID0() ); + //edm4hep::Vector3d smearedPos; + //GearSurfaces::MeasurementSurface* ms = _GEAR->getMeasurementSurfaceStore().GetMeasurementSurface( SimTHit->getCellID0() ); + gear::MeasurementSurface const* ms = _GEAR->getMeasurementSurfaceStore().GetMeasurementSurface( encoder.lowWord() );; CLHEP::Hep3Vector globalPoint(pos[0],pos[1],pos[2]); CLHEP::Hep3Vector localPoint = ms->getCoordinateSystem()->getLocalPoint(globalPoint); CLHEP::Hep3Vector localPointSmeared = localPoint; - debug() << "Position of hit before smearing global: ( "<<pos[0]<<" "<<pos[1]<<" "<<pos[2]<< " ) " + debug() << std::setprecision(8) << "Position of hit before smearing global: ( "<<pos[0]<<" "<<pos[1]<<" "<<pos[2]<< " ) " << "local: ( " << localPoint.x() << " " << localPoint.y() << " " << localPoint.z() << " )" << endmsg; // A small check, if the hit is in the boundaries: @@ -256,17 +277,18 @@ StatusCode PlanarDigiAlg::execute() << "local: ( " << localPointSmeared.x() << " " << localPointSmeared.y() << " " << localPointSmeared.z() << " )" << endmsg; - - smearedPos[0] = globalPointSmeared.x(); - smearedPos[1] = globalPointSmeared.y(); - smearedPos[2] = globalPointSmeared.z(); + + //smearedPos[0] = globalPointSmeared.x(); + //smearedPos[1] = globalPointSmeared.y(); + //smearedPos[2] = globalPointSmeared.z(); //make the TrackerHitPlaneImpl auto trkHit = trkhitVec->create(); - trkHit->setCellID0( encoder.lowWord() ); + trkHit.setCellID( encoder.lowWord() ); - trkHit->setPosition( smearedPos ) ; + edm4hep::Vector3d smearedPos(globalPointSmeared.x(), globalPointSmeared.y(), globalPointSmeared.z()); + trkHit.setPosition( smearedPos ) ; gear::CartesianCoordinateSystem* cartesian = dynamic_cast< gear::CartesianCoordinateSystem* >( ms->getCoordinateSystem() ); CLHEP::Hep3Vector uVec = cartesian->getLocalXAxis(); @@ -283,7 +305,15 @@ StatusCode PlanarDigiAlg::execute() debug() << " U[0] = "<< u_direction[0] << " U[1] = "<< u_direction[1] << " V[0] = "<< v_direction[0] << " V[1] = "<< v_direction[1] << endmsg ; - + // fucd + std::array<float, 6> cov; + cov[0] = u_direction[0]; + cov[1] = u_direction[1]; + cov[2] = resU; + cov[3] = v_direction[0]; + cov[4] = v_direction[1]; + cov[5] = resV; + trkHit.setCovMatrix(cov); /* zoujh: TODO - generate TrackerHitPlane with podio trkHit->setU( u_direction ) ; trkHit->setV( v_direction ) ; @@ -293,12 +323,12 @@ StatusCode PlanarDigiAlg::execute() if( _isStrip ) trkHit->setdV( 0 ); // no error in v direction for strip hits as there is no meesurement information in v direction else trkHit->setdV( resV ) ; */ - + trkHit.setType(8); if( _isStrip ){ - trkHit->setType( UTIL::set_bit( trkHit->getType() , UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ) ) ; + trkHit.setType( UTIL::set_bit( trkHit.getType() , UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ) ) ; } - trkHit->setEDep( SimTHit->getEDep() ); + trkHit.setEDep( SimTHit.getEDep() ); // make the relation auto rel = relCol->create(); @@ -310,10 +340,10 @@ StatusCode PlanarDigiAlg::execute() << " to tracker hit " << trkHit << " with a weight of " << weight << endmsg; - - rel.setFrom( trkHit->getObjectID() ); - rel.setTo( SimTHit->getObjectID() ); - rel.setWeight( weight ); + trkHit.addToRawHits(SimTHit.getObjectID()); + rel.setSim(SimTHit); + rel.setRec(trkHit); + rel.setWeight(weight); nCreatedHits++; diff --git a/Reconstruction/Digitisers/src/PlanarDigiAlg.h b/Digitisers/SimpleDigi/src/PlanarDigiAlg.h similarity index 80% rename from Reconstruction/Digitisers/src/PlanarDigiAlg.h rename to Digitisers/SimpleDigi/src/PlanarDigiAlg.h index 0b7b12b7d59a5b3ac089a4eb28a00089b2046d3c..30c2e091aaec8e2e986a38a77eb2e4bea4e56cb1 100644 --- a/Reconstruction/Digitisers/src/PlanarDigiAlg.h +++ b/Digitisers/SimpleDigi/src/PlanarDigiAlg.h @@ -4,10 +4,10 @@ #include "FWCore/DataHandle.h" #include "GaudiAlg/GaudiAlgorithm.h" #include <gsl/gsl_rng.h> -#include "plcio/EventHeaderCollection.h" -#include "plcio/SimTrackerHitCollection.h" -#include "plcio/TrackerHitCollection.h" -#include "plcio/LCRelationCollection.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" /** ======= PlanarDigiProcessor / PlanarDigiAlg ========== <br> * Creates TrackerHits from SimTrackerHits, smearing them according to the input parameters. @@ -81,11 +81,11 @@ protected: Gaudi::Property<bool> _isStrip{ this, "IsStrip", false }; // Input collections - DataHandle<plcio::EventHeaderCollection> _headerCol{"EventHeaderCol", Gaudi::DataHandle::Reader, this}; - DataHandle<plcio::SimTrackerHitCollection> _inColHdl{"VXDCollection", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::EventHeaderCollection> _headerCol{"EventHeaderCol", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::SimTrackerHitCollection> _inColHdl{"VXDCollection", Gaudi::DataHandle::Reader, this}; // Output collections - DataHandle<plcio::TrackerHitCollection> _outColHdl{"VXDTrackerHits", Gaudi::DataHandle::Writer, this}; - DataHandle<plcio::LCRelationCollection> _outRelColHdl{"VTXTrackerHitRelations", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _outColHdl{"VXDTrackerHits", Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCRecoTrackerAssociationCollection> _outRelColHdl{"VTXTrackerHitRelations", Gaudi::DataHandle::Writer, this}; }; #endif diff --git a/Reconstruction/Digitisers/CMakeLists.txt b/Reconstruction/Digitisers/CMakeLists.txt deleted file mode 100644 index 56952b161a470fb392408a69fa0e50f740258e6b..0000000000000000000000000000000000000000 --- a/Reconstruction/Digitisers/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -gaudi_subdir(Digitisers v0r0) - -find_package(CLHEP REQUIRED) -find_package(GEAR REQUIRED) -find_package(GSL REQUIRED ) -find_package(LCIO REQUIRED ) -find_package(podio REQUIRED ) -find_package(K4FWCore REQUIRED) - -gaudi_depends_on_subdirs( - Service/GearSvc - Service/EventSeeder -) - -# set(Digitisers_srcs -# src/*.cpp -# ) - -# # Modules -# gaudi_add_module(Digitisers ${Digitisers_srcs} -# INCLUDE_DIRS K4FWCore GaudiKernel GaudiAlgLib CLHEP gear ${plcio_INCLUDE_DIRS} ${GSL_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} -# LINK_LIBRARIES K4FWCore GaudiKernel GaudiAlgLib CLHEP $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} $ENV{PLCIO}/lib/libplcio.so ${LCIO_LIBRARIES} -# ) diff --git a/Reconstruction/SiliconTracking/CMakeLists.txt b/Reconstruction/SiliconTracking/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..93d860ba31a396d5797b31746788a39533698e2d --- /dev/null +++ b/Reconstruction/SiliconTracking/CMakeLists.txt @@ -0,0 +1,22 @@ +gaudi_subdir(SiliconTracking v0r0) + +find_package(GEAR REQUIRED) +find_package(GSL REQUIRED ) +find_package(LCIO REQUIRED ) +find_package(EDM4HEP REQUIRED ) + +gaudi_depends_on_subdirs( + Service/GearSvc + Service/EventSeeder + Service/TrackSystemSvc + Utilities/DataHelper + Utilities/KiTrack +) + +set(SiliconTracking_srcs src/*.cpp) + +# Modules +gaudi_add_module(SiliconTracking ${SiliconTracking_srcs} + INCLUDE_DIRS GaudiKernel FWCore gear ${GSLx_INCLUDE_DIRS} ${LCIOx_INCLUDE_DIRS} + LINK_LIBRARIES TrackSystemSvcLib DataHelperLib KiTrackLib GaudiKernel FWCore $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} ${LCIO_LIBRARIES} +) diff --git a/Reconstruction/SiliconTracking/src/ForwardTrackingAlg.cpp b/Reconstruction/SiliconTracking/src/ForwardTrackingAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57868b94f45e57365e7d08e85f99b96f6fa74c50 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/ForwardTrackingAlg.cpp @@ -0,0 +1,975 @@ +#include "ForwardTrackingAlg.h" +#include "GearSvc/IGearSvc.h" +#include "TrackSystemSvc/ITrackSystemSvc.h" +#include "DataHelper/Navigation.h" + +#include "edm4hep/TrackerHit.h" +#include "edm4hep/TrackerHitConst.h" +#include "edm4hep/Track.h" + +#include "UTIL/ILDConf.h" + +//#include "MarlinCED.h" + +#include "gear/GEAR.h" +#include "gear/GearParameters.h" +#include "gear/BField.h" +#include "gear/FTDParameters.h" +#include "gear/FTDLayerLayout.h" + +//----From KiTrack----------------------------- +#include "KiTrack/SubsetHopfieldNN.h" +#include "KiTrack/SubsetSimple.h" +#include "KiTrack/SegmentBuilder.h" +#include "KiTrack/Automaton.h" + +//----From KiTrackMarlin----------------------- +#include "ILDImpl/FTDTrack.h" +#include "ILDImpl/FTDHit01.h" +#include "ILDImpl/FTDNeighborPetalSecCon.h" +#include "ILDImpl/FTDSectorConnector.h" +#include "Tools/KiTrackMarlinTools.h" +//#include "Tools/KiTrackMarlinCEDTools.h" +#include "Tools/FTDHelixFitter.h" + +using namespace MarlinTrk ; + +// Used to fedine the quality of the track output collection +const int ForwardTrackingAlg::_output_track_col_quality_GOOD = 1; +const int ForwardTrackingAlg::_output_track_col_quality_FAIR = 2; +const int ForwardTrackingAlg::_output_track_col_quality_POOR = 3; + +DECLARE_COMPONENT( ForwardTrackingAlg ) + +ForwardTrackingAlg::ForwardTrackingAlg(const std::string& name, ISvcLocator* svcLoc) +: GaudiAlgorithm(name, svcLoc) { + //_description = "ForwardTracking reconstructs tracks through the FTD" ; + + declareProperty("FTDPixelHitCollection", _inFTDPixelColHdl, "Handle of the Input FTD TrackerHits collection"); + declareProperty("FTDSpacePointCollection", _inFTDSpacePointColHdl, "Handle of the Input FTD SpacePoints collection"); + declareProperty("FTDRawHitCollection", _inFTDRawColHdl, "Handle of the FTD SpacePoints raw hit collection collection"); + //std::vector< std::string > collections; + //collections.push_back( "FTDTrackerHits" ); + //collections.push_back( "FTDSpacePoints" ); + declareProperty("ForwardTrackCollection", _outColHdl, "Handle of the ForwarTrack output collection"); +} + +StatusCode ForwardTrackingAlg::initialize(){ + debug() << " init called " << endmsg; + + _nRun = 0 ; + _nEvt = 0 ; + + _useCED = false; // Setting this to on will initialise CED in the processor and tracks or segments (from the CA) + // can be printed. As this is mainly used for debugging it is not a steerable parameter. + //if( _useCED )MarlinCED::init(this) ; //CED + + // Now set min and max values for all the criteria + for( unsigned i=0; i < _criteriaNames.size(); i++ ){ + std::vector< float > emptyVec; + _critMinima[_criteriaNames[i]] = emptyVec; + _critMaxima[_criteriaNames[i]] = emptyVec; + } + if(_critMinimaInit.size()!=_critMaximaInit.size()){ + warning() << "number of Criteria min values != max values, will be filled as 0 for less" << endmsg; + } + unsigned nCritValues = std::max(_critMinimaInit.size(),_critMaximaInit.size()); + //if(nCritValues>_criteriaNames.size()){ + // warning() << "number of Criteria values > name's, will be discarded" << endmsg; + //} + //nCritValues = std::min(nCritValues, _criteriaNames.size()); + for(unsigned i=0; i<nCritValues; i++){ + int iCritName = i%_criteriaNames.size(); + std::string critName = _criteriaNames[iCritName]; + if(i<_critMinimaInit.size()) _critMinima[critName].push_back(_critMinimaInit[i]); + else _critMinima[critName].push_back(0.); + if(i<_critMaximaInit.size()) _critMaxima[critName].push_back(_critMaximaInit[i]); + else _critMaxima[critName].push_back(0.); + } + debug() << "Criteria table:" << endmsg; + for(unsigned i=0; i<_criteriaNames.size(); i++ ){ + std::string critName = _criteriaNames[i]; + debug() << "---- " << critName; + for(unsigned j=0; j<_critMinima[critName].size(); j++){ + debug() << " [" << _critMinima[critName][j] << ", " << _critMaxima[critName][j] << "]"; + } + debug() << endmsg; + } + + auto _gear = service<IGearSvc>("GearSvc"); + if ( !_gear ) { + error() << "Failed to find GearSvc ..." << endmsg; + return StatusCode::FAILURE; + } + gear::GearMgr* gearMgr = _gear->getGearMgr(); + + /**********************************************************************************************/ + /* Make a SectorSystemFTD */ + /**********************************************************************************************/ + + // The SectorSystemFTD is the object translating the sectors of the hits into layers, modules etc. and vice versa + const gear::FTDParameters& ftdParams = gearMgr->getFTDParameters() ; + const gear::FTDLayerLayout& ftdLayers = ftdParams.getFTDLayerLayout() ; + int nLayers = ftdLayers.getNLayers() + 1; // we add one layer for the IP + int nModules = ftdLayers.getNPetals(0); + int nSensors = ftdLayers.getNSensors(0); + + // make sure we take the highest number of modules / sensors available + for( int i=1; i < nLayers - 1; i++){ + + if( ftdLayers.getNPetals(i) > nModules ) nModules = ftdLayers.getNPetals(i); + if( ftdLayers.getNSensors(i) > nSensors ) nSensors = ftdLayers.getNSensors(i); + + } + + debug() << "SectorSystemFTD is using " << nLayers << " layers (including one for the IP), " << nModules << " petals and " << nSensors << " sensors." << endmsg; + + _sectorSystemFTD = new SectorSystemFTD( nLayers, nModules , nSensors ); + + // Get the B Field in z direction + _Bz = gearMgr->getBField().at( gear::Vector3D(0., 0., 0.) ).z(); //The B field in z direction + + /**********************************************************************************************/ + /* Initialise the MarlinTrkSystem, needed by the tracks for fitting */ + /**********************************************************************************************/ + auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc"); + if ( !_trackSystemSvc ) { + error() << "Failed to find TrackSystemSvc ..." << endmsg; + return StatusCode::FAILURE; + } + _trkSystem = _trackSystemSvc->getTrackSystem(); + + if( _trkSystem == 0 ){ + error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg; + return StatusCode::FAILURE; + } + + // set the options + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useQMS, _MSOn ) ; //multiple scattering + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::usedEdx, _ElossOn) ; //energy loss + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useSmoothing, _SmoothOn) ; //smoothing + + // initialise the tracking system + //_trkSystem->init() ; + + /**********************************************************************************************/ + /* Do a few checks, if the set parameters are right */ + /**********************************************************************************************/ + + // Only use allowed methods to find subsets. + assert( ( _bestSubsetFinder == "None" ) || ( _bestSubsetFinder == "SubsetHopfieldNN" ) || ( _bestSubsetFinder == "SubsetSimple" ) ); + + // Use a sensible chi2prob cut. (chi squared probability, like any probability must range from 0 to 1) + assert( _chi2ProbCut >= 0. ); + assert( _chi2ProbCut <= 1. ); + + // Make sure, every used criterion exists and has at least one min and max set + for( unsigned i=0; i<_criteriaNames.size(); i++ ){ + + std::string critName = _criteriaNames[i]; + + ICriterion* crit = Criteria::createCriterion( critName ); //throws an exception if the criterion is non existent + delete crit; + + assert( !_critMinima[ critName ].empty() ); + assert( !_critMaxima[ critName ].empty() ); + + } + return GaudiAlgorithm::initialize(); +} + +StatusCode ForwardTrackingAlg::execute(){ + debug() << " processing event number " << _nEvt << endmsg; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // // + // ForwardTracking // + // // + // Track Reconstruction in the FTD // + // // + // // + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + //--CED (only used for debugging )--------------------------------------- + // Reset drawing buffer and START drawing collection + /* + if( _useCED ){ + MarlinCED::newEvent(this , 0) ; + CEDPickingHandler &pHandler=CEDPickingHandler::getInstance(); + pHandler.update(evt); + } + */ + //----------------------------------------------------------------------- + + // Reset the quality flag of the output track collection (we start with the assumption that our results are good. + // If anything happens along the way, we modify this value ) + _output_track_col_quality = _output_track_col_quality_GOOD; + + std::vector< IHit* > hitsTBD; //Hits to be deleted at the end + _map_sector_hits.clear(); + + /**********************************************************************************************/ + /* Read in the collections, create hits from the TrackerHits and store them in a map */ + /**********************************************************************************************/ + + debug() << "\t\t---Reading in Collections---" << endmsg; + Navigation::Instance()->Initialize(); + std::vector<const edm4hep::TrackerHitCollection*> hitFTDCollections; + + try { + auto hitFTDPixelCol = _inFTDPixelColHdl.get(); + hitFTDCollections.push_back(hitFTDPixelCol); + Navigation::Instance()->AddTrackerHitCollection(hitFTDPixelCol); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inFTDPixelColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + } + + try { + auto hitFTDSpacePointCol = _inFTDSpacePointColHdl.get(); + hitFTDCollections.push_back(hitFTDSpacePointCol); + Navigation::Instance()->AddTrackerHitCollection(hitFTDSpacePointCol); + //const edm4hep::TrackerHitCollection* rawHitCol = nullptr; + try{ + auto rawHitCol = _inFTDRawColHdl.get(); + Navigation::Instance()->AddTrackerHitCollection(rawHitCol); + } + catch ( GaudiException &e ) { + fatal() << "Collection " << _inFTDRawColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + } + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inFTDSpacePointColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + } + + if(hitFTDCollections.size()==0){ + return StatusCode::SUCCESS; + } + /* + const edm4hep::TrackerHitCollection* rawHitCol = nullptr; + if(1){ + try{ + rawHitCol = _inFTDRawColHdl.get(); + } + catch ( GaudiException &e ) { + fatal() << "Collection " << _inFTDRawColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + } + } + */ + for( unsigned iCol=0; iCol < hitFTDCollections.size(); iCol++ ){ //read in all input collections + unsigned nHits = hitFTDCollections[iCol]->size(); + debug() << "Number of hits in collection " << hitFTDCollections[iCol]->getID() << ": " << nHits << endmsg; + + for(auto trackerHit : *hitFTDCollections[iCol]){ + edm4hep::ConstTrackerHit hit = trackerHit; + debug() << "hit " << trackerHit.id() << " " << KiTrackMarlin::getCellID0Info( trackerHit.getCellID() ) + << " " << KiTrackMarlin::getPositionInfo( &hit )<< endmsg; + + //Make an FTDHit01 from the TrackerHit + FTDHit01* ftdHit = new FTDHit01 ( trackerHit , _sectorSystemFTD ); + hitsTBD.push_back(ftdHit); //so we can easily delete every created hit afterwards + + _map_sector_hits[ ftdHit->getSector() ].push_back( ftdHit ); + } + } + + if( !_map_sector_hits.empty() ){ + /**********************************************************************************************/ + /* Check if no sector is overflowing with hits */ + /**********************************************************************************************/ + std::map< int , std::vector< IHit* > >::iterator it; + + for( it=_map_sector_hits.begin(); it != _map_sector_hits.end(); it++ ){ + int nHits = it->second.size(); + debug() << "Number of hits in sector " << it->first << " = " << nHits << endmsg; + + if( nHits > _maxHitsPerSector ){ + + it->second.clear(); //delete the hits in this sector, it will be dropped + + error() << " ### EVENT " << _nEvt << " :: RUN " << _nRun << " \n ### Number of Hits in FTD Sector " << it->first << ": " << nHits << " > " + << _maxHitsPerSector << " (MaxHitsPerSector)\n : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg; + + _output_track_col_quality = _output_track_col_quality_POOR; // We had to drop hits, so the quality of the result is decreased + } + } + + /**********************************************************************************************/ + /* Check the possible connections of hits on overlapping petals */ + /**********************************************************************************************/ + debug() << "\t\t---Overlapping Hits---" << endmsg; + + std::map< IHit* , std::vector< IHit* > > map_hitFront_hitsBack = getOverlapConnectionMap( _map_sector_hits, _sectorSystemFTD, _overlappingHitsDistMax); + + /**********************************************************************************************/ + /* Add the IP as virtual hit for forward and backward */ + /**********************************************************************************************/ + IHit* virtualIPHitForward = createVirtualIPHit(1 , _sectorSystemFTD ); + hitsTBD.push_back( virtualIPHitForward ); + _map_sector_hits[ virtualIPHitForward->getSector() ].push_back( virtualIPHitForward ); + + IHit* virtualIPHitBackward = createVirtualIPHit(-1 , _sectorSystemFTD ); + hitsTBD.push_back( virtualIPHitBackward ); + _map_sector_hits[ virtualIPHitBackward->getSector() ].push_back( virtualIPHitBackward ); + + /**********************************************************************************************/ + /* SegmentBuilder and Cellular Automaton */ + /**********************************************************************************************/ + unsigned round = 0; // the round we are in + std::vector < RawTrack > rawTracks; + + // The following while loop ideally only runs once. (So we do round 0 and everything works) + // It will repeat as long as the Automaton creates too many connections and as long as there are new criteria + // parameters to use to cut down the problem. + // Ideally already in round 0, there is a reasonable number of connections (not more than _maxConnectionsAutomaton), + // so the loop will be left. If however there are too many connections we stay in the loop and use + // (hopefully) tighter cut offs (if provided in the steering). This should prevent combinatorial breakdown + // for very evil events. + while( setCriteria( round ) ){ + round++; // count up the round we are in + + /**********************************************************************************************/ + /* Build the segments */ + /**********************************************************************************************/ + debug() << "\t\t---SegementBuilder---" << endmsg; + + //Create a segmentbuilder + SegmentBuilder segBuilder( _map_sector_hits ); + + segBuilder.addCriteria ( _crit2Vec ); // Add the criteria on when to connect two hits. The vector has been filled by the method setCriteria + + //Also load hit connectors + unsigned layerStepMax = 1; // how many layers to go at max + unsigned petalStepMax = 1; // how many petals to go at max + unsigned lastLayerToIP = 5;// layer 1,2,3 and 4 get connected directly to the IP + FTDSectorConnector secCon( _sectorSystemFTD , layerStepMax , petalStepMax , lastLayerToIP ); + + segBuilder.addSectorConnector ( & secCon ); // Add the sector connector (so the SegmentBuilder knows what hits from different sectors it is allowed to look for connections) + + // And get out the Cellular Automaton with the 1-segments + Automaton automaton = segBuilder.get1SegAutomaton(); + + // Check if there are not too many connections + if( automaton.getNumberOfConnections() > unsigned( _maxConnectionsAutomaton ) ){ + debug() << "Redo the Automaton with different parameters, because there are too many connections:" << endmsg + << "\tconnections( " << automaton.getNumberOfConnections() << " ) > MaxConnectionsAutomaton( " << _maxConnectionsAutomaton << " )" << endmsg; + continue; + } + + /**********************************************************************************************/ + /* Automaton */ + /**********************************************************************************************/ + debug() << "\t\t---Automaton---" << endmsg; + + //if( _useCED ) KiTrackMarlin::drawAutomatonSegments( automaton ); // draws the 1-segments (i.e. hits) + + /*******************************/ + /* 2-hit segments */ + /*******************************/ + debug() << "\t\t--2-hit-Segments--" << endmsg; + + //debug() << "Automaton has " << automaton.getTracks( 3 ).size() << " track candidates" << endmsg; //should be commented out, because it takes time + + automaton.clearCriteria(); + automaton.addCriteria( _crit3Vec ); // Add the criteria for 3 hits (i.e. 2 2-hit segments ) + + // Let the automaton lengthen its 1-hit-segments to 2-hit-segments + automaton.lengthenSegments(); + + // So now we have 2-hit-segments and are ready to perform the Cellular Automaton. + + // Perform the automaton + automaton.doAutomaton(); + + // Clean segments with bad states + automaton.cleanBadStates(); + + // Reset the states of all segments + automaton.resetStates(); + + //debug() << "Automaton has " << automaton.getTracks( 3 ).size() << " track candidates" << endmsg; //should be commented out, because it takes time + + // Check if there are not too many connections + if( automaton.getNumberOfConnections() > unsigned( _maxConnectionsAutomaton ) ){ + debug() << "Redo the Automaton with different parameters, because there are too many connections:" << endmsg + << "\tconnections( " << automaton.getNumberOfConnections() << " ) > MaxConnectionsAutomaton( " << _maxConnectionsAutomaton << " )" << endmsg; + continue; + } + + /*******************************/ + /* 3-hit segments */ + /*******************************/ + debug() << "\t\t--3-hit-Segments--" << endmsg; + + automaton.clearCriteria(); + automaton.addCriteria( _crit4Vec ); + + // Lengthen the 2-hit-segments to 3-hits-segments + automaton.lengthenSegments(); + + // Perform the Cellular Automaton + automaton.doAutomaton(); + + //Clean segments with bad states + automaton.cleanBadStates(); + + //Reset the states of all segments + automaton.resetStates(); + + //debug() << "Automaton has " << automaton.getTracks( 3 ).size() << " track candidates" << endmsg; //should be commented out, because it takes time + + // Check if there are not too many connections + if( automaton.getNumberOfConnections() > unsigned( _maxConnectionsAutomaton ) ){ + debug() << "Redo the Automaton with different parameters, because there are too many connections:" << endmsg + << "\tconnections( " << automaton.getNumberOfConnections() << " ) > MaxConnectionsAutomaton( " << _maxConnectionsAutomaton << " )" << endmsg; + continue; + } + + // get the raw tracks (raw track = just a vector of hits, the most rudimentary form of a track) + rawTracks = automaton.getTracks( 3 ); + + break; // if we reached this place all went well and we don't need another round --> exit the loop + } + + debug() << "Automaton returned " << rawTracks.size() << " raw tracks " << endmsg; + + /**********************************************************************************************/ + /* Add the overlapping hits */ + /**********************************************************************************************/ + debug() << "\t\t---Add hits from overlapping petals + fit + helix and Kalman cuts---" << endmsg; + + std::vector <ITrack*> trackCandidates; + + // for all raw tracks we got from the automaton + for( unsigned i=0; i < rawTracks.size(); i++){ + RawTrack rawTrack = rawTracks[i]; + + _nTrackCandidates++; + + // get all versions of the track plus hits from overlapping petals + std::vector < RawTrack > rawTracksPlus = getRawTracksPlusOverlappingHits( rawTrack, map_hitFront_hitsBack ); + + debug() << "For raw track number " << i << " there are " << rawTracksPlus.size() << " versions" << endmsg; + + /**********************************************************************************************/ + /* Make track candidates, fit them and throw away bad ones */ + /**********************************************************************************************/ + std::vector< ITrack* > overlappingTrackCands; + + for( unsigned j=0; j < rawTracksPlus.size(); j++ ){ + _nTrackCandidatesPlus++; + + RawTrack rawTrackPlus = rawTracksPlus[j]; + + if( rawTrackPlus.size() < unsigned( _hitsPerTrackMin ) ){ + debug() << "Trackversion discarded, too few hits: only " << rawTrackPlus.size() << " < " << _hitsPerTrackMin << "(hitsPerTrackMin)" << endmsg; + continue; + } + + FTDTrack* trackCand = new FTDTrack( _trkSystem ); + + // add the hits to the track + for( unsigned k=0; k<rawTrackPlus.size(); k++ ){ + IFTDHit* ftdHit = dynamic_cast< IFTDHit* >( rawTrackPlus[k] ); // cast to IFTDHits, as needed for an FTDTrack + if( ftdHit != NULL ) trackCand->addHit( ftdHit ); + else debug() << "Hit " << rawTrackPlus[k] << " could not be casted to IFTDHit" << endmsg; + } + + std::vector< IHit* > trackCandHits = trackCand->getHits(); + debug() << "Fitting track candidate with " << trackCandHits.size() << " hits" << endmsg; + + for( unsigned k=0; k < trackCandHits.size(); k++ ) debug() << trackCandHits[k]->getPositionInfo(); + debug() << endmsg; + + /*-----------------------------------------------*/ + /* Helix Fit */ + /*-----------------------------------------------*/ + debug() << "Fitting with Helix Fit" << endmsg; + try{ + FTDHelixFitter helixFitter( trackCand->getLcioTrack() ); + float chi2OverNdf = helixFitter.getChi2() / float( helixFitter.getNdf() ); + debug() << "chi2OverNdf = " << chi2OverNdf << endmsg; + + if( chi2OverNdf > _helixFitMax ){ + debug() << "Discarding track because of bad helix fit: chi2/ndf = " << chi2OverNdf << endmsg; + delete trackCand; + continue; + } + else debug() << "Keeping track because of good helix fit: chi2/ndf = " << chi2OverNdf << endmsg; + } + catch( FTDHelixFitterException& e ){ + debug() << "Track rejected, because fit failed: " << e.what() << endmsg; + delete trackCand; + continue; + } + + /*-----------------------------------------------*/ + /* Kalman Fit */ + /*-----------------------------------------------*/ + + debug() << "Fitting with Kalman Filter" << endmsg; + try{ + trackCand->fit(); + + debug() << " Track " << trackCand + << " chi2Prob = " << trackCand->getChi2Prob() + << "( chi2=" << trackCand->getChi2() + <<", Ndf=" << trackCand->getNdf() << " )" << endmsg; + + if ( trackCand->getChi2Prob() >= _chi2ProbCut ){ + debug() << "Track accepted (chi2prob " << trackCand->getChi2Prob() << " >= " << _chi2ProbCut << endmsg; + } + else{ + debug() << "Track rejected (chi2prob " << trackCand->getChi2Prob() << " < " << _chi2ProbCut << endmsg; + delete trackCand; + + continue; + } + } + catch( FitterException& e ){ + debug() << "Track rejected, because fit failed: " << e.what() << endmsg; + delete trackCand; + continue; + } + + // If we reach this point than the track got accepted by all cuts + overlappingTrackCands.push_back( trackCand ); + } + + /**********************************************************************************************/ + /* Take the best version of the track */ + /**********************************************************************************************/ + // Now we have all versions of one track, coming from adding possible hits from overlapping petals. + if( _takeBestVersionOfTrack ){ // we want to take only the best version + debug() << "Take the version of the track with best quality from " << overlappingTrackCands.size() << " track candidates" << endmsg; + + if( !overlappingTrackCands.empty() ){ + ITrack* bestTrack = overlappingTrackCands[0]; + + for( unsigned j=1; j < overlappingTrackCands.size(); j++ ){ + if( overlappingTrackCands[j]->getChi2Prob() > bestTrack->getChi2Prob() ){ + delete bestTrack; //delete the old one, not needed anymore + bestTrack = overlappingTrackCands[j]; + } + else{ + delete overlappingTrackCands[j]; //delete this one + } + } + debug() << "Adding best track candidate with " << bestTrack->getHits().size() << " hits" << endmsg; + + trackCandidates.push_back( bestTrack ); + } + } + else{ // we take all versions + debug() << "Taking all " << overlappingTrackCands.size() << " versions of the track" << endmsg; + trackCandidates.insert( trackCandidates.end(), overlappingTrackCands.begin(), overlappingTrackCands.end() ); + } + } + + //if( _useCED ){ + //for( unsigned i=0; i < trackCandidates.size(); i++ ) KiTrackMarlin::drawTrackRandColor( trackCandidates[i] ); + //} + + /**********************************************************************************************/ + /* Get the best subset of tracks */ + /**********************************************************************************************/ + + debug() << "The track candidates so far: " << endmsg; + for( unsigned iTrack=0; iTrack < trackCandidates.size(); iTrack++ ){ + debug() << "track " << iTrack << ": " << trackCandidates[iTrack] << "\t" << KiTrackMarlin::getTrackHitInfo( trackCandidates[iTrack] ) << endmsg; + } + + debug() << "\t\t---Get best subset of tracks---" << endmsg ; + + std::vector< ITrack* > tracks; + std::vector< ITrack* > rejected; + + TrackCompatibilityShare1SP comp; + TrackQIChi2Prob trackQI; + TrackQISpecial trackQISpecial; + + if( _bestSubsetFinder == "SubsetHopfieldNN" ){ + debug() << "Use SubsetHopfieldNN for getting the best subset" << endmsg ; + + SubsetHopfieldNN< ITrack* > subset; + subset.add( trackCandidates ); + subset.calculateBestSet( comp, trackQI ); + tracks = subset.getAccepted(); + rejected = subset.getRejected(); + } + else if( _bestSubsetFinder == "SubsetSimple" ){ + debug() << "Use SubsetSimple for getting the best subset" << endmsg ; + + SubsetSimple< ITrack* > subset; + subset.add( trackCandidates ); + subset.calculateBestSet( comp, trackQISpecial ); + tracks = subset.getAccepted(); + rejected = subset.getRejected(); + } + else { // in any other case take all tracks + debug() << "Input for subset = \"" << _bestSubsetFinder << "\". All tracks are kept" << endmsg ; + + tracks = trackCandidates; + } + + if( _useCED ){ + //for( unsigned i=0; i < tracks.size(); i++ ) KiTrackMarlin::drawTrack( tracks[i] , 0x00ff00 ); + //for( unsigned i=0; i < rejected.size(); i++ ) KiTrackMarlin::drawTrack( rejected[i] , 0xff0000 ); + } + + for ( unsigned i=0; i<rejected.size(); i++){ + delete rejected[i]; + } + + /**********************************************************************************************/ + /* Finally: Finalise and save the tracks */ + /**********************************************************************************************/ + debug() << "\t\t---Save Tracks---" << endmsg ; + + auto trkCol = _outColHdl.createAndPut(); + + for (unsigned int i=0; i < tracks.size(); i++){ + FTDTrack* myTrack = dynamic_cast< FTDTrack* >( tracks[i] ); + + if( myTrack != NULL ){ + edm4hep::Track trackImpl( *(myTrack->getLcioTrack()) ); + + try{ + finaliseTrack( &trackImpl ); + //trkCol->addElement( trackImpl ); + trkCol->push_back(trackImpl); + } + catch( FitterException& e ){ + debug() << "ForwardTracking: track couldn't be finalized due to fitter error: " << e.what() << endmsg; + //delete trackImpl; + } + } + } + + // set the quality of the output collection + switch (_output_track_col_quality) { + case _output_track_col_quality_FAIR: + //trkCol->parameters().setValue( "QualityCode" , "Fair" ) ; + break; + + case _output_track_col_quality_POOR: + //trkCol->parameters().setValue( "QualityCode" , "Poor" ) ; + break; + + default: + //trkCol->parameters().setValue( "QualityCode" , "Good" ) ; + break; + } + + //evt->addCollection(trkCol,_ForwardTrackCollection.c_str()); + + debug() << "Forward Tracking found and saved " << tracks.size() << " tracks in event " << _nEvt << endmsg; + + /**********************************************************************************************/ + /* Clean up */ + /**********************************************************************************************/ + // delete all the created IHits + for ( unsigned i=0; i<hitsTBD.size(); i++ ) delete hitsTBD[i]; + + // delete the FTracks + for (unsigned int i=0; i < tracks.size(); i++){ delete tracks[i];} + } + + //if( _useCED ) MarlinCED::draw(this); + + _nEvt ++ ; + return StatusCode::SUCCESS; +} + +StatusCode ForwardTrackingAlg::finalize(){ + for ( unsigned i=0; i< _crit2Vec.size(); i++) delete _crit2Vec[i]; + for ( unsigned i=0; i< _crit3Vec.size(); i++) delete _crit3Vec[i]; + for ( unsigned i=0; i< _crit4Vec.size(); i++) delete _crit4Vec[i]; + _crit2Vec.clear(); + _crit3Vec.clear(); + _crit4Vec.clear(); + + delete _sectorSystemFTD; + _sectorSystemFTD = NULL; + + debug() << "There are " << _nTrackCandidates << "track candidates from CA and "<< _nTrackCandidatesPlus + << " track Candidates with hits from overlapping hits" << endmsg + << "The ratio is " << float( _nTrackCandidatesPlus )/_nTrackCandidates << endmsg; + + return GaudiAlgorithm::finalize(); +} + +std::map< IHit* , std::vector< IHit* > > ForwardTrackingAlg::getOverlapConnectionMap(std::map< int , std::vector< IHit* > > & map_sector_hits, + const SectorSystemFTD* secSysFTD, + float distMax){ + + unsigned nConnections=0; + + std::map< IHit* , std::vector< IHit* > > map_hitFront_hitsBack; + std::map< int , std::vector< IHit* > >::iterator it; + + //for every sector + for ( it= map_sector_hits.begin() ; it != map_sector_hits.end(); it++ ){ + std::vector< IHit* > hitVecA = it->second; + int sector = it->first; + + // get the neighbouring petals + FTDNeighborPetalSecCon secCon( secSysFTD ); + std::set< int > targetSectors = secCon.getTargetSectors( sector ); + + //for all neighbouring petals + for ( std::set<int>::iterator itTarg = targetSectors.begin(); itTarg!=targetSectors.end(); itTarg++ ){ + std::vector< IHit* > hitVecB = map_sector_hits[ *itTarg ]; + for ( unsigned j=0; j < hitVecA.size(); j++ ){ + IHit* hitA = hitVecA[j]; + for ( unsigned k=0; k < hitVecB.size(); k++ ){ + IHit* hitB = hitVecB[k]; + + float dx = hitA->getX() - hitB->getX(); + float dy = hitA->getY() - hitB->getY(); + float dz = hitA->getZ() - hitB->getZ(); + float dist = sqrt( dx*dx + dy*dy + dz*dz ); + + if (( dist < distMax )&& ( fabs( hitB->getZ() ) > fabs( hitA->getZ() ) ) ){ // if they are close enough and B is behind A + debug() << "Connected: (" << hitA->getX() << "," << hitA->getY() << "," << hitA->getZ() << ")-->(" + << hitB->getX() << "," << hitB->getY() << "," << hitB->getZ() << ")" << endmsg; + + map_hitFront_hitsBack[ hitA ].push_back( hitB ); + nConnections++; + } + } + } + } + } + debug() << "Connected " << map_hitFront_hitsBack.size() << " hits with " << nConnections << " possible overlapping hits" << endmsg; + + return map_hitFront_hitsBack; +} + +std::string ForwardTrackingAlg::getInfo_map_sector_hits(){ + std::stringstream s; + + std::map< int , std::vector< IHit* > >::iterator it; + + for( it = _map_sector_hits.begin(); it != _map_sector_hits.end(); it++ ){ + std::vector<IHit*> hits = it->second; + int sector = it->first; + + int side = _sectorSystemFTD->getSide( sector ); + unsigned layer = _sectorSystemFTD->getLayer( sector ); + unsigned module = _sectorSystemFTD->getModule( sector ); + unsigned sensor = _sectorSystemFTD->getSensor( sector ); + + s << "sector " << sector << " (si" + << side << ",la" + << layer << ",mo" + << module << "se," + << sensor << ") has " + << hits.size() << " hits\n" ; + } + + return s.str(); +} + +std::vector < RawTrack > ForwardTrackingAlg::getRawTracksPlusOverlappingHits( RawTrack rawTrack , std::map< IHit* , std::vector< IHit* > >& map_hitFront_hitsBack ){ + // So we have a raw track (a vector of hits, that is) and a map, that tells us + // for every hit, if there is another hit in the overlapping region behind it very close, + // so that it could be part of the same track. + // + // We now want to find for a given track all possible tracks, when hits from the overlapping regions are added + // + // The method is this: start with pure track. + // Make a vector of rawTracks and fill in the pure track. + // For every hit on the original track do the following: + // Check if there are overlapping hits. + // For every overlapping hit take all the created tracks so far and make another version + // with the overlapping hit added to it and add them to the vector of rawTracks. + // + // + // Let's do an example: + // the original hits in the track are calles A,B and C. + // A has one overlapping hit A1 + // and B has two overlapping hits B1 and B2. + // + // So we start with a vector containing only the original track: {(A,B,C)} + // + // We start with the first hit: A. It has one overlapping hit A1. + // We take all tracks (which is the original one so far) and make another version containing A1 as well. + // Then we add it to the vector of tracks: + // + // {(A,B,C)(A,A1,B,C)} + // + // On to the next hit from the original track: B. Here we have overlapping hits B1 and B2. + // We take all the tracks so far and add versions with B1: (A,B,B1,C) and (A,A1,B,B1,C) + // We don't immediately add them or otherwise, we would create a track containing B1 as well as B2, which is plainly wrong + // + // So instead we make the combinations with B2: (A,B,B2,C) and (A,A1,B,B2,C) + // And now having gone through all overlapping hits of B, we add all the new versions to the vector: + // + // {(A,B,C)(A,A1,B,C)(A,B,B1,C)(A,A1,B,B1,C)(A,B,B2,C)(A,A1,B,B2,C)} + // + // So now we have all possible versions of the track with overlapping hits + + std::vector < RawTrack > rawTracksPlus; + + rawTracksPlus.push_back( rawTrack ); //add the original one + + // for every hit in the original track + for( unsigned i=0; i < rawTrack.size(); i++ ){ + IHit* frontHit = rawTrack[i]; + + // get the hits that are behind frontHit + std::map< IHit* , std::vector< IHit* > >::iterator it; + it = map_hitFront_hitsBack.find( frontHit ); + if( it == map_hitFront_hitsBack.end() ) continue; // if there are no hits on the back skip this one + std::vector< IHit* > backHits = it->second; + + // Create the different versions of the tracks so far with the hits from the back + + std::vector< RawTrack > newVersions; //here we store all the versions with overlapping hits from the different back hits at this frontHit + + // for every hit in back of the frontHit + for( unsigned j=0; j<backHits.size(); j++ ){ + IHit* backHit = backHits[j]; + // for all tracks we have so far + for( unsigned k=0; k<rawTracksPlus.size(); k++ ){ + RawTrack newVersion = rawTracksPlus[k]; // exact copy of the track + newVersion.push_back( backHit ); // add the backHit to it + newVersions.push_back( newVersion ); // store it + + } + } + // Now put all the new versions of the tracks into the rawTracksPlus vector before we go on to the next + // hit of the original track + rawTracksPlus.insert( rawTracksPlus.end(), newVersions.begin(), newVersions.end() ); + } + + return rawTracksPlus; +} + +bool ForwardTrackingAlg::setCriteria( unsigned round ){ + + // delete the old ones + for ( unsigned i=0; i< _crit2Vec.size(); i++) delete _crit2Vec[i]; + for ( unsigned i=0; i< _crit3Vec.size(); i++) delete _crit3Vec[i]; + for ( unsigned i=0; i< _crit4Vec.size(); i++) delete _crit4Vec[i]; + _crit2Vec.clear(); + _crit3Vec.clear(); + _crit4Vec.clear(); + + bool newValuesGotUsed = false; // if new values are used + for( unsigned i=0; i<_criteriaNames.size(); i++ ){ + std::string critName = _criteriaNames[i]; + + float min = _critMinima[critName].back(); + float max = _critMaxima[critName].back(); + + // use the value corresponding to the round, if there are no new ones for this criterion, just do nothing (the previous value stays in place) + if( round + 1 <= _critMinima[critName].size() ){ + min = _critMinima[critName][round]; + newValuesGotUsed = true; + } + + if( round + 1 <= _critMaxima[critName].size() ){ + max = _critMaxima[critName][round]; + newValuesGotUsed = true; + } + + ICriterion* crit = Criteria::createCriterion( critName, min , max ); + + // Some debug output about the created criterion + std::string type = crit->getType(); + + debug() << "Added: Criterion " << critName << " (type = " << type + << " ). Min = " << min + << ", Max = " << max + << ", round " << round << endmsg; + + // Add the new criterion to the corresponding vector + if( type == "2Hit" ){ + _crit2Vec.push_back( crit ); + } + else if( type == "3Hit" ){ + _crit3Vec.push_back( crit ); + } + else if( type == "4Hit" ){ + _crit4Vec.push_back( crit ); + } + else delete crit; + } + + return newValuesGotUsed; +} + +void ForwardTrackingAlg::finaliseTrack( edm4hep::Track* trackImpl ){ + + Fitter fitter( trackImpl , _trkSystem ); + + //trackImpl->trackStates().clear(); + debug() << "Track has " << trackImpl->trackStates_size() << " TrackState now, should be cleared but not supported by EDM4hep" << endmsg; + + edm4hep::TrackState trkStateIP( *fitter.getTrackState( 1/*lcio::TrackState::AtIP*/ ) ) ; + trkStateIP.location = 1; + trackImpl->addToTrackStates( trkStateIP ); + + edm4hep::TrackState trkStateFirstHit( *fitter.getTrackState( 2/*TrackState::AtFirstHit*/ ) ) ; + trkStateFirstHit.location = 2; + trackImpl->addToTrackStates( trkStateFirstHit ); + + edm4hep::TrackState trkStateLastHit( *fitter.getTrackState( 3/*TrackState::AtLastHit*/ ) ) ; + trkStateLastHit.location = 3; + trackImpl->addToTrackStates( trkStateLastHit ); + + edm4hep::TrackState trkStateAtCalo( *fitter.getTrackState( 4/*TrackState::AtCalorimeter*/ ) ) ; + trkStateAtCalo.location = 4; + trackImpl->addToTrackStates( trkStateAtCalo ); + + trackImpl->setChi2( fitter.getChi2( 1 ) ); + trackImpl->setNdf( fitter.getNdf ( 1 ) ); + + const edm4hep::Vector3f& p = trkStateFirstHit.referencePoint; + trackImpl->setRadiusOfInnermostHit( sqrt( p[0]*p[0] + p[1]*p[1] + p[2]*p[2] ) ); + + std::map<int, int> hitNumbers; + + hitNumbers[UTIL::ILDDetID::VXD] = 0; + hitNumbers[UTIL::ILDDetID::SIT] = 0; + hitNumbers[UTIL::ILDDetID::FTD] = 0; + hitNumbers[UTIL::ILDDetID::TPC] = 0; + hitNumbers[UTIL::ILDDetID::SET] = 0; + hitNumbers[UTIL::ILDDetID::ETD] = 0; + + unsigned int nHits = trackImpl->trackerHits_size(); + for( unsigned j=0; j<nHits; j++ ){ + const edm4hep::ConstTrackerHit& hit = trackImpl->getTrackerHits(j); + UTIL::BitField64 encoder( UTIL::ILDCellID0::encoder_string ); + encoder.setValue( hit.getCellID() ); + int subdet = encoder[UTIL::ILDCellID0::subdet]; + + ++hitNumbers[ subdet ]; + } + + //trackImpl->subdetectorHitNumbers().resize(2 * lcio::ILDDetID::ETD); + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::VXD - 2 ] = hitNumbers[lcio::ILDDetID::VXD]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::FTD - 2 ] = hitNumbers[lcio::ILDDetID::FTD]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::SIT - 2 ] = hitNumbers[lcio::ILDDetID::SIT]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::TPC - 2 ] = hitNumbers[lcio::ILDDetID::TPC]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::SET - 2 ] = hitNumbers[lcio::ILDDetID::SET]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::ETD - 2 ] = hitNumbers[lcio::ILDDetID::ETD]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::VXD - 1 ] = hitNumbers[lcio::ILDDetID::VXD]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::FTD - 1 ] = hitNumbers[lcio::ILDDetID::FTD]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::SIT - 1 ] = hitNumbers[lcio::ILDDetID::SIT]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::TPC - 1 ] = hitNumbers[lcio::ILDDetID::TPC]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::SET - 1 ] = hitNumbers[lcio::ILDDetID::SET]; + //trackImpl->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::ETD - 1 ] = hitNumbers[lcio::ILDDetID::ETD]; + trackImpl->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::VXD]); + trackImpl->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::SIT]); + trackImpl->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::FTD]); + trackImpl->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::TPC]); + trackImpl->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::SET]); + trackImpl->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::ETD]); + + return; +} + + diff --git a/Reconstruction/SiliconTracking/src/ForwardTrackingAlg.h b/Reconstruction/SiliconTracking/src/ForwardTrackingAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..8e9e2229f1296d99f12fb6ba88abe8753f13fad9 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/ForwardTrackingAlg.h @@ -0,0 +1,346 @@ +#ifndef ForwardTracking_h +#define ForwardTracking_h 1 + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" + +#include <string> + +#include "edm4hep/TrackerHit.h" +#include "TrackSystemSvc/IMarlinTrkSystem.h" +//#include "gear/BField.h" + +#include "KiTrack/Segment.h" +#include "KiTrack/ITrack.h" +#include "Criteria/Criteria.h" +#include "ILDImpl/SectorSystemFTD.h" + +using namespace KiTrack; +using namespace KiTrackMarlin; + +/** a simple typedef, making writing shorter. And it makes sense: a track consists of hits. But as a real track + * has more information, a vector of hits can be considered as a "raw track". */ +typedef std::vector< IHit* > RawTrack; + +/** Standallone Forward Tracking Processor for Marlin.<br> + * + * Reconstructs the tracks through the FTD <br> + * + * For a summary of what happens during each event see the method processEvent + * + * <h4>Input - Prerequisites</h4> + * The hits in the Forward Tracking Detector FTD + * + * <h4>Output</h4> + * A collection of reconstructed Tracks. + * + * @param FTDHitCollections The collections containing the FTD hits <br> + * (default value "FTDTrackerHits FTDSpacePoints" (string vector) ) + * + * @param ForwardTrackCollection Name of the Forward Tracking output collection<br> + * (default value "ForwardTracks" ) + * + * @param MultipleScatteringOn Whether to take multiple scattering into account when fitting the tracks<br> + * (default value true ) + * + * @param EnergyLossOn Whether to take energy loss into account when fitting the tracks<br> + * (default value true ) + * + * @param SmoothOn Whether to smooth all measurement sites in fit<br> + * (default value false ) + * + * @param Chi2ProbCut Tracks with a chi2 probability below this will get sorted out<br> + * (default value 0.005 ) + * + * @param HelixFitMax the maximum chi2/Ndf that is allowed as result of a helix fit + * (default value 500 ) + * + * @param OverlappingHitsDistMax The maximum distance of hits from overlapping petals belonging to one track<br> + * (default value 3.5 ) + * + * @param HitsPerTrackMin The minimum number of hits to create a track<br> + * (default value 3 ) + * + * @param BestSubsetFinder The method used to find the best non overlapping subset of tracks. Available are: SubsetHopfieldNN, SubsetSimple and None. + * None means, that no final search for the best subset is done and overlapping tracks are possible. <br> + * (default value TrackSubsetHopfieldNN ) + * + * @param Criteria A vector of the criteria that are going to be used by the Cellular Automaton. <br> + * For every criterion a min and max needs to be set!!!<br> + * (default value is defined in class Criteria ) + * + * @param NameOfACriterion_min/max For every used criterion a minimum and maximum value needs to be set. <br> + * If a criterion is named "Crit_Example", then the min parameter would be: Crit_Example_min and the max parameter Crit_Example_max.<br> + * You can enter more than one value!!! So for example you could write something like \<parameter name="Crit_Example_min" type="float">30 0.8\</parameter>.<br> + * This means, that if the Cellular Automaton creates too many connections (how many is defined in "MaxConnectionsAutomaton" ) it reruns + * it with the next set of parameters. Thus allowing to tighten the cuts, if there are too many connections and so preventing + * it from getting stuck in very bad combinatorial situations. So in this example the Automaton will first run with the Crit_Example_min of 30 + * and if that generates too many connections, it will rerun it with the value 0.8.<br> + * If for a criterion no further parameters are specified, the first ones will be taken on reruns. + * + * @param MaxConnectionsAutomaton If the automaton has more connections than this it will be redone with the next cut off values for the criteria.<br> + * If there are no further new values for the criteria, the event will be skipped.<br> + * (default value 100000 ) + * + * @param MaxHitsPerSector If on any single sector there are more hits than this, all the hits in the sector get dropped. + * This is to prevent combinatorial breakdown (It is a second safety mechanism, the first one being MaxConnectionsAutomaton. + * But if there are soooo many hits, that already the first round of the Cellular Automaton would take forever, this mechanism + * prevents it) <br> + * (default value 1000) + * + * @author Robin Glattauer HEPHY, Wien + * + */ + +class ForwardTrackingAlg : public GaudiAlgorithm { + public: + + ForwardTrackingAlg(const std::string& name, ISvcLocator* svcLoc); + + /** Called at the begin of the job before anything is read. + * Use to initialize the processor, e.g. book histograms. + */ + virtual StatusCode initialize() ; + + virtual StatusCode execute() ; + + virtual StatusCode finalize() ; + + /** Called for every run. + */ + //virtual void processRunHeader( LCRunHeader* run ) ; + + /** Called for every event - the working horse. + * + * The basic procedure for reconstruction of tracks in the FTD is as follows: + * + * -# Read in all collections of hits on the FTD that are passed as steering parameters + * -# From every hit in these collections an FTDHit01 is created. This is, because the SegmentBuilder and the Automaton + * need their own hit classes. + * -# The hits are stored in the map _map_sector_hits. The keys in this map are the sectors and the values of the map are vectors + * of the hits within those sectors. Sector here means an integer somehow representing a place in the detector. + * (For using this numbers and getting things like layer or side the class SectorSystemFTD is used.) + * -# Make a safety check to ensure no single sector is overflowing with hits. This could give a combinatorial + * disaster leading to endless calculation times. + * -# Add a virtual hit in the place of the IP. It is used by the Cellular Automaton as additional information + * (almost all reconstructable tracks come from a vertex roughly around the IP) + * -# Look for hits on overlapping petals. If two petals from the FTD overlap, a track may pass through both and thus + * create two hits in close range. For pattern recognition as it is now, they are not useful. (Imagine you try to + * guess the radius of the helix formed by a track and you have 3 hits. If these 3 hits are sensibly spaced, this is + * no problem. But now imagine, that two of them are very close. Just a small deviation in the relative position + * of those two would give entirely different results.) Such short connections are therefore looked for and stored, but + * are not dealt with until later the track candidates are found. + * -# The SegmentBuilder takes the hits and a vector of criteria.These criteria tell the SegmentBuilder when two + * hits might be part of a possible track. (For example, when we look for stiff tracks, we can form a line from one hit + * to the other and demand that this line will come close to the IP. ) + * The SegmentBuilder as the name suggests builds segments from the hits. A Segment is essentially a part of a track. + * For now a segment consists of a single hit. BUT: in contrast to a hit it knows all other segments it is + * connected to. Lets take an easy example: A track crosses layer 2,3,4 and 5 creating hits A,B,C and D. + * Then, if the track is not very ugly (huge multiple sacttering or energy loss ) the SegmentBuilder will create + * corresponding segments A,B,C and D. D is connected with C. C with B, B with A and A with the IP. + * So in these connections the true track is already contained. + * For real situations we have of course many more hits and many more tracks and background and so on. So the connections + * are plenty and if we took every possible track we could create from them, we would kill the system. + * Therefore we use the Cellular Automaton to get rid of as much as possible. + * -# The Cellular Automaton: As a result from the SegmentBuilder we get an Automaton object. It has all the segments + * the SegmentBuilder created and from us it gets some criteria to work with. (These Criteria again tell us when a + * connection makes sense and when it doesn't. Only the connections now get longer and involve first 3 hits and then 4). + * It first builds longer segments (now containing 2 hits instead of 1). These longer segments are again connected with + * each other (connections are made if the criteria allow it). The Automaton then looks for connections that go all + * the way through to the innermost layer (the IP). Segments not connected all the way through to the IP get deleted. + * It might be a good idea to look into <a href="../CellularAutomaton.pdf">Introduction to the Cellular Automaton</a> + * for more details on the Cellular Automaton. The summary is, that with every step and every criterion the CA is able + * to sort out combinatorial background until at the end we extract track candidates from it. + * -# Next we iterate over every trackcandidate we got. + * -# The hits from overlapping petals are added and every possible combination of the trackcandidate and the hits + * we could add is created. The best version is then taken (if this is switched on in the steering parameters). + * -# Cuts: First we do a helix fit. If the result (chi2 / Ndf ) is too bad the track is dropped. Then we do a + * Kalman Fit. Also if the results here (chi squared probability) are bad the track is not saved. + * -# Find the best subset: the tracks we now gathered may not be all compatible with each other (i.e. share hits). + * This situation is resolved with a best subset finder like the Hopfield Neural Network. + * -# Now the tracks are all compatible and suited our different criteria. It is time to save them. At the end they + * get finalised and stored in the output collection. + * + * + */ + //virtual void processEvent( LCEvent * evt ) ; + protected: + /* + * @return a map that links hits with overlapping hits on the petals behind + * + * @param map_sector_hits a map with first= the sector number. second = the hits in the sector. + * + * @param secSysFTD the SectorSystemFTD that is used + * + * @param distMax the maximum distance of two hits. If two hits are on the right petals and their distance is smaller + * than this, the connection will be saved in the returned map. + */ + std::map< IHit* , std::vector< IHit* > > getOverlapConnectionMap( std::map< int , std::vector< IHit* > > & map_sector_hits, + const SectorSystemFTD* secSysFTD, + float distMax); + + /* Adds hits from overlapping areas to a RawTrack in every possible combination. + * + * @return all of the resulting RawTracks + * + * @param rawTrack a RawTrack (vector of IHit* ), we want to add hits from overlapping regions + * + * @param map_hitFront_hitsBack a map, where IHit* are the keys and the values are vectors of hits that + * are in an overlapping region behind them. + */ + std::vector < RawTrack > getRawTracksPlusOverlappingHits( RawTrack rawTrack , std::map< IHit* , std::vector< IHit* > >& map_hitFront_hitsBack ); + + /* Finalises the track: fits it and adds TrackStates at IP, Calorimeter Face, inner- and outermost hit. + * Sets the subdetector hit numbers and the radius of the innermost hit. + * Also sets chi2 and Ndf. + */ + void finaliseTrack( edm4hep::Track* track ); + + /* Sets the cut off values for all the criteria + * + * This method is necessary for cases where the CA just finds too much. + * Therefore it is possible to enter a whole list of cut off values for every criterion (for every min and every max to be more precise), + * that are then used one after the other. + * If the CA finds way too many connections, we can thus make the cuts tighter and rerun it. If there are still too many + * connections, just tighten them again. + * + * This method will set the according values. It will read the passed (as steering parameter) cut off values, create + * criteria from them and store them in the corresponding vectors. + * + * If there are no new cut off values for a criterion, the last one remains. + * + * @return whether any new cut off value was set. false == there are no new cutoff values anymore + * + * @param round The number of the round we are in. I.e. the nth time we run the Cellular Automaton. + */ + bool setCriteria( unsigned round ); + + /* @return Info on the content of _map_sector_hits. Says how many hits are in each sector */ + std::string getInfo_map_sector_hits(); + + /* Input collection names */ + DataHandle<edm4hep::TrackerHitCollection> _inFTDPixelColHdl{"FTDPixelTrackerHits", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inFTDSpacePointColHdl{"FTDSpacePoints", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inFTDRawColHdl{"FTDStripTrackerHits", Gaudi::DataHandle::Reader, this}; + + /** Output collection name */ + DataHandle<edm4hep::TrackCollection> _outColHdl{"ForwardTracks", Gaudi::DataHandle::Writer, this}; + + int _nRun ; + int _nEvt ; + + /** B field in z direction */ + double _Bz; + + Gaudi::Property<double> _chi2ProbCut{this, "Chi2ProbCut", 0.005}; + Gaudi::Property<double> _helixFitMax{this, "HelixFitMax", 500}; + Gaudi::Property<double> _overlappingHitsDistMax{this, "OverlappingHitsDistMax", 3.5}; + Gaudi::Property<int> _hitsPerTrackMin{this, "HitsPerTrackMin", 4}; + Gaudi::Property<std::string> _bestSubsetFinder{this, "BestSubsetFinder", "SubsetHopfieldNN"}; + //true = when adding hits from overlapping petals, store only the best track; false = store all tracksS + Gaudi::Property<bool> _takeBestVersionOfTrack{this, "TakeBestVersionOfTrack", true}; + /* the maximum number of connections that are allowed in the automaton, if this value is surpassed, rerun + * the automaton with tighter cuts or stop it entirely. */ + Gaudi::Property<int> _maxConnectionsAutomaton{this, "MaxConnectionsAutomaton", 100000}; + Gaudi::Property<int> _maxHitsPerSector{this, "MaxHitsPerSector", 1000}; + Gaudi::Property<bool> _MSOn{this, "MultipleScatteringOn", true}; + Gaudi::Property<bool> _ElossOn{this, "EnergyLossOn", true}; + Gaudi::Property<bool> _SmoothOn{this, "SmoothOn", false}; + Gaudi::Property<std::vector<std::string> > _criteriaNames{this, "Criteria", Criteria::getAllCriteriaNamesVec()}; + Gaudi::Property<std::vector<float> > _critMinimaInit{this, "CriteriaMin", {} }; + Gaudi::Property<std::vector<float> > _critMaximaInit{this, "CriteriaMax", {} }; + + std::map<std::string, std::vector<float> > _critMinima; + std::map<std::string, std::vector<float> > _critMaxima; + + /** A map to store the hits according to their sectors */ + std::map< int , std::vector< IHit* > > _map_sector_hits; + + /** Map containing the name of a criterion and a vector of the minimum cut offs for it */ + //std::map< std::string , std::vector<float> > _critMinima; + + /** Map containing the name of a criterion and a vector of the maximum cut offs for it */ + //std::map< std::string , std::vector<float> > _critMaxima; + + /** A vector of criteria for 2 hits (2 1-hit segments) */ + std::vector <ICriterion*> _crit2Vec; + + /** A vector of criteria for 3 hits (2 2-hit segments) */ + std::vector <ICriterion*> _crit3Vec; + + /** A vector of criteria for 4 hits (2 3-hit segments) */ + std::vector <ICriterion*> _crit4Vec; + + const SectorSystemFTD* _sectorSystemFTD; + + bool _useCED; + + unsigned _nTrackCandidates; + unsigned _nTrackCandidatesPlus; + + MarlinTrk::IMarlinTrkSystem* _trkSystem; + + /** The quality of the output track collection */ + int _output_track_col_quality ; + + static const int _output_track_col_quality_GOOD; + static const int _output_track_col_quality_FAIR; + static const int _output_track_col_quality_POOR; +}; + +/** A functor to return whether two tracks are compatible: The criterion is if they share a Hit or more */ +class TrackCompatibilityShare1SP{ + public: + + inline bool operator()( ITrack* trackA, ITrack* trackB ){ + + std::vector< IHit* > hitsA = trackA->getHits(); + std::vector< IHit* > hitsB = trackB->getHits(); + + + for( unsigned i=0; i < hitsA.size(); i++){ + for( unsigned j=0; j < hitsB.size(); j++){ + if ( hitsA[i] == hitsB[j] ) return false; // a hit is shared -> incompatible + } + } + + return true; + } +}; + +/** A functor to return the quality of a track, which is currently the chi2 probability. */ +class TrackQIChi2Prob{ + public: + + inline double operator()( ITrack* track ){ return track->getChi2Prob(); } +}; + +/** A functor to return the quality of a track. + For tracks with 4 hits or more the chi2prob is mapped to* 0.5-1, with x = prob/2 + 0.5. + Tracks with 3 hits get the chi2 mapped to 0-0.5 by 1/(ln( e^2 + chi2 ); + That gives 0 for an infinite chi2 and 0.5 for a chi2 of 0. + + Reason: now 3-hit-tracks can be compared as well + */ +class TrackQISpecial{ + public: + + inline double operator()( ITrack* track ){ + if( track->getHits().size() > 3 ){ + return track->getChi2Prob()/2. +0.5; + } + else{ + return 1/( log( 7.3890561 + track->getChi2() ) ); //e^2 = 7.3890561 + } + } +}; +#endif + + + diff --git a/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..256f8fb6b6067f4e33c21cefd684b7eb4a865fe1 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.cpp @@ -0,0 +1,3055 @@ +#include "SiliconTrackingAlg.h" +#include "GearSvc/IGearSvc.h" +#include "EventSeeder/IEventSeeder.h" +#include "TrackSystemSvc/ITrackSystemSvc.h" +#include "DataHelper/Navigation.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/TrackerHit.h" +//#include "edm4hep/TrackerHitPlane.h" +#include "edm4hep/Track.h" +#include "edm4hep/TrackState.h" + +#include <iostream> +#include <algorithm> +#include <cmath> +#include <climits> + +#include <gear/GEAR.h> +#include <gear/GearMgr.h> +#include <gear/GearParameters.h> +#include <gear/VXDLayerLayout.h> +#include <gear/VXDParameters.h> +#include "gear/FTDLayerLayout.h" +#include "gear/FTDParameters.h" + +#include <gear/BField.h> + +#include <UTIL/BitField64.h> +#include <UTIL/BitSet32.h> +#include <UTIL/ILDConf.h> + +#include "TrackSystemSvc/MarlinTrkUtils.h" +#include "TrackSystemSvc/HelixTrack.h" +#include "TrackSystemSvc/HelixFit.h" +#include "TrackSystemSvc/IMarlinTrack.h" + +//#include "TrackSystemSvc/MarlinTrkDiagnostics.h" +//#ifdef MARLINTRK_DIAGNOSTICS_ON +//#include "TrackSystemSvc/DiagnosticsController.h" +//#endif + +//#include "MarlinCED.h" + +//#include "marlin/AIDAProcessor.h" + +//---- ROOT ----- +#include "TH1F.h" +#include "TH2F.h" + +using namespace edm4hep ; +//using namespace marlin ; +using namespace MarlinTrk ; + +using std::min; +using std::max; +using std::abs; + +const int SiliconTrackingAlg::_output_track_col_quality_GOOD = 1; +const int SiliconTrackingAlg::_output_track_col_quality_FAIR = 2; +const int SiliconTrackingAlg::_output_track_col_quality_POOR = 3; + +const double SiliconTrackingAlg::TWOPI = 2*M_PI; + +DECLARE_COMPONENT( SiliconTrackingAlg ) + +SiliconTrackingAlg::SiliconTrackingAlg(const std::string& name, ISvcLocator* svcLoc) +: GaudiAlgorithm(name, svcLoc) { + + //_description = "Pattern recognition in silicon trackers"; + + _fastfitter = new MarlinTrk::HelixFit(); + + _encoder = new UTIL::BitField64(lcio::ILDCellID0::encoder_string); + + _petalBasedFTDWithOverlaps = false; + + // zero triplet counters + _ntriplets = _ntriplets_good = _ntriplets_2MCP = _ntriplets_3MCP = _ntriplets_1MCP_Bad = _ntriplets_bad = 0; + + // Input Collections + // ^^^^^^^^^^^^^^^^^ + declareProperty("HeaderCol", _headerColHdl); + declareProperty("MCParticleCollection", _inMCColHdl, "Handle of the Input MCParticle collection"); + declareProperty("VTXHitCollection", _inVTXColHdl, "Handle of the Input VTX TrackerHits collection"); + declareProperty("FTDPixelHitCollection", _inFTDPixelColHdl, "Handle of the Input FTD TrackerHits collection"); + declareProperty("FTDSpacePointCollection", _inFTDSpacePointColHdl, "Handle of the Input FTD SpacePoints collection"); + declareProperty("SITHitCollection", _inSITColHdl, "Handle of the Input SIT TrackerHits collection"); + declareProperty("SITRawHitCollection", _inSITRawColHdl, "Handle of the SIT SpacePoints raw hit collection collection"); + declareProperty("FTDRawHitCollection", _inFTDRawColHdl, "Handle of the FTD SpacePoints raw hit collection collection"); + // Output Collections + // ^^^^^^^^^^^^^^^^^^ + declareProperty("SiTrackCollection", _outColHdl, "Handle of the SiTrack output collection"); + //declareProperty("TrkHitRelCollection", _outRelColHdl, "Handle of TrackerHit Track relation collection"); + // Steering parameters + // ^^^^^^^^^^^^^^^^^^^ + + _output_track_col_quality = _output_track_col_quality_GOOD; +} + + + +StatusCode SiliconTrackingAlg::initialize() { + + _nRun = -1 ; + _nEvt = 0 ; + //printParameters() ; + + // set up the geometery needed by KalTest + //FIXME: for now do KalTest only - make this a steering parameter to use other fitters + auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc"); + if ( !_trackSystemSvc ) { + error() << "Failed to find TrackSystemSvc ..." << endmsg; + return StatusCode::FAILURE; + } + _trksystem = _trackSystemSvc->getTrackSystem(); + + if( _trksystem == 0 ){ + error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg; + return StatusCode::FAILURE; + } + + _trksystem->setOption( IMarlinTrkSystem::CFG::useQMS, _MSOn ) ; + _trksystem->setOption( IMarlinTrkSystem::CFG::usedEdx, _ElossOn) ; + _trksystem->setOption( IMarlinTrkSystem::CFG::useSmoothing, _SmoothOn) ; + _trksystem->init() ; + debug() << "TrackSystem builded at address=" << _trksystem << endmsg; +#ifdef MARLINTRK_DIAGNOSTICS_ON + + void * dcv = _trksystem->getDiagnositicsPointer(); + DiagnosticsController* dc = static_cast<DiagnosticsController*>(dcv); + dc->init(_MarlinTrkDiagnosticsName,_MarlinTrkDiagnosticsName, _runMarlinTrkDiagnostics); + +#endif + + if(setupGearGeom()==StatusCode::FAILURE) return StatusCode::FAILURE; + + if (_useSIT == 0) + _nLayers = _nLayersVTX; + else + _nLayers = _nLayersVTX + _nLayersSIT; + + // initialise the container to have separate vectors for up to _nHitsChi2 hits. + _tracksWithNHitsContainer.resize(_nHitsChi2); + + _dPhi = TWOPI/_nDivisionsInPhi; + _dTheta = 2.0/_nDivisionsInTheta; + _dPhiFTD = TWOPI/_nDivisionsInPhiFTD; + // I leave this for the moment, but 0.3 is c/1e9. + // For the cut it does not make too much of a difference + double cutOnR = _cutOnPt/(0.3*_bField); + cutOnR = 1000.*cutOnR; + _cutOnOmega = 1/cutOnR; + + _output_track_col_quality = 0; + + return GaudiAlgorithm::initialize(); +} + +StatusCode SiliconTrackingAlg::execute(){ + Navigation::Instance()->Initialize(); + //_current_event = evt; + //_allHits.reserve(1000); + + _output_track_col_quality = _output_track_col_quality_GOOD; + + // zero triplet counters + _ntriplets = _ntriplets_good = _ntriplets_2MCP = _ntriplets_3MCP = _ntriplets_1MCP_Bad = _ntriplets_bad = 0; + + // Clearing the working containers from the previous event + // FIXME: partly done at the end of the event, in CleanUp. Make it consistent. + //_tracksWithNHitsContainer.clear(); + //_trackImplVec.clear(); + + //_colTrackerHits.clear(); + //_colNamesTrackerHits.clear(); + //auto header = _headerColHdl.get()->at(0); + //int evtNo = header.getEventNumber(); + //int runNo = header.getRunNumber(); + //debug() << "Processing Run[" << runNo << "]::Event[" << evtNo << "]" << endmsg; + + _trackImplVec.reserve(100); + + int successVTX = InitialiseVTX(); + //int successFTD = 0; + int successFTD = InitialiseFTD(); + if (successVTX == 1) { + + debug() << " phi theta layer nh o : m : i :: o*m*i " << endmsg; + + for (int iPhi=0; iPhi<_nDivisionsInPhi; ++iPhi) { + for (int iTheta=0; iTheta<_nDivisionsInTheta;++iTheta) { + ProcessOneSector(iPhi,iTheta); // Process one VXD sector + } + } + + debug() << "End of Processing VXD and SIT sectors" << endmsg; + + } + + if (successFTD == 1) { + debug() << " phi side layer nh o : m : i :: o*m*i " << endmsg; + TrackingInFTD(); // Perform tracking in the FTD + debug() << "End of Processing FTD sectors" << endmsg; + } + + //if(0){ + if (successVTX == 1 || successFTD == 1) { + //if (successVTX == 1 ) { + for (int nHits = _nHitsChi2; nHits >= 3 ;// the three is hard coded, sorry. + // It's the minimal number to form a track + nHits--) { + Sorting( _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ) ); + + } + debug() << "End of Sorting " << endmsg; + + for (int nHits = _nHitsChi2; nHits >= 3 ;// the three is hard coded, sorry. + // It's the minimal number to form a track + nHits--) { + + TrackExtendedVec &tracksWithNHits = _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ); + for (TrackExtendedVec::iterator trackIter = tracksWithNHits.begin(); + trackIter < tracksWithNHits.end(); trackIter++) { + CreateTrack( *trackIter ); + } + debug() << "End of creating "<< nHits << " hits tracks " << endmsg; + } + + if (_attachFast == 0) { + if(successVTX) AttachRemainingVTXHitsSlow(); + if(successFTD) AttachRemainingFTDHitsSlow(); + } + else { + if(successVTX) AttachRemainingVTXHitsFast(); + if(successFTD) AttachRemainingFTDHitsFast(); + } + + debug() << "End of picking up remaining hits " << endmsg; + + //edm4hep::TrackCollection* trkCol = nullptr; + //edm4hep::LCRelationCollection* relCol = nullptr; + auto trkCol = _outColHdl.createAndPut(); + //auto relCol = _outRelColHdl.createAndPut(); + /* + LCCollectionVec * trkCol = new LCCollectionVec(LCIO::TRACK); + // if we want to point back to the hits we need to set the flag + LCFlagImpl trkFlag(0) ; + trkFlag.setBit( LCIO::TRBIT_HITS ) ; + trkCol->setFlag( trkFlag.getFlag() ) ; + + LCCollectionVec * relCol = NULL; + */ + //FinalRefit(trkCol, relCol); + FinalRefit(trkCol); + debug() << "FinalRefit finish" << endmsg; + // set the quality of the output collection + switch (_output_track_col_quality) { + + case _output_track_col_quality_FAIR: + //trkCol->parameters().setValue( "QualityCode" , "Fair" ) ; + break; + + case _output_track_col_quality_POOR: + //trkCol->parameters().setValue( "QualityCode" , "Poor" ) ; + break; + + default: + //trkCol->parameters().setValue( "QualityCode" , "Good" ) ; + break; + } + /* + if (_UseEventDisplay) { + this->drawEvent(); + } + */ + } + + // fill event based histogram + /* + if (_createDiagnosticsHistograms) { + + // triplet histos + _histos->fill1D(DiagnosticsHistograms::hntriplets, _ntriplets); + _histos->fill1D(DiagnosticsHistograms::hntriplets_good, _ntriplets_good); + _histos->fill1D(DiagnosticsHistograms::hntriplets_2MCP, _ntriplets_2MCP); + _histos->fill1D(DiagnosticsHistograms::hntriplets_3MCP, _ntriplets_3MCP); + _histos->fill1D(DiagnosticsHistograms::hntriplets_1MCP_Bad, _ntriplets_1MCP_Bad); + _histos->fill1D(DiagnosticsHistograms::hntriplets_bad, _ntriplets_bad); + + } + */ + /* + const edm4hep::MCParticleCollection* mcCol = nullptr; + try{ + mcCol =_inMCColHdl.get(); + } + catch(...){ + } + if(mcCol){ + int id = 0; + for(auto mcP : *mcCol){ + float pos[3]; + float mom[3]; + pos[0] = mcP.vertex()[0]; + pos[1] = mcP.vertex()[1]; + pos[2] = mcP.vertex()[2]; + mom[0] = mcP.momentum()[0]; + mom[1] = mcP.momentum()[1]; + mom[2] = mcP.momentum()[2]; + float charge = mcP.getCharge(); + HelixClass helix; + helix.Initialize_VP(pos,mom,charge,_bField); + float d0 = helix.getD0(); + float z0 = helix.getZ0(); + float omega = helix.getOmega(); + float phi0 = helix.getPhi0(); + float tanLambda = helix.getTanLambda(); + std::cout <<"MCParticle: " << evtNo << " " << id << " " << sqrt(mom[0]*mom[0]+mom[1]*mom[1]) << " " << acos(mom[2]/sqrt(mom[0]*mom[0]+mom[1]*mom[1]+mom[2]*mom[2])) + << " " << atan2(mom[1],mom[0]) + << " " << d0 << " " << phi0 << " " << omega << " " << z0 << " " << tanLambda << " " << mcP.vertex() << std::endl; + id++; + } + } + + const edm4hep::TrackCollection* trkCol = nullptr; + try{ + trkCol = _outColHdl.get(); + } + catch(...){ + } + if(trkCol){ + int id = 0; + for(auto track : *trkCol){ + int nstate = track->trackStates_size(); + for(int i=0;i<nstate;i++){ + edm4hep::TrackState trkState = track->getTrackStates(i); + if(trkState.location != 1) continue; + HelixClass helix_final; + helix_final.Initialize_Canonical(trkState.phi,trkState.D0,trkState.Z0,trkState.omega,trkState.tanLambda,_bField); + float trkPx = helix_final.getMomentum()[0]; + float trkPy = helix_final.getMomentum()[1]; + float trkPz = helix_final.getMomentum()[2]; + float trkPt = sqrt(trkPx*trkPx+trkPy*trkPy); + std::cout << "Track parameter: " << evtNo << " " << id << " " << trkPt << " " << acos(trkPz/sqrt(trkPt*trkPt+trkPz*trkPz)) << " " << atan2(trkPy,trkPx) + << " " << trkState.D0 << " " << trkState.phi << " " << trkState.omega << " " << trkState.Z0 << " " << trkState.tanLambda + << " " << sqrt(trkState.covMatrix[0]) << " " << sqrt(trkState.covMatrix[2]) << " " << sqrt(trkState.covMatrix[5]) + << " " << sqrt(trkState.covMatrix[9]) << " " << sqrt(trkState.covMatrix[14]) << " " << std::endl; + id++; + break; + } + } + } + */ + CleanUp(); + debug() << "Event is done " << endmsg; + _nEvt++; + return StatusCode::SUCCESS; +} + + +void SiliconTrackingAlg::CleanUp() { + + _tracksWithNHitsContainer.clear(); + + for (int il=0;il<_nLayers;++il) { + for (int ip=0;ip<_nDivisionsInPhi;++ip) { + for (int it=0;it<_nDivisionsInTheta; ++it) { + unsigned int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it; + + if( iCode >= _sectors.size()){ + error() << "iCode index out of range: iCode = " << iCode << " _sectors.size() = " << _sectors.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg; + continue; + } + + TrackerHitExtendedVec& hitVec = _sectors[iCode]; + int nH = int(hitVec.size()); + for (int iH=0; iH<nH; ++iH) { + TrackerHitExtended * hit = hitVec[iH]; + delete hit; + } + } + } + } + + for (int iS=0;iS<2;++iS) { + for (unsigned int layer=0;layer<_nlayersFTD;++layer) { + for (int ip=0;ip<_nDivisionsInPhiFTD;++ip) { + unsigned int iCode = iS + 2*layer + 2*_nlayersFTD*ip; + + if( iCode >= _sectorsFTD.size()){ + error() << "iCode index out of range: iCode = " << iCode << " _sectorsFTD.size() = " << _sectorsFTD.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg; + continue; + } + + TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode]; + int nH = int(hitVec.size()); + for (int iH=0; iH<nH; ++iH) { + TrackerHitExtended * hit = hitVec[iH]; + delete hit; + } + } + } + } + _trackImplVec.clear(); +} + +int SiliconTrackingAlg::InitialiseFTD() { + + int success = 1; + + _nTotalFTDHits = 0; + _sectorsFTD.clear(); + _sectorsFTD.resize(2*_nlayersFTD*_nDivisionsInPhiFTD); + + // Reading in FTD Pixel Hits Collection + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + const edm4hep::TrackerHitCollection* hitFTDPixelCol = nullptr; + try { + hitFTDPixelCol = _inFTDPixelColHdl.get(); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inFTDPixelColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + success = 0; + } + + if(hitFTDPixelCol){ + //LCCollection * hitCollection = evt->getCollection(_FTDPixelHitCollection.c_str()); + + //_colNamesTrackerHits[hitCollection] = _FTDPixelHitCollection; + // _colTrackerHits.push_back(hitCollection); + + int nelem = hitFTDPixelCol->size(); + + debug() << "Number of FTD Pixel Hits = " << nelem << endmsg; + _nTotalFTDHits = nelem; + + //for (int ielem=0; ielem<nelem; ++ielem) { + for(auto hit : *hitFTDPixelCol){ + //dm4hep::TrackerHit* hit = hitFTDPixelCol->at(ielem); + TrackerHitExtended * hitExt = new TrackerHitExtended( hit ); + //gear::Vector3D U(1.0,hit->getU()[1],hit->getU()[0],gear::Vector3D::spherical); + //gear::Vector3D V(1.0,hit->getV()[1],hit->getV()[0],gear::Vector3D::spherical); + gear::Vector3D U(1.0,hit.getCovMatrix()[1],hit.getCovMatrix()[0],gear::Vector3D::spherical); + gear::Vector3D V(1.0,hit.getCovMatrix()[4],hit.getCovMatrix()[3],gear::Vector3D::spherical); + gear::Vector3D Z(0.0,0.0,1.0); + + const float eps = 1.0e-07; + // V must be the global z axis + if( fabs(V.dot(Z)) > eps ) { + error() << "SiliconTrackingAlg: VXD Hit measurment vectors V is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg; + exit(1); + } + + if( fabs(U.dot(Z)) > eps ) { + error() << "SiliconTrackingAlg: VXD Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg; + exit(1); + } + // SJA:FIXME Here dU and dV are almost certainly dX and dY ... should test ... + //double point_res_rphi = sqrt( hit->getdU()*hit->getdU() + hit->getdV()*hit->getdV() ); + double point_res_rphi = sqrt( hit.getCovMatrix()[2]*hit.getCovMatrix()[2] + hit.getCovMatrix()[5]*hit.getCovMatrix()[5] ); + hitExt->setResolutionRPhi( point_res_rphi ); + + // SJA:FIXME why is this needed? + hitExt->setResolutionZ(0.1); + + // type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse + hitExt->setType(int(INT_MAX)); + // det is no longer used set to INT_MAX to try and catch any missuse + hitExt->setDet(int(INT_MAX)); + + double pos[3]; + + for (int i=0; i<3; ++i) { + pos[i] = hit.getPosition()[i]; + } + + double Phi = atan2(pos[1],pos[0]); + if (Phi < 0.) Phi = Phi + TWOPI; + // get the layer number + unsigned int layer = static_cast<unsigned int>(getLayerID(&hit)); + unsigned int petalIndex = static_cast<unsigned int>(getModuleID(&hit)); + + if ( _petalBasedFTDWithOverlaps == true ) { + + // as we are dealing with staggered petals we will use 2*nlayers in each directions +/- z + // the layers will follow the even odd numbering of the petals + if ( petalIndex % 2 == 0 ) { + layer = 2*layer; + } + else { + layer = 2*layer + 1; + } + + } + if (layer >= _nlayersFTD) { + fatal() << "SiliconTrackingAlg => fatal error in FTD : layer is outside allowed range : " << layer << " number of layers = " << _nlayersFTD << endmsg; + exit(1); + } + + int iPhi = int(Phi/_dPhiFTD); + + int side = getSideID(&hit); + int iSemiSphere = 0; + + if (side > 0) + iSemiSphere = 1; + + int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPhi; + _sectorsFTD[iCode].push_back( hitExt ); + + debug() << " FTD Pixel Hit added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << " iPhi = " << iPhi << " iSemiSphere " << iSemiSphere << " iCode = " << iCode << " layer = " << layer << endmsg; + } + } + // Reading out FTD SpacePoint Collection + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + const edm4hep::TrackerHitCollection* hitFTDSpacePointCol = nullptr; + try { + hitFTDSpacePointCol = _inFTDSpacePointColHdl.get(); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inFTDSpacePointColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + success = 0; + } + + const edm4hep::TrackerHitCollection* rawHitCol = nullptr; + if(hitFTDSpacePointCol){ + try{ + rawHitCol = _inFTDRawColHdl.get(); + } + catch ( GaudiException &e ) { + fatal() << "Collection " << _inFTDRawColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + success = 0; + } + } + + if(hitFTDSpacePointCol&&rawHitCol){ + Navigation::Instance()->AddTrackerHitCollection(rawHitCol); + //LCCollection * hitCollection = evt->getCollection(_FTDSpacePointCollection.c_str()); + + //_colNamesTrackerHits[hitCollection] = _FTDSpacePointCollection; + //_colTrackerHits.push_back(hitCollection); + + int nelem = hitFTDSpacePointCol->size(); + + debug() << "Number of FTD SpacePoints = " << nelem << endmsg; + _nTotalFTDHits += nelem; + + //for (int ielem=0; ielem<nelem; ++ielem) { + for(auto hit : *hitFTDSpacePointCol){ + //edm4hep::TrackerHit* hit = hitFTDSpacePointCol->at(ielem); + + TrackerHitExtended * hitExt = new TrackerHitExtended(hit); + + // SJA:FIXME: fudge for now by a factor of two and ignore covariance + double point_res_rphi = 2 * sqrt( hit.getCovMatrix()[0] + hit.getCovMatrix()[2] ); + + hitExt->setResolutionRPhi( point_res_rphi ); + + // SJA:FIXME why is this needed? + hitExt->setResolutionZ(0.1); + + // type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse + hitExt->setType(int(INT_MAX)); + // det is no longer used set to INT_MAX to try and catch any missuse + hitExt->setDet(int(INT_MAX)); + + double pos[3]; + + for (int i=0; i<3; ++i) { + pos[i] = hit.getPosition()[i]; + } + + double Phi = atan2(pos[1],pos[0]); + if (Phi < 0.) Phi = Phi + TWOPI; + + // get the layer number + unsigned int layer = static_cast<unsigned int>(getLayerID(&hit)); + unsigned int petalIndex = static_cast<unsigned int>(getModuleID(&hit)); + + if ( _petalBasedFTDWithOverlaps == true ) { + + // as we are dealing with staggered petals we will use 2*nlayers in each directions +/- z + // the layers will follow the even odd numbering of the petals + if ( petalIndex % 2 == 0 ) { + layer = 2*layer; + } + else { + layer = 2*layer + 1; + } + + } + + if (layer >= _nlayersFTD) { + error() << "SiliconTrackingAlg => fatal error in FTD : layer is outside allowed range : " << layer << " number of layers = " << _nlayersFTD << endmsg; + exit(1); + } + + int iPhi = int(Phi/_dPhiFTD); + + int side = getSideID(&hit); + int iSemiSphere = 0; + + if (side > 0) + iSemiSphere = 1; + + int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPhi; + _sectorsFTD[iCode].push_back( hitExt ); + + debug() << " FTD SpacePoint Hit added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << " iPhi = " << iPhi << " iSemiSphere " << iSemiSphere << " iCode = " << iCode << " layer = " << layer << endmsg; + + } + } + + for (unsigned i=0; i<_sectorsFTD.size(); ++i) { + int nhits = _sectorsFTD[i].size(); + if( nhits != 0 ) debug() << " Number of Hits in FTD Sector " << i << " = " << _sectorsFTD[i].size() << endmsg; + if (nhits > _max_hits_per_sector) { + for (unsigned ihit=0; ihit<_sectorsFTD[i].size(); ++ihit) { + delete _sectorsFTD[i][ihit]; + } + _sectorsFTD[i].clear(); + if( nhits != 0 ) error() << " \n ### Number of Hits in FTD Sector " << i << " = " << nhits << " : Limit is set to " << _max_hits_per_sector << " : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg; + + _output_track_col_quality = _output_track_col_quality_POOR; + + } + + } + debug() << "FTD initialized" << endmsg; + return success; +} + +int SiliconTrackingAlg::InitialiseVTX() { + _nTotalVTXHits = 0; + _nTotalSITHits = 0; + _sectors.clear(); + _sectors.resize(_nLayers*_nDivisionsInPhi*_nDivisionsInTheta); + int success = 1; + // Reading out VTX Hits Collection + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + const edm4hep::TrackerHitCollection* hitVTXCol = nullptr; + try { + hitVTXCol = _inVTXColHdl.get(); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inVTXColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + success = 0; + } + if(hitVTXCol){ + //LCCollection * hitCollection = evt->getCollection(_VTXHitCollection.c_str()); + + //_colNamesTrackerHits[hitCollection] = _VTXHitCollection; + //_colTrackerHits.push_back(hitCollection); + int nelem = hitVTXCol->size(); + debug() << "Number of VTX hits = " << nelem << endmsg; + _nTotalVTXHits = nelem; + + for (int ielem=0; ielem<nelem; ++ielem) { + //for(auto hit : *hitVTXCol){ + edm4hep::TrackerHit hit = hitVTXCol->at(ielem); + //gear::Vector3D U(1.0,hit->getU()[1],hit->getU()[0],gear::Vector3D::spherical); + //gear::Vector3D V(1.0,hit->getV()[1],hit->getV()[0],gear::Vector3D::spherical); + gear::Vector3D U(1.0,hit.getCovMatrix()[1],hit.getCovMatrix()[0],gear::Vector3D::spherical); + gear::Vector3D V(1.0,hit.getCovMatrix()[4],hit.getCovMatrix()[3],gear::Vector3D::spherical); + gear::Vector3D Z(0.0,0.0,1.0); + //debug() << "covMatrix : " << hit->getCovMatrix()[0] << " " << hit->getCovMatrix()[1] << endmsg; + const float eps = 1.0e-07; + // V must be the global z axis + if( fabs(1.0 - V.dot(Z)) > eps ) { + error() << "SiliconTrackingAlg: VXD Hit measurment vectors V is not equal to the global Z axis. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg; + exit(1); + } + + if( fabs(U.dot(Z)) > eps ) { + error() << "SiliconTrackingAlg: VXD Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg; + exit(1); + } + TrackerHitExtended * hitExt = new TrackerHitExtended(hit); + debug() << "Saved TrackerHit pointer in TrackerHitExtended " << ielem << ": " << hitExt->getTrackerHit() << std::endl; + + // SJA:FIXME: just use planar res for now + hitExt->setResolutionRPhi(hit.getCovMatrix()[2]); + hitExt->setResolutionZ(hit.getCovMatrix()[5]); + + // set type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse + hitExt->setType(int(INT_MAX)); + // det is no longer used set to INT_MAX to try and catch any missuse + hitExt->setDet(int(INT_MAX)); + + double pos[3]; + double radius = 0; + + for (int i=0; i<3; ++i) { + pos[i] = hit.getPosition()[i]; + radius += pos[i]*pos[i]; + } + + radius = sqrt(radius); + + double cosTheta = pos[2]/radius; + double Phi = atan2(pos[1],pos[0]); + + if (Phi < 0.) Phi = Phi + TWOPI; + + // get the layer number + int layer = getLayerID(&hit); + + if (layer < 0 || layer >= _nLayers) { + error() << "SiliconTrackingAlg => fatal error in VTX : layer is outside allowed range : " << layer << endmsg; + exit(1); + } + + int iPhi = int(Phi/_dPhi); + int iTheta = int ((cosTheta + double(1.0))/_dTheta); + int iCode = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta; + _sectors[iCode].push_back( hitExt ); + + debug() << " VXD Hit " << hit.id() << " added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << " iPhi = " << iPhi << " iTheta " << iTheta << " iCode = " << iCode << " layer = " << layer << endmsg; + + } + } + + if (_useSIT > 0 ) { + const edm4hep::TrackerHitCollection* hitSITCol = nullptr; + try { + hitSITCol = _inSITColHdl.get(); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inSITColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + success = 0; + } + + const edm4hep::TrackerHitCollection* rawHitCol = nullptr; + if(hitSITCol){ + try{ + rawHitCol = _inSITRawColHdl.get(); + } + catch ( GaudiException &e ) { + warning() << "Collection " << _inSITRawColHdl.fullKey() << " is unavailable in event " << _nEvt << ", if SIT is Space Point, it needed " << endmsg; + //success = 0; + } + } + + if(hitSITCol){ + if(rawHitCol) Navigation::Instance()->AddTrackerHitCollection(rawHitCol); + //debug() << "SITHitCollection pointer = " << hitSITCol << endmsg; + int nelem = hitSITCol->size(); + + debug() << "Number of SIT hits = " << nelem << endmsg; + _nTotalSITHits = nelem; + + //TrackerHit* trkhit = 0; + //TrackerHitPlane* trkhit_P = 0; + //TrackerHitZCylinder* trkhit_C = 0; + + double drphi(NAN); + double dz(NAN); + + //for (int ielem=0; ielem<nelem; ++ielem) { + for(auto trkhit : *hitSITCol){ + // hit could be of the following type + // 1) TrackerHit, either ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT or just standard TrackerHit + // 2) TrackerHitPlane, either 1D or 2D + // 3) TrackerHitZCylinder, if coming from a simple cylinder design as in the LOI + + // Establish which of these it is in the following order of likelyhood + // i) ILDTrkHitTypeBit::ONE_DIMENSIONAL (TrackerHitPlane) Should Never Happen: SpacePoints Must be Used Instead + // ii) ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT (TrackerHit) + // iii) TrackerHitPlane (Two dimentional) + // iv) TrackerHitZCylinder + // v) Must be standard TrackerHit + + //const edm4hep::TrackerHit* trkhit = hitSITCol->at(ielem); + + int layer = getLayerID(&trkhit); + + // VXD and SIT are treated as one system so SIT layers start from _nLayersVTX + layer = layer + _nLayersVTX; + + if (layer < 0 || layer >= _nLayers) { + error() << "SiliconTrackingAlg => fatal error in SIT : layer is outside allowed range : " << layer << endmsg; + exit(1); + } + + // first check that we have not been given 1D hits by mistake, as they won't work here + if ( UTIL::BitSet32( trkhit.getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] ) { + fatal() << "SiliconTrackingAlg: SIT Hit cannot be of type UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL COMPOSITE SPACEPOINTS must be use instead. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg; + exit(1); + } + // most likely case: COMPOSITE_SPACEPOINT hits formed from stereo strip hits + else if ( UTIL::BitSet32( trkhit.getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ) { + + // SJA:FIXME: fudge for now by a factor of two and ignore covariance + drphi = 2 * sqrt(trkhit.getCovMatrix()[0] + trkhit.getCovMatrix()[2]); + dz = sqrt(trkhit.getCovMatrix()[5]); + + } + // or a PIXEL based SIT, using 2D TrackerHitPlane like the VXD above + // by fucd + //else if ( ( trkhit_P = dynamic_cast<TrackerHitPlane*>( hitCollection->getElementAt( ielem ) ) ) ) { + else if( UTIL::BitSet32( trkhit.getType() )[ 31 ]){ + // first we need to check if the measurement vectors are aligned with the global coordinates + //gear::Vector3D U(1.0,trkhit_P->getU()[1],trkhit_P->getU()[0],gear::Vector3D::spherical); + //gear::Vector3D V(1.0,trkhit_P->getV()[1],trkhit_P->getV()[0],gear::Vector3D::spherical); + gear::Vector3D U(1.0,trkhit.getCovMatrix()[1],trkhit.getCovMatrix()[0],gear::Vector3D::spherical); + gear::Vector3D V(1.0,trkhit.getCovMatrix()[4],trkhit.getCovMatrix()[3],gear::Vector3D::spherical); + gear::Vector3D Z(0.0,0.0,1.0); + + const float eps = 1.0e-07; + // V must be the global z axis + if( fabs(1.0 - V.dot(Z)) > eps ) { + error() << "SiliconTrackingAlg: PIXEL SIT Hit measurment vectors V is not equal to the global Z axis. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg; + exit(1); + } + + // U must be normal to the global z axis + if( fabs(U.dot(Z)) > eps ) { + error() << "SiliconTrackingAlg: PIXEL SIT Hit measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << endmsg; + exit(1); + } + + //drphi = trkhit_P->getdU(); + //dz = trkhit_P->getdV(); + drphi = trkhit.getCovMatrix()[2]; + dz = trkhit.getCovMatrix()[5]; + } + + // or a simple cylindrical design, as used in the LOI + /* by fucd + else if ( ( trkhit_C = dynamic_cast<TrackerHitZCylinder*>( hitCollection->getElementAt( ielem ) ) ) ) { + + drphi = trkhit_C->getdRPhi(); + dz = trkhit_C->getdZ(); + + } + */ + // this would be very unlikely, but who knows ... just an ordinary TrackerHit, which is not a COMPOSITE_SPACEPOINT + else { + + // SJA:FIXME: fudge for now by a factor of two and ignore covariance + drphi = 2 * sqrt(trkhit.getCovMatrix()[0] + trkhit.getCovMatrix()[2]); + dz = sqrt(trkhit.getCovMatrix()[5]); + + } + // now that the hit type has been established carry on and create a + + TrackerHitExtended * hitExt = new TrackerHitExtended(trkhit); + + // SJA:FIXME: just use planar res for now + hitExt->setResolutionRPhi(drphi); + hitExt->setResolutionZ(dz); + + // set type is now only used in one place where it is set to 0 to reject hits from a fit, set to INT_MAX to try and catch any missuse + hitExt->setType(int(INT_MAX)); + // det is no longer used set to INT_MAX to try and catch any missuse + hitExt->setDet(int(INT_MAX)); + + double pos[3]; + double radius = 0; + + for (int i=0; i<3; ++i) { + pos[i] = trkhit.getPosition()[i]; + radius += pos[i]*pos[i]; + } + + radius = sqrt(radius); + + double cosTheta = pos[2]/radius; + double Phi = atan2(pos[1],pos[0]); + + if (Phi < 0.) Phi = Phi + TWOPI; + + int iPhi = int(Phi/_dPhi); + int iTheta = int ((cosTheta + double(1.0))/_dTheta); + int iCode = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta; + _sectors[iCode].push_back( hitExt ); + + debug() << " SIT Hit " << trkhit.id() << " added : @ " << pos[0] << " " << pos[1] << " " << pos[2] << " drphi " << hitExt->getResolutionRPhi() << " dz " << hitExt->getResolutionZ() << " iPhi = " << iPhi << " iTheta " << iTheta << " iCode = " << iCode << " layer = " << layer << endmsg; + + } + } + } + + + for (unsigned i=0; i<_sectors.size(); ++i) { + int nhits = _sectors[i].size(); + if( nhits != 0 ) debug() << " Number of Hits in VXD/SIT Sector " << i << " = " << _sectors[i].size() << endmsg; + if (nhits > _max_hits_per_sector) { + for (unsigned ihit=0; ihit<_sectors[i].size(); ++ihit) { + delete _sectors[i][ihit]; + } + _sectors[i].clear(); + if( nhits != 0 ) error() << " \n ### Number of Hits in VXD/SIT Sector " << i << " = " << nhits << " : Limit is set to " << _max_hits_per_sector << " : This sector will be dropped from track search, and QualityCode set to \"Poor\" " << endmsg; + + _output_track_col_quality = _output_track_col_quality_POOR; + } + } + debug() << "VXD initialized" << endmsg; + return success; +} + +StatusCode SiliconTrackingAlg::finalize(){ + + delete _fastfitter ; _fastfitter = 0; + delete _encoder ; _encoder = 0; + //delete _trksystem ; _trksystem = 0; + //delete _histos ; _histos = 0; + info() << "Processed " << _nEvt << " events " << endmsg; + return GaudiAlgorithm::finalize(); +} + + +void SiliconTrackingAlg::ProcessOneSector(int iPhi, int iTheta) { + + int counter = 0 ; + + int iPhi_Up = iPhi + 1; + int iPhi_Low = iPhi - 1; + int iTheta_Up = iTheta + 1; + int iTheta_Low = iTheta - 1; + if (iTheta_Low < 0) iTheta_Low = 0; + if (iTheta_Up >= _nDivisionsInTheta) iTheta_Up = _nDivisionsInTheta-1; + + int nComb = int( _Combinations.size() / 3 ); // number of triplet combinations + // std::cout << iPhi << " " << iTheta << " " << _nEvt << endmsg; + int iNC = 0; + + for (int iComb=0; iComb < nComb; ++iComb) { // loop over triplets + + int nLR[3]; + + for (int iS=0; iS<3; ++iS) { + nLR[iS] = _Combinations[iNC]; + iNC++; + } + + //std::cout << iPhi << " " << iTheta << " " << nLR[0] << " " << nLR[1] << " " << nLR[2] << " " << std::endl; + + // index of theta-phi bin of outer most layer + int iCode = nLR[0] + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta; + + //std::cout << "size of vector = " << _sectors.size() << " iCode = " << iCode << std::endl; + + // get the all the hits in the outer most theta-phi bin + + TrackerHitExtendedVec& hitVecOuter = _sectors[iCode]; + + int nHitsOuter = int(hitVecOuter.size()); + if (nHitsOuter > 0) { + + //std::cout << " " << iPhi << " " << iTheta << " " << nLR[0] << " " << nLR[1] << " " << nLR[2] << " size of vector = " << hitVecOuter.size() << std::endl; + + for (int ipMiddle=iPhi_Low; ipMiddle<iPhi_Up+1;ipMiddle++) { // loop over phi in the Middle + + for (int itMiddle=iTheta_Low; itMiddle<iTheta_Up+1;itMiddle++) { // loop over theta in the Middle + + int iPhiMiddle = ipMiddle; + + // catch wrap-around + if (ipMiddle < 0) iPhiMiddle = _nDivisionsInPhi-1; + if (ipMiddle >= _nDivisionsInPhi) iPhiMiddle = ipMiddle - _nDivisionsInPhi; + + // index of current theta-phi bin of middle layer + iCode = nLR[1] + _nLayers*iPhiMiddle + _nLayers*_nDivisionsInPhi*itMiddle; + + // get the all the hits in the current middle theta-phi bin + TrackerHitExtendedVec& hitVecMiddle = _sectors[iCode]; + + int nHitsMiddle = int(hitVecMiddle.size()); + + // determine which inner theta-phi bins to look in + + int iPhiLowInner = iPhi_Low; + int iPhiUpInner = iPhi_Up; + int iThetaLowInner = iTheta_Low; + int iThetaUpInner = iTheta_Up; + + // test to see if this is the core bin of the current search + // if so, look into the neigboring bins in the inner layer + if (ipMiddle == iPhi && itMiddle==iTheta) { + iPhiLowInner = iPhi_Low; + iPhiUpInner = iPhi_Up; + iThetaLowInner = iTheta_Low; + iThetaUpInner = iTheta_Up; + } + else { + int difP = abs(ipMiddle-iPhi); // number of phi bins from core: can only be 1 or 0 due to hard coded 1 above + int difT = abs(itMiddle-iTheta);// number of theta bins from core: can only be 1 or 0 due to hard coded 1 above + int minP = min(ipMiddle,iPhi); // min phi: core bin or current phi bin middle + int minT = min(itMiddle,iTheta); // min theta: core bin or current theta bin middle + int maxP = max(ipMiddle,iPhi); // max phi: core bin or current phi bin middle + int maxT = max(itMiddle,iTheta); // max theta: core bin or current theta bin middle + + if (difP==1 && difT==1) { // if the diffence is a single bin in both phi and theta : only look in the bin adjacent to the core bin + iPhiLowInner = minP; + iPhiUpInner = maxP; + iThetaLowInner = minT; + iThetaUpInner = maxT; + } + if (difP==0) { // must be +/-1 theta : only look in bins adjacent to the middle bin + iPhiLowInner = iPhi_Low; + iPhiUpInner = iPhi_Up; + iThetaLowInner = minT; + iThetaUpInner = maxT; + } + if (difT==0) { // must be +/-1 phi : only look in bins adjacent to the middle bin + iPhiLowInner = minP; + iPhiUpInner = maxP; + iThetaLowInner = iTheta_Low; + iThetaUpInner = iTheta_Up; + } + } + if (nHitsMiddle > 0) { // look into inner bins + + for (int ipInner=iPhiLowInner; ipInner<iPhiUpInner+1;ipInner++) { // loop over phi in the Inner + + for (int itInner=iThetaLowInner; itInner<iThetaUpInner+1;itInner++) { // loop over theta in the Inner + + int iPhiInner = ipInner; + + // catch wrap-around + if (ipInner < 0) iPhiInner = _nDivisionsInPhi-1; + if (ipInner >= _nDivisionsInPhi) iPhiInner = ipInner - _nDivisionsInPhi; + + iCode = nLR[2] + _nLayers*iPhiInner + _nLayers*_nDivisionsInPhi*itInner; + + // get hit for inner bin + TrackerHitExtendedVec& hitVecInner = _sectors[iCode]; + + int nHitsInner = int(hitVecInner.size()); + + if (nHitsInner > 0) { + + debug() << " " + << std::setw(3) << iPhi << " " << std::setw(3) << ipMiddle << " " << std::setw(3) << ipInner << " " + << std::setw(3) << iTheta << " " << std::setw(3) << itMiddle << " " << std::setw(3) << itInner << " " + << std::setw(3) << nLR[0] << " " << std::setw(3) << nLR[1] << " " << std::setw(3) << nLR[2] << " " + << std::setw(3) << nHitsOuter << " : " << std::setw(3) << nHitsMiddle << " : " << std::setw(3) << nHitsInner << " :: " + << std::setw(3) << nHitsOuter*nHitsMiddle* nHitsInner << endmsg; + + // test all triplets + + for (int iOuter=0; iOuter<nHitsOuter; ++iOuter) { // loop over hits in the outer sector + TrackerHitExtended * outerHit = hitVecOuter[iOuter]; + for (int iMiddle=0;iMiddle<nHitsMiddle;iMiddle++) { // loop over hits in the middle sector + TrackerHitExtended * middleHit = hitVecMiddle[iMiddle]; + for (int iInner=0;iInner<nHitsInner;iInner++) { // loop over hits in the inner sector + TrackerHitExtended * innerHit = hitVecInner[iInner]; + HelixClass helix; + // test fit to triplet + TrackExtended * trackAR = TestTriplet(outerHit,middleHit,innerHit,helix); + if ( trackAR != NULL ) { + int nHits = BuildTrack(outerHit,middleHit,innerHit,helix,nLR[2], + iPhiLowInner,iPhiUpInner, + iThetaLowInner,iThetaUpInner,trackAR); + + _tracksWithNHitsContainer.getTracksWithNHitsVec(nHits).push_back(trackAR); + + counter ++ ; + } + } // endloop over hits in the inner sector + } // endloop over hits in the middle sector + } // endloop over hits in the outer sector + } // endif nHitsInner > 0 + } // endloop over theta in the Inner + } // endloop over phi in the Inner + } // endif nHitsMiddle > 0 + } // endloop over theta in the Middle + } // endloop over phi in the Middle + } // endif nHitsOuter > 0 + } // endloop over triplets + + //debug() << " process one sectector theta,phi " << iTheta << ", " << iPhi << " number of loops : " << counter << endmsg ; +} + +TrackExtended * SiliconTrackingAlg::TestTriplet(TrackerHitExtended * outerHit, + TrackerHitExtended * middleHit, + TrackerHitExtended * innerHit, + HelixClass & helix) { + /* + Methods checks if the triplet of hits satisfies helix hypothesis + */ + // get the tracks already associated with the triplet + TrackExtendedVec& trackOuterVec = outerHit->getTrackExtendedVec(); + TrackExtendedVec& trackMiddleVec = middleHit->getTrackExtendedVec(); + TrackExtendedVec& trackInnerVec = innerHit->getTrackExtendedVec(); + + // check if all the hits are already assigned to a track + if ( (!trackOuterVec.empty()) && (!trackMiddleVec.empty()) && (!trackInnerVec.empty())) { + + TrackExtendedVec::const_iterator middleEndIter = trackMiddleVec.end(); + TrackExtendedVec::const_iterator outerEndIter = trackOuterVec.end(); + TrackExtendedVec::const_iterator innerEndIter = trackInnerVec.end(); + TrackExtendedVec::const_iterator outerBeginIter = trackOuterVec.begin(); + TrackExtendedVec::const_iterator innerBeginIter = trackInnerVec.begin(); + + // loop over the tracks from the middle hit + for (TrackExtendedVec::const_iterator middleIter = trackMiddleVec.begin(); + middleIter < middleEndIter; + ++middleIter) { + + // loop over the track from the outer hit + for (TrackExtendedVec::const_iterator outerIter = outerBeginIter; + outerIter < outerEndIter; + ++outerIter) { + + // if track from the outer and middle are not the same progress + if ( *outerIter != *middleIter ) continue; + + // loop over the tracks from the inner hit + for (TrackExtendedVec::const_iterator innerIter = innerBeginIter; + innerIter < innerEndIter; + ++innerIter) { + + // no need to check against middle, it is idendical to outer here + if ( *outerIter == *innerIter ) { + // an existing track already contains all three hits + // return a null pointer + debug() << " TestTriplet: track " << *outerIter << " already contains all three hits: Do not create new track from these hits " << endmsg ; + return 0; + } + + }// for inner + }// for outer + }// for middle + }// if all vectors are not empty + // float dZ = FastTripletCheck(innerHit, middleHit, outerHit); + + // if (fabs(dZ) > _minDistCutAttach) + // return trackAR; + + // increase triplet count + ++_ntriplets; + + // get the hit coordinates and errors + double xh[3]; + double yh[3]; + float zh[3]; + double wrh[3]; + float wzh[3]; + float rh[3]; + float ph[3]; + + float par[5]; + float epar[15]; + + // first hit + xh[0] = outerHit->getTrackerHit()->getPosition()[0]; + yh[0] = outerHit->getTrackerHit()->getPosition()[1]; + zh[0] = float(outerHit->getTrackerHit()->getPosition()[2]); + wrh[0] = double(1.0/(outerHit->getResolutionRPhi()*outerHit->getResolutionRPhi())); + wzh[0] = 1.0/(outerHit->getResolutionZ()*outerHit->getResolutionZ()); + // second hit + xh[1] = middleHit->getTrackerHit()->getPosition()[0]; + yh[1] = middleHit->getTrackerHit()->getPosition()[1]; + zh[1] = float(middleHit->getTrackerHit()->getPosition()[2]); + wrh[1] = double(1.0/(middleHit->getResolutionRPhi()*middleHit->getResolutionRPhi())); + wzh[1] = 1.0/(middleHit->getResolutionZ()*middleHit->getResolutionZ()); + // third hit + xh[2] = innerHit->getTrackerHit()->getPosition()[0]; + yh[2] = innerHit->getTrackerHit()->getPosition()[1]; + zh[2] = float(innerHit->getTrackerHit()->getPosition()[2]); + wrh[2] = double(1.0/(innerHit->getResolutionRPhi()*innerHit->getResolutionRPhi())); + wzh[2] = 1.0/(innerHit->getResolutionZ()*innerHit->getResolutionZ()); + // calculate r and phi for all hits + for (int ih=0; ih<3; ih++) { + rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih])); + ph[ih] = atan2(yh[ih],xh[ih]); + if (ph[ih] < 0.) + ph[ih] = TWOPI + ph[ih]; + } + + int NPT = 3; + int iopt = 2; + float chi2RPhi; + float chi2Z; + + debug() << " TestTriplet: Use fastHelixFit " << endmsg ; + + _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z); + par[3] = par[3]*par[0]/fabs(par[0]); + + // get helix parameters + float omega = par[0]; + float tanlambda = par[1]; + float phi0 = par[2]; + float d0 = par[3]; + float z0 = par[4]; + + // chi2 is weighted here by a factor for both rphi and z + float Chi2 = chi2RPhi*_chi2WRPhiTriplet+chi2Z*_chi2WZTriplet; + int ndf = 2*NPT-5; + + + // check the truth information for the triplet + + // define these outside of the ifdef so that we don't need to keep repeating it. + //std::vector<TrackerHit*> hit_list; + //std::vector<MCParticle*> mcps_imo; + //std::vector<MCParticle*> mcp_s; + int triplet_code = 0; + /* +#ifdef MARLINTRK_DIAGNOSTICS_ON + + int nmcps = 0; + int nbadHits = 0; + + int layer = 9 ; + int size = 3 ; + int marker = 1 ; + int ml = 0 ; + // float helix_max_r = 0; + float helix_max_z = 0; + int color = 0; + + // use the MCTruth4HitExt to get the MCPs + + hit_list.push_back(innerHit->getTrackerHit()); + hit_list.push_back(middleHit->getTrackerHit()); + hit_list.push_back(outerHit->getTrackerHit()); + + EVENT::MCParticle* mcp_i = 0; + EVENT::MCParticle* mcp_m = 0; + EVENT::MCParticle* mcp_o = 0; + + for (unsigned ihit = 0; ihit < hit_list.size(); ++ihit) { + + EVENT::TrackerHit* trkhit = hit_list[ihit]; + std::vector<MCParticle*> mcps; + + MarlinTrk::getMCParticlesForTrackerHit(trkhit, mcps); + + if (mcps.size() == 1) { + mcps_imo.push_back(mcps[0]); + ++nmcps; + } else { + mcps_imo.push_back(0); + ++nbadHits; + } + + } + + mcp_i = mcps_imo[0]; + mcp_m = mcps_imo[1]; + mcp_o = mcps_imo[2]; + + debug() + << "\n mcp_i = " << mcp_i + << "\n mcp_m = " << mcp_m + << "\n mcp_o = " << mcp_o + << endmsg; + + if( mcp_i ) { + mcp_s.push_back(mcp_i) ; + } + + if( mcp_m && mcp_m != mcp_i ) { + mcp_s.push_back(mcp_m); + } + + if( mcp_o && mcp_o != mcp_m && mcp_o != mcp_i ){ + mcp_s.push_back(mcp_o); + } + + nmcps = mcp_s.size(); + + if (_UseEventDisplay) { + // display this triplet and the MCPs from which it is formed + + MarlinCED::newEvent(this , _detector_model_for_drawing ) ; + + // CEDPickingHandler &pHandler=CEDPickingHandler::getInstance(); + // + // pHandler.update(_current_event); + + for (unsigned imcp = 0; imcp < mcp_s.size(); ++imcp) { + + MCParticle* mcp = mcp_s[imcp]; + + helix_max_z = fabsf(mcp->getEndpoint()[2]); + + + info() << "Draw MCParticle : " << *mcp <<endmsg; + + MarlinCED::add_layer_description("MCParticle_For_Fit", layer); + + MarlinCED::drawHelix( _bField , mcp->getCharge(), mcp->getVertex()[0], mcp->getVertex()[1], mcp->getVertex()[2], + mcp->getMomentum()[0], mcp->getMomentum()[1], mcp->getMomentum()[2], layer , size , 0x7af774 , + 0.0, _helix_max_r , + helix_max_z, mcp->id() ) ; + + } + + const std::string colName = "Hits_For_Fit"; + + + size = 10 ; + layer = 11 ; + // ml = marker | ( layer << CED_LAYER_SHIFT ) ; + + //ced_describe_layer( colName.c_str() ,layer); + MarlinCED::add_layer_description(colName, layer); + + + color = 0xFFFFFF; + + for( std::vector<TrackerHit* >::const_iterator it = hit_list.begin(); it != hit_list.end() ; it++ ) { + + TrackerHit* trkhit = *it; + + ced_hit_ID(trkhit->getPosition()[0], + trkhit->getPosition()[1], + trkhit->getPosition()[2], + marker, layer, size , color, trkhit->id() ) ; + + } // hits + + } + + if (_createDiagnosticsHistograms) { + + // if no bad hits are present triplet_code = nmcps; + triplet_code = nmcps + nbadHits * 3 ; + + _histos->fill1D(DiagnosticsHistograms::htriplets, triplet_code); + + double pt = (2.99792458E-4*_bField) / omega ; // for r in mm, p in GeV and Bz in Tesla + + if (triplet_code == 1) { + ++_ntriplets_good; + _histos->fill2D(DiagnosticsHistograms::htripletChi2vPt_good, pt, Chi2 ); + _histos->fill1D(DiagnosticsHistograms::htriplets_chi2_good, Chi2 ); + _histos->fill1D(DiagnosticsHistograms::htriplets_pt_good, pt ); + } else { + + _histos->fill2D(DiagnosticsHistograms::htripletChi2vPt_bad, pt, Chi2); + _histos->fill1D(DiagnosticsHistograms::htriplets_chi2_bad, Chi2 ); + _histos->fill1D(DiagnosticsHistograms::htriplets_pt_bad, pt ); + + if(triplet_code == 2) { + ++_ntriplets_2MCP; + } else if (triplet_code == 3) { + ++_ntriplets_3MCP; + } else if (triplet_code == 4) { + ++_ntriplets_1MCP_Bad; + } else { + ++_ntriplets_bad; + } + } + + } + +#endif + */ + + // Check if track satisfies all conditions + + + // std::cout << "Chi2/ndf = " << Chi2/float(ndf) << " , cut = " << _chi2FitCut << endmsg; + // std::cout << "d0 = " << d0 << " , cut = " << _cutOnD0 << endmsg; + // std::cout << "z0 = " << z0 << " , cut = " << _cutOnZ0 << endmsg; + // std::cout << "omega = " << omega << " , cut = " << _cutOnOmega << endmsg; + + // if ( Chi2/float(ndf) > _chi2FitCut || fabs(d0) > _cutOnD0 || fabs(z0) > _cutOnZ0 || fabs(omega)>_cutOnOmega) + // return a null pointer + // return 0; + + bool failed = false; + + int quality_code = triplet_code * 10 ; + + if ( Chi2/float(ndf) > _chi2FitCut ) { + debug() << "Chi2/ndf = " << Chi2/float(ndf) << " , cut = " << _chi2FitCut << endmsg; + failed = true; + quality_code += 1; + } else if (fabs(d0) > _cutOnD0 ) { + debug() << "d0 = " << d0 << " , cut = " << _cutOnD0 << endmsg; + failed = true; + quality_code += 2; + } else if (fabs(z0) > _cutOnZ0 ) { + debug() << "z0 = " << z0 << " , cut = " << _cutOnZ0 << endmsg; + failed = true; + quality_code += 3; + } else if ( fabs(omega)>_cutOnOmega) { + debug() << "omega = " << omega << " , cut = " << _cutOnOmega << endmsg; + failed = true; + quality_code += 4; + } else { + debug() << "Success !!!!!!!" << endmsg; + } + /* + if (_createDiagnosticsHistograms) _histos->fill1D(DiagnosticsHistograms::htriplets, quality_code); + + if (_UseEventDisplay) { + drawEvent(); + } + */ + + if( failed ) { + // return a null pointer + return 0; + } + + + helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField); + + TrackExtended * trackAR = new TrackExtended(); + trackAR->addTrackerHitExtended(outerHit); + trackAR->addTrackerHitExtended(middleHit); + trackAR->addTrackerHitExtended(innerHit); + outerHit->addTrackExtended(trackAR); + middleHit->addTrackExtended(trackAR); + innerHit->addTrackExtended(trackAR); + trackAR->setD0(d0); + trackAR->setZ0(z0); + trackAR->setPhi(phi0); + trackAR->setTanLambda(tanlambda); + trackAR->setOmega(omega); + trackAR->setChi2( Chi2 ); + trackAR->setNDF( ndf ); + trackAR->setCovMatrix(epar); + + + return trackAR; + +} + +int SiliconTrackingAlg::BuildTrack(TrackerHitExtended * outerHit, + TrackerHitExtended * middleHit, + TrackerHitExtended * innerHit, + HelixClass & helix, + int innerLayer, + int iPhiLow, int iPhiUp, + int iThetaLow, int iThetaUp, + TrackExtended * trackAR) { + /** + Method for building up track in the VXD. Method starts from the found triplet and performs + sequential attachment of hits in other layers, which have hits within the search window. + Only searches inwards. + Given that we know we are now jumping over layers due to the doublet nature of the VXD, we + could optimise this to look for the hits in interleaving layers as well. + Currently a fast fit is being done for each additional hit, it could be more efficient to try and use kaltest? + + */ + + debug() << " BuildTrack starting " << endmsg; + + for (int layer = innerLayer-1; layer>=0; layer--) { // loop over remaining layers + float distMin = 1.0e+20; + TrackerHitExtended * assignedhit = NULL; + // loop over phi in the Inner region + for (int ipInner=iPhiLow; ipInner<iPhiUp+1;ipInner++) { + // loop over theta in the Inner region + for (int itInner=iThetaLow; itInner<iThetaUp+1;itInner++) { + int iPhiInner = ipInner; + + // catch wrap-around + if (ipInner < 0) iPhiInner = _nDivisionsInPhi-1; + if (ipInner >= _nDivisionsInPhi) iPhiInner = ipInner - _nDivisionsInPhi; + + // get the index of the theta-phi bin to search + int iCode = layer + _nLayers*iPhiInner + _nLayers*_nDivisionsInPhi*itInner; + + // get the hits from this bin + TrackerHitExtendedVec& hitVecInner = _sectors[iCode]; + + int nHitsInner = int(hitVecInner.size()); + + // loop over hits in the Inner sector + for (int iInner=0;iInner<nHitsInner;iInner++) { + + TrackerHitExtended * currentHit = hitVecInner[iInner]; + + // get the position of the hit to test + float pos[3]; + float distance[3]; + + for (int i=0; i<3; ++i) { + pos[i] = float(currentHit->getTrackerHit()->getPosition()[i]); + } + + // get the distance of closest approach and distance s traversed to the POCA + float time = helix.getDistanceToPoint(pos,distance); + + // sanity check on s + if (time < 1.0e+10) { + + // check if this is the closest hit yet + if (distance[2] < distMin) { // distance[2] = sqrt( d0*d0 + z0*z0 ) + + // if yes store hit and distance + distMin = distance[2]; + assignedhit = currentHit; + } + } + } // endloop over hits in the Inner sector + } // endloop over theta in the Inner region + } // endloop over phi in the Inner region + // check if closest hit fulfills the min distance cut + if (distMin < _minDistCutAttach) { + // if yes try to include it in the fit + TrackerHitExtendedVec& hvec = trackAR->getTrackerHitExtendedVec(); + int nHits = int(hvec.size()); + double * xh = new double[nHits+1]; + double * yh = new double[nHits+1]; + float * zh = new float[nHits+1]; + double * wrh = new double[nHits+1]; + float * wzh = new float[nHits+1]; + float * rh = new float[nHits+1]; + float * ph = new float[nHits+1]; + float par[5]; + float epar[15]; + + for (int ih=0;ih<nHits;++ih) { + edm4hep::TrackerHit * trkHit = hvec[ih]->getTrackerHit(); + xh[ih] = trkHit->getPosition()[0]; + yh[ih] = trkHit->getPosition()[1]; + zh[ih] = float(trkHit->getPosition()[2]); + wrh[ih] = double(1.0/(hvec[ih]->getResolutionRPhi()*hvec[ih]->getResolutionRPhi())); + wzh[ih] = 1.0/(hvec[ih]->getResolutionZ()*hvec[ih]->getResolutionZ()); + rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih])); + ph[ih] = float(atan2(yh[ih],xh[ih])); + if (ph[ih] < 0.) + ph[ih] = TWOPI + ph[ih]; + } + edm4hep::TrackerHit * assignedTrkHit = assignedhit->getTrackerHit(); + xh[nHits] = assignedTrkHit->getPosition()[0]; + yh[nHits] = assignedTrkHit->getPosition()[1]; + zh[nHits] = float(assignedTrkHit->getPosition()[2]); + rh[nHits] = float(sqrt(xh[nHits]*xh[nHits]+yh[nHits]*yh[nHits])); + ph[nHits] = float(atan2(yh[nHits],xh[nHits])); + if (ph[nHits] < 0.) + ph[nHits] = TWOPI + ph[nHits]; + wrh[nHits] = double(1.0/(assignedhit->getResolutionRPhi()*assignedhit->getResolutionRPhi())); + wzh[nHits] = 1.0/(assignedhit->getResolutionZ()*assignedhit->getResolutionZ()); + + int NPT = nHits + 1; + int iopt = 2; + float chi2RPhi; + float chi2Z; + + //debug() << "######## number of hits to fit with _fastfitter = " << NPT << endmsg; + + _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z); + par[3] = par[3]*par[0]/fabs(par[0]); + + + delete[] xh; + delete[] yh; + delete[] zh; + delete[] wrh; + delete[] wzh; + delete[] rh; + delete[] ph; + + bool validCombination = 0; + float Chi2 = FLT_MAX; + + if ((nHits+1) == 4) { + Chi2 = chi2RPhi*_chi2WRPhiQuartet+chi2Z*_chi2WZQuartet; + } + if ((nHits+1) >= 5) { + Chi2 = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet; + } + int ndf = 2*NPT-5; + + // check if this is valid combination based on the chi2/ndf + validCombination = Chi2/float(ndf) < _chi2FitCut; + + if ( validCombination ) { + // assign hit to track and track to hit, update the track parameters + trackAR->addTrackerHitExtended(assignedhit); + assignedhit->addTrackExtended(trackAR); + float omega = par[0]; + float tanlambda = par[1]; + float phi0 = par[2]; + float d0 = par[3]; + float z0 = par[4]; + helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField); + trackAR->setD0(d0); + trackAR->setZ0(z0); + trackAR->setPhi(phi0); + trackAR->setTanLambda(tanlambda); + trackAR->setOmega(omega); + trackAR->setChi2( Chi2 ); + trackAR->setCovMatrix(epar); + trackAR->setNDF( ndf ); + } + + } + } // endloop over remaining layers + TrackerHitExtendedVec& hvec = trackAR->getTrackerHitExtendedVec(); + int nTotalHits = int(hvec.size()); + debug() << "######## number of hits to return = " << nTotalHits << endmsg; + return nTotalHits; +} + + +void SiliconTrackingAlg::Sorting(TrackExtendedVec & trackVec) { + /** + Sorting of Track Vector in ascending order of chi2/ndf + */ + + std::sort(trackVec.begin(), trackVec.end(), compare_TrackExtended() ); + + // also clean up? what does this do here? + for (size_t i=0, sizeOfVector=trackVec.size(); i<sizeOfVector; ++i) { + + TrackerHitExtendedVec& hitVec = trackVec[i]->getTrackerHitExtendedVec(); + int nHits = int(hitVec.size()); + + for (int ih=0;ih<nHits;ih++) { + hitVec[ih]->clearTrackVec(); + } + } + +} + +void SiliconTrackingAlg::CreateTrack(TrackExtended * trackAR ) { + + /** + Method which creates Track out of TrackExtended objects. Checks for possible + track splitting (separate track segments in VXD and FTD). + */ + + + TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec(); + int nHits = int(hitVec.size()); + + for (int i=0; i<nHits; ++i) { + TrackExtendedVec& trackVec = hitVec[i]->getTrackExtendedVec(); + if (trackVec.size() != 0) + return ; + } + + // First check if the current track is piece of the split one + // look for matching track segment + + int found = 0; + + int nTrk = int(_trackImplVec.size()); + + for (int itrk=0; itrk<nTrk; ++itrk) { + TrackExtended * trackOld = _trackImplVec[itrk]; + TrackerHitExtendedVec& hitVecOld = trackOld->getTrackerHitExtendedVec(); + + float phiNew = trackAR->getPhi(); + float phiOld = trackOld->getPhi(); + float thetaNew = M_PI_2 - atan(trackAR->getTanLambda()); + float thetaOld = M_PI_2 - atan(trackOld->getTanLambda()); + + float angle = (cos(phiNew)*cos(phiOld)+sin(phiNew)*sin(phiOld))*sin(thetaNew)*sin(thetaOld)+cos(thetaNew)*cos(thetaOld); + angle = acos(angle); + + if (angle < _angleCutForMerging) { + int nHitsOld = int(hitVecOld.size()); + int nTotHits = nHits + nHitsOld; + double * xh = new double[nTotHits]; + double * yh = new double[nTotHits]; + float * zh = new float[nTotHits]; + double * wrh = new double[nTotHits]; + float * wzh = new float[nTotHits]; + float * rh = new float[nTotHits]; + float * ph = new float[nTotHits]; + float par[5]; + float epar[15]; + float refPoint[3] = {0.,0.,0.}; + for (int ih=0;ih<nHits;++ih) { + edm4hep::TrackerHit * trkHit = hitVec[ih]->getTrackerHit(); + float rR = hitVec[ih]->getResolutionRPhi(); + float rZ = hitVec[ih]->getResolutionZ(); + if (int(hitVec[ih]->getTrackExtendedVec().size()) != 0) + debug() << "WARNING : HIT POINTS TO TRACK " << endmsg; + xh[ih] = trkHit->getPosition()[0]; + yh[ih] = trkHit->getPosition()[1]; + zh[ih] = float(trkHit->getPosition()[2]); + wrh[ih] = double(1.0/(rR*rR)); + wzh[ih] = 1.0/(rZ*rZ); + rh[ih] = float(sqrt(xh[ih]*xh[ih]+yh[ih]*yh[ih])); + ph[ih] = float(atan2(yh[ih],xh[ih])); + } + for (int ih=0;ih<nHitsOld;++ih) { + edm4hep::TrackerHit * trkHit = hitVecOld[ih]->getTrackerHit(); + xh[ih+nHits] = trkHit->getPosition()[0]; + yh[ih+nHits] = trkHit->getPosition()[1]; + zh[ih+nHits] = float(trkHit->getPosition()[2]); + float rR = hitVecOld[ih]->getResolutionRPhi(); + float rZ = hitVecOld[ih]->getResolutionZ(); + wrh[ih+nHits] = double(1.0/(rR*rR)); + wzh[ih+nHits] = 1.0/(rZ*rZ); + rh[ih+nHits] = float(sqrt(xh[ih+nHits]*xh[ih+nHits]+yh[ih+nHits]*yh[ih+nHits])); + ph[ih+nHits] = float(atan2(yh[ih+nHits],xh[ih+nHits])); + + } + int NPT = nTotHits; + int iopt = 2; + float chi2RPhi; + float chi2Z; + int ndf = 2*NPT - 5; + + _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z); + par[3] = par[3]*par[0]/fabs(par[0]); + + float omega = par[0]; + float tanlambda = par[1]; + float phi0 = par[2]; + float d0 = par[3]; + float z0 = par[4]; + + float eparmin[15]; + for (int iparam=0;iparam<15;++iparam) + eparmin[iparam] = epar[iparam]; + + float refPointMin[3]; + for (int ipp=0;ipp<3;++ipp) + refPointMin[ipp] = refPoint[ipp]; + + float chi2Min = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet; + chi2Min = chi2Min/float(ndf); + + float chi2MinRPhi = chi2RPhi; + float chi2MinZ = chi2Z; + + int iBad = -1; + if (chi2Min < _chi2FitCut) { + found = 1; + } + else { // SJA:FIXME: UH What is going on here? setting weights to 0 and refitting? + float * wzhOld = new float[nTotHits]; + double * wrhOld = new double[nTotHits]; + for (int i=0;i<nTotHits;++i) { + wzhOld[i] = wzh[i]; + wrhOld[i] = wrh[i]; + } + for (int i=0; i<nTotHits; ++i) { + for (int j=0;j<nTotHits;++j) { + if (i == j) { + wrh[j] = 0.0; + wzh[j] = 0.0; + } + else { + wrh[j] = wrhOld[j]; + wzh[j] = wzhOld[j]; + } + } + + _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z); + par[3] = par[3]*par[0]/fabs(par[0]); + + float chi2Cur = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet; + chi2Cur = chi2Cur/float(ndf); + + if (chi2Cur < chi2Min) { + chi2Min = chi2Cur; + chi2MinRPhi = chi2RPhi; + chi2MinZ = chi2Z; + omega = par[0]; + tanlambda = par[1]; + phi0 = par[2]; + d0 = par[3]; + z0 = par[4]; + for (int iparam=0;iparam<15;++iparam) + eparmin[iparam] = epar[iparam]; + for (int ipp=0;ipp<3;++ipp) + refPointMin[ipp] = refPoint[ipp]; + iBad = i; + } + } + if (chi2Min < _chi2FitCut) { + found = 1; + } + delete[] wzhOld; + delete[] wrhOld; + } + + // Split track is found. + // Attach hits belonging to the current track segment to + // the track already created + if (found == 1) { + trackOld->ClearTrackerHitExtendedVec(); + for (int i=0;i<nHits;++i) { + TrackerHitExtended * trkHit = hitVec[i]; + trkHit->clearTrackVec(); + if (i == iBad) { + } + else { + trackOld->addTrackerHitExtended(trkHit); + trkHit->addTrackExtended( trackOld ); + } + } + for (int i=0;i<nHitsOld;++i) { + int icur = i+nHits; + TrackerHitExtended * trkHit = hitVecOld[i]; + trkHit->clearTrackVec(); + if (icur == iBad) { + } + else { + trackOld->addTrackerHitExtended(trkHit); + trkHit->addTrackExtended( trackOld ); + } + } + trackOld->setOmega(omega); + trackOld->setTanLambda(tanlambda); + trackOld->setPhi(phi0); + trackOld->setD0(d0); + trackOld->setZ0(z0); + + //debug() << "Split track found " << d0 << " " << z0 << endmsg; + + // killeb: In the original SiliconTrackingAlg this was in the NOT simple helix branch. + // The rest of the code uses the simple helix branch, where ndf_D is never set. + // In fact it has never been initialised or used anywhere. I think this line should not be executed. + // ndf = ndf_D; + + trackOld->setChi2(chi2Min*float(ndf)); + trackOld->setNDF(ndf); + trackOld->setCovMatrix(eparmin); + // trackOld->setReferencePoint(refPointMin); + } + + delete[] xh; + delete[] yh; + delete[] zh; + delete[] wrh; + delete[] wzh; + delete[] rh; + delete[] ph; + + } + if (found == 1) + break; + } + + // Candidate is a unique track + // No other segments are found + if (found == 0 ) { + _trackImplVec.push_back(trackAR); + for (int i=0;i<nHits;++i) { + TrackerHitExtended * hit = hitVec[i]; + hit->addTrackExtended( trackAR ); + } + } + + +} + +void SiliconTrackingAlg::AttachRemainingVTXHitsFast() { + + std::vector<TrackerHitExtendedVec> nonAttachedHits; + nonAttachedHits.resize(_nDivisionsInPhi*_nDivisionsInTheta); + std::vector<TrackExtendedVec> trackVector; + trackVector.resize(_nDivisionsInPhi*_nDivisionsInTheta); + int nTracks = int(_trackImplVec.size()); + + for (int iTrk=0;iTrk<nTracks;++iTrk) { + TrackExtended * track = _trackImplVec[iTrk]; + double Phi = double(track->getPhi()); + if (Phi < 0) + Phi = Phi + TWOPI; + float tanlambda = track->getTanLambda(); + double cosTheta = double(tanlambda/sqrt(1+tanlambda*tanlambda)); + int iPhi = int(Phi/_dPhi); + int iTheta = int ((cosTheta + double(1.0))/_dTheta); + int iCode = iPhi + _nDivisionsInPhi*iTheta; + trackVector[iCode].push_back( track ); + } + + for (int il=0;il<_nLayers;++il) { + for (int ip=0;ip<_nDivisionsInPhi;++ip) { + for (int it=0;it<_nDivisionsInTheta; ++it) { + int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it; + TrackerHitExtendedVec& hitVec = _sectors[iCode]; + int nH = int(hitVec.size()); + for (int iH=0; iH<nH; ++iH) { + TrackerHitExtended * hitExt = hitVec[iH]; + TrackExtendedVec& trackVec = hitExt->getTrackExtendedVec(); + if (trackVec.size()==0) { + edm4hep::TrackerHit * hit = hitExt->getTrackerHit(); + double pos[3]; + double radius = 0; + for (int i=0; i<3; ++i) { + pos[i] = hit->getPosition()[i]; + radius += pos[i]*pos[i]; + } + radius = sqrt(radius); + double cosTheta = pos[2]/radius; + double Phi = atan2(pos[1],pos[0]); + if (Phi < 0.) Phi = Phi + TWOPI; + int iPhi = int(Phi/_dPhi); + int iTheta = int ((cosTheta + double(1.0))/_dTheta); + iCode = iPhi + _nDivisionsInPhi*iTheta; + nonAttachedHits[iCode].push_back( hitExt ); + } + } + } + } + } + + for (int iT=0; iT<_nDivisionsInTheta; ++iT) { + for (int iP=0; iP<_nDivisionsInPhi; ++iP) { + int iCode = iP + _nDivisionsInPhi*iT; + int nHits = int(nonAttachedHits[iCode].size()); + int iT1 = iT - 1; + int iT2 = iT + 1; + if (iT == 0) { + iT1 = iT; + iT2 = iT1 + 1; + } + if (iT == _nDivisionsInTheta - 1) { + iT2 = iT; + iT1 = iT2 - 1; + } + int iPHI[3]; + iPHI[0] = iP - 1; + iPHI[1] = iP; + iPHI[2] = iP + 1; + if (iP == 0) + iPHI[0] = _nDivisionsInPhi - 1; + if (iP == _nDivisionsInPhi - 1 ) + iPHI[2] = 0; + + for (int ihit = 0; ihit<nHits; ++ihit) { + + TrackerHitExtended * hit = nonAttachedHits[iCode][ihit]; + TrackExtended * trackToAttach = NULL; + float minDist = 1.0e+6; + + for (int iTheta = iT1; iTheta <iT2+1; ++iTheta) { + for (int indexP=0;indexP<3;++indexP) { + int iPhi = iPHI[indexP]; + int iCodeForTrack = iPhi + _nDivisionsInPhi*iTheta; + int nTrk = int(trackVector[iCodeForTrack].size()); + for (int iTrk=0; iTrk<nTrk; ++iTrk) { + TrackExtended * trackAR = trackVector[iCodeForTrack][iTrk]; + bool consider = true; + if (_checkForDelta) { + TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec(); + int NHITS = int(hitVector.size()); + for (int IHIT=0;IHIT<NHITS;++IHIT) { + + // Here we are trying to find if a hits are too close i.e. closer than _minDistToDelta + edm4hep::TrackerHit* trkhit1 = hit->getTrackerHit(); + edm4hep::TrackerHit* trkhit2 = hitVector[IHIT]->getTrackerHit(); + + if ( trkhit1->getCellID() == trkhit2->getCellID() ){ // i.e. they are in the same sensor + float distance = 0.; + for (int iC=0;iC<3;++iC) { + float posFirst = float(hit->getTrackerHit()->getPosition()[iC]); + float posSecond = float(hitVector[IHIT]->getTrackerHit()->getPosition()[iC]); + float deltaPos = posFirst - posSecond; + distance += deltaPos*deltaPos; + } + distance = sqrt(distance); + if (distance<_minDistToDelta) { + consider = false; + break; + } + } + } + } + if (consider) { + float phi0 = trackAR->getPhi(); + float d0 = trackAR->getD0(); + float z0 = trackAR->getZ0(); + float omega = trackAR->getOmega(); + float tanlambda = trackAR->getTanLambda(); + HelixClass helix; + helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField); + int layer = getLayerID(hit->getTrackerHit()); + if (layer > _minimalLayerToAttach) { + float pos[3]; + for (int i=0; i<3; ++i) + pos[i] = hit->getTrackerHit()->getPosition()[i]; + float distance[3]; + float time = helix.getDistanceToPoint(pos,distance); + if (time < 1.0e+10) { + if (distance[2] < minDist) { + minDist = distance[2]; + trackToAttach = trackAR; + } + } + } + } + } + } + } + if (minDist < _minDistCutAttach && trackToAttach != NULL) { + int iopt = 2; + AttachHitToTrack(trackToAttach,hit,iopt); + } + } + } + } +} + +void SiliconTrackingAlg::AttachRemainingVTXHitsSlow() { + + TrackerHitExtendedVec nonAttachedHits; + nonAttachedHits.clear(); + + for (int il=0;il<_nLayers;++il) { + for (int ip=0;ip<_nDivisionsInPhi;++ip) { + for (int it=0;it<_nDivisionsInTheta; ++it) { + int iCode = il + _nLayers*ip + _nLayers*_nDivisionsInPhi*it; + TrackerHitExtendedVec& hitVec = _sectors[iCode]; + int nH = int(hitVec.size()); + for (int iH=0; iH<nH; ++iH) { + TrackerHitExtended * hit = hitVec[iH]; + TrackExtendedVec& trackVec = hit->getTrackExtendedVec(); + // if (trackVec.size()==0) + // nonAttachedHits.push_back( hit ); + //-- allow hits that are only used in triplets to be re-attached + unsigned int maxTrackSize = 0; + for(unsigned int itrack = 0;itrack < trackVec.size();itrack++){ + TrackerHitExtendedVec hitVec_tmp= trackVec[itrack]->getTrackerHitExtendedVec(); + unsigned int isize = hitVec_tmp.size(); + if(isize>maxTrackSize)maxTrackSize = isize; + } + if (maxTrackSize<=3) { + debug() << " Add non attached hit to list: id = " << hit->getTrackerHit()->id() << endmsg; + nonAttachedHits.push_back( hit ); + } + + + } + } + } + } + + int nNotAttached = int(nonAttachedHits.size()); + + int nTrk = int(_trackImplVec.size()); + for (int iHit=0; iHit<nNotAttached; ++iHit) { + TrackerHitExtended * hit = nonAttachedHits[iHit]; + debug() << " Try hit: id = " << hit->getTrackerHit()->id() << endmsg; + int layer = getLayerID( hit->getTrackerHit() ); + if (layer > _minimalLayerToAttach) { + float pos[3]; + for (int i=0; i<3; ++i) + pos[i] = hit->getTrackerHit()->getPosition()[i]; + float minDist = 1e+10; + TrackExtended * trackToAttach = NULL; + for (int iTrk=0; iTrk<nTrk; ++iTrk) { + TrackExtended * trackAR = _trackImplVec[iTrk]; + bool consider = true; + if (_checkForDelta) { + TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec(); + int NHITS = int(hitVector.size()); + for (int IHIT=0;IHIT<NHITS;++IHIT) { + + // Here we are trying to find if a hits are too close i.e. closer than _minDistToDelta + edm4hep::TrackerHit* trkhit1 = hit->getTrackerHit(); + edm4hep::TrackerHit* trkhit2 = hitVector[IHIT]->getTrackerHit(); + + if ( trkhit1->getCellID() == trkhit2->getCellID() ){ // i.e. they are in the same sensor + + float distance = 0.; + for (int iC=0;iC<3;++iC) { + float posFirst = float(hit->getTrackerHit()->getPosition()[iC]); + float posSecond = float(hitVector[IHIT]->getTrackerHit()->getPosition()[iC]); + float deltaPos = posFirst - posSecond; + distance += deltaPos*deltaPos; + } + distance = sqrt(distance); + if (distance<_minDistToDelta) { + consider = false; + debug() << " hit: id = " << hit->getTrackerHit()->id() << " condsidered delta together with hit " << trkhit2->id() << endmsg; + break; + } + } + } + } + if (consider) { + HelixClass helix; + float phi0 = trackAR->getPhi(); + float d0 = trackAR->getD0(); + float z0 = trackAR->getZ0(); + float omega = trackAR->getOmega(); + float tanlambda = trackAR->getTanLambda(); + helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField); + float distance[3]; + float time = helix.getDistanceToPoint(pos,distance); + if (time < 1.0e+10) { + if (distance[2] < minDist) { + minDist = distance[2]; + trackToAttach = trackAR; + } + } + } + } + if (minDist < _minDistCutAttach && trackToAttach != NULL) { + int iopt = 2; + debug() << " Hit: id = " << hit->getTrackerHit()->id() << " : try attachement"<< endmsg; + AttachHitToTrack(trackToAttach,hit,iopt); + } else { + debug() << " Hit: id = " << hit->getTrackerHit()->id() << " rejected due to distance cut of " <<_minDistCutAttach<< " min distance = " << minDist << endmsg; + } + } + } +} + +void SiliconTrackingAlg::AttachRemainingFTDHitsSlow() { + TrackerHitExtendedVec nonAttachedHits; + nonAttachedHits.clear(); + + for (int iS=0;iS<2;++iS) { + for (unsigned int layer=0;layer<_nlayersFTD;++layer) { + for (int ip=0;ip<_nDivisionsInPhiFTD;++ip) { + int iCode = iS + 2*layer + 2*_nlayersFTD*ip; + TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode]; + int nH = int(hitVec.size()); + for (int iH=0; iH<nH; ++iH) { + TrackerHitExtended * hit = hitVec[iH]; + TrackExtendedVec& trackVec = hit->getTrackExtendedVec(); + if (trackVec.size()==0) + nonAttachedHits.push_back( hit ); + } + } + } + } + + int nNotAttached = int(nonAttachedHits.size()); + + int nTrk = int(_trackImplVec.size()); + for (int iHit=0; iHit<nNotAttached; ++iHit) { + TrackerHitExtended * hit = nonAttachedHits[iHit]; + float pos[3]; + for (int i=0; i<3; ++i) + pos[i] = hit->getTrackerHit()->getPosition()[i]; + float minDist = 1e+10; + TrackExtended * trackToAttach = NULL; + for (int iTrk=0; iTrk<nTrk; ++iTrk) { + TrackExtended * trackAR = _trackImplVec[iTrk]; + bool consider = true; + TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec(); + int NHITS = int(hitVector.size()); + + for (int IHIT=0;IHIT<NHITS;++IHIT) { + + // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works + // if (hit->getTrackerHit()->getType() == hitVector[IHIT]->getTrackerHit()->getType()) { + if (hit->getTrackerHit()->getCellID() == hitVector[IHIT]->getTrackerHit()->getCellID()) { + + consider = false; + break; + } + } + + + if (consider) { + HelixClass helix; + float phi0 = trackAR->getPhi(); + float d0 = trackAR->getD0(); + float z0 = trackAR->getZ0(); + float omega = trackAR->getOmega(); + float tanlambda = trackAR->getTanLambda(); + if (tanlambda*float(getSideID(hit->getTrackerHit())) > 0) { + helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField); + float distance[3]; + float time = helix.getDistanceToPoint(pos,distance); + if (time < 1.0e+10) { + if (distance[2] < minDist) { + minDist = distance[2]; + trackToAttach = trackAR; + } + } + } + } + } + if (minDist < _minDistCutAttach && trackToAttach != NULL) { + int iopt = 2; + AttachHitToTrack(trackToAttach,hit,iopt); + } + } +} + + +void SiliconTrackingAlg::AttachRemainingFTDHitsFast() { + int nTrk = _trackImplVec.size(); + + for (int iTrk=0; iTrk<nTrk; ++iTrk) { + TrackExtended * trackAR = _trackImplVec[iTrk]; + HelixClass helix; + float phi0 = trackAR->getPhi(); + float d0 = trackAR->getD0(); + float z0 = trackAR->getZ0(); + float omega = trackAR->getOmega(); + float tanlambda = trackAR->getTanLambda(); + helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField); + int iSemiSphere = 0; + if (tanlambda > 0) + iSemiSphere = 1; + float ref[3]; + for (int i=0;i<3;++i) + ref[i] = helix.getReferencePoint()[i]; + // Start loop over FTD layers + for (unsigned int layer=0;layer<_nlayersFTD;layer++) { + float ZL = _zLayerFTD[layer]; + if (iSemiSphere == 0) + ZL = - ZL; + float point[3]; + helix.getPointInZ(ZL,ref,point); + float Phi = atan2(point[1],point[0]); + if (Phi < 0) + Phi = Phi + TWOPI; + int iPhi = int(Phi/_dPhiFTD); + float distMin = 1e+10; + TrackerHitExtended * attachedHit = NULL; + for (int iP=iPhi-1;iP<=iPhi+1;++iP) { + int iPP = iP; + if (iP < 0) + iPP = iP + _nDivisionsInPhiFTD; + if (iP >= _nDivisionsInPhiFTD) + iPP = iP - _nDivisionsInPhiFTD; + int iCode = iSemiSphere + 2*layer + 2*_nlayersFTD*iPP; + int nHits = int(_sectorsFTD[iCode].size()); + for (int iHit=0;iHit<nHits;++iHit) { + TrackerHitExtended * hit = _sectorsFTD[iCode][iHit]; + bool consider = true; + TrackerHitExtendedVec& hitVector = trackAR->getTrackerHitExtendedVec(); + int NHITS = int(hitVector.size()); + + // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works + for (int IHIT=0;IHIT<NHITS;++IHIT) { + // if (hit->getTrackerHit()->getType() == hitVector[IHIT]->getTrackerHit()->getType()) { + if (hit->getTrackerHit()->getCellID() == hitVector[IHIT]->getTrackerHit()->getCellID()) { + consider = false; + break; + } + } + + + if (consider) { + float pos[3]; + for (int i=0;i<3;++i) { + pos[i] = hit->getTrackerHit()->getPosition()[i]; + } + float distance[3]; + float time = helix.getDistanceToPoint(pos,distance); + if (time < 1.0e+10) { + if (distance[2] < distMin) { + distMin = distance[2]; + attachedHit = hit; + } + } + } + } + } + if (distMin < _minDistCutAttach && attachedHit != NULL) { + int iopt = 2; + AttachHitToTrack(trackAR,attachedHit, iopt); + } + } + } +} + +void SiliconTrackingAlg::TrackingInFTD() { + + int nComb = int(_CombinationsFTD.size()) / 3; + + for (int iComb=0;iComb<nComb;++iComb) { + + int nLS[3]; + nLS[0] = _CombinationsFTD[3*iComb]; + nLS[1] = _CombinationsFTD[3*iComb+1]; + nLS[2] = _CombinationsFTD[3*iComb+2]; + + for (int iS=0;iS<2;++iS) { // loop over +z and -z + + // std::cout << "Combinations : " << iS << " " << nLS[0] << " " << nLS[1] << " " << nLS[2] << endmsg; + // int iC = iS + 2*nLS[0]; + // TrackerHitExtendedVec& hitVec = _sectorsFTD[iC]; + // int nO = int(hitVec.size()); + // iC = iS + 2*nLS[1]; + // hitVec = _sectorsFTD[iC]; + // int nM = int(hitVec.size()); + // iC = iS + 2*nLS[2]; + // hitVec = _sectorsFTD[iC]; + // int nI = int(hitVec.size()); + // std::cout << nO << " " << nM << " " << nI << endmsg; + + for (int ipOuter=0;ipOuter<_nDivisionsInPhiFTD;++ipOuter) { + + int ipMiddleLow = ipOuter - 1; + int ipMiddleUp = ipOuter + 1; + + unsigned int iCodeOuter = iS + 2*nLS[0] + 2*_nlayersFTD*ipOuter; + + if( iCodeOuter >= _sectorsFTD.size()){ + error() << "iCodeOuter index out of range: iCodeOuter = " << iCodeOuter << " _sectorsFTD.size() = " << _sectorsFTD.size() << " exit(1) called from file " << __FILE__ << " line " << __LINE__<< endmsg; + exit(1); + } + + TrackerHitExtendedVec& hitVecOuter = _sectorsFTD[iCodeOuter]; + + int nOuter = int(hitVecOuter.size()); + + for (int iOuter=0;iOuter<nOuter;++iOuter) { + + TrackerHitExtended * hitOuter = hitVecOuter[iOuter]; + + for (int ipMiddle=ipMiddleLow;ipMiddle<=ipMiddleUp;++ipMiddle) { + //for(int ipMiddle=0;ipMiddle<_nDivisionsInPhiFTD;++ipMiddle) { + int ipM = ipMiddle; + if (ipM < 0) + ipM = ipMiddle + _nDivisionsInPhiFTD; + if (ipM >= _nDivisionsInPhiFTD) + ipM = ipMiddle - _nDivisionsInPhiFTD; + int iCodeMiddle = iS + 2*nLS[1] + 2*_nlayersFTD*ipM; + + TrackerHitExtendedVec& hitVecMiddle = _sectorsFTD[iCodeMiddle]; + int ipInnerLow,ipInnerUp; + ipInnerLow = ipMiddle - 1; + ipInnerUp = ipMiddle + 1; + + int nMiddle = int(hitVecMiddle.size()); + + for (int iMiddle=0;iMiddle<nMiddle;++iMiddle) { + TrackerHitExtended * hitMiddle = hitVecMiddle[iMiddle]; + for (int ipInner=ipInnerLow;ipInner<=ipInnerUp;++ipInner) { + //for (int ipInner=0;ipInner<_nDivisionsInPhiFTD;++ipInner) { + int ipI = ipInner; + if (ipI < 0) + ipI = ipInner + _nDivisionsInPhiFTD; + if (ipI >= _nDivisionsInPhiFTD) + ipI = ipInner - _nDivisionsInPhiFTD; + int iCodeInner = iS + 2*nLS[2] + 2*_nlayersFTD*ipI; + TrackerHitExtendedVec& hitVecInner = _sectorsFTD[iCodeInner]; + + int nInner = int(hitVecInner.size()); + + for (int iInner=0;iInner<nInner;++iInner) { + + TrackerHitExtended * hitInner = hitVecInner[iInner]; + HelixClass helix; + // std::cout << endmsg; + // std::cout << "Outer Hit Type " << hitOuter->getTrackerHit()->getType() << " z = " << hitOuter->getTrackerHit()->getPosition()[2] + // << "\nMiddle Hit Type "<< hitMiddle->getTrackerHit()->getType() << " z = " << hitMiddle->getTrackerHit()->getPosition()[2] + // << "\nInner Hit Type "<< hitInner->getTrackerHit()->getType() << " z = " << hitInner->getTrackerHit()->getPosition()[2] << endmsg; + + debug() << " " + << std::setw(3) << ipOuter << " " << std::setw(3) << ipMiddle << " " << std::setw(3) << ipInner << " " + << std::setw(3) << iS << " " + << std::setw(3) << nLS[0] << " " << std::setw(3) << nLS[1] << " " << std::setw(3) << nLS[2] << " " + << std::setw(3) << nOuter << " : " << std::setw(3) << nMiddle << " : " << std::setw(3) << nInner << " :: " + << std::setw(3) << nOuter*nMiddle* nInner << endmsg; + + + TrackExtended * trackAR = TestTriplet(hitOuter,hitMiddle,hitInner,helix); + if (trackAR != NULL) { + // std::cout << "FTD triplet found" << endmsg; + int nHits = BuildTrackFTD(trackAR,nLS,iS); + + _tracksWithNHitsContainer.getTracksWithNHitsVec( nHits ).push_back( trackAR ); + } + } + } + } + } + } + } + } + } +} + + +int SiliconTrackingAlg::BuildTrackFTD(TrackExtended * trackAR, int * nLR, int iS) { + // std::cout << "BuildTrackFTD: Layers = " << nLR[0] << " " << nLR[1] << " " << nLR[2] << endmsg; + + // initialise a helix from the track + HelixClass helix; + const float d0 = trackAR->getD0(); + const float z0 = trackAR->getZ0(); + const float phi0 = trackAR->getPhi(); + const float tanlambda = trackAR->getTanLambda(); + const float omega = trackAR->getOmega(); + helix.Initialize_Canonical(phi0,d0,z0,omega,tanlambda,_bField); + float ref[3] = {helix.getReferencePoint()[0], + helix.getReferencePoint()[1], + helix.getReferencePoint()[2]}; + + for (int iL=0; iL < static_cast<int>(_nlayersFTD); ++iL) { + if (iL != nLR[0] && iL != nLR[1] && iL != nLR[2]) { + float point[3]; + float ZL = _zLayerFTD[iL]; + if (iS == 0) + ZL = - ZL; + helix.getPointInZ(ZL,ref,point); + // float Phi = atan2(point[1],point[0]); + // int iPhi = int(Phi/_dPhiFTD); + float distMin = 1e+6; + TrackerHitExtended * attachedHit = NULL; + for (int ip=0;ip<=_nDivisionsInPhiFTD;++ip) { + int iP = ip; + if (iP < 0) + iP = ip + _nDivisionsInPhiFTD; + if (iP >= _nDivisionsInPhiFTD) + iP = ip - _nDivisionsInPhiFTD; + int iCode = iS + 2*iL + 2*_nlayersFTD*iP; + TrackerHitExtendedVec& hitVec = _sectorsFTD[iCode]; + int nH = int(hitVec.size()); + for (int iH=0; iH<nH; ++iH) { + TrackerHitExtended * hit = hitVec[iH]; + edm4hep::TrackerHit * trkHit = hit->getTrackerHit(); + float pos[3]; + for (int i=0;i<3;++i) + pos[i] = float(trkHit->getPosition()[i]); + float distance[3]; + float time = helix.getDistanceToPoint(pos,distance); + if (time < 1.0e+10) { + if (distance[2] < distMin) { + distMin = distance[2]; + attachedHit = hit; + } + } + } + } + // std::cout << "Layer = " << iL << " distMin = " << distMin << endmsg; + if (distMin < _minDistCutAttach && attachedHit != NULL) { + int iopt = 2; + AttachHitToTrack( trackAR, attachedHit, iopt); + } + } + } + TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec(); + int nH = int (hitVec.size()); + return nH; +} + +int SiliconTrackingAlg::AttachHitToTrack(TrackExtended * trackAR, TrackerHitExtended * hit, int iopt) { + + int attached = 0; + TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec(); + int nHits = int(hitVec.size()); + + double * xh = new double[nHits+1]; + double * yh = new double[nHits+1]; + float * zh = new float[nHits+1]; + double * wrh = new double[nHits+1]; + float * wzh = new float[nHits+1]; + float * rh = new float[nHits+1]; + float * ph = new float[nHits+1]; + float par[5]; + float epar[15]; + + for (int i=0; i<nHits; ++i) { + edm4hep::TrackerHit * trkHit = hitVec[i]->getTrackerHit(); + xh[i] = double(trkHit->getPosition()[0]); + yh[i] = double(trkHit->getPosition()[1]); + zh[i] = float(trkHit->getPosition()[2]); + ph[i] = float(atan2(yh[i],xh[i])); + rh[i] = float(sqrt(xh[i]*xh[i]+yh[i]*yh[i])); + float rR = hitVec[i]->getResolutionRPhi(); + float rZ = hitVec[i]->getResolutionZ(); + wrh[i] = double(1.0/(rR*rR)); + wzh[i] = 1.0/(rZ*rZ); + } + + edm4hep::TrackerHit * trkHit = hit->getTrackerHit(); + xh[nHits] = double(trkHit->getPosition()[0]); + yh[nHits] = double(trkHit->getPosition()[1]); + zh[nHits] = float(trkHit->getPosition()[2]); + ph[nHits] = float(atan2(yh[nHits],xh[nHits])); + rh[nHits] = float(sqrt(xh[nHits]*xh[nHits]+yh[nHits]*yh[nHits])); + + float rR = hit->getResolutionRPhi(); + float rZ = hit->getResolutionZ(); + wrh[nHits] = double(1.0/(rR*rR)); + wzh[nHits] = 1.0/(rZ*rZ); + + + int NPT = nHits + 1; + + // SJA:FIXME the newtonian part is giving crazy results for FTD so just use iopt 2 for simply attaching hits + // using SIT and VXD doesn't seem to give any problems, so make it a function parameter and let the caller decide + // int iopt = 3; + + float chi2RPhi = 0 ; + float chi2Z = 0 ; + + + int error = _fastfitter->fastHelixFit(NPT, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z); + par[3] = par[3]*par[0]/fabs(par[0]); + + + float omega = par[0]; + float tanlambda = par[1]; + float phi0 = par[2]; + float d0 = par[3]; + float z0 = par[4]; + float chi2 = FLT_MAX; + int ndf = INT_MAX; + + if (NPT == 3) { + chi2 = chi2RPhi*_chi2WRPhiTriplet+chi2Z*_chi2WZTriplet; + } + if (NPT == 4) { + chi2 = chi2RPhi*_chi2WRPhiQuartet+chi2Z*_chi2WZQuartet; + } + if (NPT > 4) { + chi2 = chi2RPhi*_chi2WRPhiSeptet+chi2Z*_chi2WZSeptet; + } + ndf = 2*NPT-5; + + + if ( error == 0 && chi2/float(ndf) < _chi2FitCut ) { + trackAR->addTrackerHitExtended(hit); + hit->addTrackExtended( trackAR ); + trackAR->setChi2( chi2 ); + trackAR->setOmega( omega ); + trackAR->setTanLambda( tanlambda ); + trackAR->setD0( d0 ); + trackAR->setZ0( z0 ); + trackAR->setPhi( phi0 ); + trackAR->setNDF( ndf ); + trackAR->setCovMatrix( epar ); + attached = 1; + debug() << "Attachement succeeded chi2/float(ndf) = " << chi2/float(ndf) << " cut = " << _chi2FitCut << " chi2RPhi = " << chi2RPhi << " chi2Z = " << chi2Z << " error = " << error << endmsg; + } else { + debug() << "Attachement failed chi2/float(ndf) = " << chi2/float(ndf) << " cut = " << _chi2FitCut << " chi2RPhi = " << chi2RPhi << " chi2Z = " << chi2Z << " error = " << error << endmsg; + } + + delete[] xh; + delete[] yh; + delete[] zh; + delete[] wrh; + delete[] wzh; + delete[] rh; + delete[] ph; + + return attached; + + +} + +void SiliconTrackingAlg::FinalRefit(edm4hep::TrackCollection* trk_col) { + + int nTracks = int(_trackImplVec.size()); + + int nSiSegments = 0; + float eTot = 0.; + float pxTot = 0.; + float pyTot = 0.; + float pzTot = 0.; + debug() << "Total " << nTracks << " candidate tracks will be dealed" << endmsg; + for (int iTrk=0;iTrk<nTracks;++iTrk) { + + TrackExtended * trackAR = _trackImplVec[iTrk]; + TrackerHitExtendedVec& hitVec = trackAR->getTrackerHitExtendedVec(); + + int nHits = int(hitVec.size()); + //debug() << " Track " << iTrk << " has hits: " << nHits << endmsg; + if( nHits >= _minimalHits) { + // int * lh = new int[nHits]; + std::vector<int> lh; + lh.resize(nHits); + + for (int i=0; i<nHits; ++i) { + lh[i]=0; + } + + float d0 = trackAR->getD0(); + float z0 = trackAR->getZ0(); + float omega = trackAR->getOmega(); + float tanlambda = trackAR->getTanLambda(); + float phi0 = trackAR->getPhi(); + + HelixClass * helix = new HelixClass(); + helix->Initialize_Canonical(phi0, d0, z0, omega, + tanlambda, _bField); + + // get the point of closest approach to the reference point + // here it is implicitly assumed that the reference point is the origin + float Pos[3]; + Pos[0] = -d0*sin(phi0); + Pos[1] = d0*cos(phi0); + Pos[2] = z0; + + // at this point is is possible to have hits from the same layer ... + // so a check is made to ensure that the hit with the smallest distance to the + // current helix hypothosis is used, the other hit has lh set to 0 + + // start loop over the hits to + for (int ihit=0;ihit<nHits;++ihit) { + + lh[ihit] = 1; // only hits which have lh=1 will be used for the fit + + // get the pointer to the lcio trackerhit for this hit + edm4hep::TrackerHit * trkHit = hitVec[ihit]->getTrackerHit(); + + int det = getDetectorID(trkHit); + + if (det == lcio::ILDDetID::VXD || det == lcio::ILDDetID::FTD || det == lcio::ILDDetID::SIT) { // only accept VXD, FTD or SIT + + + // int layer = getLayerID(trkHit); + // int moduleIndex = getModuleID(trkHit); + + // start a double loop over the hits which have already been checked + for (int lhit=0;lhit<ihit;++lhit) { + + // get the pointer to the lcio trackerhit for the previously checked hit + edm4hep::TrackerHit * trkHitS = hitVec[lhit]->getTrackerHit(); + + + // int layerS = getLayerID(trkHitS); + // int moduleIndexS = getModuleID(trkHitS); + + // SJA:FIXME: check to see if allowing no hits in the same sensor vs no hits in the same layer works + // if they are on the same layer and the previously checked hits has been declared good for fitting + // if ((trkHitS->getType() == trkHit->getType()) && (lh[lhit] == 1)) { + // check if the hits have the same layer and petal number + // hitVec[ihit]-> + // if ((layer == layerS) && (moduleIndex==moduleIndexS) && (lh[lhit] == 1)) { + if ( (trkHit->getCellID() == trkHitS->getCellID()) && (lh[lhit] == 1)) { + + // get the position of the hits + float xP[3]; + float xPS[3]; + for (int iC=0;iC<3;++iC) { + xP[iC] = float(trkHit->getPosition()[iC]); + xPS[iC] = float(trkHitS->getPosition()[iC]); + } + + // get the intersection of the helix with the either the cylinder or plane containing the hit + float Point[6]; + float PointS[6]; + + if (det == lcio::ILDDetID::FTD) { + + float time = helix->getPointInZ(xP[2],Pos,Point); + time = helix->getPointInZ(xPS[2],Pos,PointS); + + } else { + + float RAD = sqrt(xP[0]*xP[0]+xP[1]*xP[1]); + float RADS = sqrt(xPS[0]*xPS[0]+xPS[1]*xPS[1]); + float time = helix->getPointOnCircle(RAD,Pos,Point); + time = helix->getPointOnCircle(RADS,Pos,PointS); + + } + + float DIST = 0; + float DISTS = 0; + + // get the euclidean distance between the hit and the point of intersection + for (int iC=0;iC<3;++iC) { + DIST += (Point[iC]-xP[iC])*(Point[iC]-xP[iC]); + DISTS += (PointS[iC]-xPS[iC])*(PointS[iC]-xPS[iC]); + } + if (DIST < DISTS) { + lh[lhit] = 0; + } + else { + lh[ihit] = 0; + } + break; + } + } + } + } + + delete helix; + + std::vector<TrackerHit*> trkHits; + std::vector<TrackerHit*> trkHits_used_inFit; + + int nFit = 0; + for (int i=0; i<nHits; ++i) { + // check if the hit has been rejected as being on the same layer and further from the helix lh==0 + if (lh[i] == 1) { + edm4hep::TrackerHit * trkHit = hitVec[i]->getTrackerHit(); + debug() << "TrackerHit " << i << " address = " << trkHit << endmsg; + nFit++; + if(trkHit) { + trkHits.push_back(trkHit); + } + else{ + throw EVENT::Exception( std::string("SiliconTrackingAlg::FinalRefit: TrackerHit pointer == NULL ") ) ; + } + } + else { // reject hit + // SJA:FIXME missuse of type find a better way to signal rejected hits + hitVec[i]->setType(int(0)); + } + } + + if( trkHits.size() < 3 ) { + debug() << "SiliconTrackingAlg::FinalRefit: Cannot fit less than 3 hits. Number of hits = " << trkHits.size() << endmsg; + continue ; + } + //TrackImpl* Track = new TrackImpl ; + auto track = trk_col->create(); + //fucd + //edm4hep::Track track;// = new edm4hep::Track; + // setup initial dummy covariance matrix + //std::vector<float> covMatrix; + //covMatrix.resize(15); + std::array<float,15> covMatrix; + + for (unsigned icov = 0; icov<covMatrix.size(); ++icov) { + covMatrix[icov] = 0; + } + + covMatrix[0] = ( _initialTrackError_d0 ); //sigma_d0^2 + covMatrix[2] = ( _initialTrackError_phi0 ); //sigma_phi0^2 + covMatrix[5] = ( _initialTrackError_omega ); //sigma_omega^2 + covMatrix[9] = ( _initialTrackError_z0 ); //sigma_z0^2 + covMatrix[14] = ( _initialTrackError_tanL ); //sigma_tanl^2 + + + std::vector< std::pair<float, edm4hep::TrackerHit*> > r2_values; + r2_values.reserve(trkHits.size()); + + for (std::vector<edm4hep::TrackerHit*>::iterator it=trkHits.begin(); it!=trkHits.end(); ++it) { + edm4hep::TrackerHit* h = *it; + float r2 = h->getPosition()[0]*h->getPosition()[0]+h->getPosition()[1]*h->getPosition()[1]; + r2_values.push_back(std::make_pair(r2, *it)); + } + + sort(r2_values.begin(),r2_values.end()); + + trkHits.clear(); + trkHits.reserve(r2_values.size()); + + for (std::vector< std::pair<float, edm4hep::TrackerHit*> >::iterator it=r2_values.begin(); it!=r2_values.end(); ++it) { + trkHits.push_back(it->second); + } + //std::cout << "fucd------------------3 " << _trksystem << std::endl; + //for (unsigned ihit_indx=0 ; ihit_indx < trkHits.size(); ++ihit_indx) { + // std::cout << "fucd trk hit " << *trkHits[ihit_indx] << " " << trkHits[ihit_indx]->getCovMatrix()[0] + // << " " << BitSet32(trkHits[ihit_indx]->getType())[ ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] << endmsg; + //} + /* + auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc"); + if ( !_trackSystemSvc ) { + error() << "Failed to find TrackSystemSvc ..." << endmsg; + return; + } + _trksystem = _trackSystemSvc->getTrackSystem(); + + if( _trksystem == 0 ){ + error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg; + return; + } + debug() << "_trksystem pointer " << _trksystem << endmsg; + + _trksystem->setOption( IMarlinTrkSystem::CFG::useQMS, _MSOn ) ; + _trksystem->setOption( IMarlinTrkSystem::CFG::usedEdx, _ElossOn) ; + _trksystem->setOption( IMarlinTrkSystem::CFG::useSmoothing, _SmoothOn) ; + _trksystem->init() ; + */ + bool fit_backwards = IMarlinTrack::backward; + + MarlinTrk::IMarlinTrack* marlinTrk = nullptr; + try{ + marlinTrk = _trksystem->createTrack(); + } + catch(...){ + error() << "Cannot create MarlinTrack ! " << endmsg; + return; + } + + int status = 0; + debug() << "call createFinalisedLCIOTrack now" << endmsg; + try { + status = MarlinTrk::createFinalisedLCIOTrack(marlinTrk, trkHits, &track, fit_backwards, covMatrix, _bField, _maxChi2PerHit); + } catch (...) { + // delete Track; + // delete marlinTrk; + error() << "MarlinTrk::createFinalisedLCIOTrack fail" << endmsg; + //throw ; + } + debug() << "createFinalisedLCIOTrack finish" << endmsg; + /* +#ifdef MARLINTRK_DIAGNOSTICS_ON + if ( status != IMarlinTrack::success && _runMarlinTrkDiagnostics ) { + void * dcv = _trksystem->getDiagnositicsPointer(); + DiagnosticsController* dc = static_cast<DiagnosticsController*>(dcv); + dc->skip_current_track(); + } +#endif + */ + + std::vector<std::pair<edm4hep::TrackerHit* , double> > hits_in_fit ; + std::vector<std::pair<edm4hep::TrackerHit* , double> > outliers ; + std::vector<edm4hep::TrackerHit*> all_hits; + all_hits.reserve(300); + + marlinTrk->getHitsInFit(hits_in_fit); + + for ( unsigned ihit = 0; ihit < hits_in_fit.size(); ++ihit) { + debug() << "Hit address=" << hits_in_fit[ihit].first << endmsg; + edm4hep::TrackerHit* trk = hits_in_fit[ihit].first; + all_hits.push_back(trk);//hits_in_fit[ihit].first); + } + + UTIL::BitField64 cellID_encoder( UTIL::ILDCellID0::encoder_string ) ; + + MarlinTrk::addHitNumbersToTrack(&track, all_hits, true, cellID_encoder); + + marlinTrk->getOutliers(outliers); + + for ( unsigned ihit = 0; ihit < outliers.size(); ++ihit) { + all_hits.push_back(outliers[ihit].first); + } + + MarlinTrk::addHitNumbersToTrack(&track, all_hits, false, cellID_encoder); + + delete marlinTrk; + + int nhits_in_vxd = track.getSubDetectorHitNumbers(0); + int nhits_in_ftd = track.getSubDetectorHitNumbers(1); + int nhits_in_sit = track.getSubDetectorHitNumbers(2); + + //debug() << " Hit numbers for Track "<< track->id() << ": " + debug() << " Hit numbers for Track "<< iTrk <<": " + << " vxd hits = " << nhits_in_vxd + << " ftd hits = " << nhits_in_ftd + << " sit hits = " << nhits_in_sit + << endmsg; + + //if (nhits_in_vxd > 0) Track->setTypeBit( lcio::ILDDetID::VXD ) ; + //if (nhits_in_ftd > 0) Track->setTypeBit( lcio::ILDDetID::FTD ) ; + //if (nhits_in_sit > 0) Track->setTypeBit( lcio::ILDDetID::SIT ) ; + + if( status != IMarlinTrack::success ) { + //delete track; + debug() << "FinalRefit: Track fit failed with error code " << status << " track dropped. Number of hits = "<< trkHits.size() << endmsg; + continue ; + } + + if( track.getNdf() < 0) { + //delete track; + debug() << "FinalRefit: Track fit returns " << track.getNdf() << " degress of freedom track dropped. Number of hits = "<< trkHits.size() << endmsg; + //delete track; + continue ; + } + + //trk_col->addElement(Track); + //fucd + //trk_col->push_back(track); + for(int i=0;i<track.trackStates_size();i++){ + // 1 = lcio::EVENT::TrackState::AtIP + edm4hep::TrackState trkStateIP = track.getTrackStates(i); + if(trkStateIP.location !=1) continue; + /* + if (trkStateIP == 0) { + debug() << "SiliconTrackingAlg::FinalRefit: Track fit returns " << track->getNdf() << " degress of freedom track dropped. Number of hits = "<< trkHits.size() << endmsg; + throw EVENT::Exception( std::string("SiliconTrackingAlg::FinalRefit: trkStateIP pointer == NULL ") ) ; + } + */ + // note trackAR which is of type TrackExtended, only takes fits set for ref point = 0,0,0 + trackAR->setOmega(trkStateIP.omega); + trackAR->setTanLambda(trkStateIP.tanLambda); + trackAR->setPhi(trkStateIP.phi); + trackAR->setD0(trkStateIP.D0); + trackAR->setZ0(trkStateIP.Z0); + + float cov[15]; + + for (int i = 0 ; i<15 ; ++i) { + cov[i] = trkStateIP.covMatrix.operator[](i); + } + + trackAR->setCovMatrix(cov); + trackAR->setChi2(track.getChi2()); + trackAR->setNDF(track.getNdf()); + + nSiSegments++; + + HelixClass helix_final; + + helix_final.Initialize_Canonical(trkStateIP.phi,trkStateIP.D0,trkStateIP.Z0,trkStateIP.omega,trkStateIP.tanLambda,_bField); + + float trkPx = helix_final.getMomentum()[0]; + float trkPy = helix_final.getMomentum()[1]; + float trkPz = helix_final.getMomentum()[2]; + float trkP = sqrt(trkPx*trkPx+trkPy*trkPy+trkPz*trkPz); + eTot += trkP; + pxTot += trkPx; + pyTot += trkPy; + pzTot += trkPz; + } + } + } + + debug() << " -> run " << _nRun << " event " << _nEvt << endmsg; + debug() << "Number of Si tracks = " << nSiSegments << endmsg; + debug() << "Total 4-momentum of Si Tracks : E = " << std::setprecision(7) << eTot + << " Px = " << pxTot + << " Py = " << pyTot + << " Pz = " << pzTot << endmsg; +} + +StatusCode SiliconTrackingAlg::setupGearGeom(){ + auto _gear = service<IGearSvc>("GearSvc"); + if ( !_gear ) { + error() << "Failed to find GearSvc ..." << endmsg; + return StatusCode::FAILURE; + } + gear::GearMgr* gearMgr = _gear->getGearMgr(); + _bField = gearMgr->getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + debug() << "Field " << _bField << endmsg; + //-- VXD Parameters-- + _nLayersVTX = 0 ; + const gear::VXDParameters* pVXDDetMain = 0; + const gear::VXDLayerLayout* pVXDLayerLayout = 0; + + try{ + + debug() << " filling VXD parameters from gear::SITParameters " << endmsg ; + + pVXDDetMain = &gearMgr->getVXDParameters(); + pVXDLayerLayout = &(pVXDDetMain->getVXDLayerLayout()); + _nLayersVTX = pVXDLayerLayout->getNLayers(); + } + catch( gear::UnknownParameterException& e){ + + debug() << " ### gear::VXDParameters Not Present in GEAR FILE" << endmsg ; + + } + + + + //-- SIT Parameters-- + _nLayersSIT = 0 ; + const gear::ZPlanarParameters* pSITDetMain = 0; + const gear::ZPlanarLayerLayout* pSITLayerLayout = 0; + + try{ + + debug() << " filling SIT parameters from gear::SITParameters " << endmsg ; + + pSITDetMain = &gearMgr->getSITParameters(); + pSITLayerLayout = &(pSITDetMain->getZPlanarLayerLayout()); + _nLayersSIT = pSITLayerLayout->getNLayers(); + + } + catch( gear::UnknownParameterException& e){ + + debug() << " ### gear::SITParameters Not Present in GEAR FILE" << endmsg ; + + } + + if( _nLayersSIT == 0 ){ + // try the old LOI style key value pairs as defined in the SSit03 Mokka drive + try{ + + info() << " SiliconTrackingAlg - Simple Cylinder Based SIT using parameters defined by SSit03 Mokka driver " << endmsg ; + + // SIT + + const gear::GearParameters& pSIT = gearMgr->getGearParameters("SIT"); + + const std::vector<double>& SIT_r = pSIT.getDoubleVals("SITLayerRadius" ) ; + const std::vector<double>& SIT_hl = pSIT.getDoubleVals("SITSupportLayerHalfLength" ) ; + + _nLayersSIT = SIT_r.size() ; + + if (_nLayersSIT != SIT_r.size() || _nLayersSIT != SIT_hl.size()) { + + error() << "ILDSITCylinderKalDetector miss-match between DoubleVec and nlayers exit(1) called from file " << __FILE__ << " line " << __LINE__ << endmsg ; + exit(1); + + } + } + catch( gear::UnknownParameterException& e){ + + debug() << " ### gear::SIT Parameters from as defined in SSit03 Not Present in GEAR FILE" << endmsg ; + + } + + } + + + + //-- FTD Parameters-- + _petalBasedFTDWithOverlaps = false; + _nlayersFTD = 0; + + try{ + + debug() << " filling FTD parameters from gear::FTDParameters " << endmsg ; + + const gear::FTDParameters& pFTD = gearMgr->getFTDParameters(); + const gear::FTDLayerLayout& ftdlayers = pFTD.getFTDLayerLayout() ; + + _nlayersFTD = ftdlayers.getNLayers() ; + + for (unsigned int disk=0; disk < _nlayersFTD; ++disk) { + + _zLayerFTD.push_back( ftdlayers.getSensitiveZposition(disk, 0, 1) ); // front petal even numbered + + if ( ftdlayers.getNPetals(disk) > 0) { + _zLayerFTD.push_back( ftdlayers.getSensitiveZposition(disk, 1, 1) ); // front petal odd numbered + _petalBasedFTDWithOverlaps = true; + } + + } + + // SJA: Here we increase the size of _nlayersFTD as we are treating the + _nlayersFTD =_zLayerFTD.size() ; + + } + catch( gear::UnknownParameterException& e){ + + debug() << " ### gear::FTDParameters Not Present in GEAR FILE" << endmsg ; + + } + + if( _nlayersFTD == 0 ){ + + // FTD + try{ + + info() << " SiliconTrackingAlg - Simple Disc Based FTD using parameters defined by SFtd05 Mokka driver " << endmsg ; + + const gear::GearParameters& pFTD = gearMgr->getGearParameters("FTD"); + + const std::vector<double>* pFTD_z = NULL; + + info() << " For FTD using parameters defined by SFtd05 Mokka driver " << endmsg ; + + pFTD_z = &pFTD.getDoubleVals("FTDZCoordinate" ) ; + + _nlayersFTD = pFTD_z->size(); + + for (unsigned int i = 0; i<_nlayersFTD; ++i) { + _zLayerFTD.push_back((*pFTD_z)[i]); + } + } + catch( gear::UnknownParameterException& e){ + + debug() << " ### gear::FTD Parameters as defined in SFtd05 Not Present in GEAR FILE" << endmsg ; + + } + } + return StatusCode::SUCCESS; +} + +void SiliconTrackingAlg::TracksWithNHitsContainer::clear() +{ + for (std::vector< TrackExtendedVec >::iterator trackVecIter = _tracksNHits.begin(); + trackVecIter < _tracksNHits.end(); trackVecIter++) + { + for (TrackExtendedVec::iterator trackIter = trackVecIter->begin(); + trackIter < trackVecIter->end(); trackIter++) + { + delete *trackIter; + } + + trackVecIter->clear(); + } +} + diff --git a/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..67ffdb960ed726b73cf352c5099aa037740d0428 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/SiliconTrackingAlg.h @@ -0,0 +1,427 @@ +#ifndef SiliconTrackingAlg_h +#define SiliconTrackingAlg_h + +//#include "marlin/Processor.h" +//#include <marlin/Global.h> +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" + +//#include "lcio.h" +#include <string> +#include <vector> +#include <cmath> +//#include <IMPL/TrackImpl.h> +#include "DataHelper/ClusterExtended.h" +#include "DataHelper/TrackExtended.h" +#include "DataHelper/TrackerHitExtended.h" +#include "DataHelper/HelixClass.h" + +#include "TrackSystemSvc/IMarlinTrack.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +//using namespace edm4hep ; + +namespace gear{ + class GearMgr ; +} + +namespace MarlinTrk { + class HelixFit; + class IMarlinTrkSystem ; +} + +namespace UTIL{ + class LCRelationNavigator ; +} + +class TrackExtended; +class TrackerHitExtended; +class HelixClass; + +/** === Silicon Tracking Processor === <br> + * Processor performing stand-alone pattern recognition + * in the vertex detector (VTX), forward tracking disks and SIT. <br> + * The procedure consists of three steps : <br> + * 1) Tracking in VTX and SIT ; <br> + * 2) Tracking in FTD ; <br> + * 3) Merging compatible track segments reconstructed in VTX and FTD <br> + * STEP 1 : TRACKING IN VTX and SIT <br> + * Algorithm starts with finding of hit triplets satisfying helix hypothesis <br> + * in three different layers. Two layers of SIT are effectively considered as outermost <br> + * layers of the vertex detector. To accelerate procedure, the 4-pi solid angle + * is divided in NDivisionsInTheta and NDivisionsInPhi sectors in cosQ and Phi, + * respectively. Triplets are looked for in 2x2 window of adjacent sectors. + * Once triplet is found, attempt is made to associate additional hits to + * track. Combinatin of hits is accepted for further analysis if the Chi2 + * of the fit is less than certain predefined threshold. All accepted + * combinations are sorted in ascending order of their Chi2. First track candidate + * in the sorted array is automatically accepted. The hits belonging to this track are + * marked as used, and track candidates sharing these hits are discarded. + * The procedure proceeds with increasing index of track candidate in the sorted + * array until all track candidate have been output or discarded. <br> + * STEP 2 : TRACKING IN FTD <br> + * In the next step tracking in FTD is performed. The strategy of tracking in the FTD + * is the same as used for tracking in the VTX+SIT. <br> + * STEP 3 : MERGING TRACK SEGMENTS FOUND IN FTD AND VTX+SIT <br> + * In the last step, track segments reconstructed in the FTD and VTX+SIT, belonging to the + * same track are identified and merged into one track. All possible + * pairings are tested for their compatibility. + * The number of pairings considered is Ntrk_VTX_SIT*Ntrk_FTD, where Ntrk_VTX_SIT is the number of + * track segments reconstructed in the first step in VTX+SIT (segments containing solely VTX and SIT hits) and + * Ntrk_FTD is the number of track segments reconstructed in the second step + * (segments containing solely FTD hits). + * Pair of segments is accepted for further examination if the angle between track segments and + * than certain specified threshold. + * Pairing satisfying this condition is subjected for + * addtitional test. The fit is performed on unified array of hits belonging to both segments. + * If the chi2 of the fit does not exceed predefined cut value two segments are unified into + * one track. + * <h4>Input collections and prerequisites</h4> + * Processor requires collection of digitized vertex, sit and ftd tracker hits. <br> + * If such a collections with the user specified names do not exist + * processor takes no action. <br> + * <h4>Output</h4> + * Processor produces an LCIO collection of the Tracks. Each track is characterised by + * five parameters : Omega (signed curvuture), Tan(lambda) where + * lambda is the dip angle, Phi (azimuthal angle @ point of closest approach), D0 (signed impact parameter), + * Z0 (displacement along z axis at the point of closest approach to IP). Covariance matrix for these parameters is also provided. + * Only lower left corner of the covariance matrix is stored. The sequence of the covariance matrix elements + * assigned to track is the following: <br> + * (Omega,Omega) <br> + * (Omega,TanLambda), (TanLambda,TanLambda) <br> + * (Omega,Phi), (TanLamda,Phi), (Phi,Phi) <br> + * (Omega,D0), (TanLambda,D0), (Phi,D0), (D0,D0) <br> + * (Omega,Z0), (TanLambda,Z0), (Phi,Z0), (D0,Z0), (Z0,Z0) <br> + * The number of hits in the different subdetectors associated + * with each track can be accessed via method Track::getSubdetectorHitNumbers(). + * This method returns vector of integers : <br> + * number of VTX hits in track is the first element in this vector + * (Track::getSubdetectorHitNumbers()[0]) <br> + * number of FTD hits in track is the second element in this vector + * (Track::getSubdetectorHitNumbers()[1]) <br> + * number of SIT hits in track is the third element in this vector + * (Track::getSubdetectorHitNumbers()[2]) <br> + * Output track collection has a name "SiTracks". <br> + * @param VTXHitCollectionName name of input VTX TrackerHit collection <br> + * (default parameter value : "VTXTrackerHits") <br> + * @param FTDHitCollectionName name of input FTD TrackerHit collection <br> + * (default parameter value : "FTDTrackerHits") <br> + * @param SITHitCollectionName name of input SIT TrackerHit collection <br> + * (default parameter value : "SITTrackerHits") <br> + * @param SiTrackCollectionName name of the output Silicon track collection <br> + * (default parameter value : "SiTracks") <br> + * @param LayerCombinations combinations of layers used to search for hit triplets in VTX+SIT <br> + * (default parameters : 6 4 3 6 4 2 6 3 2 5 4 3 5 4 2 5 3 2 4 3 2 4 3 1 4 2 1 3 2 1) <br> + * Note that in the VTX+SIT system the first and the second layers of SIT have indicies nLayerVTX and nLayerVTX+1. + * Combination given above means that triplets are looked first in layers 6 4 3, and then + * in 6 4 2; 5 4 3; 6 3 2 etc. NOTE THAT LAYER INDEXING STARTS FROM 0. + * LAYER 0 is the innermost layer <br> + * @param LayerCombinationsFTD combinations of layers used to search for hit triplets in FTD <br> + * (default parameters 6 5 4 5 4 3 5 4 2 5 4 1 5 3 2 5 3 1 5 2 1 4 3 2 4 3 1 + * 4 3 0 4 2 1 4 2 0 4 1 0 3 2 1 3 2 0 3 1 0 2 1 0). + * NOTE THAT TRACKS IN FTD ARE SEARCHED ONLY IN ONE HEMISPHERE. TRACK IS NOT + * ALLOWED TO HAVE HITS BOTH IN BACKWARD AND FORWARD PARTS OF FTD SIMULTANEOUSLY. + * @param NDivisionsInPhi Number of divisions in Phi for tracking in VTX+SIT <br> + * (default value is 40) <br> + * @param NDivisionsInTheta Number of divisions in cosQ for tracking in VTX+SIT <br> + * (default value is 40) <br> + * @param NDivisionsInPhiFTD Number of divisions in Phi for tracking in FTD <br> + * (default value is 3) <br> + * @param Chi2WRphiTriplet weight on chi2 in R-Phi plane for track with 3 hits <br> + * (default value is 1) <br> + * @param Chi2WZTriplet weight on chi2 in S-Z plane for track with 3 hits <br> + * (default value is 0.5) <br> + * @param Chi2WRphiQuartet weight on chi2 in R-Phi plane to accept track with 4 hits <br> + * (default value is 1) <br> + * @param Chi2WZQuartet weight on chi2 in S-Z plane for track with 4 hits <br> + * (default value is 0.5) <br> + * @param Chi2WRphiSeptet weight on chi2 in R-Phi plane for track with 5 and more hits <br> + * (default value is 1) <br> + * @param Chi2WZSeptet Cut on chi2 in S-Z plane for track with 5 and more hits <br> + * (default value is 0.5) <br> + * @param Chi2FitCut Cut on chi2/ndf to accept track candidate <br> + * (default value is 100.) <br> + * @param AngleCutForMerging cut on the angle between two track segments. + * If the angle is greater than this cut, segments are not allowed to be merged. <br> + * (default value is 0.1) <br> + * @param MinDistCutAttach cut on the distance (in mm) from hit to the helix. This parameter is used + * to decide whether hit can be attached to the track. If the distance is less than + * cut value. The track is refitted with a given hit being added to the list of hits already + * assigned for the track. Additional hit is assigned if chi2 of the new fit has good chi2. <br> + * (default value is 2 ) <br> + * @param MinLayerToAttach the minimal layer index to attach VTX hits to the found hit triplets <br> + * (default value is -1) <br> + * @param CutOnZ0 cut on Z0 parameter of track (in mm). If abs(Z0) is greater than the cut value, track is + * discarded (used to suppress fake + * track rate in the presence of beam induced background hits) <br> + * (default value is 100) <br> + * @param CutOnD0 cut on D0 parameter of track (in mm). If abs(D0) is greater than the cut value, track is + * discarded (used to suppress fake + * track rate in the presence of beam induced background hits) <br> + * (default value is 100) <br> + * @param CutOnPt cut on Pt (GeV/c). If Pt is less than this cut, track is discarded (used to suppress fake + * track rate in the presence of beam induced background hits) <br> + * (default value is 0.1) <br> + * @param MinimalHits minimal number of hits in track required <br> + * (default value is 3) <br> + * @param NHitsChi2 Maximal number of hits for which a track with n hits is aways better than one with n-1 hits. + * For tracks with equal or more than NHitsChi2 the track with the lower \f$\chi^2\f$ is better. + * (default value is 5) <br> + * @param FastAttachment if this flag is set to 1, less accurate but fast procedure to merge additional hits to tracks is used <br> + * if set to 0, a more accurate, but slower procedure is invoked <br> + * (default value is 0) <br> + * @param UseSIT When this flag is set to 1, SIT is included in pattern recognition. When this flag is set + * to 0, SIT is excluded from the procedure of pattern recognition <br> + * (default value is 1) <br> + * <br> + * @author A. Raspereza (MPI Munich)<br> + */ +class SiliconTrackingAlg : public GaudiAlgorithm { + public: + + SiliconTrackingAlg(const std::string& name, ISvcLocator* svcLoc); + + virtual StatusCode initialize() ; + + virtual StatusCode execute() ; + + virtual StatusCode finalize() ; + + protected: + + int _nRun ; + int _nEvt ; + //EVENT::LCEvent* _current_event; + int _nLayers; + unsigned int _nLayersVTX; + unsigned int _nLayersSIT; + int _ntriplets, _ntriplets_good, _ntriplets_2MCP, _ntriplets_3MCP, _ntriplets_1MCP_Bad, _ntriplets_bad; + + MarlinTrk::HelixFit* _fastfitter; + gear::GearMgr* _GEAR; + /** pointer to the IMarlinTrkSystem instance + */ + MarlinTrk::IMarlinTrkSystem* _trksystem ; + //bool _runMarlinTrkDiagnostics; + //std::string _MarlinTrkDiagnosticsName; + typedef std::vector<int> IntVec; + + Gaudi::Property<IntVec> _Combinations{this, "LayerCombinations", + {8,6,5, 8,6,4, 8,6,3, 8,6,2, 8,5,3, 8,5,2, 8,4,3, 8,4,2, 6,5,3, 6,5,2, 6,4,3, 6,4,2, 6,3,1, 6,3,0, 6,2,1, 6,2,0, + 5,3,1, 5,3,0, 5,2,1, 5,2,0, 4,3,1, 4,3,0, 4,2,1, 4,2,0}}; + Gaudi::Property<IntVec> _CombinationsFTD{this, "LayerCombinationsFTD", {4,3,2, 4,3,1, 4,3,0, 4,2,1, 4,2,0, 4,1,0, 3,2,1, 3,2,0, 3,1,0, 2,1,0, + 9,8,7, 9,8,6, 9,8,5, 9,7,6, 9,7,5, 9,6,5, 8,7,6, 8,7,5, 8,6,5, 7,6,5}}; + Gaudi::Property<int> _nDivisionsInPhi{this, "NDivisionsInPhi", 80}; + Gaudi::Property<int> _nDivisionsInPhiFTD{this, "NDivisionsInPhiFTD", 30}; + Gaudi::Property<int> _nDivisionsInTheta{this, "NDivisionsInTheta", 80}; + Gaudi::Property<float> _chi2WRPhiTriplet{this, "Chi2WRphiTriplet", 1.}; + Gaudi::Property<float> _chi2WRPhiQuartet{this, "Chi2WRphiQuartet", 1.}; + Gaudi::Property<float> _chi2WRPhiSeptet{this, "Chi2WRphiSeptet", 1.}; + Gaudi::Property<float> _chi2WZTriplet{this, "Chi2WZTriplet", 0.5}; + Gaudi::Property<float> _chi2WZQuartet{this, "Chi2WZQuartet", 0.5}; + Gaudi::Property<float> _chi2WZSeptet{this, "Chi2WZSeptet", 0.5}; + Gaudi::Property<float> _chi2FitCut{this, "Chi2FitCut", 120.}; + Gaudi::Property<float> _angleCutForMerging{this, "AngleCutForMerging", 0.1}; + Gaudi::Property<float> _minDistCutAttach{this, "MinDistCutAttach", 2.5}; + Gaudi::Property<float> _minimalLayerToAttach{this, "MinLayerToAttach", -1}; + Gaudi::Property<float> _cutOnD0{this, "CutOnD0", 100.0}; + Gaudi::Property<float> _cutOnZ0{this, "CutOnZ0", 100.0}; + Gaudi::Property<float> _cutOnPt{this, "CutOnPt", 0.05}; + Gaudi::Property<int> _minimalHits{this, "MinimalHits",3}; + Gaudi::Property<int> _nHitsChi2{this, "NHitsChi2", 5}; + Gaudi::Property<int> _max_hits_per_sector{this, "MaxHitsPerSector", 100}; + Gaudi::Property<int> _attachFast{this, "FastAttachment", 0}; + Gaudi::Property<bool> _useSIT{this, "UseSIT", true}; + Gaudi::Property<float> _initialTrackError_d0{this, "InitialTrackErrorD0",1e6}; + Gaudi::Property<float> _initialTrackError_phi0{this, "InitialTrackErrorPhi0",1e2}; + Gaudi::Property<float> _initialTrackError_omega{this, "InitialTrackErrorOmega",1e-4}; + Gaudi::Property<float> _initialTrackError_z0{this, "InitialTrackErrorZ0",1e6}; + Gaudi::Property<float> _initialTrackError_tanL{this, "InitialTrackErrorTanL",1e2}; + Gaudi::Property<float> _maxChi2PerHit{this, "MaxChi2PerHit", 1e2}; + Gaudi::Property<int> _checkForDelta{this, "CheckForDelta", 1}; + Gaudi::Property<float> _minDistToDelta{this, "MinDistToDelta", 0.25}; + Gaudi::Property<bool> _MSOn{this, "MultipleScatteringOn", true}; + Gaudi::Property<bool> _ElossOn{this, "EnergyLossOn", true}; + Gaudi::Property<bool> _SmoothOn{this, "SmoothOn", true}; + Gaudi::Property<float> _helix_max_r{this, "HelixMaxR", 2000.}; + + //std::vector<int> _colours; + + /** helper function to get collection using try catch block */ + //LCCollection* GetCollection( LCEvent * evt, std::string colName ) ; + + /** helper function to get relations using try catch block */ + //LCRelationNavigator* GetRelations( LCEvent * evt, std::string RelName ) ; + + /** input MCParticle collection and threshold used for Drawing + */ + //Gaudi::Property<Float> _MCpThreshold{this, "MCpThreshold", 0.1}; + //std::string _colNameMCParticles; + + /// Compare tracks according to their chi2/ndf + struct compare_TrackExtended{ + // n.b.: a and b should be TrackExtended const *, but the getters are not const :-( + bool operator()(TrackExtended *a, TrackExtended *b) const { + if ( a == b ) return false; + return (a->getChi2()/a->getNDF() < b->getChi2()/b->getNDF() ); + } + }; + + + //std::string _VTXHitCollection; + //std::string _FTDPixelHitCollection; + //std::string _FTDSpacePointCollection; + //std::string _SITHitCollection; + //std::string _siTrkCollection; + + //std::vector< LCCollection* > _colTrackerHits; + //std::map< LCCollection*, std::string > _colNamesTrackerHits; + + // Input collections + DataHandle<edm4hep::EventHeaderCollection> _headerColHdl{"EventHeaderCol", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCParticleCollection> _inMCColHdl{"MCParticle", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inVTXColHdl{"VXDTrackerHits", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inFTDPixelColHdl{"FTDPixelTrackerHits", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inFTDSpacePointColHdl{"FTDSpacePoints", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inSITColHdl{"SITSpacePoints", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inSITRawColHdl{"SITTrackerHits", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inFTDRawColHdl{"FTDStripTrackerHits", Gaudi::DataHandle::Reader, this}; + // Output collections + DataHandle<edm4hep::TrackCollection> _outColHdl{"SiTracks", Gaudi::DataHandle::Writer, this}; + //DataHandle<edm4hep::LCRelationCollection> _outRelColHdl{"TrackerHitRelations", Gaudi::DataHandle::Reader, this}; + + std::vector<TrackerHitExtendedVec> _sectors; + std::vector<TrackerHitExtendedVec> _sectorsFTD; + + /** + * A helper class to allow good code readability by accessing tracks with N hits. + * As the smalest valid track contains three hits, but the first index in a vector is 0, + * this class hides the index-3 calculation. As the vector access is inline there should be + * no performance penalty. + */ + class TracksWithNHitsContainer { + public: + /// Empty all the vectors and delete the tracks contained in it. + void clear(); + + /// Set the size to allow a maximum of maxHit hits. + inline void resize(size_t maxHits) { + _tracksNHits.resize(maxHits-2); + _maxIndex=(maxHits-3); + } + + // Sort all track vectors according to chi2/nDof + // void sort(); + + /// Returns the TrackExtendedVec for track with n hits. + /// In case n is larger than the maximal number the vector with the largest n ist returned. + /// \attention The smallest valid number is three! For + /// performance reasons there is no safety check! + inline TrackExtendedVec & getTracksWithNHitsVec( size_t nHits ) { + //return _tracksNHits[ std::min(nHits-3, _maxIndex) ]; + // for debugging: with boundary check + return _tracksNHits.at(std::min(nHits-3, _maxIndex)); + } + + protected: + std::vector< TrackExtendedVec > _tracksNHits; + size_t _maxIndex; /// local cache variable to avoid calculation overhead + }; + + TracksWithNHitsContainer _tracksWithNHitsContainer; + + int InitialiseVTX(); + int InitialiseFTD(); + void ProcessOneSector(int iSectorPhi, int iSectorTheta); + void CleanUp(); + TrackExtended * TestTriplet(TrackerHitExtended * outerHit, + TrackerHitExtended * middleHit, + TrackerHitExtended * innerHit, + HelixClass & helix); + + int BuildTrack(TrackerHitExtended * outerHit, + TrackerHitExtended * middleHit, + TrackerHitExtended * innerHit, + HelixClass & helix, + int innerlayer, + int iPhiLow, int iPhiUp, + int iTheta, int iThetaUp, + TrackExtended * trackAR); + + void Sorting( TrackExtendedVec & trackVec); + void CreateTrack(TrackExtended * trackAR ); + void AttachRemainingVTXHitsSlow(); + void AttachRemainingFTDHitsSlow(); + void AttachRemainingVTXHitsFast(); + void AttachRemainingFTDHitsFast(); + void TrackingInFTD(); + int BuildTrackFTD(TrackExtended* trackAR, int* nLR, int iS); + int AttachHitToTrack(TrackExtended * trackAR, TrackerHitExtended * hit, int iopt); + + void FinalRefit(edm4hep::TrackCollection*);//, edm4hep::LCRelationCollection*); + + float _bField; + + // two pi is not a constant in cmath. Calculate it, once! + static const double TWOPI; + + double _dPhi; + double _dTheta; + double _dPhiFTD; + + float _resolutionRPhiVTX; + float _resolutionZVTX; + + float _resolutionRPhiFTD; + float _resolutionZFTD; + + float _resolutionRPhiSIT; + float _resolutionZSIT; + + float _phiCutForMerging; + float _tanlambdaCutForMerging; + //float _angleCutForMerging; + + float _distRPhi; + float _distZ; + + float _cutOnOmega; + + TrackExtendedVec _trackImplVec; + + int _nTotalVTXHits,_nTotalFTDHits,_nTotalSITHits; + + // int _createMap; + + UTIL::BitField64* _encoder; + int getDetectorID(edm4hep::TrackerHit* hit) { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::subdet]; } + int getSideID(edm4hep::TrackerHit* hit) { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::side]; }; + int getLayerID(edm4hep::TrackerHit* hit) { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::layer]; }; + int getModuleID(edm4hep::TrackerHit* hit) { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::module]; }; + int getSensorID(edm4hep::TrackerHit* hit) { _encoder->setValue(hit->getCellID()); return (*_encoder)[lcio::ILDCellID0::sensor]; }; + + StatusCode setupGearGeom() ; + + std::vector<float> _zLayerFTD; + + unsigned int _nlayersFTD; + bool _petalBasedFTDWithOverlaps; + + int _output_track_col_quality; + static const int _output_track_col_quality_GOOD; + static const int _output_track_col_quality_FAIR; + static const int _output_track_col_quality_POOR; +} ; + +#endif + + + diff --git a/Reconstruction/SiliconTracking/src/SpacePointBuilderAlg.cpp b/Reconstruction/SiliconTracking/src/SpacePointBuilderAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2a9b87c350c0d5f7b9595623c2e1d425430c923 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/SpacePointBuilderAlg.cpp @@ -0,0 +1,765 @@ +#include "SpacePointBuilderAlg.h" +#include "GearSvc/IGearSvc.h" +#include "TrackSystemSvc/ITrackSystemSvc.h" + +#include "UTIL/ILDConf.h" +//#include "UTIL/LCRelationNavigator.h" + +#include "gear/GEAR.h" +#include "gear/GearParameters.h" +#include "gear/FTDParameters.h" +#include "gear/FTDLayerLayout.h" +#include "gear/ZPlanarParameters.h" +#include "gear/ZPlanarLayerLayout.h" + +#include "gear/gearsurf/MeasurementSurfaceStore.h" +#include "gear/gearsurf/MeasurementSurface.h" +#include "gear/gearsurf/ICoordinateSystem.h" +#include "gear/gearsurf/CartesianCoordinateSystem.h" + +#include "CLHEP/Matrix/SymMatrix.h" +#include "CLHEP/Matrix/Matrix.h" + +#include <cmath> +#include <sstream> + +DECLARE_COMPONENT(SpacePointBuilderAlg) + +SpacePointBuilderAlg::SpacePointBuilderAlg(const std::string& name, ISvcLocator* svcLoc) +: GaudiAlgorithm(name, svcLoc) { + //declareProperty("HeaderCol", _headerColHdl); + declareProperty("MCParticleCollection", _inMCColHdl, "Handle of the Input MCParticle collection"); + declareProperty("TrackerHitCollection", _inHitColHdl, "Handle of the Input TrackerHits collection"); + //declareProperty("FTDPixelHitCollection", _inFTDPixelColHdl, "Handle of the Input FTD TrackerHits collection"); + declareProperty("TrackerHitAssociationCollection", _inHitAssColHdl, "Handle of the Input MCRecoTrackerAssociation collection"); + //declareProperty("SITHitCollection", _inSITColHdl, "Handle of the Input SIT TrackerHits collection"); + declareProperty("SpacePointCollection", _outSPColHdl, "Handle of the SpacePoint output collection"); + declareProperty("SpacePointAssociationCollection", _outSPAssColHdl, "Handle of the SpacePoints association output collection"); +} + +StatusCode SpacePointBuilderAlg::initialize() { + debug() << " init called " << endmsg; + // usually a good idea to + _nRun = 0 ; + _nEvt = 0 ; + + _nominal_vertex.set(_nominal_vertex_x, _nominal_vertex_y, _nominal_vertex_z); + + auto gearSvc = service<IGearSvc>("GearSvc"); + if ( !gearSvc ) { + error() << "Failed to find GearSvc ..." << endmsg; + return StatusCode::FAILURE; + } + _GEAR = gearSvc->getGearMgr(); + + //FIXME:SJA: if we want the surface store to be filled we need to create an instance of MarlinTrk implemented with KalTest/KalDet + auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc"); + if ( !_trackSystemSvc ) { + error() << "Failed to find TrackSystemSvc ..." << endmsg; + return StatusCode::FAILURE; + } + + MarlinTrk::IMarlinTrkSystem* _trksystem = _trackSystemSvc->getTrackSystem(); + _trksystem->init(); + + _trackSystemSvc->removeTrackSystem(); + + return GaudiAlgorithm::initialize(); +} + +StatusCode SpacePointBuilderAlg::execute(){ + StatusCode sc; + const edm4hep::TrackerHitCollection* hitCol = nullptr; + try { + hitCol = _inHitColHdl.get(); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inHitColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + return sc; + } + + const edm4hep::MCRecoTrackerAssociationCollection* hitAssCol = nullptr; + try { + hitAssCol = _inHitAssColHdl.get(); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inHitAssColHdl.fullKey() << " is unavailable in event " << _nEvt << endmsg; + return sc; + } + + if(hitCol!=NULL && hitAssCol!=NULL){ + unsigned createdSpacePoints = 0; + unsigned rawStripHits = 0; + unsigned possibleSpacePoints = 0; + _nOutOfBoundary = 0; + _nStripsTooParallel = 0; + _nPlanesNotParallel = 0; + + edm4hep::TrackerHitCollection* spCol = new edm4hep::TrackerHitCollection(); // output spacepoint collection + edm4hep::MCRecoTrackerAssociationCollection* relCol = new edm4hep::MCRecoTrackerAssociationCollection(); // output relation collection + + // to store the weights + //LCFlagImpl lcFlag(0) ; + //lcFlag.setBit( LCIO::LCREL_WEIGHTED ) ; + //relCol->setFlag( lcFlag.getFlag() ) ; + + unsigned nHits = hitCol->size(); + debug() << "Number of hits: " << nHits << endmsg; + + //store hits in map according to their CellID0 + std::map<long long, std::vector<edm4hep::TrackerHit> > map_cellID0_hits; + std::map<long long, std::vector<edm4hep::TrackerHit> >::iterator it; + for(auto trkHit : *hitCol){ + debug() << "Add hit with CellID0 = " << trkHit.getCellID() << " " << getCellID0Info( trkHit.getCellID() ) << endmsg; + map_cellID0_hits[ trkHit.getCellID() ].push_back( trkHit ); + } + + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + // now loop over all CellID0s + for( it= map_cellID0_hits.begin(); it!= map_cellID0_hits.end(); it++ ){ + rawStripHits += it->second.size(); + std::vector<edm4hep::TrackerHit>& hitsFront = it->second; + unsigned long long cellID0 = it->first; + //get the CellID0s at the back of this sensor + std::vector<int> cellID0sBack = getCellID0sAtBack( cellID0 ); + + for( unsigned i=0; i< cellID0sBack.size(); i++ ){ + int cellID0Back = cellID0sBack[i]; + std::vector<edm4hep::TrackerHit>& hitsBack = map_cellID0_hits[ cellID0Back ]; + debug() << "strips: CellID0 " << cellID0 << " " << getCellID0Info( cellID0 ) << "(" << hitsFront.size() + << " hits) <---> CellID0 " << cellID0Back << getCellID0Info( cellID0Back ) + << "(" << hitsBack.size() << " hits)" << endmsg + << "--> " << hitsFront.size() * hitsBack.size() << " possible combinations" << endmsg; + + possibleSpacePoints += hitsFront.size() * hitsBack.size(); + // Now iterate over all combinations and store those that make sense + for( unsigned ifront=0; ifront<hitsFront.size(); ifront++ ){ + edm4hep::TrackerHit& hitFront = hitsFront[ifront]; + for( unsigned j=0; j<hitsBack.size(); j++ ){ + edm4hep::TrackerHit& hitBack = hitsBack[j]; + + std::vector<edm4hep::ConstSimTrackerHit> simHitsFront; + std::vector<edm4hep::ConstSimTrackerHit> simHitsBack; + for(auto hitAss : *hitAssCol){ + if(hitAss.getRec().id()==hitFront.id()) simHitsFront.push_back(hitAss.getSim()); + if(hitAss.getRec().id()==hitBack.id()) simHitsBack.push_back(hitAss.getSim()); + } + debug() << "attempt to create space point from:" << endmsg; + debug() << " front hit: " << hitFront.id() << " no. of simhit = " << simHitsFront.size() ; + if( simHitsFront.size()!=0 ) { + edm4hep::ConstSimTrackerHit& simhit = simHitsFront[0]; + debug() << " first simhit = " << simhit.id() << " mcp = " << simhit.getMCParticle().id() << " (" << simhit.getPosition() << ") " ; + } + debug() << endmsg; + debug() << " rear hit: " << hitBack.id() << " no. of simhit = " << simHitsBack.size() ; + if( simHitsBack.size()!=0 ) { + edm4hep::ConstSimTrackerHit& simhit = simHitsBack[0]; + debug() << " first simhit = " << simhit.id() << " mcp = "<< simhit.getMCParticle().id() << " (" << simhit.getPosition() << ") " ; + } + debug() << endmsg; + + bool ghost_hit = true; + if (simHitsFront.size()==1 && simHitsBack.size() == 1) { + debug() << "SpacePoint creation from two good hits:" << endmsg; + ghost_hit = simHitsFront[0].getMCParticle().id() != simHitsBack[0].getMCParticle().id(); + } + if ( ghost_hit == true ) { + debug() << "SpacePoint Ghosthit!" << endmsg; + } + + cellID.setValue( cellID0 ); + int subdet = cellID[ UTIL::ILDCellID0::subdet ] ; + double strip_length_mm = 0; + if (subdet == UTIL::ILDDetID::SIT) { + strip_length_mm = _GEAR->getSITParameters().getDoubleVal("strip_length_mm"); + } + else if (subdet == UTIL::ILDDetID::SET) { + strip_length_mm = _GEAR->getSETParameters().getDoubleVal("strip_length_mm"); + } + else if (subdet == UTIL::ILDDetID::FTD) { + strip_length_mm = _GEAR->getFTDParameters().getDoubleVal("strip_length_mm"); + } + else { + std::stringstream errorMsg; + errorMsg << "SpacePointBuilderAlg::processEvent: unsupported detector ID = " << subdet << ": file " << __FILE__ << " line " << __LINE__ ; + throw GaudiException( errorMsg.str(), "CellID not matched", StatusCode::FAILURE ); + } + + // add tolerence + strip_length_mm = strip_length_mm * (1.0 + _striplength_tolerance); + try{ + edm4hep::TrackerHit spacePoint = createSpacePoint( &hitFront, &hitBack, strip_length_mm); + + //UTIL::CellIDEncoder<TrackerHitImpl> cellid_encoder( UTIL::ILDCellID0::encoder_string , spCol ); + //cellid_encoder.setValue( cellID0 ); //give the new hit, the CellID0 of the front hit + //cellid_encoder.setCellID( spacePoint ) ; + spacePoint.setCellID(cellID0); + + // store the hits it's composed of: + spacePoint.addToRawHits( hitFront.getObjectID() ); + spacePoint.addToRawHits( hitBack.getObjectID() ); + + spacePoint.setType( UTIL::set_bit( spacePoint.getType() , UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ) ) ; + + spCol->push_back( spacePoint ); + //debug() << "push_back space point's id=" << spCol->at(spCol->size()-1).id() << endmsg; + createdSpacePoints++; + + /////////////////////////////// + // make the relations + if( simHitsFront.size() == 1 ){ + edm4hep::ConstSimTrackerHit& simHit = simHitsFront[0]; + edm4hep::MCRecoTrackerAssociation spAss = relCol->create(); + spAss.setRec(spacePoint); + spAss.setSim(simHit); + spAss.setWeight( 0.5 ); + } + if( simHitsBack.size() == 1 ){ + edm4hep::ConstSimTrackerHit& simHit = simHitsBack[0]; + edm4hep::MCRecoTrackerAssociation spAss = relCol->create(); + spAss.setRec(spacePoint); + spAss.setSim(simHit); + spAss.setWeight( 0.5 ); + } + } + catch(std::runtime_error& e){ + if ( ghost_hit == true ) { + debug() << "Ghosthit correctly rejected" << endmsg; + } + else { + debug() << "True hit rejected!" << endmsg; + } + } + } + } + } + } + + if(spCol->size()!=0) _outSPColHdl.put(spCol); + else delete spCol; + if(relCol->size()!=0) _outSPAssColHdl.put(relCol); + else delete relCol; + + debug() << "\nCreated " << createdSpacePoints << " space points ( raw strip hits: " << rawStripHits << ")\n" + << " There were " << rawStripHits << " strip hits available, giving " + << possibleSpacePoints << " possible space points" << endmsg; + debug() << " " << _nStripsTooParallel << " space points couldn't be created, because the strips were too parallel\n" + << " " << _nPlanesNotParallel << " space points couldn't be created, because the planes of the measurement surfaces where not parallel enough\n" + << " " << _nOutOfBoundary << " space points couldn't be created, because the result was outside the sensor boundary\n" << endmsg; + } + + _nEvt ++ ; + return sc; +} + +StatusCode SpacePointBuilderAlg::finalize(){ + info() << "Processed " << _nEvt << " events " << endmsg; + return GaudiAlgorithm::finalize(); +} + +edm4hep::TrackerHit SpacePointBuilderAlg::createSpacePoint( edm4hep::TrackerHit* a , edm4hep::TrackerHit* b, double stripLength ){ + + const edm4hep::Vector3d& pa = a->getPosition(); + double xa = pa[0]; + double ya = pa[1]; + double za = pa[2]; + CLHEP::Hep3Vector PA( xa,ya,za ); + //double du_a = a->getdU(); + float du_a = a->getCovMatrix(2); + + gear::MeasurementSurface const* msA = _GEAR->getMeasurementSurfaceStore().GetMeasurementSurface( a->getCellID() ); + gear::CartesianCoordinateSystem* ccsA = dynamic_cast< gear::CartesianCoordinateSystem* >( msA->getCoordinateSystem() ); + + CLHEP::Hep3Vector WA = ccsA->getLocalZAxis(); // the vector W of the local coordinate system the measurement surface has + CLHEP::Hep3Vector VA = ccsA->getLocalYAxis(); // the vector V of the local coordinate system the measurement surface has + CLHEP::Hep3Vector UA = ccsA->getLocalXAxis(); // the vector U of the local coordinate system the measurement surface has + + const edm4hep::Vector3d& pb = b->getPosition(); + double xb = pb[0]; + double yb = pb[1]; + double zb = pb[2]; + CLHEP::Hep3Vector PB( xb,yb,zb ); + //double du_b = b->getdU(); + float du_b = b->getCovMatrix(2); + + gear::MeasurementSurface const* msB = _GEAR->getMeasurementSurfaceStore().GetMeasurementSurface( b->getCellID() ); + gear::CartesianCoordinateSystem* ccsB = dynamic_cast< gear::CartesianCoordinateSystem* >( msB->getCoordinateSystem() ); + CLHEP::Hep3Vector WB = ccsB->getLocalZAxis(); // the vector W of the local coordinate system the measurement surface has + CLHEP::Hep3Vector VB = ccsB->getLocalYAxis(); // the vector V of the local coordinate system the measurement surface has + CLHEP::Hep3Vector UB = ccsB->getLocalXAxis(); // the vector U of the local coordinate system the measurement surface has + + debug() << "\t ( " << xa << " " << ya << " " << za << " ) <--> ( " << xb << " " << yb << " " << zb << " )" << endmsg; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // First: check if the two measurement surfaces are parallel (i.e. the w are parallel or antiparallel) + double angle = fabs(WB.angle(WA)); + double angleMax = 1.*M_PI/180.; + if(( angle > angleMax )&&( angle < M_PI-angleMax )){ + _nPlanesNotParallel++; + debug() << "\tThe planes of the measurement surfaces are not parallel enough, the angle between the W vectors is " << angle + << " where the angle has to be smaller than " << angleMax << " or bigger than " << M_PI-angleMax << endmsg; + throw std::runtime_error(""); //calculate the xing point and if that fails don't create a spacepoint + } + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Next: check if the angle between the strips is not 0 + angle = fabs(VB.angle(VA)); + double angleMin= 1.*M_PI/180.; + if(( angle < angleMin )||( angle > M_PI-angleMin )){ + _nStripsTooParallel++; + debug() << "\tThe strips (V vectors) of the measurement surfaces are too parallel, the angle between the V vectors is " << angle + << " where the angle has to be between " << angleMax << " or bigger than " << M_PI-angleMin << endmsg; + throw std::runtime_error(""); //calculate the xing point and if that fails don't create a spacepoint + } + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Next we want to calculate the crossing point. + + CLHEP::Hep3Vector point; + +// calculatePointBetweenTwoLines( PA, VA, PB, VB, point ); +// +// // we want to set the space point on the surface of the hit closest to the IP +// if (PA.mag2() < PB.mag2()) { +// calculatePointBetweenTwoLines( PA, VA, PB, VB, point ); +// } else { +// calculatePointBetweenTwoLines( PB, VB, PA, VA, point ); +// } +// +// +// +// streamlog_out( DEBUG2 ) << "\tStandard: Position of space point (global) : ( " << point.x() << " " << point.y() << " " << point.z() << " )\n"; + + CLHEP::Hep3Vector vertex(0.,0.,0.); + CLHEP::Hep3Vector L1 = ccsA->getLocalPoint(PA); + CLHEP::Hep3Vector L2 = ccsB->getLocalPoint(PB); + + debug() << " L1 = " << L1 << endmsg; + debug() << " L2 = " << L2 << endmsg; + + L1.setY(-stripLength/2.0); + CLHEP::Hep3Vector SL1 = L1; + L1.setY( stripLength/2.0); + CLHEP::Hep3Vector EL1 = L1; + + + L2.setY(-stripLength/2.0); + CLHEP::Hep3Vector SL2 = L2; + L2.setY( stripLength/2.0); + CLHEP::Hep3Vector EL2 = L2; + + + CLHEP::Hep3Vector S1 = ccsA->getGlobalPoint(SL1); + CLHEP::Hep3Vector E1 = ccsA->getGlobalPoint(EL1); + + CLHEP::Hep3Vector S2 = ccsB->getGlobalPoint(SL2); + CLHEP::Hep3Vector E2 = ccsB->getGlobalPoint(EL2); + + debug() << " stripLength = " << stripLength << endmsg; + debug() << " S1 = " << S1 << endmsg; + debug() << " E1 = " << E1 << endmsg; + debug() << " S2 = " << S2 << endmsg; + debug() << " E2 = " << E2 << endmsg; + + point.set(0.0, 0.0, 0.0); + + int valid_intersection = calculatePointBetweenTwoLines_UsingVertex( S1, E1, S2, E2, vertex, point ); + + if (valid_intersection != 0) { + debug() << "\tNo valid intersection for lines" << endmsg; + throw std::runtime_error(""); + } + + debug() << "\tVertex: Position of space point (global) : ( " << point.x() << " " << point.y() << " " << point.z() << " )" << endmsg; + + // Check if the new hit is within the boundaries + CLHEP::Hep3Vector localPointA = ccsA->getLocalPoint(point); + localPointA.setZ(0.);// we set w to 0 so it is in the plane ( we are only interested if u and v are in or out of range, to exclude w from the check it is set to 0) + + CLHEP::Hep3Vector localPointB = ccsB->getLocalPoint(point); + localPointB.setZ(0.);// we set w to 0 so it is in the plane ( we are only interested if u and v are in or out of range, to exclude w from the check it is set to 0) + + if( !msA->isLocalInBoundary( localPointA ) ){ + _nOutOfBoundary++; + debug() << "\tSpacePoint position lies outside the boundary of the first layer: local coordinates are ( " + << localPointA.x() << " " << localPointA.y() << " " << localPointA.z() << " )" << endmsg; + throw std::runtime_error(""); + } + if( !msB->isLocalInBoundary( localPointB ) ){ + _nOutOfBoundary++; + debug() << "\tSecond hit is out of boundary: local coordinates are ( " + << localPointB.x() << " " << localPointB.y() << " " << localPointB.z() << " )" << endmsg; + throw std::runtime_error(""); + } + + //Create the new TrackerHit + edm4hep::TrackerHit spacePoint;// = new edm4hep::TrackerHit(); + + edm4hep::Vector3d pos(point.x(), point.y(), point.z()); + spacePoint.setPosition(pos) ; + + // set error treating the strips as stereo with equal and opposite rotation -- for reference see Karimaki NIM A 374 p367-370 + + // first calculate the covariance matrix in the cartisian coordinate system defined by the sensor + // here we assume that du is the same for both sides + + if( fabs(du_a - du_b) > 1.0e-06 ){ + error() << "\tThe measurement errors of the two 1D hits must be equal " << endmsg; + assert( fabs(du_a - du_b) > 1.0e-06 == false ); + throw std::runtime_error(""); //measurement errors are not equal don't create a spacepoint + } + + double du2 = du_a*du_a; + + // rotate the strip system back to double-layer wafer system + CLHEP::Hep3Vector u_sensor = UA + UB; + CLHEP::Hep3Vector v_sensor = VA + VB; + CLHEP::Hep3Vector w_sensor = WA + WB; + + CLHEP::HepRotation rot_sensor( u_sensor, v_sensor, w_sensor ); + CLHEP::HepMatrix rot_sensor_matrix; + rot_sensor_matrix = rot_sensor; + + double cos2_alpha = VA.cos2Theta(v_sensor) ; // alpha = strip angle + double sin2_alpha = 1 - cos2_alpha ; + + CLHEP::HepSymMatrix cov_plane(3,0); // u,v,w + + cov_plane(1,1) = (0.5 * du2) / cos2_alpha; + cov_plane(2,2) = (0.5 * du2) / sin2_alpha; + + debug() << "\t cov_plane = " << cov_plane << endmsg; + debug() << "\tstrip_angle = " << VA.angle(VB)/(M_PI/180) / 2.0 << " degrees " << endmsg; + + CLHEP::HepSymMatrix cov_xyz= cov_plane.similarity(rot_sensor_matrix); + + debug() << "\t cov_xyz = " << cov_xyz << endmsg; + + std::array<float, 6> cov; + //EVENT::FloatVec cov( 9 ) ; + int icov = 0 ; + for(int irow=0; irow<3; ++irow ){ + for(int jcol=0; jcol<irow+1; ++jcol){ + // std::cout << "row = " << irow << " col = " << jcol << std::endl ; + cov[icov] = cov_xyz[irow][jcol] ; +// std::cout << "cov["<< icov << "] = " << cov[icov] << std::endl ; + ++icov ; + } + } + + spacePoint.setCovMatrix(cov); + + debug() << "\tHit accepted id=" << spacePoint.id() << endmsg; + + return spacePoint; +} +/* +TrackerHitImpl* SpacePointBuilderAlg::createSpacePointOld( TrackerHitPlane* a , TrackerHitPlane* b ){ + + streamlog_out( DEBUG2 ) << "\t OLD OLD OLD OLD\n"; + + + const double* p1 = a->getPosition(); + double x1 = p1[0]; + double y1 = p1[1]; + double z1 = p1[2]; + const float* v1 = a->getV(); + float ex1 = cos( v1[1] ) * sin( v1[0] ); + float ey1 = sin( v1[1] ) * sin( v1[0] ); + + const double* p2 = b->getPosition(); + double x2 = p2[0]; + double y2 = p2[1]; + double z2 = p2[2]; + const float* v2 = b->getV(); + float ex2 = cos( v2[1] ) * sin( v2[0] ); + float ey2 = sin( v2[1] ) * sin( v2[0] ); + + streamlog_out( DEBUG2 ) << "\t ( " << x1 << " " << y1 << " " << z1 << " ) <--> ( " << x2 << " " << y2 << " " << z2 << " )\n"; + + double x=0.; + double y=0.; + + if ( calculateXingPoint( x1, y1, ex1, ey1, x2, y2, ex2, ey2, x, y ) != 0 ){ + + _nStripsTooParallel++; + streamlog_out( DEBUG2 ) << "\tStrips too parallel\n\n"; + return NULL; //calculate the xing point and if that fails don't create a spacepoint + + } + + double z= (z1 + z2)/2.; + + streamlog_out( DEBUG2 ) << "\tPosition of space point (global) : ( " << x << " " << y << " " << z << " )\n"; + + // Check if the new hit is within the boundary + CLHEP::Hep3Vector globalPoint(x,y,z); + // gear::MeasurementSurface* ms = gear::MeasurementSurfaceStore::Instance().GetMeasurementSurface( a->getCellID() ); + CLHEP::Hep3Vector localPoint = ms->getCoordinateSystem()->getLocalPoint(globalPoint); + localPoint.setZ( 0. ); // we set w to 0 so it is in the plane ( we are only interested if u and v are in or out of range, to exclude w from the check it is set to 0) + if( !ms->isLocalInBoundary( localPoint ) ){ + + _nOutOfBoundary++; + streamlog_out( DEBUG2 ) << "\tHit is out of boundary: local coordinates are ( " + << localPoint.x() << " " << localPoint.y() << " " << localPoint.z() << " )\n\n"; + + return NULL; + + } + + + //Create the new TrackerHit + TrackerHitImpl* spacePoint = new TrackerHitImpl(); + + double pos[3] = {x,y,z}; + spacePoint->setPosition( pos ) ; + + streamlog_out( DEBUG2 ) << "\tHit accepted\n\n"; + + return spacePoint; + +} +*/ + + + +int SpacePointBuilderAlg::calculatePointBetweenTwoLines_UsingVertex( + const CLHEP::Hep3Vector& PA, + const CLHEP::Hep3Vector& PB, + const CLHEP::Hep3Vector& PC, + const CLHEP::Hep3Vector& PD, + const CLHEP::Hep3Vector& Vertex, + CLHEP::Hep3Vector& point){ + + + // A general point on the line joining point PA to point PB is + // x, where 2*x=(1+m)*PA + (1-m)*PB. Similarly for 2*y=(1+n)*PC + (1-n)*PD. + // Suppose that v is the vertex. Requiring that the two 'general + // points' lie on a straight through v means that the vector x-v is a + // multiple of y-v. This condition fixes the parameters m and n. + // We then return the 'space-point' x, supposed to be the layer containing PA and PB. + // We require that -1<m<1, otherwise x lies + // outside the segment PA to PB; and similarly for n. + + bool ok = true; + +// streamlog_out( DEBUG1 ) << " Vertex = " << Vertex << std::endl; +// +// streamlog_out( DEBUG1 ) << " PA = " << PA << std::endl; +// streamlog_out( DEBUG1 ) << " PB = " << PB << std::endl; +// streamlog_out( DEBUG1 ) << " PC = " << PC << std::endl; +// streamlog_out( DEBUG1 ) << " PD = " << PD << std::endl; + + CLHEP::Hep3Vector VAB(PA-PB); + CLHEP::Hep3Vector VCD(PC-PD); + +// streamlog_out( DEBUG1 ) << " VAB = " << VAB << std::endl; +// streamlog_out( DEBUG1 ) << " VCD = " << VCD << std::endl; + + CLHEP::Hep3Vector s(PA+PB-2*Vertex); // twice the vector from vertex to midpoint + CLHEP::Hep3Vector t(PC+PD-2*Vertex); // twice the vector from vertex to midpoint + + CLHEP::Hep3Vector qs(VAB.cross(s)); + CLHEP::Hep3Vector rt(VCD.cross(t)); + +// streamlog_out( DEBUG1 ) << " s = " << s << std::endl; +// streamlog_out( DEBUG1 ) << " t = " << t << std::endl; +// streamlog_out( DEBUG1 ) << " qs = " << qs << std::endl; +// streamlog_out( DEBUG1 ) << " rt = " << rt << std::endl; + + + double m = (-(s*rt)/(VAB*rt)); // ratio for first line + + double limit = 1.0; + + if (m>limit || m<-1.*limit) { + debug() << "m' = " << m << endmsg; + ok = false; + } + else { + double n = (-(t*qs)/(VCD*qs)); // ratio for second line + if (n>limit || n<-1.*limit) { + debug() << "n' = " << n << endmsg; + ok = false; + } + } + + if (ok) { + point = 0.5*(PA + PB + m*VAB); + } + + return ok ? 0 : 1; +} + + + +int SpacePointBuilderAlg::calculatePointBetweenTwoLines( const CLHEP::Hep3Vector& P1, const CLHEP::Hep3Vector& V1, const CLHEP::Hep3Vector& P2, const CLHEP::Hep3Vector& V2, CLHEP::Hep3Vector& point ){ + + // Richgungsvektor normal auf die anderen beiden: + CLHEP::Hep3Vector n = V1.cross( V2 ); + + // Now we want to rotate into a coordinate system, where n is parallel to the z axis + // For this: first set phi to 0 + // then: set theta to 0 (we set phi to 0 first, so we can then rotate arount the y axis) + CLHEP::HepRotation rot; + rot.rotateZ( -n.phi() ); + CLHEP::Hep3Vector nPrime = rot * n; //now the phi of nPrime should be 0 + debug() << "phi of n'' = " << nPrime.phi() << " (it should be 0!!!)\n"; + rot.rotateY( -n.theta() ); + nPrime = rot * n; + debug() << "phi of n' = " << nPrime.phi() << " (it should be 0!!!)\n"; + debug() << "theta of n' = " << nPrime.theta() << " (it should be 0!!!)" << endmsg; + + // Now rotate all the vectors and points into this coordinatesystem. + CLHEP::Hep3Vector P1prime = rot * P1; + CLHEP::Hep3Vector V1prime = rot * V1; + CLHEP::Hep3Vector P2prime = rot * P2; + CLHEP::Hep3Vector V2prime = rot * V2; + + // What is the gain of rotating into this system? + // A: + double x; + double y; + int res = calculateXingPoint( P1prime.x(), P1prime.y(), V1prime.x(), V1prime.y(), P2prime.x(), P2prime.y(), V2prime.x(), V2prime.y(), x, y ); + + if ( res != 0 ) return 1; + + point.setX( x ); + point.setY( y ); + point.setZ( (P1prime.z() + P2prime.z())/2. ); + + // Now transform back to the global coordinates + point = rot.inverse() * point; + + return 0; +} + + +int SpacePointBuilderAlg::calculateXingPoint( double x1, double y1, float ex1, float ey1, double x2, double y2, float ex2, float ey2, double& x, double& y ){ + float a = (x1*ey1 - y1*ex1) - (x2*ey1 - y2*ex1); + float b = ex2*ey1 - ex1*ey2; + + const float epsilon = 0.00001; + + if( fabs(b) < epsilon ) return 1; // if b==0 the two directions e1 and e2 are parallel and there is no crossing! + + float t = a/b; + + x = x2 + t*ex2; + y = y2 + t*ey2; + + return 0; +} + + +std::vector< int > SpacePointBuilderAlg::getCellID0sAtBack( int cellID0 ){ + std::vector< int > back; + + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + cellID.setValue( cellID0 ); + + int subdet = cellID[ UTIL::ILDCellID0::subdet ] ; + + if( subdet == UTIL::ILDDetID::FTD ) return getCellID0sAtBackOfFTD( cellID0 ); + if( subdet == UTIL::ILDDetID::SIT ) return getCellID0sAtBackOfSIT( cellID0 ); + if( subdet == UTIL::ILDDetID::SET ) return getCellID0sAtBackOfSET( cellID0 ); + + return back; +} + + +std::vector< int > SpacePointBuilderAlg::getCellID0sAtBackOfFTD( int cellID0 ){ + std::vector< int > back; + + const gear::FTDLayerLayout& ftdLayers = _GEAR->getFTDParameters().getFTDLayerLayout(); + + //find out layer, module, sensor + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + cellID.setValue( cellID0 ); + +// int side = cellID[ UTIL::ILDCellID0::side ]; +// int module = cellID[ UTIL::ILDCellID0::module ]; + int sensor = cellID[ UTIL::ILDCellID0::sensor ]; + int layer = cellID[ UTIL::ILDCellID0::layer ]; + + //check if sensor is in front + if(( ftdLayers.isDoubleSided( layer ) ) && ( sensor <= ftdLayers.getNSensors( layer ) / 2 ) ){ + cellID[ UTIL::ILDCellID0::sensor ] = sensor + ftdLayers.getNSensors( layer ) / 2; + // it is assumed (according to current gear and mokka), that sensors 1 until n/2 will be on front + // and sensor n/2 + 1 until n are at the back + // so the sensor x, will have sensor x+n/2 at the back + back.push_back( cellID.lowWord() ); + } + return back; +} + +std::vector< int > SpacePointBuilderAlg::getCellID0sAtBackOfSIT( int cellID0 ){ + std::vector< int > back; + +// const gear::ZPlanarLayerLayout& sitLayout = _GEAR->getSITParameters().getZPlanarLayerLayout(); + + //find out layer, module, sensor + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + cellID.setValue( cellID0 ); + +// int side = cellID[ UTIL::ILDCellID0::side ]; +// int module = cellID[ UTIL::ILDCellID0::module ]; +// int sensor = cellID[ UTIL::ILDCellID0::sensor ]; + int layer = cellID[ UTIL::ILDCellID0::layer ]; + + //check if sensor is in front + if( layer%2 == 0 ){ // even layers are front sensors + cellID[ UTIL::ILDCellID0::layer ] = layer + 1; + // it is assumed that the even layers are the front layers + // and the following odd ones the back layers + back.push_back( cellID.lowWord() ); + } + return back; +} + +std::vector< int > SpacePointBuilderAlg::getCellID0sAtBackOfSET( int cellID0 ){ + std::vector< int > back; + +// const gear::ZPlanarLayerLayout& setLayout = _GEAR->getSETParameters().getZPlanarLayerLayout(); + + //find out layer, module, sensor + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + cellID.setValue( cellID0 ); + + // int side = cellID[ UTIL::ILDCellID0::side ]; + // int module = cellID[ UTIL::ILDCellID0::module ]; + // int sensor = cellID[ UTIL::ILDCellID0::sensor ]; + int layer = cellID[ UTIL::ILDCellID0::layer ]; + + //check if sensor is in front + if( layer%2 == 0 ){ // even layers are front sensors + cellID[ UTIL::ILDCellID0::layer ] = layer + 1; + // it is assumed that the even layers are the front layers + // and the following odd ones the back layers + back.push_back( cellID.lowWord() ); + } + return back; +} + +std::string SpacePointBuilderAlg::getCellID0Info( int cellID0 ){ + std::stringstream s; + + //find out layer, module, sensor + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + cellID.setValue( cellID0 ); + + int subdet = cellID[ UTIL::ILDCellID0::subdet ] ; + int side = cellID[ UTIL::ILDCellID0::side ]; + int module = cellID[ UTIL::ILDCellID0::module ]; + int sensor = cellID[ UTIL::ILDCellID0::sensor ]; + int layer = cellID[ UTIL::ILDCellID0::layer ]; + + s << "(su" << subdet << ",si" << side << ",la" << layer << ",mo" << module << ",se" << sensor << ")"; + + return s.str(); +} + + + diff --git a/Reconstruction/SiliconTracking/src/SpacePointBuilderAlg.h b/Reconstruction/SiliconTracking/src/SpacePointBuilderAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..17cae2394b7e9801ad2cd1a44865da0b28e81ec7 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/SpacePointBuilderAlg.h @@ -0,0 +1,185 @@ +#ifndef SpacePointBuilder_h +#define SpacePointBuilder_h 1 + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +//#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" + +#include "CLHEP/Vector/ThreeVector.h" + +/** ================= FTD Space Point Builder ================= + * + * Builds space points for pairs of silicon strip detectors. + * The digitisers create TrackerHitPlanars for the front and the back strips. + * In order to get a spacepoint (as is needed by track reconstruction) those strip measurements need to be combined into one space point. + * + * This is done by this processor. + * + * <h4>Input - Prerequisites</h4> + * + * The TrackerHitPlanars as created by the Digitisers of FTD, SET or SIT. + * This could of course be used for other detectors as well, but as information about the detector + * is acquired from gear, and as different detectors (at the moment) are stored differently + * in gear, used detectors have to be taken care of in the code. + * + * <h4>Output</h4> + * + * A collection of TrackerHits containing the constructed space points. + * The created hits will store the original strip hits in their rawHits. + * + * @param TrackerHitCollection The name of the input collection of TrackerHits coming from strip detectors on the FTD, SIT or SET <br> + * (default name FTDTrackerHits) <br> + * + * @param SpacePointsCollection The name of the output collection of the created spacepoints <br> + * (default name FTDSpacePoints) <br> + * + * @param TrackerHitSimHitRelCollection The name of the input collection of the relations of the TrackerHits to SimHits<br> + * (default name FTDTrackerHitRelations)<br> + * + * @param SimHitSpacePointRelCollection The name of the SpacePoint SimTrackerHit relation output collection <br> + * (default name VTXTrackerHitRelations) <br> + * + * @author Robin Glattauer HEPHY, Vienna + * + */ + +namespace gear { class GearMgr; } + +class SpacePointBuilderAlg : public GaudiAlgorithm { + public: + + SpacePointBuilderAlg(const std::string& name, ISvcLocator* svcLoc); + + /** Called at the begin of the job before anything is read. + * Use to initialize the processor, e.g. book histograms. + */ + virtual StatusCode initialize() ; + + virtual StatusCode execute() ; + + virtual StatusCode finalize() ; + + //virtual void check( LCEvent * evt ) ; + + + /** Called after data processing for clean up. + */ + //virtual void end() ; + + protected: + // Input collection + DataHandle<edm4hep::MCParticleCollection> _inMCColHdl{"MCParticle", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackerHitCollection> _inHitColHdl{"FTDStripTrackerHits", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoTrackerAssociationCollection> _inHitAssColHdl{"FTDStripTrackerHitsAssociation", Gaudi::DataHandle::Reader, this}; + // Output collection + DataHandle<edm4hep::TrackerHitCollection> _outSPColHdl{"FTDSpacePoints", Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCRecoTrackerAssociationCollection> _outSPAssColHdl{"FTDSpacePointsAssociation", Gaudi::DataHandle::Writer, this}; + /** Calculates the 2 dimensional crossing point of two lines. + * Each line is specified by a point (x,y) and a direction vector (ex,ey). + * + * @return 0, if the calculation has been successful, another number if there was a problem. + */ + //static + int calculateXingPoint( double x1, double y1, float ex1, float ey1, double x2, double y2, float ex2, float ey2, double& x, double& y ); + + /** Calculates a point between two lines in a way that it is equidistant from both lines and as close to them as + * possible. + * So when you calculate the distance between two lines, and you actually draw this distance as a short connecting + * line, the point in the middle of this line, is what this method finds. + * \verbatim + / + / + /|___here!!! + / | + ---------/-------------- (line a) + / + /(line b) + + \endverbatim + * (If this sketch looks terrible, you probably read this in doxygen and it still needs to be formatted in a + * way, that it still looks sensible in doxygen.) + * + * @param P1 a point on the first line + * @param V1 the direction vector of the first line + * + * @param point the reference to a point where the result will be stored + */ + //static + int calculatePointBetweenTwoLines( + const CLHEP::Hep3Vector& P1, + const CLHEP::Hep3Vector& V1, + const CLHEP::Hep3Vector& P2, + const CLHEP::Hep3Vector& V2, + CLHEP::Hep3Vector& point ); + + + + /** Calculates the intersection of a line L and line PAPB ( strip on the first sensor ). + * L is constrained to pass through the point "Vertex" and bisect both lines PAPB ( strip on the first sensor ) and PCPD ( strip on the second sensor ) + * @param PA start of the first line + * @param PB end of the first line + * @param PC start of the second line + * @param PD end of the second line + * @param Vertex the position + * + * @param point the reference to a point where the result will be stored + */ + //static + int calculatePointBetweenTwoLines_UsingVertex( + const CLHEP::Hep3Vector& PA, + const CLHEP::Hep3Vector& PB, + const CLHEP::Hep3Vector& PC, + const CLHEP::Hep3Vector& PD, + const CLHEP::Hep3Vector& Vertex, + CLHEP::Hep3Vector& point); + + + /** @return a spacepoint (in the form of a TrackerHitImpl* ) created from two TrackerHitPlane* which stand for si-strips */ + edm4hep::TrackerHit createSpacePoint( edm4hep::TrackerHit* a , edm4hep::TrackerHit* b, double stripLength ); + +// TrackerHitImpl* createSpacePointOld( TrackerHitPlane* a , TrackerHitPlane* b ); + + /** @return the CellID0s of the sensors that are back to back to a given front sensor. If the given sensor + * is in the back itself or has no corresponding sensor(s) on the back the vector will be empty. + * + * @param cellID0 a CellID0 corresponding to a sensor + */ + std::vector< int > getCellID0sAtBack( int cellID0 ); + + std::vector< int > getCellID0sAtBackOfFTD( int cellID0 ); + + std::vector< int > getCellID0sAtBackOfSET( int cellID0 ); + + std::vector< int > getCellID0sAtBackOfSIT( int cellID0 ); + + + /** @return information about the contents of the passed CellID0 */ + std::string getCellID0Info( int cellID0 ); + + gear::GearMgr* _GEAR; + + int _nRun ; + int _nEvt ; + + unsigned _nOutOfBoundary; + unsigned _nStripsTooParallel; + unsigned _nPlanesNotParallel; + + float _nominal_vertex_x; + float _nominal_vertex_y; + float _nominal_vertex_z; + + CLHEP::Hep3Vector _nominal_vertex; + + float _striplength_tolerance; + +} ; + +#endif + + + diff --git a/Reconstruction/SiliconTracking/src/TrackSubsetAlg.cpp b/Reconstruction/SiliconTracking/src/TrackSubsetAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8961484d60abc0b61f9106325a37974176fa5732 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/TrackSubsetAlg.cpp @@ -0,0 +1,338 @@ +#include "TrackSubsetAlg.h" + +#include "GearSvc/IGearSvc.h" +#include "TrackSystemSvc/ITrackSystemSvc.h" +#include "DataHelper/Navigation.h" + +#include <UTIL/ILDConf.h> + +#include <gear/BField.h> + +#include "KiTrack/SubsetSimple.h" +#include "KiTrack/SubsetHopfieldNN.h" +#include "Tools/Fitter.h" +#include "Tools/KiTrackMarlinTools.h" + +#include "TrackSystemSvc/MarlinTrkUtils.h" + +using namespace KiTrack; + +DECLARE_COMPONENT(TrackSubsetAlg) + +TrackSubsetAlg::TrackSubsetAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc){ + + // modify processor description + //_description = "TrackSubsetAlg takes tracks from multiple sources and outputs them (or modified versions, or a subset of them) as one track collection." ; + + //std::vector< std::string > trackInputColNamesDefault; + //trackInputColNamesDefault.push_back( "ForwardTracks" ); + //trackInputColNamesDefault.push_back( "SiTracks" ); + + declareProperty("TrackSubsetCollection", _outColHdl, "Handle of the SiTrack output collection"); +} + +StatusCode TrackSubsetAlg::initialize() { + + debug() << " init called " << endmsg; + + _nRun = 0 ; + _nEvt = 0 ; + + for(unsigned i=0; i<_trackInputColNames.size(); i++){ + _inTrackColHdls.push_back(new DataHandle<edm4hep::TrackCollection> (_trackInputColNames[i], Gaudi::DataHandle::Reader, this)); + } + + for(unsigned i=0; i<_trackerHitInputColNames.size(); i++){ + _inTrackerHitColHdls.push_back(new DataHandle<edm4hep::TrackerHitCollection> (_trackerHitInputColNames[i], Gaudi::DataHandle::Reader, this)); + } + /**********************************************************************************************/ + /* Initialise the MarlinTrkSystem, needed by the tracks for fitting */ + /**********************************************************************************************/ + auto _gear = service<IGearSvc>("GearSvc"); + if ( !_gear ) { + error() << "Failed to find GearSvc ..." << endmsg; + return StatusCode::FAILURE; + } + gear::GearMgr* gearMgr = _gear->getGearMgr(); + _bField = gearMgr->getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + // set upt the geometry + auto _trackSystemSvc = service<ITrackSystemSvc>("TrackSystemSvc"); + if ( !_trackSystemSvc ) { + error() << "Failed to find TrackSystemSvc ..." << endmsg; + return StatusCode::FAILURE; + } + _trkSystem = _trackSystemSvc->getTrackSystem(); + + if( _trkSystem == 0 ){ + error() << "Cannot initialize MarlinTrkSystem of Type: KalTest" <<endmsg; + return StatusCode::FAILURE; + } + + // set the options + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useQMS, _MSOn ) ; //multiple scattering + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::usedEdx, _ElossOn) ; //energy loss + _trkSystem->setOption( MarlinTrk::IMarlinTrkSystem::CFG::useSmoothing, _SmoothOn) ; //smoothing + + // initialise the tracking system + //_trkSystem->init() ; + + return GaudiAlgorithm::initialize(); +} + +StatusCode TrackSubsetAlg::finalize(){ + for(unsigned i=0; i<_inTrackColHdls.size(); i++){ + delete _inTrackColHdls[i]; + } + _inTrackColHdls.clear(); + + for(unsigned i=0; i<_inTrackerHitColHdls.size(); i++){ + delete _inTrackerHitColHdls[i]; + } + _inTrackerHitColHdls.clear(); + + return GaudiAlgorithm::finalize(); +} + +StatusCode TrackSubsetAlg::execute(){ + std::vector<edm4hep::Track> tracks; + + /**********************************************************************************************/ + /* Read in the collections */ + /**********************************************************************************************/ + debug() << "Try to load " << _trackInputColNames.size() << " input track collections" << endmsg; + + unsigned nTrackLoaded = 0; + + for( unsigned i=0; i < _inTrackColHdls.size(); i++ ){ + const edm4hep::TrackCollection* trackCol = nullptr; + try { + trackCol = _inTrackColHdls[i]->get(); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inTrackColHdls[i]->fullKey() << " is unavailable in event " << _nEvt << endmsg; + continue; + } + + if(trackCol){ + int nTracks = trackCol->size(); + debug() << "Load track input collection " << _trackInputColNames[i] << " with " << nTracks << " tracks" << endmsg; + + for(auto track : *trackCol){ + tracks.push_back( track ); + nTrackLoaded++; + } + } + else error() << "track input collection " << _trackInputColNames[i] << " could not be found, but not throw exception!!!" << endmsg; + } + + debug() << "Loaded all in all " << nTrackLoaded << " tracks, which will now get further processed" << endmsg; + if(tracks.size()==0) return StatusCode::SUCCESS; + + Navigation::Instance()->Initialize(); + for(unsigned i=0; i < _inTrackerHitColHdls.size(); i++){ + try { + auto trackCol = _inTrackerHitColHdls[i]->get(); + Navigation::Instance()->AddTrackerHitCollection(trackCol); + } + catch ( GaudiException &e ) { + debug() << "Collection " << _inTrackerHitColHdls[i]->fullKey() << " is unavailable in event " << _nEvt << endmsg; + continue; + } + } + /**********************************************************************************************/ + /* Make sure that all tracks are compatible: find the best subset */ + /**********************************************************************************************/ + debug() << "Find the best subset of tracks using the Hopfield Neural Network" << endmsg; + + TrackQI trackQI( _trkSystem ); + + debug() << "The tracks and their qualities (and their hits ): " << endmsg; + + std::vector<edm4hep::Track*> tracks_p; + for( unsigned i=0; i < tracks.size(); i++ ){ + edm4hep::Track* track = &tracks[i]; + tracks_p.push_back(track); + double qi = trackQI( track ); + debug() << "Track " << track->id() << " address " << track << "\t" << qi << "( "; + std::vector<edm4hep::ConstTrackerHit> hits; + std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(hits)); + + std::sort( hits.begin(), hits.end(), KiTrackMarlin::compare_TrackerHit_z ); + + for( unsigned j=0; j<hits.size(); j++ ){ + debug() << hits[j].id() << " "; + double x = hits[j].getPosition()[0]; + double y = hits[j].getPosition()[1]; + double z = hits[j].getPosition()[2]; + debug() << "[" << x << "," << y << "," << z << "]"; + } + debug() << ")" << endmsg; + } + + TrackCompatibility comp; + + SubsetHopfieldNN<edm4hep::Track*> subset; + //SubsetSimple<edm4hep::Track* > subset; + subset.add( tracks_p ); + subset.setOmega( _omega ); + subset.calculateBestSet( comp, trackQI ); + + std::vector<edm4hep::Track*> accepted = subset.getAccepted(); + std::vector<edm4hep::Track*> rejected = subset.getRejected(); + + debug() << "\tThe accepted tracks:" << endmsg; + for( unsigned i=0; i < accepted.size(); i++ ){ + debug() << accepted[i]->id() << " address " << accepted[i] << endmsg; + } + + debug() << "\tThe rejected tracks:" << endmsg; + for( unsigned i=0; i < rejected.size(); i++ ){ + debug() << rejected[i]->id() << " address " << rejected[i] << endmsg; + } + + /**********************************************************************************************/ + /* Save the tracks to a collection (make new TrackImpls from them) */ + /**********************************************************************************************/ + debug() << "Fitting and saving of the tracks" << endmsg; + + auto trkCol = _outColHdl.createAndPut(); + + for( unsigned i=0; i < accepted.size(); i++ ){ + edm4hep::Track trackImpl; + + edm4hep::Track* track = accepted[i]; + + std::vector<edm4hep::ConstTrackerHit> trackerHitsObj; + std::vector<edm4hep::TrackerHit*> trackerHits; + std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(trackerHitsObj)); + + for(unsigned i=0; i<trackerHitsObj.size(); i++){ + //debug() << trackerHitsObj[i].id() << endmsg; + trackerHits.push_back(Navigation::Instance()->GetTrackerHit(trackerHitsObj[i].getObjectID())); + } + // setup initial dummy covariance matrix + std::array<float,15> covMatrix; + for (unsigned icov = 0; icov<covMatrix.size(); ++icov) { + covMatrix[icov] = 0; + } + + covMatrix[0] = ( _initialTrackError_d0 ); //sigma_d0^2 + covMatrix[2] = ( _initialTrackError_phi0 ); //sigma_phi0^2 + covMatrix[5] = ( _initialTrackError_omega ); //sigma_omega^2 + covMatrix[9] = ( _initialTrackError_z0 ); //sigma_z0^2 + covMatrix[14] = ( _initialTrackError_tanL ); //sigma_tanl^2 + + std::vector< std::pair<float, edm4hep::TrackerHit*> > r2_values; + r2_values.reserve(trackerHits.size()); + + for (std::vector<edm4hep::TrackerHit*>::iterator it=trackerHits.begin(); it!=trackerHits.end(); ++it) { + edm4hep::TrackerHit* h = *it; + float r2 = h->getPosition()[0]*h->getPosition()[0]+h->getPosition()[1]*h->getPosition()[1]; + r2_values.push_back(std::make_pair(r2, *it)); + } + + sort(r2_values.begin(),r2_values.end()); + + trackerHits.clear(); + trackerHits.reserve(r2_values.size()); + + for (std::vector< std::pair<float, edm4hep::TrackerHit*> >::iterator it=r2_values.begin(); it!=r2_values.end(); ++it) { + trackerHits.push_back(it->second); + } + + bool fit_backwards = MarlinTrk::IMarlinTrack::backward; + + MarlinTrk::IMarlinTrack* marlinTrk = _trkSystem->createTrack(); + + int error = 0; + + try { + + error = MarlinTrk::createFinalisedLCIOTrack(marlinTrk, trackerHits, &trackImpl, fit_backwards, covMatrix, _bField, _maxChi2PerHit); + + } catch (...) { + + // delete Track; + // delete marlinTrk; + + throw ; + + } + + // Add hit numbers + + std::vector<std::pair<edm4hep::TrackerHit* , double> > hits_in_fit ; + std::vector<std::pair<edm4hep::TrackerHit* , double> > outliers ; + std::vector<edm4hep::TrackerHit*> all_hits; + all_hits.reserve(300); + + marlinTrk->getHitsInFit(hits_in_fit); + + for ( unsigned ihit = 0; ihit < hits_in_fit.size(); ++ihit) { + all_hits.push_back(hits_in_fit[ihit].first); + } + + UTIL::BitField64 cellID_encoder( lcio::ILDCellID0::encoder_string ) ; + + MarlinTrk::addHitNumbersToTrack(&trackImpl, all_hits, true, cellID_encoder); + + marlinTrk->getOutliers(outliers); + + for ( unsigned ihit = 0; ihit < outliers.size(); ++ihit) { + all_hits.push_back(outliers[ihit].first); + } + + MarlinTrk::addHitNumbersToTrack(&trackImpl, all_hits, false, cellID_encoder); + + delete marlinTrk; + + if( error != MarlinTrk::IMarlinTrack::success ) { + //delete trackImpl; + debug() << "TrackSubsetAlg:: Track fit failed with error code " << error << " track dropped. Number of hits = "<< trackerHits.size() << endmsg; + continue ; + } + + if( trackImpl.getNdf() < 0) { + //delete trackImpl; + debug() << "TrackSubsetAlg:: Track fit returns " << trackImpl.getNdf() << " degress of freedom track dropped. Number of hits = "<< trackerHits.size() << endmsg; + continue ; + } + + trkCol->push_back(trackImpl); + +// try{ +// +// Fitter fitter( trackImpl , _trkSystem ); +// +// TrackStateImpl* trkStateIP = new TrackStateImpl( fitter.getTrackState( lcio::TrackState::AtIP ) ) ; +// trackImpl->setChi2( fitter.getChi2( lcio::TrackState::AtIP ) ); +// trackImpl->setNdf( fitter.getNdf( lcio::TrackState::AtIP ) ); +// trkStateIP->setLocation( TrackState::AtIP ); +// trackImpl->addTrackState( trkStateIP ); +// +// trackVec->addElement(trackImpl); +// +// } +// catch( FitterException e ){ +// +// delete trackImpl; +// +// streamlog_out( ERROR ) << "TrackImpl nr " << i << " rejected, because fit failed: " << e.what() << "\n"; +// continue; +// +// } + } + + debug() << "Saving " << trkCol->size() << " tracks" << endmsg; + + _nEvt ++ ; + return StatusCode::SUCCESS; +} + + + + + + diff --git a/Reconstruction/SiliconTracking/src/TrackSubsetAlg.h b/Reconstruction/SiliconTracking/src/TrackSubsetAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..5676d977e038ead73ce3088922b618a04e8e7549 --- /dev/null +++ b/Reconstruction/SiliconTracking/src/TrackSubsetAlg.h @@ -0,0 +1,117 @@ +#ifndef TrackSubsetAlg_h +#define TrackSubsetAlg_h 1 + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" + +#include "edm4hep/TrackCollection.h" +//#include "edm4hep/Track.h" +#include "TrackSystemSvc/IMarlinTrkSystem.h" + +#include "Math/ProbFunc.h" + +/** Processor that takes tracks from multiple sources and outputs them (or modified versions, or a subset of them) + * as one track collection. + * + * <h4>Input - Prerequisites</h4> + * Track collections + * + * <h4>Output</h4> + * A single track collection + * + * @param TrackInputCollections A vector of the input track collections <br> + * (default value ForwardTracks SiTracks ) + * + * @param TrackOutputCollection Name of the output track collection <br> + * (default value SubsetTracks ) + * + * @param MultipleScatteringOn Whether to take multiple scattering into account when fitting the tracks<br> + * (default value true ) + * + * @param EnergyLossOn Whether to take energyloss into account when fitting the tracks<br> + * (default value true ) + * + * @param SmoothOn Whether to smooth all measurement sites in fit<br> + * (default value false ) + * + * @param Omega The parameter omega for the HNN. Controls the influence of the quality indicator. Between 0 and 1: + * 1 means high influence of quality indicator, 0 means no influence. + * + * @author Robin Glattauer, HEPHY + * + */ + +class TrackSubsetAlg : public GaudiAlgorithm { + public: + + TrackSubsetAlg(const std::string& name, ISvcLocator* svcLoc); + + virtual StatusCode initialize() ; + + virtual StatusCode execute() ; + + virtual StatusCode finalize() ; + + protected: + MarlinTrk::IMarlinTrkSystem* _trkSystem; + /* Input collection */ + std::vector<DataHandle<edm4hep::TrackCollection>* > _inTrackColHdls; + std::vector<DataHandle<edm4hep::TrackerHitCollection>* > _inTrackerHitColHdls; + /* Output collection */ + DataHandle<edm4hep::TrackCollection> _outColHdl{"SubsetTracks", Gaudi::DataHandle::Writer, this}; + + Gaudi::Property<std::vector<std::string> > _trackInputColNames{this, "TrackInputCollections", {"ForwardTracks", "SiTracks"}}; + Gaudi::Property<std::vector<std::string> > _trackerHitInputColNames{this, "RawTrackerHitCollections", + {"VXDTrackerHits", "SITTrackerHits", "FTDPixelTrackerHits", "FTDStripTrackerHits"}}; + Gaudi::Property<bool> _MSOn{this, "MultipleScatteringOn", true}; + Gaudi::Property<bool> _ElossOn{this, "EnergyLossOn", true}; + Gaudi::Property<bool> _SmoothOn{this, "SmoothOn", false}; + Gaudi::Property<float> _initialTrackError_d0{this, "InitialTrackErrorD0",1e6}; + Gaudi::Property<float> _initialTrackError_phi0{this, "InitialTrackErrorPhi0",1e2}; + Gaudi::Property<float> _initialTrackError_omega{this, "InitialTrackErrorOmega",1e-4}; + Gaudi::Property<float> _initialTrackError_z0{this, "InitialTrackErrorZ0",1e6}; + Gaudi::Property<float> _initialTrackError_tanL{this, "InitialTrackErrorTanL",1e2}; + Gaudi::Property<double> _maxChi2PerHit{this, "MaxChi2PerHit", 1e2}; + Gaudi::Property<double> _omega{this, "Omega", 0.75}; + + float _bField; + + int _nRun ; + int _nEvt ; +}; + +/** A functor to return whether two tracks are compatible: The criterion is if the share a TrackerHit or more */ +class TrackCompatibility{ + public: + inline bool operator()( edm4hep::Track* trackA, edm4hep::Track* trackB ){ + unsigned nHitsA = trackA->trackerHits_size(); + unsigned nHitsB = trackB->trackerHits_size(); + for( unsigned i=0; i < nHitsA; i++){ + for( unsigned j=0; j < nHitsB; j++){ + if ( trackA->getTrackerHits(i) == trackB->getTrackerHits(j) ) return false; // a hit is shared -> incompatible + } + } + + return true; + } +}; + + +/** A functor to return the quality of a track, which is currently the chi2 probability. */ +class TrackQI{ + public: + /** @param trkSystem a pointer to an IMarlinTrkSystem, needed for fitting of tracks */ + TrackQI( MarlinTrk::IMarlinTrkSystem* trkSystem ): _trkSystem(trkSystem){} + + inline double operator()( edm4hep::Track* track ){ + return ROOT::Math::chisquared_cdf_c( track->getChi2() , track->getNdf() ); + } + + protected: + + MarlinTrk::IMarlinTrkSystem* _trkSystem; +}; +#endif + + + diff --git a/Service/TrackSystemSvc/CMakeLists.txt b/Service/TrackSystemSvc/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..98f32914f19370b83261a09ff94619532c2c67d6 --- /dev/null +++ b/Service/TrackSystemSvc/CMakeLists.txt @@ -0,0 +1,33 @@ +gaudi_subdir(TrackSystemSvc v0r0) + +find_package(ROOT 6.14 REQUIRED COMPONENTS Matrix Physics) +find_package(CLHEP REQUIRED) +find_package(GEAR REQUIRED) +find_package(LCIO REQUIRED) +find_package(EDM4HEP REQUIRED) +#find_package(KalTest REQUIRED) +#find_package(KalDet REQUIRED) + +gaudi_depends_on_subdirs(Service/GearSvc Detector/DetInterface Utilities/DataHelper Utilities/KalTest Utilities/KalDet) + +set(TrackSystemSvc_srcs src/*.cpp) +set(TrackSystemSvcLib_srcs src/*.cc) + +gaudi_install_headers(TrackSystemSvc) + +#message( "${INCLUDE_DIRS}" ) +#message( "${LINK_LIBRARIES}" ) + +gaudi_add_library(TrackSystemSvcLib ${TrackSystemSvcLib_srcs} + PUBLIC_HEADERS TrackSystemSvc + INCLUDE_DIRS GaudiKernel ROOT CLHEP gear ${LCIO_INCLUDE_DIRS} ${EDM4HEP_INCLUDE_DIRS} + LINK_LIBRARIES DataHelperLib KalTestLib KalDetLib GaudiKernel ROOT CLHEP $ENV{GEAR}/lib/libgear.so $ENV{GEAR}/lib/libgearsurf.so ${LCIO_LIBRARIES} + -Wl,--no-as-needed + EDM4HEP::edm4hep EDM4HEP::edm4hepDict + -Wl,--as-needed +) + +gaudi_add_module(TrackSystemSvc ${TrackSystemSvc_srcs} + INCLUDE_DIRS GaudiKernel gear + LINK_LIBRARIES TrackSystemSvcLib GaudiKernel $ENV{GEAR}/lib/libgear.so +) diff --git a/Service/TrackSystemSvc/TrackSystemSvc/ConfigFlags.h b/Service/TrackSystemSvc/TrackSystemSvc/ConfigFlags.h new file mode 100644 index 0000000000000000000000000000000000000000..bba197528272dd3fd14cd9b6a4c190fc84ce2bb4 --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/ConfigFlags.h @@ -0,0 +1,94 @@ +#ifndef ConfigFlags_h +#define ConfigFlags_h + +#include <string> +#include <iostream> +#include <exception> +#include <map> + +namespace MarlinTrk { + + class ConfigFlags ; + + inline std::ostream& operator<<(std::ostream& os, const ConfigFlags& cf) ; + + class ConfigFlags{ + + friend std::ostream& operator<<(std::ostream& os, const ConfigFlags& flags) ; + + typedef std::pair<std::string, bool> Flag ; + typedef std::map< unsigned, Flag > Map ; + + + public: + + /** Helper class that holds a number of boolean properties for configuration. + * The property keys (type: unsigned) have to be defined in the class using + * this class. + */ + ConfigFlags() {} + + ~ConfigFlags(){} + + + void registerOption( unsigned key, const std::string& name, bool defaultValue=false ){ + + _map[ key ] = std::make_pair( name , defaultValue ) ; + } + + bool option(unsigned key) const { + + Map::const_iterator it = _map.find( key ) ; + + if( it == _map.end() ) + return false ; + + return it->second.second ; + } + + bool operator[](unsigned key) const { + return option( key ) ; + } + + void setOption(unsigned key , bool val) { + + Map::iterator it = _map.find( key ) ; + + if( it !=_map.end() ) + it->second.second = val ; + } + + + std::string& optionName(unsigned key) { + + static std::string empty("UNKNOWN") ; + + Map::iterator it = _map.find( key ) ; + + if( it == _map.end() ) + return empty ; + + return it->second.first ; + } + + protected: + Map _map ; + + }; + + + inline std::ostream& operator<<(std::ostream& os, const MarlinTrk::ConfigFlags& cf) { + + for( ConfigFlags::Map::const_iterator it = cf._map.begin(); it != cf._map.end() ; ++it){ + + os << " option: " << it->second.first << "\t: " << it->second.second << std::endl ; + } + + return os ; + } + +} // namespace + + +#endif + diff --git a/Service/TrackSystemSvc/TrackSystemSvc/HelixFit.h b/Service/TrackSystemSvc/TrackSystemSvc/HelixFit.h new file mode 100644 index 0000000000000000000000000000000000000000..6497531b35b1dd9cb4e2bf3a17761e40c6407d86 --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/HelixFit.h @@ -0,0 +1,57 @@ +#ifndef __HELIXFIT__ +#define __HELIXFIT__ +// +// HelixFit.h +// MarlinTrk +// + +/** + // Created by Steve Aplin on 9/16/11. + // DESY + // + // C++ rewrite of the aleph Fortran routine TFITHL + // + //! Fast helix fit + // + // + // Input: NPT Number of 3-D points to be fit + // xf Array of X-values of points to be fit + // yf Array of Y-values of points to be fit + // zf Array of Z-values of points to be fit + // wf Array of 1/(sig(rphi))**2 for each point + // wzf Array of 1/(sig(z))**2 for each point + // iopt < 3 : error matrix calculated + // = 3 : 3-dimensional iteration + // + // OUTPUT: vv0 = Helix parameter in perigee form + // ee0 = INVERSE OF ERROR MATRIX IN TRIANG. FORM + // chi2ph = CHI SQUARED = SUM (PHI DEVIATIONS/ERRORS)**2 + // CH2Z = CHI SQUARED = SUM (Z DEVIATIONS/ERRORS)**2 + // NOTE: DEGREES OF FREEDOM = 2*NPT-5 + //---------------------------------------------------------------- + // BASED ON SUBROUTINE CIRCLE + // REFERENCE: COMPUTER PHYSICS COMMUNICATIONS VOL 33,P329 + // + // AUTHORS: N. CHERNOV, G. OSOSKOV & M. POPPE + // Modified by: Fred Weber, 8 Jun 1989 + // Modified by: M.Cattaneo, 27-Jan-1998 + // Protect against arg SIN > 1.0 + // + //----------------------------------------------------------------- + */ + +namespace MarlinTrk { + + class HelixFit { + + + public: + + int fastHelixFit(int npt, double* xf, double* yf, float* rf, float* pf, double* wf, float* zf , float* wzf, int iopt, + float* vv0, float* ee0, float& ch2ph, float& ch2z); + + }; + +} + +#endif diff --git a/Service/TrackSystemSvc/TrackSystemSvc/HelixTrack.h b/Service/TrackSystemSvc/TrackSystemSvc/HelixTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..0f049621a314f62d16d457e45c63737e00bc107f --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/HelixTrack.h @@ -0,0 +1,62 @@ +#ifndef HelixTrack_h +#define HelixTrack_h + +#include <cmath> + +namespace edm4hep{ + class Vector3d; +} + +class HelixTrack { + +public: + + HelixTrack( double ref_point_x, double ref_point_y, double ref_point_z, double d0, double z0, double phi0, double omega, double tanLambda ) + : _ref_point_x(ref_point_x), _ref_point_y(ref_point_y), _ref_point_z(ref_point_z), _d0(d0), _z0(z0), _phi0(phi0), _omega(omega), _tanLambda(tanLambda) + { + while ( _phi0 < -M_PI ) _phi0 += 2.0*M_PI ; + while ( _phi0 >= M_PI ) _phi0 -= 2.0*M_PI; + } + + HelixTrack( const edm4hep::Vector3d& x1, const edm4hep::Vector3d& x2, const edm4hep::Vector3d& x3, double Bz, bool direction ); + + HelixTrack( const edm4hep::Vector3d& position, const edm4hep::Vector3d& p, double charge, double Bz ) ; + + double moveRefPoint( double x, double y, double z) ; + + double getRefPointX() const { return _ref_point_x ; } + double getRefPointY() const { return _ref_point_y ; } + double getRefPointZ() const { return _ref_point_z ; } + double getD0() const { return _d0 ; } + double getZ0() const { return _z0 ; } + double getPhi0() const { return _phi0; } + double getOmega() const { return _omega ; } + double getTanLambda() const { return _tanLambda ; } + + // defines if s of the helix increases in the direction of x2 to x3 + static bool forwards; + +private: + + double _ref_point_x ; + double _ref_point_y ; + double _ref_point_z ; + double _d0 ; + double _z0 ; + double _phi0 ; + double _omega ; + double _tanLambda ; + + /** helper function to restrict the range of the azimuthal angle to ]-pi,pi]*/ + inline double toBaseRange( double phi) const { + while( phi <= -M_PI ){ phi += 2. * M_PI ; } + while( phi > M_PI ){ phi -= 2. * M_PI ; } + return phi ; + } + +} ; + + + + +#endif diff --git a/Service/TrackSystemSvc/TrackSystemSvc/IMarlinTrack.h b/Service/TrackSystemSvc/TrackSystemSvc/IMarlinTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..2abcdd52a59e1955445375b91c1eb4d5b2b69a5d --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/IMarlinTrack.h @@ -0,0 +1,232 @@ +#ifndef IMarlinTrack_h +#define IMarlinTrack_h + +#include <cfloat> + +//#include "lcio.h" + +#include "edm4hep/TrackerHit.h" +#include "edm4hep/TrackState.h" + +//#include "gearimpl/Vector3D.h" +//#include "plcio/DoubleThree.h" +#include "edm4hep/Vector3d.h" + +#include <exception> + + /** Interface for generic tracks in MarlinTrk. The interface should provide the functionality to + * perform track finding and fitting. It is asssumed that the underlying implemetation will by + * a Kalman Filter or a similar algorithm. + * + * @version $Id: IMarlinTrack.h 3989 2012-09-04 07:16:44Z aplin $ + * @author S.Aplin, F. Gaede DESY + */ +namespace MarlinTrk{ + class IMarlinTrack { + + public: + + /** boolean constant for defining backward direction - to be used for intitialise */ + static const bool backward ; + + /** boolean constant for defining backward direction - to be used for intitialise */ + static const bool forward ; + + + + static const int modeBackward ; + static const int modeClosest ; + static const int modeForward ; + + + static const int success ; // no error + static const int error ; + static const int bad_intputs ; + static const int no_intersection ; // no intersection found + static const int site_discarded ; // measurement discarded by the fitter + static const int site_fails_chi2_cut ; // measurement discarded by the fitter due to chi2 cut + static const int all_sites_fail_fit ; // no single measurement added to the fit + + + /**default d'tor*/ + virtual ~IMarlinTrack() {}; + + /** add hit to track - the hits have to be added ordered in time ( i.e. typically outgoing ) + * this order will define the direction of the energy loss used in the fit + */ + virtual int addHit(edm4hep::TrackerHit* hit) = 0 ; + + /** initialise the fit using the hits added up to this point - + * the fit direction has to be specified using IMarlinTrack::backward or IMarlinTrack::forward. + * this is the order wrt the order used in addHit() that will be used in the fit() + */ + virtual int initialise( bool fitDirection ) = 0 ; + + /** initialise the fit with a track state, and z component of the B field in Tesla. + * the fit direction has to be specified using IMarlinTrack::backward or IMarlinTrack::forward. + * this is the order that will be used in the fit(). + * it is the users responsibility that the track state is consistent with the order + * of the hits used in addHit() ( i.e. the direction of energy loss ) + */ + virtual int initialise( const edm4hep::TrackState& ts, double bfield_z, bool fitDirection ) = 0 ; + + + /** perform the fit of all current hits, returns error code ( IMarlinTrack::success if no error ) . + * the fit will be performed in the order specified at initialise() wrt the order used in addHit(), i.e. + * IMarlinTrack::backward implies fitting from the outside to the inside for tracks comming from the IP. + */ + virtual int fit( double maxChi2Increment=DBL_MAX ) = 0 ; + + + /** update the current fit using the supplied hit, return code via int. Provides the Chi2 increment to the fit from adding the hit via reference. + * the given hit will not be added if chi2increment > maxChi2Increment. + */ + virtual int addAndFit( edm4hep::TrackerHit* hit, double& chi2increment, double maxChi2Increment=DBL_MAX ) = 0 ; + + + /** obtain the chi2 increment which would result in adding the hit to the fit. This method will not alter the current fit, and the hit will not be stored in the list of hits or outliers + */ + virtual int testChi2Increment( edm4hep::TrackerHit* hit, double& chi2increment ) = 0 ; + + + /** smooth all track states + */ + virtual int smooth() = 0 ; + + + /** smooth track states from the last filtered hit back to the measurement site associated with the given hit + */ + virtual int smooth( edm4hep::TrackerHit* hit ) = 0 ; + + + + // Track State Accessesors + + /** get track state, returning TrackState, chi2 and ndf via reference + */ + virtual int getTrackState( edm4hep::TrackState& ts, double& chi2, int& ndf ) = 0 ; + + + /** get track state at measurement associated with the given hit, returning TrackState, chi2 and ndf via reference + */ + virtual int getTrackState( edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf ) = 0 ; + + /** get the list of hits included in the fit, together with the chi2 contributions of the hits. + * Pointers to the hits together with their chi2 contribution will be filled into a vector of + * pairs consitining of the pointer as the first part of the pair and the chi2 contribution as + * the second. + */ + virtual int getHitsInFit( std::vector<std::pair<edm4hep::TrackerHit*, double> >& hits ) = 0 ; + + /** get the list of hits which have been rejected by from the fit due to the a chi2 increment greater than threshold, + * Pointers to the hits together with their chi2 contribution will be filled into a vector of + * pairs consitining of the pointer as the first part of the pair and the chi2 contribution as + * the second. + */ + virtual int getOutliers( std::vector<std::pair<edm4hep::TrackerHit*, double> >& hits ) = 0 ; + + /** get the current number of degrees of freedom for the fit. + */ + virtual int getNDF( int& ndf ) = 0 ; + + /** get TrackeHit at which fit became constrained, i.e. ndf >= 0 + */ + virtual int getTrackerHitAtPositiveNDF( edm4hep::TrackerHit*& trkhit ) = 0 ; + + // PROPAGATORS + + /** propagate the fit to the point of closest approach to the given point, returning TrackState, chi2 and ndf via reference + */ + virtual int propagate( const edm4hep::Vector3d& point, edm4hep::TrackState& ts, double& chi2, int& ndf ) = 0 ; + + + /** propagate the fit at the measurement site associated with the given hit, to the point of closest approach to the given point, + * returning TrackState, chi2 and ndf via reference + */ + virtual int propagate( const edm4hep::Vector3d& point, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf ) = 0 ; + + + /** propagate fit to numbered sensitive layer, returning TrackState, chi2, ndf and integer ID of the intersected sensitive detector element via reference + */ + virtual int propagateToLayer( int layerID, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) = 0 ; + + /** propagate the fit at the measurement site associated with the given hit, to numbered sensitive layer, + * returning TrackState, chi2, ndf and integer ID of the intersected sensitive detector element via reference + */ + virtual int propagateToLayer(int layerID, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) = 0; + + /** propagate the fit to sensitive detector element, returning TrackState, chi2 and ndf via reference + */ + virtual int propagateToDetElement( int detElementID, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) = 0 ; + + /** propagate the fit at the measurement site associated with the given hit, to sensitive detector element, + * returning TrackState, chi2 and ndf via reference + */ + virtual int propagateToDetElement( int detEementID, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) = 0 ; + + + + // EXTRAPOLATORS + + /** extrapolate the fit to the point of closest approach to the given point, returning TrackState, chi2 and ndf via reference + */ + virtual int extrapolate( const edm4hep::Vector3d& point, edm4hep::TrackState& ts, double& chi2, int& ndf ) = 0 ; + + /** extrapolate the fit at the measurement site associated with the given hit, to the point of closest approach to the given point, + * returning TrackState, chi2 and ndf via reference + */ + virtual int extrapolate( const edm4hep::Vector3d& point, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf ) = 0 ; + + /** extrapolate the fit to numbered sensitive layer, returning TrackState, chi2, ndf and integer ID of the intersected sensitive detector element via reference + */ + virtual int extrapolateToLayer( int layerID, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) = 0 ; + + /** extrapolate the fit at the measurement site associated with the given hit, to numbered sensitive layer, + * returning TrackState, chi2, ndf and integer ID of the intersected sensitive detector element via reference + */ + virtual int extrapolateToLayer( int layerID, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) = 0 ; + + /** extrapolate the fit to sensitive detector element, returning TrackState, chi2 and ndf via reference + */ + virtual int extrapolateToDetElement( int detElementID, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) = 0 ; + + /** extrapolate the fit at the measurement site associated with the given hit, to sensitive detector element, + * returning TrackState, chi2 and ndf via reference + */ + virtual int extrapolateToDetElement( int detEementID, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) = 0 ; + + + // INTERSECTORS + + /** extrapolate the fit to numbered sensitive layer, returning intersection point in global coordinates and integer ID of the + * intersected sensitive detector element via reference + */ + virtual int intersectionWithLayer( int layerID, edm4hep::Vector3d& point, int& detElementID, int mode=modeClosest ) = 0 ; + + /** extrapolate the fit at the measurement site associated with the given hit, to numbered sensitive layer, + * returning intersection point in global coordinates and integer ID of the intersected sensitive detector element via reference + */ + virtual int intersectionWithLayer( int layerID, edm4hep::TrackerHit* hit, edm4hep::Vector3d& point, int& detElementID, int mode=modeClosest ) = 0 ; + + + /** extrapolate the fit to numbered sensitive detector element, returning intersection point in global coordinates via reference + */ + virtual int intersectionWithDetElement( int detElementID, edm4hep::Vector3d& point, int mode=modeClosest ) = 0 ; + + /** extrapolate the fit at the measurement site associated with the given hit, to sensitive detector element, + * returning intersection point in global coordinates via reference + */ + virtual int intersectionWithDetElement( int detEementID, edm4hep::TrackerHit* hit, edm4hep::Vector3d& point, int mode=modeClosest ) = 0 ; + + + protected: + + private: + + IMarlinTrack& operator=( const IMarlinTrack&) ; // disallow assignment operator + + } ; + std::string errorCode( int error ); +} +#endif + diff --git a/Service/TrackSystemSvc/TrackSystemSvc/IMarlinTrkSystem.h b/Service/TrackSystemSvc/TrackSystemSvc/IMarlinTrkSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..2c19b1e420c3fecccc917d4ba20e9e1959856f58 --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/IMarlinTrkSystem.h @@ -0,0 +1,105 @@ +#ifndef IMarlinTrkSystem_h +#define IMarlinTrkSystem_h + +//#include "MarlinTrkDiagnostics.h" + +#include <exception> +#include "ConfigFlags.h" + +namespace MarlinTrk{ +class IMarlinTrack ; + +/** Exception thrown in IMarlinTrk namespace (implemetations of IMarlinTrkSystem + * and IMarlinTrack). + */ +class Exception : public std::exception { + + protected: + std::string message ; + + Exception(){ /*no_op*/ ; } + + public: + virtual ~Exception() throw() { /*no_op*/; } + + Exception( const std::string& text ){ + message = "MarlinTrk::Exception: " + text ; + } + + virtual const char* what() const throw() { return message.c_str() ; } + +}; + +//---------------------------------------------------------------------------------------------------- + +/** Base class for tracking system implementations in MarlinTrk. + * + * @version $Id: IMarlinTrkSystem.h 3288 2012-04-03 09:25:12Z aplin $ + * @author S.Aplin, F. Gaede DESY + */ + +class IMarlinTrkSystem { + + public: + + /** 'Enums' for configuration options to be used with setOption(). + */ + struct CFG { + /** Use multiple scattering in the track fits. */ + static const unsigned useQMS = 1 ; + /** Use multiple scattering in the track fits. */ + static const unsigned usedEdx = 2 ; + /** Use smoothing when calling fit( bool fitDirection ) */ + static const unsigned useSmoothing = 3 ; + //--- + static const unsigned size = 4 ; + + } ; + + + /** D'tor - cleans up any allocated resources.*/ + virtual ~IMarlinTrkSystem() {}; + + + /** Sets the specified option ( one of the constants defined in IMarlinTrkSystem::CFG ) + * to the given value. + */ + void setOption(unsigned CFGOption, bool val) ; + + /** Return the option's current value - false if option not defined. + */ + bool getOption( unsigned CFGOption) ; + + /** String with all configuration options and their current values. + */ + std::string getOptions() ; + + + /** Initialise tracking system - to be called after configuration with setOption() - + * IMarlinTrkSystem cannot be used before a call to init(). + */ + virtual void init() = 0 ; + + + /** Return an instance of IMarlinTrack corresponding to the current implementation. + */ + virtual IMarlinTrack* createTrack() = 0 ; + + protected: + + MarlinTrk::ConfigFlags _cfg ; + + /** Register the possible configuration options + */ + void registerOptions() ; + + + + private: + + IMarlinTrkSystem& operator=( const IMarlinTrkSystem&) ; // disallow assignment operator + +}; +} +#endif + diff --git a/Service/TrackSystemSvc/TrackSystemSvc/ITrackSystemSvc.h b/Service/TrackSystemSvc/TrackSystemSvc/ITrackSystemSvc.h new file mode 100644 index 0000000000000000000000000000000000000000..699d26bab97dae97c77f5bf5969f5bd68631e835 --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/ITrackSystemSvc.h @@ -0,0 +1,21 @@ +#ifndef ITrackSystemSvc_h +#define ITrackSystemSvc_h + +#include "GaudiKernel/IService.h" +#include "IMarlinTrkSystem.h" + +// ITrackSystemSvc is the interface between Gaudi and Track. + +class ITrackSystemSvc: virtual public IService { + public: + DeclareInterfaceID(ITrackSystemSvc, 0, 1); // major/minor version + + virtual ~ITrackSystemSvc() = default; + + //Get the track manager + virtual MarlinTrk::IMarlinTrkSystem* getTrackSystem() = 0; + + virtual void removeTrackSystem() = 0; +}; + +#endif diff --git a/Service/TrackSystemSvc/TrackSystemSvc/LCIOTrackPropagators.h.remove b/Service/TrackSystemSvc/TrackSystemSvc/LCIOTrackPropagators.h.remove new file mode 100644 index 0000000000000000000000000000000000000000..a697cbd304b64cc5736be59a2e3171a6f38fd24b --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/LCIOTrackPropagators.h.remove @@ -0,0 +1,42 @@ +#ifndef LCIOTrackPropagators_h +#define LCIOTrackPropagators_h + +namespace EVENT{ + class TrackState ; +} + +namespace IMPL{ + class TrackStateImpl ; +} + + +namespace LCIOTrackPropagators{ + + /** Propagate trackstate to a new reference point + */ + int PropagateLCIOToNewRef( IMPL::TrackStateImpl& ts, double xref, double yref, double zref) ; + + /** Propagate trackstate to a new reference point taken as its crossing point with a cylinder of infinite length centered at x0,y0, parallel to the z axis. + For direction== 0 the closest crossing point will be taken + For direction== 1 the first crossing traversing in positive s will be taken + For direction==-1 the first crossing traversing in negative s will be taken + */ + int PropagateLCIOToCylinder( IMPL::TrackStateImpl& ts, float r, float x0, float y0, int direction=0, double epsilon=1.0e-8) ; + + + /** Propagate trackstate to a new reference point taken as its crossing point with an infinite plane located at z, perpendicular to the z axis + */ + int PropagateLCIOToZPlane( IMPL::TrackStateImpl& ts, float z) ; + + /** Propagate trackstate to a new reference point taken as its crossing point with a plane parallel to the z axis, containing points x1,x2 and y1,y2. Tolerance for intersection determined by epsilon. + For direction== 0 the closest crossing point will be taken + For direction== 1 the first crossing traversing in positive s will be taken + For direction==-1 the first crossing traversing in negative s will be taken + */ + int PropagateLCIOToPlaneParralelToZ( IMPL::TrackStateImpl& ts, float x1, float y1, float x2, float y2, int direction=0, double epsilon=1.0e-8) ; + + + +} + +#endif diff --git a/Service/TrackSystemSvc/TrackSystemSvc/MarlinTrkDiagnostics.h.remove b/Service/TrackSystemSvc/TrackSystemSvc/MarlinTrkDiagnostics.h.remove new file mode 100644 index 0000000000000000000000000000000000000000..ffa97ef3a475db11770b447d8ac9c4ab9047775a --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/MarlinTrkDiagnostics.h.remove @@ -0,0 +1,31 @@ +#ifndef MarlinTrkDiagnostics_h +#define MarlinTrkDiagnostics_h + +//// switch to turn on diagnostics code +//#define MARLINTRK_DIAGNOSTICS_ON + +#ifdef MARLINTRK_DIAGNOSTICS_ON + +#include "lcio.h" +#include "EVENT/SimTrackerHit.h" +#include "EVENT/TrackerHit.h" + + +namespace MarlinTrk{ + + + // LCIO Extension creating a pointer to the simhit for trackerhits + struct MCTruth4HitExtStruct{ + MCTruth4HitExtStruct() : simhit(0) {} + EVENT::SimTrackerHit* simhit; + } ; + struct MCTruth4HitExt : lcio::LCOwnedExtension<MCTruth4HitExt, MCTruth4HitExtStruct> {} ; + + // fills a vector of MCParticle pointers with the MCParticles assosiated with the provided tracker hit using MCTruth4HitExtStruct + void getMCParticlesForTrackerHit(EVENT::TrackerHit* trkhit, std::vector<EVENT::MCParticle*>& mcps) ; + +} + +#endif + +#endif diff --git a/Service/TrackSystemSvc/TrackSystemSvc/MarlinTrkUtils.h b/Service/TrackSystemSvc/TrackSystemSvc/MarlinTrkUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..73826c710158625139ec872ef6c6c0fe4a7903a7 --- /dev/null +++ b/Service/TrackSystemSvc/TrackSystemSvc/MarlinTrkUtils.h @@ -0,0 +1,86 @@ +#ifndef INCLUDE_MarlinTrkUtils +#define INCLUDE_MarlinTrkUtils 1 + +#include <vector> +#include <array> +#include <cfloat> + +#include <LCIOSTLTypes.h> + +namespace edm4hep{ + class Track; + class TrackerHit; + class TrackState; +} + +namespace UTIL { + class BitField64; +} + + +namespace MarlinTrk{ + class IMarlinTrack ; +} + + +namespace MarlinTrk{ + enum Location{ + AtOther = 0, + AtIP = 1, + AtFirstHit = 2, + AtLastHit = 3, + AtCalorimeter = 4, + AtVertex = 5, + LastLocation = 6 + }; + /** Takes a list of hits and uses the IMarlinTrack inferface to fit them using a supplied prefit containing + * a covariance matrix for the initialisation. The TrackImpl will have the 4 trackstates added to + * it @IP, @First_Hit, @Last_Hit and @CaloFace */ + int createFinalisedLCIOTrack( + IMarlinTrack* marlinTrk, + std::vector<edm4hep::TrackerHit*>& hit_list, + edm4hep::Track* track, + bool fit_backwards, + edm4hep::TrackState* pre_fit, + float bfield_z, + double maxChi2Increment=DBL_MAX); + + /** Takes a list of hits and uses the IMarlinTrack inferface to fit them using a supplied covariance matrix + * for the initialisation. The TrackImpl will have the 4 trackstates added to + * it @IP, @First_Hit, @Last_Hit and @CaloFace */ + int createFinalisedLCIOTrack( + IMarlinTrack* marlinTrk, + std::vector<edm4hep::TrackerHit*>& hit_list, + edm4hep::Track* track, + bool fit_backwards, + const std::array<float,15>& initial_cov_for_prefit, + float bfield_z, + double maxChi2Increment=DBL_MAX); + + /** Provides the values of a track state from the first, middle and last hits in the hit_list. */ + int createPrefit( std::vector<edm4hep::TrackerHit*>& hit_list, edm4hep::TrackState* pre_fit, float bfield_z, bool fit_backwards ); + + /** Takes a list of hits and uses the IMarlinTrack inferface to fit them using a supplied prefit containing a covariance matrix for the initialisation. */ + int createFit( std::vector<edm4hep::TrackerHit*>& hit_list, IMarlinTrack* marlinTrk, edm4hep::TrackState* pre_fit, float bfield_z, bool fit_backwards, double maxChi2Increment=DBL_MAX ); + + /** Takes a fitted MarlinTrack, TrackImpl to record the fit and the hits which have been added to the fit. + * The TrackImpl will have the 4 trackstates added to it @IP, @First_Hit, @Last_Hit and @CaloFace. + * Note: the hit list is needed as the IMarlinTrack only contains the hits used in the fit, not the spacepoints + * (if any have been included) so as the strip hits cannot point to the space points we need to have the list so + * that they can be recorded in the LCIO TrackImpl */ + int finaliseLCIOTrack( + IMarlinTrack* marlinTrk, + edm4hep::Track* track, + std::vector<edm4hep::TrackerHit*>& hit_list, + edm4hep::TrackState* atLastHit=0, + edm4hep::TrackState* atCaloFace=0); + + /** Set the subdetector hit numbers for the TrackImpl */ + void addHitNumbersToTrack(edm4hep::Track* track, std::vector<edm4hep::TrackerHit*>& hit_list, bool hits_in_fit, UTIL::BitField64& cellID_encoder); + + /** Set the subdetector hit numbers for the TrackImpl */ + void addHitNumbersToTrack(edm4hep::Track* track, std::vector<std::pair<edm4hep::TrackerHit* , double> >& hit_list, bool hits_in_fit, UTIL::BitField64& cellID_encoder); + +} + +#endif diff --git a/Service/TrackSystemSvc/src/DiagnosticsController.cc.remove b/Service/TrackSystemSvc/src/DiagnosticsController.cc.remove new file mode 100644 index 0000000000000000000000000000000000000000..cbdf6b64b8119ebf24ae44ca533993fef1085f3a --- /dev/null +++ b/Service/TrackSystemSvc/src/DiagnosticsController.cc.remove @@ -0,0 +1,883 @@ + +#include "MarlinTrkDiagnostics.h" + +#ifdef MARLINTRK_DIAGNOSTICS_ON + +#include "DiagnosticsController.h" + +#define MarlinTrkNtuple_cxx +#include "MarlinTrkNtuple.h" + +#include "MarlinKalTestTrack.h" + +#include "streamlog/streamlog.h" + +#include "kaldet/ILDVTrackHit.h" +#include "kaltest/TKalTrackSite.h" +#include "kaltest/TKalTrack.h" + +#include "TFile.h" +#include "TTree.h" + +//#include "MarlinTrk/MarlinTrkNtuple.h" + +#include "HelixTrack.h" + +#include "EVENT/MCParticle.h" +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + + +namespace MarlinTrk{ + + DiagnosticsController::DiagnosticsController() { + + _initialised = false; + _recording_on = false; // recording is set to off by default so that processors do not have to perform any action if they are not interested in diagnostics, i.e. no need to call init + _current_track = 0; + _currentMCP = 0; + _mcpInfoStored=false; + _skip_track = false; + _ntracks_skipped = 0; + _ntracks_written = 0; + _track_record = 0; + _tree = 0; + _root_file = 0; + + } // constructor + + DiagnosticsController::~DiagnosticsController(){ + if(_track_record) { delete _track_record; _track_record = 0; } + } + + void DiagnosticsController::init(std::string root_file_name, std::string root_tree_name, bool recording_on){ + + streamlog_out(DEBUG4) << " DiagnosticsController::init called " << "\n" + << "\t root file name = " << root_file_name << "\n" + << "\t root tree name = " << root_tree_name << "\n" + << "\t recording on = " << recording_on << "\n" + << std::endl; + + _recording_on = recording_on; + + if ( _recording_on == false ) { + _initialised = true; + return; + } + + _root_file_name = root_file_name+".root"; + _root_tree_name = root_tree_name; + + _root_file = new TFile(_root_file_name.c_str(),"RECREATE"); + + _tree = new TTree( _root_tree_name.c_str(), _root_tree_name.c_str()); + + _track_record = new MarlinTrkNtuple(); + + _track_record->CreateBranches(_tree); + + _initialised = true; + + } + + + void DiagnosticsController::skip_current_track(){ + + streamlog_out(DEBUG) << " DiagnosticsController::skip_current_track called " << std::endl; + + if ( _recording_on == false ) { + return; + } + + _skip_track = true ; + this->clear_track_record(); + } + + void DiagnosticsController::clear_track_record(){ + + streamlog_out(DEBUG) << " DiagnosticsController::clear_track_record called " << std::endl; + + if ( _recording_on == false ) { + return; + } + + _track_record->error_code = 0 ; + + _track_record->nsites = 0 ; + + _track_record->nsites_vxd = 0 ; + _track_record->nsites_sit = 0 ; + _track_record->nsites_ftd = 0 ; + _track_record->nsites_tpc = 0 ; + _track_record->nsites_set = 0 ; + + _track_record->x_mcp = 0 ; + _track_record->y_mcp = 0 ; + _track_record->z_mcp = 0 ; + + _track_record->px_mcp = 0 ; + _track_record->py_mcp = 0 ; + _track_record->pz_mcp = 0 ; + _track_record->p_mcp = 0 ; + _track_record->theta_mcp = 0 ; + _track_record->phi_mcp = 0 ; + _track_record->pdg_mcp = 0 ; + + _track_record->d0_mcp = 0 ; + _track_record->phi0_mcp = 0 ; + _track_record->omega_mcp = 0 ; + _track_record->z0_mcp = 0 ; + _track_record->tanL_mcp = 0 ; + + _track_record->ndf = 0 ; + _track_record->chi2 = 0 ; + _track_record->prob = 0 ; + + _track_record->d0_seed = 0 ; + _track_record->phi0_seed = 0 ; + _track_record->omega_seed = 0 ; + _track_record->z0_seed = 0 ; + _track_record->tanL_seed = 0 ; + + _track_record->seed_ref_point_x = 0 ; + _track_record->seed_ref_point_y = 0 ; + _track_record->seed_ref_point_z = 0 ; + + _track_record->cov_seed_d0d0 = 0 ; + _track_record->cov_seed_phi0d0 = 0 ; + _track_record->cov_seed_phi0phi0 = 0 ; + _track_record->cov_seed_kappad0 = 0 ; + _track_record->cov_seed_kappaphi0 = 0 ; + _track_record->cov_seed_kappakappa = 0 ; + _track_record->cov_seed_z0d0 = 0 ; + _track_record->cov_seed_z0phi0 = 0 ; + _track_record->cov_seed_z0kappa = 0 ; + _track_record->cov_seed_z0z0 = 0 ; + _track_record->cov_seed_tanLd0 = 0 ; + _track_record->cov_seed_tanLphi0 = 0 ; + _track_record->cov_seed_tanLkappa = 0 ; + _track_record->cov_seed_tanLz0 = 0 ; + _track_record->cov_seed_tanLtanL = 0 ; + + + _track_record->d0_ip = 0 ; + _track_record->phi0_ip = 0 ; + _track_record->omega_ip = 0 ; + _track_record->z0_ip = 0 ; + _track_record->tanL_ip = 0 ; + + _track_record->cov_ip_d0d0 = 0 ; + _track_record->cov_ip_phi0d0 = 0 ; + _track_record->cov_ip_phi0phi0 = 0 ; + _track_record->cov_ip_omegad0 = 0 ; + _track_record->cov_ip_omegaphi0 = 0 ; + _track_record->cov_ip_omegaomega = 0 ; + _track_record->cov_ip_z0d0 = 0 ; + _track_record->cov_ip_z0phi0 = 0 ; + _track_record->cov_ip_z0omega = 0 ; + _track_record->cov_ip_z0z0 = 0 ; + _track_record->cov_ip_tanLd0 = 0 ; + _track_record->cov_ip_tanLphi0 = 0 ; + _track_record->cov_ip_tanLomega = 0 ; + _track_record->cov_ip_tanLz0 = 0 ; + _track_record->cov_ip_tanLtanL = 0 ; + + for ( int i = 0 ; i<MAX_SITES; ++i) { + + _track_record->CellID0[i] = 0 ; + _track_record->rejected[i] = 0 ; + + _track_record->site_x[i] = 0 ; + _track_record->site_y[i] = 0 ; + _track_record->site_z[i] = 0 ; + + _track_record->ref_point_x[i] = 0 ; + _track_record->ref_point_y[i] = 0 ; + _track_record->ref_point_z[i] = 0 ; + + _track_record->d0_mc[i] = 0 ; + _track_record->phi0_mc[i] = 0 ; + _track_record->omega_mc[i] = 0 ; + _track_record->z0_mc[i] = 0 ; + _track_record->tanL_mc[i] = 0 ; + + _track_record->d0_predicted[i] = 0 ; + _track_record->phi0_predicted[i] = 0 ; + _track_record->omega_predicted[i] = 0 ; + _track_record->z0_predicted[i] = 0 ; + _track_record->tanL_predicted[i] = 0 ; + + _track_record->d0_filtered[i] = 0 ; + _track_record->phi0_filtered[i] = 0 ; + _track_record->omega_filtered[i] = 0 ; + _track_record->z0_filtered[i] = 0 ; + _track_record->tanL_filtered[i] = 0 ; + + _track_record->d0_smoothed[i] = 0 ; + _track_record->phi0_smoothed[i] = 0 ; + _track_record->omega_smoothed[i] = 0 ; + _track_record->z0_smoothed[i] = 0 ; + _track_record->tanL_smoothed[i] = 0 ; + + + _track_record->chi2_inc_filtered[i] = 0 ; + _track_record->chi2_inc_smoothed[i] = 0 ; + _track_record->dim[i] = 0 ; + + _track_record->cov_predicted_d0d0[i] = 0 ; + _track_record->cov_predicted_phi0d0[i] = 0 ; + _track_record->cov_predicted_phi0phi0[i] = 0 ; + _track_record->cov_predicted_omegad0[i] = 0 ; + _track_record->cov_predicted_omegaphi0[i] = 0 ; + _track_record->cov_predicted_omegaomega[i] = 0 ; + _track_record->cov_predicted_z0d0[i] = 0 ; + _track_record->cov_predicted_z0phi0[i] = 0 ; + _track_record->cov_predicted_z0omega[i] = 0 ; + _track_record->cov_predicted_z0z0[i] = 0 ; + _track_record->cov_predicted_tanLd0[i] = 0 ; + _track_record->cov_predicted_tanLphi0[i] = 0 ; + _track_record->cov_predicted_tanLomega[i] = 0 ; + _track_record->cov_predicted_tanLz0[i] = 0 ; + _track_record->cov_predicted_tanLtanL[i] = 0 ; + + _track_record->cov_filtered_d0d0[i] = 0 ; + _track_record->cov_filtered_phi0d0[i] = 0 ; + _track_record->cov_filtered_phi0phi0[i] = 0 ; + _track_record->cov_filtered_omegad0[i] = 0 ; + _track_record->cov_filtered_omegaphi0[i] = 0 ; + _track_record->cov_filtered_omegaomega[i] = 0 ; + _track_record->cov_filtered_z0d0[i] = 0 ; + _track_record->cov_filtered_z0phi0[i] = 0 ; + _track_record->cov_filtered_z0omega[i] = 0 ; + _track_record->cov_filtered_z0z0[i] = 0 ; + _track_record->cov_filtered_tanLd0[i] = 0 ; + _track_record->cov_filtered_tanLphi0[i] = 0 ; + _track_record->cov_filtered_tanLomega[i] = 0 ; + _track_record->cov_filtered_tanLz0[i] = 0 ; + _track_record->cov_filtered_tanLtanL[i] = 0 ; + + _track_record->cov_smoothed_d0d0[i] = 0 ; + _track_record->cov_smoothed_phi0d0[i] = 0 ; + _track_record->cov_smoothed_phi0phi0[i] = 0 ; + _track_record->cov_smoothed_omegad0[i] = 0 ; + _track_record->cov_smoothed_omegaphi0[i] = 0 ; + _track_record->cov_smoothed_omegaomega[i] = 0 ; + _track_record->cov_smoothed_z0d0[i] = 0 ; + _track_record->cov_smoothed_z0phi0[i] = 0 ; + _track_record->cov_smoothed_z0omega[i] = 0 ; + _track_record->cov_smoothed_z0z0[i] = 0 ; + _track_record->cov_smoothed_tanLd0[i] = 0 ; + _track_record->cov_smoothed_tanLphi0[i] = 0 ; + _track_record->cov_smoothed_tanLomega[i] = 0 ; + _track_record->cov_smoothed_tanLz0[i] = 0 ; + _track_record->cov_smoothed_tanLtanL[i] = 0 ; + + + + } + + } + + void DiagnosticsController::new_track(MarlinKalTestTrack* trk){ + + if ( _recording_on == false ) { + return; + } + + if ( _initialised == false ){ + streamlog_out(ERROR) << "DiagnosticsController::new_track: Diagnostics not initialised call init(std::string root_file_name, std::string root_tree_name, bool recording_off) first : exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + } + + streamlog_out(DEBUG3) << " DiagnosticsController::new_track called " << std::endl; + + this->clear_track_record(); + + _current_track = trk; + + _skip_track = false; + _currentMCP = 0; + _mcpInfoStored=false; + + } + + + + void DiagnosticsController::set_intial_track_parameters(double d0, double phi0, double omega, double z0, double tanL, double pivot_x, double pivot_y, double pivot_z, TKalMatrix& cov){ + + if ( _recording_on == false ) { + return; + } + + if ( _initialised == false ){ + streamlog_out(ERROR) << "DiagnosticsController::set_intial_track_parameters: Diagnostics not initialised call init(std::string root_file_name, std::string root_tree_name, bool recording_off) first : exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + } + + streamlog_out(DEBUG3) << " DiagnosticsController::set_intial_track_parameters called " << std::endl; + + _track_record->d0_seed= d0; + _track_record->phi0_seed= phi0; + _track_record->omega_seed= omega; + _track_record->z0_seed= z0; + _track_record->tanL_seed= tanL; + + _track_record->seed_ref_point_x = pivot_x ; + _track_record->seed_ref_point_y = pivot_y ; + _track_record->seed_ref_point_z = pivot_z ; + + + _track_record->cov_seed_d0d0 = cov( 0 , 0 ) ; + _track_record->cov_seed_phi0d0 = cov( 1 , 0 ) ; + _track_record->cov_seed_phi0phi0 = cov( 1 , 1 ) ; + _track_record->cov_seed_kappad0 = cov( 2 , 0 ) ; + _track_record->cov_seed_kappaphi0 = cov( 2 , 1 ) ; + _track_record->cov_seed_kappakappa = cov( 2 , 2 ) ; + _track_record->cov_seed_z0d0 = cov( 3 , 0 ) ; + _track_record->cov_seed_z0phi0 = cov( 3 , 1 ) ; + _track_record->cov_seed_z0kappa = cov( 3 , 2 ) ; + _track_record->cov_seed_z0z0 = cov( 3 , 3 ) ; + _track_record->cov_seed_tanLd0 = cov( 4 , 0 ) ; + _track_record->cov_seed_tanLphi0 = cov( 4 , 1 ) ; + _track_record->cov_seed_tanLkappa = cov( 4 , 2 ) ; + _track_record->cov_seed_tanLz0 = cov( 4 , 3 ) ; + _track_record->cov_seed_tanLtanL = cov( 4 , 4 ) ; + + // cov.Print(); + + + streamlog_out(DEBUG3) << " $#$#$# Initial Track Parameters: " + << "d0 = " << d0 << " " << "[+/-" << sqrt( _track_record->cov_seed_d0d0 ) << "] " + << "phi0 = " << phi0 << " " << "[+/-" << sqrt( _track_record->cov_seed_phi0phi0 ) << "] " + << "omega = " << omega << " " << "[+/-" << sqrt( _track_record->cov_seed_kappakappa ) << "] " + << "z0 = " << z0 << " " << "[+/-" << sqrt( _track_record->cov_seed_z0z0 ) << "] " + << "tanL = " << tanL << " " << "[+/-" << sqrt( _track_record->cov_seed_tanLtanL ) << "] " + << "ref = " << pivot_x << " " << pivot_y << " " << pivot_z << " " + << std::endl; + + } + + + void DiagnosticsController::record_rejected_site(ILDVTrackHit* hit, TKalTrackSite* site){ + + if ( _recording_on == false ) { + return; + } + + if ( _initialised == false ){ + streamlog_out(ERROR) << "DiagnosticsController::record_rejected_site: Diagnostics not initialised call init(std::string root_file_name, std::string root_tree_name, bool recording_off) first : exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + } + + + if(_skip_track) return; + + _track_record->rejected[_track_record->nsites] = 1; + _track_record->CellID0[_track_record->nsites] = hit->getLCIOTrackerHit()->getCellID0(); + + + EVENT::MCParticle* mcp = hit->getLCIOTrackerHit()->ext<MarlinTrk::MCTruth4HitExt>()->simhit->getMCParticle(); + + ++_track_record->nsites; + streamlog_out(DEBUG2) << "record_rejected_site _track_record->nsites = " << _track_record->nsites << " MCParticle of simhit = " << mcp << " pdg " << mcp->getPDG() << " energy = " << mcp->getEnergy() << " id = " << mcp->id() << std::endl; + + } + + + void DiagnosticsController::record_site(ILDVTrackHit* hit, TKalTrackSite* site){ + + if ( _recording_on == false ) { + return; + } + + if ( _initialised == false ){ + streamlog_out(ERROR) << "DiagnosticsController::record_site: Diagnostics not initialised call init(std::string root_file_name, std::string root_tree_name, bool recording_off) first : exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + } + + streamlog_out(DEBUG2) << "DiagnosticsController::record_site called " << std::endl; + + if(_skip_track) return; + + EVENT::TrackerHit* trkhit = hit->getLCIOTrackerHit(); + + MarlinTrk::MCTruth4HitExtStruct* ext = trkhit->ext<MarlinTrk::MCTruth4HitExt>(); + + if ( ! ext ) { + + streamlog_out(ERROR) << "MCTruth4HitExt not attached to TrackerHit use processor SetTrackerHitExtensions to set them: exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + + } + + EVENT::SimTrackerHit* simhit = trkhit->ext<MarlinTrk::MCTruth4HitExt>()->simhit; + + if ( ! simhit ) { + + streamlog_out(ERROR) << "SimTrackerHit not attached to TrackerHit using MCTruth4HitExt use processor SetTrackerHitExtensions to set them: exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + + } + + EVENT::MCParticle* mcp = simhit->getMCParticle() ; + + + if( _track_record->nsites >= 0 ){ + + if ( _mcpInfoStored == false ) { + + streamlog_out(DEBUG2) << "DiagnosticsController::record_site store MCParticle parameters for " << mcp << " pdg " << mcp->getPDG() << " energy = " << mcp->getEnergy() << " id = " << mcp->id() << std::endl; + + _currentMCP = mcp; + + _track_record->x_mcp = mcp->getVertex()[0]; + _track_record->y_mcp = mcp->getVertex()[1]; + _track_record->z_mcp = mcp->getVertex()[2]; + + _track_record->px_mcp = mcp->getMomentum()[0]; + _track_record->py_mcp = mcp->getMomentum()[1]; + _track_record->pz_mcp = mcp->getMomentum()[2]; + + double pt = sqrt(_track_record->px_mcp*_track_record->px_mcp + + _track_record->py_mcp*_track_record->py_mcp ) ; + + _track_record->p_mcp = sqrt( pt*pt + _track_record->pz_mcp*_track_record->pz_mcp ); + + + _track_record->theta_mcp = atan2( pt, _track_record->pz_mcp ); + _track_record->phi_mcp = atan2( _track_record->py_mcp, _track_record->px_mcp ); + + _track_record->pdg_mcp = mcp->getPDG(); + + // HelixTrack helixMC( sim_pos, sim_mom, mcp->getCharge(), ml.GetBz() ) ; + HelixTrack helixMC( mcp->getVertex(), mcp->getMomentum(), mcp->getCharge(), site->GetBfield() ) ; + + helixMC.moveRefPoint(0.0, 0.0, 0.0); + + _track_record->d0_mcp= helixMC.getD0(); + _track_record->phi0_mcp = helixMC.getPhi0(); + _track_record->omega_mcp = helixMC.getOmega(); + _track_record->z0_mcp = helixMC.getZ0(); + _track_record->tanL_mcp = helixMC.getTanLambda(); + + _mcpInfoStored = true; + + } + else if( _currentMCP != mcp ) { + _skip_track = true ; // do not store tracks formed from more than one MCParticle + streamlog_out(WARNING) << "DiagnosticsController::record_site: Track skipped. Not storing tracks formed from more than one MCParticle " << std::endl; + return ; + } + + double sim_pos[3]; + sim_pos[0] = simhit->getPosition()[0]; + sim_pos[1] = simhit->getPosition()[1]; + sim_pos[2] = simhit->getPosition()[2]; + + double sim_mom[3]; + sim_mom[0] = simhit->getMomentum()[0]; + sim_mom[1] = simhit->getMomentum()[1]; + sim_mom[2] = simhit->getMomentum()[2]; + + if ( fabs(sim_mom[0]) < 1.e-09 && fabs(sim_mom[1]) < 1.e-09 && fabs(sim_mom[2]) < 1.e-09 ) { + // then the momentum is sub eV and therefore the momentum was certainly not set + streamlog_out(ERROR) << "Momentum not set in SimTrackerHit exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + + } + + + _track_record->CellID0[_track_record->nsites] = trkhit->getCellID0() ; + + UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string); + encoder.setValue( trkhit->getCellID0() ); + + if (encoder[lcio::ILDCellID0::subdet] == lcio::ILDDetID::VXD) { + ++_track_record->nsites_vxd; + } + else if (encoder[lcio::ILDCellID0::subdet] == lcio::ILDDetID::SIT) { + ++_track_record->nsites_sit; + } + else if (encoder[lcio::ILDCellID0::subdet] == lcio::ILDDetID::FTD) { + ++_track_record->nsites_ftd; + } + else if (encoder[lcio::ILDCellID0::subdet] == lcio::ILDDetID::TPC) { + ++_track_record->nsites_tpc; + } + else if (encoder[lcio::ILDCellID0::subdet] == lcio::ILDDetID::SET) { + ++_track_record->nsites_set; + } + + _track_record->chi2_inc_filtered[_track_record->nsites] = site->GetDeltaChi2(); + _track_record->dim[_track_record->nsites] = site->GetDimension(); + + // create helix from MCTruth at sim hit + // HelixTrack helixMC( sim_pos, sim_mom, mcp->getCharge(), ml.GetBz() ) ; + HelixTrack helixMC( sim_pos, sim_mom, mcp->getCharge(), site->GetBfield() ) ; + + // here perhaps we should move the helix to the hit to calculate the deltas or though this could still be done in the analysis code, as both sim and rec hit positions are stored ? + // helixMC.moveRefPoint(0.0, 0.0, 0.0); + + streamlog_out(DEBUG2) << " $#$#$# SimHit Track Parameters: " + << "x = " << sim_pos[0] << " " + << "y = " << sim_pos[1] << " " + << "z = " << sim_pos[2] << " " + << "px = " << sim_mom[0] << " " + << "py = " << sim_mom[1] << " " + << "pz = " << sim_mom[2] << " " + << "p = " << sqrt(sim_mom[0]*sim_mom[0] + sim_mom[1]*sim_mom[1] + sim_mom[2]*sim_mom[2]) << " " + << "d0 = " << helixMC.getD0() << " " + << "phi0 = " << helixMC.getPhi0() << " " + << "omega = " << helixMC.getOmega() << " " + << "z0 = " << helixMC.getZ0() << " " + << "tanL = " << helixMC.getTanLambda() << " " + << " mcp ID = " << simhit->getMCParticle()->id() + << std::endl; + + _track_record->d0_mc[_track_record->nsites] = helixMC.getD0(); + _track_record->phi0_mc[_track_record->nsites] = helixMC.getPhi0(); + _track_record->omega_mc[_track_record->nsites] = helixMC.getOmega(); + _track_record->z0_mc[_track_record->nsites] = helixMC.getZ0(); + _track_record->tanL_mc[_track_record->nsites] = helixMC.getTanLambda(); + + double rec_x = trkhit->getPosition()[0]; + double rec_y = trkhit->getPosition()[1]; + double rec_z = trkhit->getPosition()[2]; + + _track_record->site_x[_track_record->nsites] = rec_x; + _track_record->site_y[_track_record->nsites] = rec_y; + _track_record->site_z[_track_record->nsites] = rec_z; + + +// // move track state to the sim hit for comparison + const TVector3 tpoint( sim_pos[0], sim_pos[1], sim_pos[2] ) ; + + // move track state to the IP to make all comparisons straight forward + // const TVector3 tpoint( 0.0, 0.0, 0.0 ) ; + + + IMPL::TrackStateImpl ts; + int ndf; + double chi2; + double dPhi ; + + + TKalTrackState& trkState_predicted = (TKalTrackState&) site->GetState(TVKalSite::kPredicted); // this segfaults if no hits are present + + THelicalTrack helix_predicted = trkState_predicted.GetHelix() ; + TMatrixD c0_predicted(trkState_predicted.GetCovMat()); + + Int_t sdim = trkState_predicted.GetDimension(); // dimensions of the track state, it will be 5 or 6 + + // now move to the point + TKalMatrix DF(sdim,sdim); + DF.UnitMatrix(); + helix_predicted.MoveTo( tpoint , dPhi , &DF , &c0_predicted) ; // move helix to desired point, and get propagator matrix + + streamlog_out(DEBUG2) << "DiagnosticsController::record_site get PREDICTED trackstate " << std::endl; + + _current_track->ToLCIOTrackState( helix_predicted, c0_predicted, ts, chi2, ndf ); + + _track_record->d0_predicted[_track_record->nsites] = ts.getD0() ; + _track_record->phi0_predicted[_track_record->nsites] = ts.getPhi() ; + _track_record->omega_predicted[_track_record->nsites] = ts.getOmega() ; + _track_record->z0_predicted[_track_record->nsites] = ts.getZ0() ; + _track_record->tanL_predicted[_track_record->nsites] = ts.getTanLambda() ; + + + _track_record->cov_predicted_d0d0[_track_record->nsites] = ts.getCovMatrix()[0]; + _track_record->cov_predicted_phi0d0[_track_record->nsites] = ts.getCovMatrix()[1]; + _track_record->cov_predicted_phi0phi0[_track_record->nsites] = ts.getCovMatrix()[2]; + _track_record->cov_predicted_omegad0[_track_record->nsites] = ts.getCovMatrix()[3]; + _track_record->cov_predicted_omegaphi0[_track_record->nsites] = ts.getCovMatrix()[4]; + _track_record->cov_predicted_omegaomega[_track_record->nsites] = ts.getCovMatrix()[5]; + _track_record->cov_predicted_z0d0[_track_record->nsites] = ts.getCovMatrix()[6]; + _track_record->cov_predicted_z0phi0[_track_record->nsites] = ts.getCovMatrix()[7]; + _track_record->cov_predicted_z0omega[_track_record->nsites] = ts.getCovMatrix()[8]; + _track_record->cov_predicted_z0z0[_track_record->nsites] = ts.getCovMatrix()[9]; + _track_record->cov_predicted_tanLd0[_track_record->nsites] = ts.getCovMatrix()[10]; + _track_record->cov_predicted_tanLphi0[_track_record->nsites] = ts.getCovMatrix()[11]; + _track_record->cov_predicted_tanLomega[_track_record->nsites] = ts.getCovMatrix()[12]; + _track_record->cov_predicted_tanLz0[_track_record->nsites] = ts.getCovMatrix()[13]; + _track_record->cov_predicted_tanLtanL[_track_record->nsites] = ts.getCovMatrix()[14]; + + + streamlog_out(DEBUG2) << "DiagnosticsController::record_site get FILTERED trackstate " << std::endl; + + TKalTrackState& trkState_filtered = (TKalTrackState&) site->GetState(TVKalSite::kFiltered); // this segfaults if no hits are present + + THelicalTrack helix_filtered = trkState_filtered.GetHelix() ; + TMatrixD c0_filtered(trkState_filtered.GetCovMat()); + + DF.UnitMatrix(); + helix_filtered.MoveTo( tpoint , dPhi , &DF , &c0_filtered) ; // move helix to desired point, and get propagator matrix + + IMPL::TrackStateImpl ts_f; + + _current_track->ToLCIOTrackState( helix_filtered, c0_filtered, ts_f, chi2, ndf ); + + _track_record->d0_filtered[_track_record->nsites] = ts_f.getD0() ; + _track_record->phi0_filtered[_track_record->nsites] = ts_f.getPhi() ; + _track_record->omega_filtered[_track_record->nsites] = ts_f.getOmega() ; + _track_record->z0_filtered[_track_record->nsites] = ts_f.getZ0() ; + _track_record->tanL_filtered[_track_record->nsites] = ts_f.getTanLambda() ; + + + _track_record->cov_filtered_d0d0[_track_record->nsites] = ts_f.getCovMatrix()[0]; + _track_record->cov_filtered_phi0d0[_track_record->nsites] = ts_f.getCovMatrix()[1]; + _track_record->cov_filtered_phi0phi0[_track_record->nsites] = ts_f.getCovMatrix()[2]; + _track_record->cov_filtered_omegad0[_track_record->nsites] = ts_f.getCovMatrix()[3]; + _track_record->cov_filtered_omegaphi0[_track_record->nsites] = ts_f.getCovMatrix()[4]; + _track_record->cov_filtered_omegaomega[_track_record->nsites] = ts_f.getCovMatrix()[5]; + _track_record->cov_filtered_z0d0[_track_record->nsites] = ts_f.getCovMatrix()[6]; + _track_record->cov_filtered_z0phi0[_track_record->nsites] = ts_f.getCovMatrix()[7]; + _track_record->cov_filtered_z0omega[_track_record->nsites] = ts_f.getCovMatrix()[8]; + _track_record->cov_filtered_z0z0[_track_record->nsites] = ts_f.getCovMatrix()[9]; + _track_record->cov_filtered_tanLd0[_track_record->nsites] = ts_f.getCovMatrix()[10]; + _track_record->cov_filtered_tanLphi0[_track_record->nsites] = ts_f.getCovMatrix()[11]; + _track_record->cov_filtered_tanLomega[_track_record->nsites] = ts_f.getCovMatrix()[12]; + _track_record->cov_filtered_tanLz0[_track_record->nsites] = ts_f.getCovMatrix()[13]; + _track_record->cov_filtered_tanLtanL[_track_record->nsites] = ts_f.getCovMatrix()[14]; + + + + _track_record->ref_point_x[_track_record->nsites] = tpoint.X(); + _track_record->ref_point_y[_track_record->nsites] = tpoint.Y(); + _track_record->ref_point_z[_track_record->nsites] = tpoint.Z(); + + + } + + ++_track_record->nsites; + + if (_track_record->nsites > MAX_SITES) { + _skip_track = true ; + this->clear_track_record(); + streamlog_out(DEBUG4) << " DiagnosticsController::end_track: Number of site too large. Track Skipped. nsites = " << _track_record->nsites << " : maximum number of site allowed = " << MAX_SITES << std::endl; + return; + } + + + streamlog_out(DEBUG2) << "_track_record->nsites = " << _track_record->nsites << std::endl; + } + + void DiagnosticsController::end_track(){ + + + + if ( _recording_on == false ) { + return; + } + + if ( _initialised == false ){ + streamlog_out(ERROR) << "DiagnosticsController::end_track: Diagnostics not initialised call init(std::string root_file_name, std::string root_tree_name, bool recording_off) first : exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + } + + streamlog_out(DEBUG3) << " DiagnosticsController::end_track called " << std::endl; + + if ( _skip_track ) { // just clear the track buffers and return. + ++_ntracks_skipped; + this->clear_track_record(); + return; + } else { + + _track_record->chi2 = _current_track->_kaltrack->GetChi2(); + _track_record->ndf = _current_track->_kaltrack->GetNDF(); + _track_record->prob = TMath::Prob(_track_record->chi2, _track_record->ndf); + + TIter it(_current_track->_kaltrack,kIterForward); + + Int_t nsites = _current_track->_kaltrack->GetEntries(); + + if (nsites > MAX_SITES) { + _skip_track = true ; + ++_ntracks_skipped; + this->clear_track_record(); + streamlog_out(DEBUG4) << " DiagnosticsController::end_track: Number of site too large. Track Skipped. nsites = " << nsites << " : maximum number of site allowed = " << MAX_SITES << std::endl; + return; + } + + + if( _current_track->_smoothed ){ + + for (Int_t isite=1; isite<nsites; isite++) { + + UTIL::BitField64 encoder(lcio::ILDCellID0::encoder_string); + encoder.setValue( _track_record->CellID0[isite] ); + + + TVKalSite* site = static_cast<TVKalSite *>( _current_track->_kaltrack->At(isite)); + + if ( _track_record->rejected[isite] == 0 && encoder[lcio::ILDCellID0::subdet] != 0 ) { + + + _track_record->chi2_inc_smoothed[isite] = site->GetDeltaChi2(); + + TKalTrackState& trkState_smoothed = (TKalTrackState&) site->GetState(TVKalSite::kSmoothed); // this segfaults if no hits are present + + THelicalTrack helix_smoothed = trkState_smoothed.GetHelix() ; + TMatrixD c0_smoothed(trkState_smoothed.GetCovMat()); + + Int_t sdim = trkState_smoothed.GetDimension(); // dimensions of the track state, it will be 5 or 6 + + // move track state to the sim hit for comparison + const TVector3 tpoint( _track_record->ref_point_x[isite], _track_record->ref_point_y[isite], _track_record->ref_point_z[isite] ) ; + + // now move to the point + TKalMatrix DF(sdim,sdim); + DF.UnitMatrix(); + + double dPhi=0; + + helix_smoothed.MoveTo( tpoint , dPhi , &DF , &c0_smoothed) ; // move helix to desired point, and get propagator matrix + + IMPL::TrackStateImpl ts; + int ndf; + double chi2; + + _current_track->ToLCIOTrackState( helix_smoothed, c0_smoothed, ts, chi2, ndf ); + + + _track_record->d0_smoothed[isite] = ts.getD0() ; + _track_record->phi0_smoothed[isite] = ts.getPhi() ; + _track_record->omega_smoothed[isite] = ts.getOmega() ; + _track_record->z0_smoothed[isite] = ts.getZ0() ; + _track_record->tanL_smoothed[isite] = ts.getTanLambda() ; + + + _track_record->cov_smoothed_d0d0[isite] = ts.getCovMatrix()[0]; + _track_record->cov_smoothed_phi0d0[isite] = ts.getCovMatrix()[1]; + _track_record->cov_smoothed_phi0phi0[isite] = ts.getCovMatrix()[2]; + _track_record->cov_smoothed_omegad0[isite] = ts.getCovMatrix()[3]; + _track_record->cov_smoothed_omegaphi0[isite] = ts.getCovMatrix()[4]; + _track_record->cov_smoothed_omegaomega[isite] = ts.getCovMatrix()[5]; + _track_record->cov_smoothed_z0d0[isite] = ts.getCovMatrix()[6]; + _track_record->cov_smoothed_z0phi0[isite] = ts.getCovMatrix()[7]; + _track_record->cov_smoothed_z0omega[isite] = ts.getCovMatrix()[8]; + _track_record->cov_smoothed_z0z0[isite] = ts.getCovMatrix()[9]; + _track_record->cov_smoothed_tanLd0[isite] = ts.getCovMatrix()[10]; + _track_record->cov_smoothed_tanLphi0[isite] = ts.getCovMatrix()[11]; + _track_record->cov_smoothed_tanLomega[isite] = ts.getCovMatrix()[12]; + _track_record->cov_smoothed_tanLz0[isite] = ts.getCovMatrix()[13]; + _track_record->cov_smoothed_tanLtanL[isite] = ts.getCovMatrix()[14]; + + } + + } + } + + IMPL::TrackStateImpl ts_at_ip; + int ndf; + double chi2; + + gear::Vector3D point(0.0,0.0,0.0); + _current_track->propagate( point, ts_at_ip, chi2, ndf ); + + _track_record->d0_ip = ts_at_ip.getD0() ; + _track_record->phi0_ip = ts_at_ip.getPhi() ; + _track_record->omega_ip = ts_at_ip.getOmega() ; + _track_record->z0_ip = ts_at_ip.getZ0() ; + _track_record->tanL_ip = ts_at_ip.getTanLambda() ; + + + _track_record->cov_ip_d0d0 = ts_at_ip.getCovMatrix()[0]; + _track_record->cov_ip_phi0d0 = ts_at_ip.getCovMatrix()[1]; + _track_record->cov_ip_phi0phi0 = ts_at_ip.getCovMatrix()[2]; + _track_record->cov_ip_omegad0 = ts_at_ip.getCovMatrix()[3]; + _track_record->cov_ip_omegaphi0 = ts_at_ip.getCovMatrix()[4]; + _track_record->cov_ip_omegaomega = ts_at_ip.getCovMatrix()[5]; + _track_record->cov_ip_z0d0 = ts_at_ip.getCovMatrix()[6]; + _track_record->cov_ip_z0phi0 = ts_at_ip.getCovMatrix()[7]; + _track_record->cov_ip_z0omega = ts_at_ip.getCovMatrix()[8]; + _track_record->cov_ip_z0z0 = ts_at_ip.getCovMatrix()[9]; + _track_record->cov_ip_tanLd0 = ts_at_ip.getCovMatrix()[10]; + _track_record->cov_ip_tanLphi0 = ts_at_ip.getCovMatrix()[11]; + _track_record->cov_ip_tanLomega = ts_at_ip.getCovMatrix()[12]; + _track_record->cov_ip_tanLz0 = ts_at_ip.getCovMatrix()[13]; + _track_record->cov_ip_tanLtanL = ts_at_ip.getCovMatrix()[14]; + + _tree->Fill(); + + ++_ntracks_written; + + } + + } + + void DiagnosticsController::end(){ + + if ( _recording_on == false ) { + return; + } + + if ( _initialised == false ){ + streamlog_out(ERROR) << "DiagnosticsController::end: Diagnostics not initialised call init(std::string root_file_name, std::string root_tree_name, bool recording_off) first : exit(1) called from file " + << __FILE__ + << " line " + << __LINE__ + << std::endl; + + exit(1); + } + + streamlog_out(DEBUG4) << " DiagnosticsController::end() called \n" + << "\t number of tracks written = " << _ntracks_written + << "\t number of tracks skipped = " << _ntracks_skipped + << std::endl; + + + + // _tree->Print(); + _root_file->Write(); + _root_file->Close(); + delete _root_file; _root_file = 0; + + } + + +} + + + +#endif diff --git a/Service/TrackSystemSvc/src/DiagnosticsController.h.remove b/Service/TrackSystemSvc/src/DiagnosticsController.h.remove new file mode 100644 index 0000000000000000000000000000000000000000..2e42d0c37ba964a5d11aea60a5d21cce92de73e7 --- /dev/null +++ b/Service/TrackSystemSvc/src/DiagnosticsController.h.remove @@ -0,0 +1,90 @@ +#ifndef DiagnosticsController_h +#define DiagnosticsController_h + +#include "MarlinTrk/MarlinTrkDiagnostics.h" + +#ifdef MARLINTRK_DIAGNOSTICS_ON + +class TFile; +class TH1F; +class TTree; +class TKalMatrix; + +namespace EVENT { + class MCParticle; +} + +class ILDVTrackHit; +class TKalTrackSite; +class MarlinTrkNtuple; + +namespace MarlinTrk{ + + class MarlinKalTestTrack; + class IMarlinTrack; + + + class DiagnosticsController { + + public: + + /** constructor */ + DiagnosticsController(); + + /** Destructor */ + virtual ~DiagnosticsController(); + + + void init(std::string root_file_name, std::string root_Tree_name, bool _recording_on=true ) ; + + void new_track(MarlinKalTestTrack* trk) ; + + void set_intial_track_parameters(double d0, double phi0, double omega, double z0, double tanL, double pivot_x, double pivot_y, double pivot_z, TKalMatrix& cov); + + void record_site(ILDVTrackHit* hit, TKalTrackSite* site); + + void record_rejected_site(ILDVTrackHit* hit, TKalTrackSite* site); + + void skip_current_track(); + + void end_track() ; + + void end(); + + + private: + + DiagnosticsController(const DiagnosticsController&) ; // Prevent copy-construction + DiagnosticsController& operator=(const DiagnosticsController&) ; // Prevent assignment + + void clear_track_record(); + + bool _initialised; + bool _recording_on; + + int _ntracks_written; + int _ntracks_skipped; + + std::string _root_file_name; + std::string _root_tree_name; + + TFile* _root_file; + TTree* _tree; + MarlinTrkNtuple* _track_record; + + MarlinKalTestTrack* _current_track; + + EVENT::MCParticle* _currentMCP; + + bool _mcpInfoStored; + bool _skip_track; + + + }; + + +} + +#endif + +#endif diff --git a/Service/TrackSystemSvc/src/HelixFit.cc b/Service/TrackSystemSvc/src/HelixFit.cc new file mode 100644 index 0000000000000000000000000000000000000000..070bbf6cdbd853dc5e932dddc626e2ef35918444 --- /dev/null +++ b/Service/TrackSystemSvc/src/HelixFit.cc @@ -0,0 +1,577 @@ +// +// HelixFit.cc +// MarlinTrk +// +// Created by Steve Aplin on 9/16/11. +// + +#include "TrackSystemSvc/IMarlinTrack.h" + +#include "TrackSystemSvc/HelixFit.h" +#include "TrackSystemSvc/HelixTrack.h" +//#include "streamlog/streamlog.h" + +#include "CLHEP/Matrix/SymMatrix.h" + +namespace MarlinTrk{ + + + int HelixFit::fastHelixFit(int npt, double* xf, double* yf, float* rf, float* pf, double* wf, float* zf , float* wzf,int iopt, + float* vv0, float* ee0, float& ch2ph, float& ch2z){ + + + + if (npt < 3) { + //streamlog_out(ERROR) << "Cannot fit less than 3 points return 1" << std::endl; + ch2ph = 1.0e30; + ch2z = 1.0e30; + return 1; + } + + double eps = 1.0e-16; +#define ITMAX 15 +#define MPT 600 +#define MAX_CHI2 5000.0 + + + float sp2[MPT], + del[MPT],deln[MPT],delzn[MPT],sxy[MPT],ss0[MPT],eee[MPT], + delz[MPT],grad[5],cov[15],vv1[5],dv[5]; + + // double xf[MPT],yf[MPT],wf[MPT],zf[MPT],wzf[MPT]; + + double alf,a0,a1,a2,a22,bet,cur, + dd,den,det,dy,d2,f,fact,fg,f1,g,gam,gam0,g1, + h,h2,p2,q2,rm,rn, + xa,xb,xd,xi,xm,xx,xy,x1,x2,den2, + ya,yb,yd,yi,ym,yy,y1,y2,wn,sa2b2,dd0,phic,aaa; + + + xm = 0.; + ym = 0.; + + for(int i=1; i < 15; ++i){ + ee0[i]=0.0; + } + + for( int i=1; i < 5; ++i){ + grad[i]= 0.0; + vv0[i] = 0.0; + } + + float chi2=0.0; + ch2ph = 0.0; + ch2z = 0.0; + + for (int i = 0; i<npt; ++i) { + sp2[i] = wf[i]*(rf[i]*rf[i]); + } + + + //std::cout << "npt = " << npt << std::endl; + + // for(int i = 0; i<n; ++i){ + //std::cout << "xf = " << xf[i] << " " << i << std::endl; + //std::cout << "yf = " << yf[i] << " " << i << std::endl; + //std::cout << "zf = " << zf[i] << " " << i << std::endl; + //std::cout << "rf = " << rf[i] << " " << i << std::endl; + //std::cout << "pf = " << pf[i] << " " << i << std::endl; + //std::cout << "wf = " << wf[i] << " " << i << std::endl; + //std::cout << "wzf = " << wzf[i] << " " << i << std::endl; + //} + + + wn=0.0; + + for (int i =0; i<npt; ++i) { + xm = xm + xf[i]*wf[i]; + ym = ym + yf[i]*wf[i]; + wn = wn + wf[i]; + } + + rn = 1.0/wn; + + xm = xm * rn; + ym = ym * rn; + x2 = 0.; + y2 = 0.; + xy = 0.; + xd = 0.; + yd = 0.; + d2 = 0.; + + //std::cout << "xm = " << xm << std::endl; + //std::cout << "ym = " << ym << std::endl; + //std::cout << "rn = " << rn << std::endl; + + for (int i =0; i<npt; ++i) { + xi = xf[i] - xm; + yi = yf[i] - ym; + xx = xi*xi; + yy = yi*yi; + x2 = x2 + xx*wf[i]; + y2 = y2 + yy*wf[i]; + xy = xy + xi*yi*wf[i]; + dd = xx + yy; + xd = xd + xi*dd*wf[i]; + yd = yd + yi*dd*wf[i]; + d2 = d2 + dd*dd*wf[i]; + } + + + //std::cout << "xd = " << xd << std::endl; + //std::cout << "yd = " << yd << std::endl; + //std::cout << "d2 = " << d2 << std::endl; + + + x2 = x2*rn; + y2 = y2*rn; + xy = xy*rn; + d2 = d2*rn; + xd = xd*rn; + yd = yd*rn; + f = 3.0* x2 + y2; + g = 3.0* y2 + x2; + fg = f*g; + h = xy + xy; + h2 = h*h; + p2 = xd*xd; + q2 = yd*yd; + gam0 = x2 + y2; + fact = gam0*gam0; + a2 = (fg-h2-d2)/fact; + fact = fact*gam0; + a1 = (d2*(f+g) - 2.0*(p2+q2))/fact; + fact = fact*gam0; + a0 = (d2*(h2-fg) + 2.0*(p2*g + q2*f) - 4.0*xd*yd*h)/fact; + a22 = a2 + a2; + yb = 1.0e30; + xa = 1.0; + + //std::cout << "a0 = " << a0 << std::endl; + //std::cout << "a22 = " << a22 << std::endl; + + + // ** main iteration + + for (int i = 0 ; i < ITMAX; ++i) { + + ya = a0 + xa*(a1 + xa*(a2 + xa*(xa-4.0))); + dy = a1 + xa*(a22 + xa*(4.0*xa - 12.0)); + xb = xa - ya/dy; + + if (fabs(ya) > fabs(yb)) { + xb = 0.5 * (xb+xa) ; + } + + if (fabs(xa-xb) < eps) break ; + xa = xb; + yb = ya; + + + } + + // ** + + gam = gam0*xb; + f1 = f - gam; + g1 = g - gam; + x1 = xd*g1 - yd*h; + y1 = yd*f1 - xd*h; + det = f1*g1 - h2; + den2= 1.0/(x1*x1 + y1*y1 + gam*det*det); + + if(den2 <= 0.0) { + // streamlog_out(ERROR) << "den2 less than or equal to zero" + // << " x1 = " << x1 + // << " y1 = " << y1 + // << " gam = " << gam + // << " det = " << det + // << std::endl; + ch2ph = 1.0e30; + ch2z = 1.0e30; + return 1; + } + + den = sqrt(den2); + cur = det*den + 0.0000000001 ; + alf = -(xm*det + x1)*den ; + bet = -(ym*det + y1)*den ; + rm = xm*xm + ym*ym ; + gam = ((rm-gam)*det + 2.0*(xm*x1 + ym*y1))*den*0.5; + + + // + // --------> calculation of standard circle parameters + // nb: cur is always positive + + double rr0=cur; + double asym = bet*xm-alf*ym; + double sst = 1.0; + + if(asym < 0.0) { + sst = -1.0 ; + } + + rr0 = sst*cur; + + if( (alf*alf+bet*bet) <= 0.0 ){ + // streamlog_out(ERROR) << "(alf*alf+bet*bet) less than or equal to zero" << std::endl; + ch2ph = 1.0e30; + ch2z = 1.0e30; + return 1; + } + + sa2b2 = 1.0/sqrt(alf*alf+bet*bet); + dd0 = (1.0-1.0/sa2b2)/cur; + aaa = alf*sa2b2; + + if( aaa > 1.0 ) aaa = 1.0; + if( aaa < -1.0 ) aaa =-1.0; + + // std::cout << std::setprecision(10) << "aaa = " << aaa << std::endl; + + phic = asin(aaa)+ M_PI_2; + + if( bet > 0 ) phic = 2*M_PI - phic; + + double ph0 = phic + M_PI_2; + + if(rr0 <= 0.0) ph0=ph0-M_PI; + if(ph0 > 2*M_PI) ph0=ph0-2*M_PI; + if(ph0 < 0.0) ph0=ph0+2*M_PI; + + vv0[0] = rr0; + vv0[2] = ph0; + vv0[3] = dd0; + + // std::cout << std::setprecision(10) << "rr0 = " << rr0 << std::endl; + // std::cout << "ph0 = " << ph0 << std::endl; + // std::cout << "dd0 = " << dd0 << std::endl; + + double check=sst*rr0*dd0; + // std::cout << "check = " << check << std::endl; + + if(check > 1.0-eps && check < 1.0+eps) { + dd0 = dd0 - 0.007; + vv0[3]=dd0; + } + + // + // -----> calculate phi distances to measured points + // + + double aa0 = sst; + double ome = rr0; + double gg0 = ome*dd0-aa0; + + double hh0 = 1.0/gg0; + + // std::cout << "dd0 = " << dd0 << std::endl; + // std::cout << "ome = " << ome << std::endl; + // std::cout << "aa0 = " << aa0 << std::endl; + // std::cout << "hh0 = " << hh0 << std::endl; + // std::cout << "gg0 = " << gg0 << std::endl; + + for (int i = 0 ; i < npt ; ++i) { + + asym = bet*xf[i]-alf*yf[i] ; + ss0[i] = 1.0 ; + + if(asym < 0.0) ss0[i] = -1.0 ; + + double ff0 = ome*(rf[i]*rf[i]-dd0*dd0)/(2.0*rf[i]*gg0) + dd0/rf[i]; + + if(ff0 < -1.0) ff0 = -1.0; + if(ff0 > 1.0) ff0 = 1.0; + + del[i]= ph0 + (ss0[i]-aa0)* M_PI_2 + ss0[i]*asin(ff0) - pf[i]; + + // std::cout << "asin(ff0) = " << asin(ff0) << " i = " << i << std::endl; + // std::cout << "aa0 = " << aa0 << " i = " << i << std::endl; + // std::cout << "M_PI_2 = " << M_PI_2 << " i = " << i << std::endl; + // std::cout << "pf[i] = " << pf[i] << " i = " << i << std::endl; + // std::cout << "ff0 = " << ff0 << " i = " << i << std::endl; + // std::cout << "ss0[i] = " << ss0[i] << " i = " << i << std::endl; + // std::cout << "ph0 + (ss0[i]-aa0)* M_PI_2 = " << ph0 + (ss0[i]-aa0)* M_PI_2 << " i = " << i << std::endl; + // std::cout << "ss0[i]*asin(ff0) = " << ss0[i]*asin(ff0) << " i = " << i << std::endl; + // std::cout << "ph0 + (ss0[i]-aa0)* M_PI_2 + ss0[i]*asin(ff0) = " << ph0 + (ss0[i]-aa0)* M_PI_2 + ss0[i]*asin(ff0) << std::endl; + // std::cout << "del[i] = " << del[i] << " i = " << i << std::endl; + + if(del[i] > M_PI) del[i] = del[i] - 2*M_PI; + if(del[i] < -M_PI) del[i] = del[i] + 2*M_PI; + + + + } + + + + // + // -----> fit straight line in s-z + // + + + for (int i = 0 ; i < npt ; ++i) { + + eee[i] = 0.5*vv0[0] * sqrt( fabs( (rf[i] * rf[i]-vv0[3]*vv0[3]) / (1.0-aa0*vv0[0]*vv0[3]) ) ); + + if(eee[i] > 0.99990) eee[i]= 0.99990; + if(eee[i] < -0.99990) eee[i]= -0.99990; + + sxy[i]=2.0*asin(eee[i])/ome; + + } + + + double sums = 0.0; + double sumss = 0.0; + double sumz = 0.0; + double sumzz = 0.0; + double sumsz = 0.0; + double sumw = 0.0; + + for (int i = 0; i<npt; ++i) { + sumw = sumw + wzf[i]; + sums = sums + sxy[i] * wzf[i]; + sumss = sumss + sxy[i]*sxy[i] * wzf[i]; + sumz = sumz + zf[i] * wzf[i]; + sumzz = sumzz + zf[i]*zf[i] * wzf[i]; + sumsz = sumsz + zf[i]*sxy[i] * wzf[i]; + } + + double denom = sumw*sumss - sums*sums; + + if (fabs(denom) < eps){ + // streamlog_out(ERROR) << "fabs(denom) less than or equal to zero" << std::endl; + ch2ph = 1.0e30; + ch2z = 1.0e30; + return 1; + } + + double dzds = (sumw*sumsz-sums*sumz) /denom; + double zz0 = (sumss*sumz-sums*sumsz)/denom; + + vv0[1]= dzds; + vv0[4]= zz0; + + // + // -----> calculation chi**2 + // + for (int i = 0 ; i<npt; ++i) { + + delz[i]= zz0+dzds*sxy[i]-zf[i]; + ch2ph = ch2ph + sp2[i]*del[i]*del[i]; + ch2z = ch2z + wzf[i]*delz[i]*delz[i]; + chi2 = ch2ph + ch2z; + + } + + if(chi2 > MAX_CHI2) { + // streamlog_out(ERROR) << "Chi2 greater than " << MAX_CHI2 << "return 1 " << std::endl; + ch2ph = 1.0e30; + ch2z = 1.0e30; + return 1; + } + + for (int i = 0 ; i<npt; ++i) { + + double ff0 = ome*(rf[i]*rf[i]-dd0*dd0)/(2.0*rf[i]*gg0) + dd0/rf[i]; + + if (ff0 > 0.99990) ff0 = 0.99990; + + if (ff0 < -0.99990) ff0 = -0.99990; + + double eta = ss0[i]/sqrt(fabs((1.0+ff0)*(1.0-ff0))); + double dfd = (1.0+hh0*hh0*(1.0-ome*ome*rf[i]*rf[i]))/(2.0*rf[i]); + double dfo = -aa0*(rf[i]*rf[i]-dd0*dd0)*hh0*hh0/(2.0*rf[i]); + double dpd = eta*dfd; + double dpo = eta*dfo; + + // -----> derivatives of z component + double ggg = eee[i]/sqrt(fabs( (1.0+eee[i])*(1.0-eee[i]))); + double dza = sxy[i]; + check = rf[i]*rf[i]-vv0[3]*vv0[3]; + + if(fabs(check) > 1.0-eps) check=2.*0.007; + + double dzd = 2.0*( vv0[1]/vv0[0] ) * fabs( ggg ) * ( 0.5*aa0*vv0[0]/( 1.0-aa0*vv0[3]*vv0[0] )-vv0[3]/check ); + + double dzo = -vv0[1]*sxy[i]/vv0[0] + vv0[1] * ggg/( vv0[0]*vv0[0]) * ( 2.0+ aa0*vv0[0]*vv0[3]/(1.0-aa0*vv0[0]*vv0[3]) ); + + // -----> error martix + + ee0[0] = ee0[0] + sp2[i]* dpo*dpo + wzf[i] * dzo*dzo; + ee0[1] = ee0[1] + wzf[i] * dza*dzo; + ee0[2] = ee0[2] + wzf[i] * dza*dza; + ee0[3] = ee0[3] + sp2[i]* dpo; + ee0[4] = ee0[4]; + ee0[5] = ee0[5] + sp2[i]; + ee0[6] = ee0[6] + sp2[i]* dpo*dpd + wzf[i] * dzo*dzd; + ee0[7] = ee0[7] + wzf[i] * dza*dzd; + ee0[8] = ee0[8] + sp2[i]* dpd; + ee0[9] = ee0[9] + sp2[i]* dpd*dpd + wzf[i] * dzd*dzd; + ee0[10]= ee0[10] + wzf[i] * dzo; + ee0[11]= ee0[11] + wzf[i] * dza; + ee0[12]= ee0[12]; + ee0[13]= ee0[13] + wzf[i] * dzd; + ee0[14]= ee0[14] + wzf[i]; + + // -----> gradient vector + grad[0]=grad[0] - del[i] *sp2[i]*dpo - delz[i]*wzf[i]*dzo; + grad[1]=grad[1] - delz[i]*wzf[i]*dza; + grad[2]=grad[2] - del[i] *sp2[i]; + grad[3]=grad[3] - del[i] *sp2[i]*dpd - delz[i]*wzf[i]*dzd; + grad[4]=grad[4] - delz[i]*wzf[i]; + + + } + + if (iopt < 3) { + /* + streamlog_out(DEBUG1) << "HelixFit: " << + " d0 = " << vv0[3] << + " phi0 = " << vv0[2] << + " omega = " << vv0[0] << + " z0 = " << vv0[4] << + " tanL = " << vv0[1] << + std::endl; + */ + return 0 ; + } + + // ------> NEWTONS NEXT GUESS + + for (int i =0; i<15; ++i) { + cov[i]=ee0[i]; + } + + // Convert Covariance Matrix + CLHEP::HepSymMatrix cov0(5) ; + + int icov = 0 ; + + for(int irow=0; irow<5; ++irow ){ + for(int jcol=0; jcol<irow+1; ++jcol){ + // std::cout << "row = " << irow << " col = " << jcol << std::endl ; + // std::cout << "cov["<< icov << "] = " << _cov[icov] << std::endl ; + cov0[irow][jcol] = ee0[icov] ; + ++icov ; + } + } + + int error = 0 ; + cov0.invert(error); + + if( error != 0 ) { + //streamlog_out(ERROR) << "CLHEP Matrix inversion failed" << "return 1 " << std::endl; + ch2ph = 1.0e30; + ch2z = 1.0e30; + return 1; + } + + icov = 0 ; + + for(int irow=0; irow<5; ++irow ){ + for(int jcol=0; jcol<irow+1; ++jcol){ + // std::cout << "row = " << irow << " col = " << jcol << std::endl ; + // std::cout << "cov["<< icov << "] = " << _cov[icov] << std::endl ; + cov[icov] = cov0[irow][jcol]; + ++icov ; + } + } + + // here we need to invert the matrix cov[15] + + + + for (int i = 0; i<5; ++i) { + dv[i] = 0.0 ; + for (int j = 0; j<5; ++j) { + int index = 0; + if ( i >= j ) { + index = (i*i-i)/2+j ; + } + else{ + index = (j*j-j)/2+i; + } + dv[i] = dv[i] + cov[index] * grad[j] ; + } + } + + + for (int i = 0; i<5; ++i) { + vv1[i] = vv0[i]+dv[i]; + } + + gg0 = vv1[0]*vv1[3]-aa0; + + for (int i=0; i<npt; ++i) { + double ff0 = vv1[0]*(rf[i]*rf[i]-vv1[3]*vv1[3]) / (2.0*rf[i]*gg0) + vv1[3]/rf[i]; + + if (ff0 > 1) ff0 = 1.0; + if (ff0 < -1) ff0 = -1.0; + + deln[i] = vv1[2] + (ss0[i]-aa0)*M_PI_2+ss0[i]*asin(ff0)-pf[i]; + + if(deln[i] > M_PI) deln[i] = deln[i] - 2*M_PI; + if(deln[i] < -M_PI) deln[i] = deln[i] + 2*M_PI; + + eee[i] = 0.5*vv1[0]*sqrt( fabs( (rf[i]*rf[i]-vv1[3]*vv1[3]) / (1.0-aa0*vv1[0]*vv1[3]) ) ); + + if(eee[i] > 0.99990) eee[i]= 0.99990; + if(eee[i] < -0.99990) eee[i]= -0.99990; + + sxy[i] = 2.0*asin(eee[i])/vv1[0]; + delzn[i]= vv1[4]+vv1[1]*sxy[i]-zf[i]; + + } + + double chi1 = 0.0; + ch2ph = 0.0; + ch2z = 0.0; + + for (int i =0; i<5; ++i) { + chi1 = chi1 + sp2[i]*deln[i]*deln[i] + wzf[i]*delzn[i]*delzn[i]; + ch2ph = ch2ph + sp2[i]*deln[i]*deln[i]; + ch2z = ch2z + wzf[i]*delzn[i]*delzn[i]; + } + + if (chi1<chi2) { + for (int i =0; i<5; ++i) { + vv0[i] = vv1[i]; + } + chi2 = chi1; + } + std::cout << "HelixFit: " << + //streamlog_out(DEBUG1) << "HelixFit: " << + " d0 = " << vv0[3] << + " phi0 = " << vv0[2] << + " omega = " << vv0[0] << + " z0 = " << vv0[4] << + " tanL = " << vv0[1] << + std::endl; + + return 0; + + } + + +} + + + + + + + + + + + + + + + + + diff --git a/Service/TrackSystemSvc/src/HelixTrack.cc b/Service/TrackSystemSvc/src/HelixTrack.cc new file mode 100644 index 0000000000000000000000000000000000000000..8901f5034ad92ba556baca32b90490cf8eac81a6 --- /dev/null +++ b/Service/TrackSystemSvc/src/HelixTrack.cc @@ -0,0 +1,114 @@ + +#include "TrackSystemSvc/IMarlinTrack.h" +#include "TrackSystemSvc/HelixTrack.h" +#include <cmath> +#include <TVector3.h> +#include <kaltest/THelicalTrack.h> +#include <edm4hep/Vector3d.h> //plcio/DoubleThree.h> +//#include "streamlog/streamlog.h" + +// defines if s of the helix increases in the direction of x2 to x3 +bool HelixTrack::forwards = true; + +HelixTrack::HelixTrack( const edm4hep::Vector3d& x1, const edm4hep::Vector3d& x2, const edm4hep::Vector3d& x3, double Bz, bool direction ){ + + // Make a KalTest THelicalTrack + TVector3 p1( x1[0], x1[1], x1[2] ); + TVector3 p2( x2[0], x2[1], x2[2] ); + TVector3 p3( x3[0], x3[1], x3[2] ); + /* + std::cout << "debug: " << "HelixTrack::HelixTrack Create from hits: \n " + << "P1 x = " << p1.x() << " y = " << p1.y() << " z = " << p1.z() << " r = " << p1.Perp() << "\n " + << "P2 x = " << p2.x() << " y = " << p2.y() << " z = " << p2.z() << " r = " << p2.Perp() << "\n " + << "P3 x = " << p3.x() << " y = " << p3.y() << " z = " << p3.z() << " r = " << p3.Perp() << "\n " + << "Bz = " << Bz << " direction = " << direction + << std::endl; + */ + THelicalTrack* helicalTrack; + + helicalTrack = new THelicalTrack( p1, p2, p3, Bz, direction ); + + // Set the track parameters and convert from the KalTest system to the lcio system + + _phi0 = toBaseRange( helicalTrack->GetPhi0() + M_PI/2. ) ; + _omega = 1. / helicalTrack->GetRho(); + _z0 = helicalTrack->GetDz(); + _d0 = - helicalTrack->GetDrho(); + _tanLambda = helicalTrack->GetTanLambda(); + + _ref_point_x = helicalTrack->GetPivot().X() ; + _ref_point_y = helicalTrack->GetPivot().Y() ; + _ref_point_z = helicalTrack->GetPivot().Z() ; + + delete helicalTrack; + +} + + +HelixTrack::HelixTrack( const edm4hep::Vector3d& position, const edm4hep::Vector3d& p, double charge, double Bz ){ + + _ref_point_x = position[0] ; + _ref_point_y = position[1] ; + _ref_point_z = position[2] ; + + _d0 = 0.0 ; + _z0 = 0.0 ; + + const double pt = sqrt(p[0]*p[0]+p[1]*p[1]) ; + + double radius = pt / (2.99792458E-4*Bz) ; // for r in mm, p in GeV and Bz in Tesla + + _omega = charge/radius ; + _tanLambda = p[2]/pt ; + + _phi0 = atan2(p[1],p[0]); + + _phi0 = toBaseRange(_phi0); + +} + +double HelixTrack::moveRefPoint( double x, double y, double z){ + + const double radius = 1.0/_omega ; + + const double sinPhi0 = sin(_phi0) ; + const double cosPhi0 = cos(_phi0) ; + + const double deltaX = x - _ref_point_x ; + const double deltaY = y - _ref_point_y ; + + double phi0Prime = atan2( sinPhi0 - (deltaX/(radius-_d0)) , cosPhi0 + (deltaY/(radius-_d0)) ) ; + + while ( phi0Prime < 0 ) phi0Prime += 2.0*M_PI ; + while ( phi0Prime >= 2.0*M_PI ) phi0Prime -= 2.0*M_PI ; + + const double d0Prime = _d0 + deltaX*sinPhi0 - deltaY*cosPhi0 + ( ( deltaX*cosPhi0 + deltaY*sinPhi0 ) * tan( (phi0Prime-_phi0) / 2.0) ) ; + + // In order to have terms which behave well as Omega->0 we make use of deltaX and deltaY to replace sin( phi0Prime - phi0 ) and cos( phi0Prime - phi0 ) + + const double sinDeltaPhi = ( -_omega / ( 1.0 - ( _omega * d0Prime ) ) ) * ( deltaX * cosPhi0 + deltaY * sinPhi0 ) ; + + const double cosDeltaPhi = 1.0 + ( _omega*_omega / ( 2.0 * ( 1.0 - _omega * d0Prime ) ) ) * ( d0Prime*d0Prime - ( deltaX + _d0 * sinPhi0 )*( deltaX + _d0 * sinPhi0 ) - ( deltaY - _d0 * cosPhi0 )*( deltaY - _d0 * cosPhi0 ) ) ; + + const double s = atan2(-sinDeltaPhi,cosDeltaPhi) / _omega ; + + const double z0Prime = _ref_point_z - z + _z0 + _tanLambda * s ; + + phi0Prime = toBaseRange(phi0Prime); + + _d0 = d0Prime ; + _phi0 = phi0Prime ; + _z0 = z0Prime ; + + _ref_point_x = x; + _ref_point_y = y; + _ref_point_z = z; + + return (s/radius); + +} + + + + + diff --git a/Service/TrackSystemSvc/src/IMarlinTrack.cc b/Service/TrackSystemSvc/src/IMarlinTrack.cc new file mode 100644 index 0000000000000000000000000000000000000000..494c171698b459352d22b5609393bffae3558ebd --- /dev/null +++ b/Service/TrackSystemSvc/src/IMarlinTrack.cc @@ -0,0 +1,38 @@ + +#include "TrackSystemSvc/IMarlinTrack.h" + +namespace MarlinTrk{ + + const bool IMarlinTrack::backward = false ; + const bool IMarlinTrack::forward = ! IMarlinTrack::backward; + + const int IMarlinTrack::modeBackward = - 1 ; + const int IMarlinTrack::modeClosest = 0 ; + const int IMarlinTrack::modeForward = + 1 ; + + + const int IMarlinTrack::success = 0 ; // no error + const int IMarlinTrack::error = 1 ; + const int IMarlinTrack::bad_intputs = 3 ; + const int IMarlinTrack::no_intersection = 4 ; // no intersection found + const int IMarlinTrack::site_discarded = 5 ; // measurement discarded by the fitter + const int IMarlinTrack::site_fails_chi2_cut = 6 ; // measurement discarded by the fitter due to chi2 cut + const int IMarlinTrack::all_sites_fail_fit = 7 ; // no single measurement added to the fit + + + /** Helper function to convert error return code to string */ + std::string errorCode( int error ){ + + switch ( error ){ + case IMarlinTrack::success : return "IMarlinTrack::success"; break; + case IMarlinTrack::error : return "IMarlinTrack::error"; break; + case IMarlinTrack::bad_intputs : return "IMarlinTrack::bad_intputs"; break; + case IMarlinTrack::no_intersection : return "IMarlinTrack::no_intersection"; break; + case IMarlinTrack::site_discarded : return "IMarlinTrack::site_discarded"; break; + case IMarlinTrack::site_fails_chi2_cut : return "IMarlinTrack::site_fails_chi2_cut"; break; + case IMarlinTrack::all_sites_fail_fit : return "IMarlinTrack::all_sites_fail_fit"; break; + default: return "UNKNOWN" ; + } + } + +} diff --git a/Service/TrackSystemSvc/src/IMarlinTrkSystem.cc b/Service/TrackSystemSvc/src/IMarlinTrkSystem.cc new file mode 100644 index 0000000000000000000000000000000000000000..9ed3a16b27f7a602d5fbd03f1123d09fcb7bc422 --- /dev/null +++ b/Service/TrackSystemSvc/src/IMarlinTrkSystem.cc @@ -0,0 +1,33 @@ +#include "TrackSystemSvc/IMarlinTrkSystem.h" +#include <sstream> + +namespace MarlinTrk{ + + void IMarlinTrkSystem::setOption(unsigned CFGOption, bool val) { + _cfg.setOption( CFGOption, val ) ; + } + + + bool IMarlinTrkSystem::getOption( unsigned CFGOption) { + return _cfg[ CFGOption] ; + } + + + std::string IMarlinTrkSystem::getOptions() { + + std::stringstream ss ; + ss << _cfg ; + return ss.str() ; + } + + void IMarlinTrkSystem::registerOptions() { + + _cfg.registerOption( IMarlinTrkSystem::CFG::useQMS, "useMultipleScattering", true) ; + _cfg.registerOption( IMarlinTrkSystem::CFG::usedEdx, "useEnergyLoss", true) ; + _cfg.registerOption( IMarlinTrkSystem::CFG::useSmoothing, "useSmoothingInFit", false) ; + + + } + + +} diff --git a/Service/TrackSystemSvc/src/LCIOTrackPropagators.cc.remove b/Service/TrackSystemSvc/src/LCIOTrackPropagators.cc.remove new file mode 100644 index 0000000000000000000000000000000000000000..19a4f650b0dd37e9a278d1389eca463fc9ff604f --- /dev/null +++ b/Service/TrackSystemSvc/src/LCIOTrackPropagators.cc.remove @@ -0,0 +1,489 @@ + +#include "LCIOTrackPropagators.h" + +#include <cmath> +#include <iostream> + +#include "IMPL/TrackStateImpl.h" + +#include "CLHEP/Matrix/Matrix.h" +#include "CLHEP/Matrix/SymMatrix.h" +#include "CLHEP/Vector/TwoVector.h" + +//#include "streamlog/streamlog.h" + + +namespace LCIOTrackPropagators{ + + int PropagateLCIOToNewRef( IMPL::TrackStateImpl& ts, double xref, double yref, double zref ) { + + // std::cout << "PropagateLCIOToNewRef: x:y:z = " << xref << " : " << yref << " : " << zref << std::endl ; + + // Convert Parameters + + const double d0 = ts.getD0() ; + const double phi0 = ts.getPhi() ; + const double omega = ts.getOmega() ; + const double z0 = ts.getZ0() ; + const double tanL = ts.getTanLambda() ; + + // const double charge = omega/fabs(omega) ; + const float* ref = ts.getReferencePoint() ; + + const double radius = 1.0/omega ; + + const double sinPhi0 = sin(phi0) ; + const double cosPhi0 = cos(phi0) ; + + const double deltaX = xref - ref[0] ; + const double deltaY = yref - ref[1] ; + + double phi0Prime = atan2( sinPhi0 - (deltaX/(radius-d0)) , cosPhi0 + (deltaY/(radius-d0)) ) ; + + while ( phi0Prime < 0 ) phi0Prime += 2.0*M_PI ; + while ( phi0Prime >= 2.0*M_PI ) phi0Prime -= 2.0*M_PI ; + + const double d0Prime = d0 + deltaX*sinPhi0 - deltaY*cosPhi0 + ( ( deltaX*cosPhi0 + deltaY*sinPhi0 ) * tan( (phi0Prime-phi0) / 2.0) ) ; + + // In order to have terms which behave well as Omega->0 we make use of deltaX and deltaY to replace sin( phi0Prime - phi0 ) and cos( phi0Prime - phi0 ) + + const double sinDeltaPhi = ( -omega / ( 1.0 - ( omega * d0Prime ) ) ) * ( deltaX * cosPhi0 + deltaY * sinPhi0 ) ; + + const double cosDeltaPhi = 1.0 + ( omega*omega / ( 2.0 * ( 1.0 - omega * d0Prime ) ) ) * ( d0Prime*d0Prime - ( deltaX + d0 * sinPhi0 )*( deltaX + d0 * sinPhi0 ) - ( deltaY - d0 * cosPhi0 )*( deltaY - d0 * cosPhi0 ) ) ; + + const double s = atan2(-sinDeltaPhi,cosDeltaPhi) / omega ; + + const double z0Prime = ref[2] - zref + z0 + tanL * s ; + + + // Convert Covariance Matrix + CLHEP::HepSymMatrix cov0(5) ; + + int icov = 0 ; + + for(int irow=0; irow<5; ++irow ){ + for(int jcol=0; jcol<irow+1; ++jcol){ + // std::cout << "row = " << irow << " col = " << jcol << std::endl ; + // std::cout << "cov["<< icov << "] = " << _cov[icov] << std::endl ; + cov0[irow][jcol] = ts.getCovMatrix()[icov] ; + ++icov ; + } + } + + CLHEP::HepMatrix propagatorMatrix(5, 5, 0) ; + + // LC_0 = { d0, phi0, omega, z0, tanLambda } + + // d d0' / d LC_0 + propagatorMatrix(1,1) = cosDeltaPhi ; + propagatorMatrix(1,2) = -( radius - d0 ) * sinDeltaPhi ; + propagatorMatrix(1,3) = radius*radius * ( cosDeltaPhi -1 ) ; + + // d phi0' / d LC_0 + propagatorMatrix(2,1) = sinDeltaPhi / ( radius - d0Prime ) ; + propagatorMatrix(2,2) = ( ( radius - d0 ) * cosDeltaPhi ) / ( radius - d0Prime ) ; + propagatorMatrix(2,3) = radius*radius * sinDeltaPhi / ( radius - d0Prime ) ; + + // d omega' / d LC_0 + propagatorMatrix(3,3) = 1.0 ; + + // d z0' / d LC_0 + propagatorMatrix(4,1) = radius * tanL * sinDeltaPhi / ( d0Prime + radius ) ; + propagatorMatrix(4,2) = radius * tanL * ( 1.0 - ( ( d0 + radius ) * cosDeltaPhi / ( d0Prime + radius ) ) ) ; + propagatorMatrix(4,3) = radius*radius * tanL * ( (phi0Prime - phi0) - radius * sinDeltaPhi / ( d0Prime + radius ) ) ; + propagatorMatrix(4,4) = 1.0 ; + propagatorMatrix(4,5) = s ; + + // d tanLambda' / d LC_0 + propagatorMatrix(5,5) = 1.0 ; + + + CLHEP::HepSymMatrix covPrime = cov0.similarity(propagatorMatrix); + + EVENT::FloatVec cov( 15 ) ; + + icov = 0 ; + + for(int irow=0; irow<5; ++irow ){ + for(int jcol=0; jcol<irow+1; ++jcol){ + // std::cout << "row = " << irow << " col = " << jcol << std::endl ; + cov[icov] = covPrime[irow][jcol] ; + // std::cout << "lcCov["<< icov << "] = " << lcCov[icov] << std::endl ; + ++icov ; + } + } + + while ( phi0Prime < -M_PI ) phi0Prime += 2.0*M_PI ; + while ( phi0Prime >= M_PI ) phi0Prime -= 2.0*M_PI ; + + ts.setD0( d0Prime ) ; + ts.setPhi( phi0Prime ) ; + ts.setOmega( omega ) ; + ts.setZ0( z0Prime ) ; + ts.setTanLambda( tanL ) ; + + + float refPointPrime[3] ; + refPointPrime[0] = xref ; + refPointPrime[1] = yref ; + refPointPrime[2] = zref ; + + ts.setReferencePoint(refPointPrime) ; + + ts.setCovMatrix( cov ) ; + + return 0 ; + + + } + + // Propagate track to a new reference point taken as its crossing point with a cylinder of infinite length centered at x0,y0, parallel to the z axis. + // For direction== 0 the closest crossing point will be taken + // For direction== 1 the first crossing traversing in positive s will be taken + // For direction==-1 the first crossing traversing in negative s will be taken + + int PropagateLCIOToCylinder( IMPL::TrackStateImpl& ts, float r0, float x0, float y0, int direction, double epsilon){ + + // taken from http://paulbourke.net/geometry/2circle/tvoght.c + + // std::cout << "PropagateLCIOToCylinder: r = " << r0 << " x0:y0 = " << x0 << " : " << y0 << " direction = " << direction << std::endl ; + + + const double x_ref = ts.getReferencePoint()[0] ; + const double y_ref = ts.getReferencePoint()[1] ; + const double z_ref = ts.getReferencePoint()[2] ; + + const double d0 = ts.getD0() ; + const double z0 = ts.getZ0() ; + const double phi0 = ts.getPhi() ; + const double tanl = ts.getTanLambda() ; + const double omega = ts.getOmega() ; + + const double rho = 1.0 / omega ; + const double x_pca = x_ref - d0 * sin(phi0) ; + const double y_pca = y_ref + d0 * cos(phi0) ; + const double z_pca = z_ref + z0 ; + + const double sin_phi0 = sin(phi0); + const double cos_phi0 = cos(phi0); + + const double x_c = x_ref + ( rho - d0) * sin_phi0 ; + const double y_c = y_ref - ( rho - d0) * cos_phi0 ; + + const double r1 = fabs(rho) ; + + /* dx and dy are the vertical and horizontal distances between + * the circle centers. + */ + const double dx = x_c - x0; + const double dy = y_c - y0; + + /* Determine the straight-line distance between the centers. */ + const double d = hypot(dx,dy); + + /* Check for solvability. */ + if (d > (r0 + r1)) + { + /* no solution. circles do not intersect. */ + return 1; + } + if (d < fabs(r0 - r1)) + { + /* no solution. one circle is contained in the other */ + return 2; + } + if (d < epsilon) + { + /* no solution. circles have common centre */ + return 3; + } + + /* 'point 2' is the point where the line through the circle + * intersection points crosses the line between the circle + * centers. + */ + + /* Determine the distance from point 0 to point 2. */ + const double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ; + + /* Determine the coordinates of point 2. */ + const double x2 = x0 + (dx * a/d); + const double y2 = y0 + (dy * a/d); + + /* Determine the distance from point 2 to either of the + * intersection points. + */ + const double h = sqrt((r0*r0) - (a*a)); + + /* Now determine the offsets of the intersection points from + * point 2. + */ + const double rx = -dy * (h/d); + const double ry = dx * (h/d); + + /* Determine the absolute intersection points. */ + const double x_ins1 = x2 + rx; + const double y_ins1 = y2 + ry; + + const double x_ins2 = x2 - rx; + const double y_ins2 = y2 - ry; + + // std::cout << "PropagateLCIOToCylinder: 1st solution x:y = " << x_ins1 << " : " << y_ins1 << std::endl ; + // std::cout << "PropagateLCIOToCylinder: 2nd solution x:y = " << x_ins2 << " : " << y_ins2 << std::endl ; + + // now calculate the path lengths + double s_1 = 0.0 ; + double s_2 = 0.0 ; + + const double delta_x1 = x_ins1 - x_pca ; + const double delta_y1 = y_ins1 - y_pca ; + + const double sin_delta_phi1 = - omega*delta_x1*cos_phi0 - omega*delta_y1*sin_phi0 ; + const double cos_delta_phi1 = 1.0 - omega*delta_x1*sin_phi0 + omega*delta_y1*cos_phi0 ; + + s_1 = atan2(-sin_delta_phi1,cos_delta_phi1) / omega ; + + + const double delta_x2 = x_ins2 - x_pca ; + const double delta_y2 = y_ins2 - y_pca ; + + const double sin_delta_phi2 = - omega*delta_x2*cos_phi0 - omega*delta_y2*sin_phi0 ; + const double cos_delta_phi2 = 1.0 - omega*delta_x2*sin_phi0 + omega*delta_y2*cos_phi0 ; + + s_2 = atan2(-sin_delta_phi2,cos_delta_phi2) / omega ; + + double x=0, y=0, z=0 ; + + if( direction == 0 ) { // take closest intersection + if( fabs(s_1) < fabs(s_2) ) { + // std::cout << "PropagateLCIOToCylinder: use 1st solution" << std::endl ; + x = x_ins1 ; + y = y_ins1 ; + z = z_pca + s_1 * tanl ; + } + else { + // std::cout << "PropagateLCIOToCylinder: use 2nd solution" << std::endl ; + x = x_ins2 ; + y = y_ins2 ; + z = z_pca + s_2 * tanl ; + } + } + + else { + + if ( s_1 < 0.0 ) s_1 += 2.0*M_PI * r1 ; + if ( s_2 < 0.0 ) s_2 += 2.0*M_PI * r1 ; + + if( direction == 1 ){ // take the intersection with smallest s + if( s_1 < s_2 ) { + x = x_ins1 ; + y = y_ins1 ; + z = z_pca + s_1 * tanl ; + } + else { + x = x_ins2 ; + y = y_ins2 ; + z = z_pca + s_2 * tanl ; + } + } + else if(direction == -1) { // else take the intersection with largest s + if( s_1 > s_2 ){ + x = x_ins1 ; + y = y_ins1 ; + z = z_pca + s_1 * tanl ; + } + else{ + x = x_ins2 ; + y = y_ins2 ; + z = z_pca + s_2 * tanl ; + } + } + } + + + return PropagateLCIOToNewRef(ts,x,y,z); + + } + + int PropagateLCIOToZPlane( IMPL::TrackStateImpl& ts, float z) { + + + const double x_ref = ts.getReferencePoint()[0] ; + const double y_ref = ts.getReferencePoint()[1] ; + const double z_ref = ts.getReferencePoint()[2] ; + + const double d0 = ts.getD0() ; + const double z0 = ts.getZ0() ; + const double phi0 = ts.getPhi() ; + const double tanl = ts.getTanLambda() ; + const double omega = ts.getOmega() ; + + const double x_pca = x_ref - d0 * sin(phi0) ; + const double y_pca = y_ref + d0 * cos(phi0) ; + const double z_pca = z_ref + z0 ; + + // get path length to crossing point + const double s = ( z - z_pca ) / tanl; + + const double delta_phi_half = (omega*s)/2.0 ; + + const double x = x_pca + s * ( sin(delta_phi_half) / delta_phi_half ) * cos( phi0 - delta_phi_half ) ; + const double y = y_pca + s * ( sin(delta_phi_half) / delta_phi_half ) * sin( phi0 - delta_phi_half ) ; + + return PropagateLCIOToNewRef(ts,x,y,z); + + } + + + + // Propagate track to a new reference point taken as its crossing point with a plane parallel to the z axis, containing points x1,x2 and y1,y2. Tolerance for intersection determined by epsilon. + // For direction == 0 the closest crossing point will be taken + // For direction == 1 the first crossing traversing in positive s will be taken + // For direction == -1 the first crossing traversing in negative s will be taken + int PropagateLCIOToPlaneParralelToZ( IMPL::TrackStateImpl& ts, float x1, float y1, float x2, float y2, int direction, double epsilon) { + + // check that direction has one of the correct values + if( !( direction == 0 || direction == 1 || direction == -1) ) return -1 ; + + // taken from http://paulbourke.net/geometry/sphereline/raysphere.c + + const double x_ref = ts.getReferencePoint()[0] ; + const double y_ref = ts.getReferencePoint()[1] ; + const double z_ref = ts.getReferencePoint()[2] ; + + const double d0 = ts.getD0() ; + const double z0 = ts.getZ0() ; + const double phi0 = ts.getPhi() ; + const double tanl = ts.getTanLambda() ; + const double omega = ts.getOmega() ; + + const double rho = 1.0 / omega ; + const double x_pca = x_ref - d0 * sin(phi0) ; + const double y_pca = y_ref + d0 * cos(phi0) ; + const double z_pca = z_ref + z0 ; + + const double sin_phi0 = sin(phi0); + const double cos_phi0 = cos(phi0); + + const double x_c = x_ref + ( rho - d0) * sin_phi0 ; + const double y_c = y_ref - ( rho - d0) * cos_phi0 ; + + const double dx = x2 - x1 ; + const double dy = y2 - y1 ; + + const double a = dx * dx + dy * dy ; + + const double b = 2.0 * ( dx * (x1 - x_c) + dy * (y1 - y_c) ) ; + + double c = x_c * x_c + y_c * y_c; + c += x1 * x1 + y1 * y1 ; + + c -= 2.0 * ( x_c * x1 + y_c * y1 ); + c -= rho * rho; + + const double bb4ac = b * b - 4.0 * a * c; + + double u1 ; // first solution + double u2 ; // second solution + + /* Check for solvability. */ + if (bb4ac + epsilon < 0.0 ) { // no intersection + return(1); + } + else if(bb4ac - epsilon < 0.0) { // circle intersects at one point, tangential + return(2); + } + else{ + u1 = (-b + sqrt(bb4ac)) / (2.0 * a); + u2 = (-b - sqrt(bb4ac)) / (2.0 * a); + } + + const double x_ins1 = x1 + u1 * (dx) ; + const double y_ins1 = y1 + u1 * (dy) ; + + const double x_ins2 = x1 + u2 * (dx) ; + const double y_ins2 = y1 + u2 * (dy) ; + + // std::cout << "PropagateLCIOToPlaneParralelToZ: 1st solution u = " << u1 << " : " << u1 * dx << " " << u1 * dy << std::endl ; + // std::cout << "PropagateLCIOToPlaneParralelToZ: 2nd solution u = " << u2 << " : " << u2 * dx << " " << u2 * dy << std::endl ; + // std::cout << "PropagateLCIOToPlaneParralelToZ: 1st solution x:y = " << x_ins1 << " : " << y_ins1 << std::endl ; + // std::cout << "PropagateLCIOToPlaneParralelToZ: 2nd solution x:y = " << x_ins2 << " : " << y_ins2 << std::endl ; + + // now calculate the path lengths + double s_1 = 0.0 ; + double s_2 = 0.0 ; + + const double delta_x1 = x_ins1 - x_pca ; + const double delta_y1 = y_ins1 - y_pca ; + + const double sin_delta_phi1 = - omega*delta_x1*cos_phi0 - omega*delta_y1*sin_phi0 ; + const double cos_delta_phi1 = 1.0 - omega*delta_x1*sin_phi0 + omega*delta_y1*cos_phi0 ; + + s_1 = atan2(-sin_delta_phi1,cos_delta_phi1) / omega ; + + const double delta_x2 = x_ins2 - x_pca ; + const double delta_y2 = y_ins2 - y_pca ; + + const double sin_delta_phi2 = - omega*delta_x2*cos_phi0 - omega*delta_y2*sin_phi0 ; + const double cos_delta_phi2 = 1.0 - omega*delta_x2*sin_phi0 + omega*delta_y2*cos_phi0 ; + + s_2 = atan2(-sin_delta_phi2,cos_delta_phi2) / omega ; + + double x(0.0), y(0.0), z(0.0) ; + + if( direction == 0 ) { // take closest intersection + if( fabs(s_1) < fabs(s_2) ) { + // std::cout << "PropagateLCIOToPlaneParralelToZ: take 1st solution " << std::endl; + x = x_ins1 ; + y = y_ins1 ; + z = z_pca + s_1 * tanl ; + } + else { + // std::cout << "PropagateLCIOToPlaneParralelToZ: take 2nd solution " << std::endl; + x = x_ins2 ; + y = y_ins2 ; + z = z_pca + s_2 * tanl ; + } + } + + else{ + + if ( s_1 < 0.0 ) s_1 += 2.0*M_PI * fabs(rho) ; + if ( s_2 < 0.0 ) s_2 += 2.0*M_PI * fabs(rho) ; + + if( direction == 1 ){ // take the intersection with smallest s + if( s_1 < s_2 ) { + // std::cout << "PropagateLCIOToPlaneParralelToZ: take 1st solution " << std::endl; + x = x_ins1 ; + y = y_ins1 ; + z = z_pca + s_1 * tanl ; + } + else { + // std::cout << "PropagateLCIOToPlaneParralelToZ: take 2nd solution " << std::endl; + x = x_ins2 ; + y = y_ins2 ; + z = z_pca + s_2 * tanl ; + } + } + else if( direction == -1 ) { // else take the intersection with largest s + if( s_1 > s_2 ){ + // std::cout << "PropagateLCIOToPlaneParralelToZ: take 1st solution " << std::endl; + x = x_ins1 ; + y = y_ins1 ; + z = z_pca + s_1 * tanl ; + } + else{ + // std::cout << "PropagateLCIOToPlaneParralelToZ: take 2nd solution " << std::endl; + x = x_ins2 ; + y = y_ins2 ; + z = z_pca + s_2 * tanl ; + } + } + } + + return PropagateLCIOToNewRef(ts,x,y,z); + + } + + +} // end of TrackPropagators diff --git a/Service/TrackSystemSvc/src/MarlinKalTest.cc b/Service/TrackSystemSvc/src/MarlinKalTest.cc new file mode 100644 index 0000000000000000000000000000000000000000..b6e32021c64d9520611e7737dd1e734922d15a37 --- /dev/null +++ b/Service/TrackSystemSvc/src/MarlinKalTest.cc @@ -0,0 +1,518 @@ +#include "MarlinKalTest.h" +#include "MarlinKalTestTrack.h" + +#include "kaltest/TKalDetCradle.h" +#include "kaltest/TVKalDetector.h" +#include "kaltest/THelicalTrack.h" + +#include "kaldet/ILDVMeasLayer.h" + +#include "kaldet/ILDSupportKalDetector.h" +#include "kaldet/ILDVXDKalDetector.h" +#include "kaldet/ILDSITKalDetector.h" +#include "kaldet/ILDSITCylinderKalDetector.h" +#include "kaldet/ILDSETKalDetector.h" +#include "kaldet/ILDFTDKalDetector.h" +#include "kaldet/ILDFTDDiscBasedKalDetector.h" +#include "kaldet/ILDTPCKalDetector.h" + +#include "kaldet/LCTPCKalDetector.h" + +//SJA:FIXME: only needed for storing the modules in the layers map +#include <UTIL/BitField64.h> +#include "UTIL/ILDConf.h" + +#include "gear/GEAR.h" +#include "gear/BField.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "DetInterface/IGeoSvc.h" + +#include <math.h> +#include <cmath> + +#include <utility> + +//#include "streamlog/streamlog.h" + +#include "kaldet/ILDMeasurementSurfaceStoreFiller.h" + +namespace MarlinTrk{ + + MarlinKalTest::MarlinKalTest( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc) : + _ipLayer(NULL) , + _gearMgr( &gearMgr ), + _geoSvc(geoSvc){ + + //streamlog_out( DEBUG4 ) << " MarlinKalTest - initializing the detector ..." << std::endl ; + + _det = new TKalDetCradle ; // from kaltest. TKalDetCradle inherits from TObjArray ... + _det->SetOwner( true ) ; // takes care of deleting subdetector in the end ... + + is_initialised = false; + + this->registerOptions() ; + + //streamlog_out( DEBUG4 ) << " MarlinKalTest - established " << std::endl ; + + + } + + MarlinKalTest::~MarlinKalTest(){ + +#ifdef MARLINTRK_DIAGNOSTICS_ON + _diagnostics.end(); +#endif + + delete _det ; + } + + + void MarlinKalTest::init() { + + //streamlog_out( DEBUG4 ) << " MarlinKalTest - call this init " << std::endl ; + + + MeasurementSurfaceStore& surfstore = _gearMgr->getMeasurementSurfaceStore(); + + // Check if the store is filled if not fill it. NOTE: In the case it is filled we just take what we are given and in debug print a message + if( surfstore.isFilled() == false ) { + + ILDMeasurementSurfaceStoreFiller filler( *_gearMgr ); + //streamlog_out( DEBUG4 ) << " MarlinKalTest - set up gear surface store using " << filler.getName() << std::endl ; + surfstore.FillStore(&filler); + + } + else { + + //streamlog_out( DEBUG4 ) << " MarlinKalTest - MeasurementSurfaceStore is already full. Using store as filled by MeasurementSurfaceStoreFiller " << surfstore.getFillerName() << std::endl ; + + } + + if (_gearMgr -> getDetectorName() == "LPTPC") { + try{ + kaldet::LCTPCKalDetector* tpcdet = new kaldet::LCTPCKalDetector( *_gearMgr ) ; + // store the measurement layer id's for the active layers + this->storeActiveMeasurementModuleIDs(tpcdet); + _det->Install( *tpcdet ) ; + } + catch( gear::UnknownParameterException& e){ + //streamlog_out( MESSAGE ) << " MarlinKalTest - TPC missing in gear file: TPC Not Built " << std::endl ; + } + } + else { + + try{ + ILDSupportKalDetector* supportdet = new ILDSupportKalDetector( *_gearMgr, _geoSvc ) ; + // get the dedicated ip layer + _ipLayer = supportdet->getIPLayer() ; + // store the measurement layer id's for the active layers, Calo is defined as active + this->storeActiveMeasurementModuleIDs(supportdet); + _det->Install( *supportdet ) ; + } + catch( gear::UnknownParameterException& e){ + std::cout << "Error: " << "MarlinKalTest - Support Material missing in gear file: Cannot proceed as propagations and extrapolations for cannonical track states are impossible: exit(1) called" << std::endl ; + exit(1); + } + + try{ + ILDVXDKalDetector* vxddet = new ILDVXDKalDetector( *_gearMgr, _geoSvc ) ; + // store the measurement layer id's for the active layers + this->storeActiveMeasurementModuleIDs(vxddet); + _det->Install( *vxddet ) ; + } + catch( gear::UnknownParameterException& e){ + std::cout << "Warning: " << " MarlinKalTest - VXD missing in gear file: VXD Material Not Built " << std::endl ; + } + + + bool SIT_found = false ; + try{ + ILDSITKalDetector* sitdet = new ILDSITKalDetector( *_gearMgr ) ; + // store the measurement layer id's for the active layers + this->storeActiveMeasurementModuleIDs(sitdet); + _det->Install( *sitdet ) ; + SIT_found = true ; + } + catch( gear::UnknownParameterException& e){ + //streamlog_out( MESSAGE ) << " MarlinKalTest - SIT missing in gear file: SIT Not Built " << std::endl ; + } + + if( ! SIT_found ){ + try{ + ILDSITCylinderKalDetector* sitdet = new ILDSITCylinderKalDetector( *_gearMgr ) ; + // store the measurement layer id's for the active layers + this->storeActiveMeasurementModuleIDs(sitdet); + _det->Install( *sitdet ) ; + } + catch( gear::UnknownParameterException& e){ + std::cout << "Warning: " << " MarlinKalTest - Simple Cylinder Based SIT missing in gear file: Simple Cylinder Based SIT Not Built " << std::endl ; + } + } + + try{ + ILDSETKalDetector* setdet = new ILDSETKalDetector( *_gearMgr ) ; + // store the measurement layer id's for the active layers + this->storeActiveMeasurementModuleIDs(setdet); + _det->Install( *setdet ) ; + } + catch( gear::UnknownParameterException& e){ + std::cout << "Warning: " << " MarlinKalTest - SET missing in gear file: SET Not Built " << std::endl ; + } + + + bool FTD_found = false ; + try{ + ILDFTDKalDetector* ftddet = new ILDFTDKalDetector( *_gearMgr ) ; + // store the measurement layer id's for the active layers + this->storeActiveMeasurementModuleIDs(ftddet); + _det->Install( *ftddet ) ; + FTD_found = true ; + } + catch( gear::UnknownParameterException& e){ + std::cout << "Warning: " << " MarlinKalTest - Petal Based FTD missing in gear file: Petal Based FTD Not Built " << std::endl ; + } + + if( ! FTD_found ){ + try{ + ILDFTDDiscBasedKalDetector* ftddet = new ILDFTDDiscBasedKalDetector( *_gearMgr ) ; + // store the measurement layer id's for the active layers + this->storeActiveMeasurementModuleIDs(ftddet); + _det->Install( *ftddet ) ; + } + catch( gear::UnknownParameterException& e){ + std::cout << "Warning: " << " MarlinKalTest - Simple Disc Based FTD missing in gear file: Simple Disc Based FTD Not Built " << std::endl ; + } + } + + try{ + ILDTPCKalDetector* tpcdet = new ILDTPCKalDetector( *_gearMgr ) ; + // store the measurement layer id's for the active layers + this->storeActiveMeasurementModuleIDs(tpcdet); + _det->Install( *tpcdet ) ; + } + catch( gear::UnknownParameterException& e){ + std::cout << "Warning: " << " MarlinKalTest - TPC missing in gear file: TPC Not Built " << std::endl ; + } + } + + _det->Close() ; // close the cradle + _det->Sort() ; // sort meas. layers from inside to outside + + //streamlog_out( DEBUG4 ) << " MarlinKalTest - number of layers = " << _det->GetEntriesFast() << std::endl ; + + //streamlog_out( DEBUG4 ) << "Options: " << std::endl << this->getOptions() << std::endl ; + + this->includeMultipleScattering( getOption(IMarlinTrkSystem::CFG::useQMS) ) ; + this->includeEnergyLoss( getOption(IMarlinTrkSystem::CFG::usedEdx) ) ; + + + is_initialised = true; + + } + + MarlinTrk::IMarlinTrack* MarlinKalTest::createTrack() { + //std::cout << "fucd " << "creatTrack" << std::endl; + if ( ! is_initialised ) { + std::stringstream errorMsg; + errorMsg << "MarlinKalTest::createTrack: Fitter not initialised. MarlinKalTest::init() must be called before MarlinKalTest::createTrack()" << std::endl ; + throw MarlinTrk::Exception(errorMsg.str()); + + } + return new MarlinTrk::MarlinKalTestTrack(this) ; + } + + void MarlinKalTest::includeMultipleScattering( bool msOn ) { + + if( msOn == true ) { + _det->SwitchOnMS(); + } + else{ + _det->SwitchOffMS(); + } + + } + + void MarlinKalTest::includeEnergyLoss( bool energyLossOn ) { + + if( energyLossOn == true ) { + _det->SwitchOnDEDX(); + } + else{ + _det->SwitchOffDEDX(); + } + + } + + void MarlinKalTest::getSensitiveMeasurementModulesForLayer( int layerID, std::vector< const ILDVMeasLayer *>& measmodules) const { + + if( ! measmodules.empty() ) { + + std::stringstream errorMsg; + errorMsg << "MarlinKalTest::getSensitiveMeasurementModulesForLayer vector passed as second argument is not empty " << std::endl ; + throw MarlinTrk::Exception(errorMsg.str()); + + } + + //streamlog_out( DEBUG0 ) << "MarlinKalTest::getSensitiveMeasurementModulesForLayer: layerID = " << layerID << std::endl; + + std::multimap<Int_t, const ILDVMeasLayer *>::const_iterator it; //Iterator to be used along with ii + + + + // for(it = _active_measurement_modules_by_layer.begin(); it != _active_measurement_modules_by_layer.end(); ++it) { + // streamlog_out( DEBUG0 ) << "Key = "<< ttdecodeILD(it->first) <<" Value = "<<it->second << std::endl ; + // } + + + std::pair<std::multimap<Int_t, const ILDVMeasLayer *>::const_iterator, std::multimap<Int_t, const ILDVMeasLayer *>::const_iterator> ii; + + // set the module and sensor bit ranges to zero as these are not used in the map + lcio::BitField64 bf( UTIL::ILDCellID0::encoder_string ) ; + bf.setValue( layerID ) ; + bf[lcio::ILDCellID0::module] = 0 ; + bf[lcio::ILDCellID0::sensor] = 0 ; + layerID = bf.lowWord(); + + ii = this->_active_measurement_modules_by_layer.equal_range(layerID); // set the first and last entry in ii; + + for(it = ii.first; it != ii.second; ++it) { + // streamlog_out( DEBUG0 ) <<"Key = "<< it->first <<" Value = "<<it->second << std::endl ; + measmodules.push_back( it->second ) ; + } + + } + + void MarlinKalTest::getSensitiveMeasurementModules( int moduleID , std::vector< const ILDVMeasLayer *>& measmodules ) const { + + if( ! measmodules.empty() ) { + + std::stringstream errorMsg; + errorMsg << "MarlinKalTest::getSensitiveMeasurementLayer vector passed as second argument is not empty " << std::endl ; + throw MarlinTrk::Exception(errorMsg.str()); + + } + + std::pair<std::multimap<int, const ILDVMeasLayer *>::const_iterator, std::multimap<Int_t, const ILDVMeasLayer *>::const_iterator> ii; + ii = this->_active_measurement_modules.equal_range(moduleID); // set the first and last entry in ii; + + std::multimap<int,const ILDVMeasLayer *>::const_iterator it; //Iterator to be used along with ii + + + for(it = ii.first; it != ii.second; ++it) { + // std::cout<<"Key = "<<it->first<<" Value = "<<it->second << std::endl ; + measmodules.push_back( it->second ) ; + } + } + + + void MarlinKalTest::storeActiveMeasurementModuleIDs(TVKalDetector* detector) { + + Int_t nLayers = detector->GetEntriesFast() ; + + for( int i=0; i < nLayers; ++i ) { + + const ILDVMeasLayer* ml = dynamic_cast<const ILDVMeasLayer*>( detector->At( i ) ); + + if( ! ml ) { + std::stringstream errorMsg; + errorMsg << "MarlinKalTest::storeActiveMeasurementLayerIDs dynamic_cast to ILDVMeasLayer* failed " << std::endl ; + throw MarlinTrk::Exception(errorMsg.str()); + } + + if( ml->IsActive() ) { + + // then get all the sensitive element id's assosiated with this ILDVMeasLayer and store them in the map + std::vector<int>::const_iterator it = ml->getCellIDs().begin(); + + while ( it!=ml->getCellIDs().end() ) { + + int sensitive_element_id = *it; + this->_active_measurement_modules.insert(std::pair<int,const ILDVMeasLayer*>( sensitive_element_id, ml )); + ++it; + + } + + int subdet_layer_id = ml->getLayerID() ; + + this->_active_measurement_modules_by_layer.insert(std::pair<int ,const ILDVMeasLayer*>(subdet_layer_id,ml)); + + //streamlog_out(DEBUG0) << "MarlinKalTest::storeActiveMeasurementLayerIDs added active layer with " + //<< " LayerID = " << subdet_layer_id << " and DetElementIDs " ; + + for (it = ml->getCellIDs().begin(); it!=ml->getCellIDs().end(); ++it) { + + //streamlog_out(DEBUG0) << " : " << *it ; + + } + + //streamlog_out(DEBUG0) << std::endl; + + + + + } + + } + + } + + const ILDVMeasLayer* MarlinKalTest::getLastMeasLayer(THelicalTrack const& hel, TVector3 const& point) const { + + THelicalTrack helix = hel; + + double deflection_to_point = 0 ; + helix.MoveTo( point, deflection_to_point , 0 , 0) ; + + bool isfwd = ((helix.GetKappa() > 0 && deflection_to_point < 0) || (helix.GetKappa() <= 0 && deflection_to_point > 0)) ? true : false; + + int mode = isfwd ? -1 : +1 ; + + // streamlog_out( DEBUG4 ) << " MarlinKalTest - getLastMeasLayer deflection to point = " << deflection_to_point << " kappa = " << helix.GetKappa() << " mode = " << mode << std::endl ; + // streamlog_out( DEBUG4 ) << " Point to move to:" << std::endl; + // point.Print(); + + int nsufaces = _det->GetEntriesFast(); + + const ILDVMeasLayer* ml_retval = 0; + double min_deflection = DBL_MAX; + + for(int i=0; i<nsufaces; ++i) { + + const ILDVMeasLayer &ml = *dynamic_cast< const ILDVMeasLayer *>(_det->At(i)); + + double defection_angle = 0 ; + TVector3 crossing_point ; + + const TVSurface *sfp = dynamic_cast<const TVSurface *>(&ml); // surface at destination + + + int does_cross = sfp->CalcXingPointWith(helix, crossing_point, defection_angle, mode) ; + + if( does_cross ) { + + const double deflection = fabs( deflection_to_point - defection_angle ) ; + + if( deflection < min_deflection ) { + + // streamlog_out( DEBUG4 ) << " MarlinKalTest - crossing found for suface = " << ml.GetMLName() + // << std::endl + // << " min_deflection = " << min_deflection + // << " deflection = " << deflection + // << " deflection angle = " << defection_angle + // << std::endl + // << " x = " << crossing_point.X() + // << " y = " << crossing_point.Y() + // << " z = " << crossing_point.Z() + // << " r = " << crossing_point.Perp() + // << std::endl ; + + min_deflection = deflection ; + ml_retval = &ml ; + } + + } + + } + + return ml_retval; + } + + const ILDVMeasLayer* MarlinKalTest::findMeasLayer( edm4hep::TrackerHit* trkhit) const { + + const TVector3 hit_pos( trkhit->getPosition()[0], trkhit->getPosition()[1], trkhit->getPosition()[2]) ; + + return this->findMeasLayer( trkhit->getCellID(), hit_pos ) ; + + } + + const ILDVMeasLayer* MarlinKalTest::findMeasLayer( int detElementID, const TVector3& point) const { + + const ILDVMeasLayer* ml = 0; // return value + + std::vector<const ILDVMeasLayer*> meas_modules ; + + // search for the list of measurement layers associated with this CellID + this->getSensitiveMeasurementModules( detElementID, meas_modules ) ; + + if( meas_modules.size() == 0 ) { // no measurement layers found + + UTIL::BitField64 encoder( UTIL::ILDCellID0::encoder_string ) ; + encoder.setValue(detElementID) ; + + std::stringstream errorMsg; + errorMsg << "MarlinKalTest::findMeasLayer module id unkown: moduleID = " << detElementID + << " subdet = " << encoder[UTIL::ILDCellID0::subdet] + << " side = " << encoder[UTIL::ILDCellID0::side] + << " layer = " << encoder[UTIL::ILDCellID0::layer] + << " module = " << encoder[UTIL::ILDCellID0::module] + << " sensor = " << encoder[UTIL::ILDCellID0::sensor] + << std::endl ; + throw MarlinTrk::Exception(errorMsg.str()); + + } + else if (meas_modules.size() == 1) { // one to one mapping + + ml = meas_modules[0] ; + + } + else { // layer has been split + + bool surf_found(false); + + // loop over the measurement layers associated with this CellID and find the correct one using the position of the hit + for( unsigned int i=0; i < meas_modules.size(); ++i) { + + + + const TVSurface* surf = 0; + + if( ! (surf = dynamic_cast<const TVSurface*> ( meas_modules[i] )) ) { + std::stringstream errorMsg; + errorMsg << "MarlinKalTest::findMeasLayer dynamic_cast failed for surface type: moduleID = " << detElementID << std::endl ; + throw MarlinTrk::Exception(errorMsg.str()); + } + + bool hit_on_surface = surf->IsOnSurface(point); + + if( (!surf_found) && hit_on_surface ){ + + ml = meas_modules[i] ; + surf_found = true ; + + } + else if( surf_found && hit_on_surface ) { // only one surface should be found, if not throw + + std::stringstream errorMsg; + errorMsg << "MarlinKalTest::findMeasLayer point found to be on two surfaces: moduleID = " << detElementID << std::endl ; + throw MarlinTrk::Exception(errorMsg.str()); + } + + } + if( ! surf_found ){ // print out debug info + /* + streamlog_out(DEBUG1) << "MarlinKalTest::findMeasLayer point not found to be on any surface matching moduleID = " + << detElementID + << ": x = " << point.x() + << " y = " << point.y() + << " z = " << point.z() + << std::endl ; + */ + } + else{ + /* + streamlog_out(DEBUG1) << "MarlinKalTest::findMeasLayer point found to be on surface matching moduleID = " + << detElementID + << ": x = " << point.x() + << " y = " << point.y() + << " z = " << point.z() + << std::endl ; + */ + } + } + + return ml ; + + } + +} // end of namespace MarlinTrk diff --git a/Service/TrackSystemSvc/src/MarlinKalTest.h b/Service/TrackSystemSvc/src/MarlinKalTest.h new file mode 100644 index 0000000000000000000000000000000000000000..ac9ed1520838f32a35d8547a3e982dab0ddb89d1 --- /dev/null +++ b/Service/TrackSystemSvc/src/MarlinKalTest.h @@ -0,0 +1,104 @@ +#ifndef MarlinKalTest_h +#define MarlinKalTest_h + +#include "TrackSystemSvc/IMarlinTrkSystem.h" + +#include "gear/GearMgr.h" + +//LCIO: +//#include "lcio.h" +#include "UTIL/BitField64.h" +//#include "UTIL/LCTOOLS.h" +//#include <LCRTRelations.h> + +//#include "streamlog/streamlog.h" + +#include "TObjArray.h" +#include "TVector3.h" + +#include <cmath> +#include <vector> +#include "DetInterface/IGeoSvc.h" + +class TKalDetCradle ; +class TVKalDetector ; +class ILDVMeasLayer ; +class THelicalTrack ; +//class IGeoSvc; +class ILDCylinderMeasLayer; + +namespace edm4hep{ + class TrackerHit ; +} +namespace MarlinTrk{ + /** Interface to KaltTest Kalman fitter - instantiates and holds the detector geometry. + */ + class MarlinKalTest : public IMarlinTrkSystem { + + public: + + friend class MarlinKalTestTrack; + + // define some configuration constants + static const bool FitBackward = kIterBackward ; + static const bool FitForward = kIterForward ; + static const bool OrderOutgoing = true ; + static const bool OrderIncoming = false ; + + + /** Default c'tor, initializes the geometry from GEAR. */ + MarlinKalTest( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc) ; + + /** d'tor */ + ~MarlinKalTest() ; + + /** initialise track fitter system */ + void init() ; + + /** instantiate its implementation of the IMarlinTrack */ + IMarlinTrack* createTrack(); + + protected: + + /** take multiple scattering into account during the fit */ + void includeMultipleScattering(bool on); + + /** take energy loss into account during the fit */ + void includeEnergyLoss(bool on); + + /** Store active measurement module IDs for a given TVKalDetector needed for navigation */ + void storeActiveMeasurementModuleIDs(TVKalDetector* detector); + + /** Store active measurement module IDs needed for navigation */ + void getSensitiveMeasurementModules(int detElementID, std::vector< const ILDVMeasLayer *>& measmodules) const; + + /** Store active measurement module IDs needed for navigation */ + void getSensitiveMeasurementModulesForLayer(int layerID, std::vector<const ILDVMeasLayer *>& measmodules) const; + + // void init(bool MSOn, bool EnergyLossOn) ; + bool is_initialised ; + + //** find the measurment layer for a given hit + const ILDVMeasLayer* findMeasLayer(edm4hep::TrackerHit* trkhit) const ; + //** find the measurment layer for a given det element ID and point in space + const ILDVMeasLayer* findMeasLayer(int detElementID, const TVector3& point) const ; + + // get the last layer crossed by the helix when extrapolating from the present position to the pca to point + const ILDVMeasLayer* getLastMeasLayer(THelicalTrack const& helix, TVector3 const& point) const ; + + const ILDCylinderMeasLayer* getIPLayer() const { return _ipLayer; } + + const ILDCylinderMeasLayer* _ipLayer ; + + const gear::GearMgr* _gearMgr ; + IGeoSvc* _geoSvc; + + TKalDetCradle* _det ; // the detector cradle + + std::multimap< int,const ILDVMeasLayer *> _active_measurement_modules; + + std::multimap< int,const ILDVMeasLayer *> _active_measurement_modules_by_layer; + + } ; +} +#endif diff --git a/Service/TrackSystemSvc/src/MarlinKalTestTrack.cc b/Service/TrackSystemSvc/src/MarlinKalTestTrack.cc new file mode 100644 index 0000000000000000000000000000000000000000..a98029db9132c5c1f45a5392e6403888598549aa --- /dev/null +++ b/Service/TrackSystemSvc/src/MarlinKalTestTrack.cc @@ -0,0 +1,1698 @@ +#include "MarlinKalTestTrack.h" + +#include "MarlinKalTest.h" +#include "TrackSystemSvc/IMarlinTrkSystem.h" + +#include <kaltest/TKalDetCradle.h> +#include <kaltest/TKalTrack.h> +#include <kaltest/TKalTrackState.h> +#include "kaltest/TKalTrackSite.h" +#include "kaltest/TKalFilterCond.h" + +//#include <lcio.h> +#include <edm4hep/TrackerHit.h> +//#include <plcio/TrackerHitPlane.h> + +#include <UTIL/BitField64.h> +#include <UTIL/Operators.h> +#include <UTIL/ILDConf.h> + +#include "kaldet/ILDCylinderMeasLayer.h" // needed for dedicated IP Layer +#include "kaldet/ILDCylinderHit.h" + +#include "kaldet/ILDPlanarHit.h" +#include "kaldet/ILDPlanarStripHit.h" + +#include "gear/GEAR.h" +#include "gear/BField.h" + +//#include "streamlog/streamlog.h" + + +/** Helper class for defining a filter condition based on the delta chi2 in the AddAndFilter step. + */ +class KalTrackFilter : public TKalFilterCond{ + +public: + + /** C'tor - takes as optional argument the maximum allowed delta chi2 for adding the hit (in IsAccepted() ) + */ + KalTrackFilter(double maxDeltaChi2 = DBL_MAX) : _maxDeltaChi2( maxDeltaChi2 ), _passed_last_filter_step(true) { + } + virtual ~KalTrackFilter() {} + + virtual Bool_t IsAccepted(const TKalTrackSite &site) { + + double deltaChi2 = site.GetDeltaChi2(); + + //streamlog_out( DEBUG1 ) << " KalTrackFilter::IsAccepted called ! deltaChi2 = " << std::scientific << deltaChi2 << " _maxDeltaChi2 = " << _maxDeltaChi2 << std::endl; + + _passed_last_filter_step = deltaChi2 < _maxDeltaChi2; + + return ( _passed_last_filter_step ) ; + } + + void resetFilterStatus() { _passed_last_filter_step = true; } + bool passedLastFilterStep() const { return _passed_last_filter_step; } + +protected: + + double _maxDeltaChi2 ; + bool _passed_last_filter_step; + +} ; + +namespace MarlinTrk { + + //--------------------------------------------------------------------------------------------------------------- + + std::string decodeILD(int detElementID) { + lcio::BitField64 bf(UTIL::ILDCellID0::encoder_string) ; + bf.setValue(detElementID) ; + return bf.valueString() ; + } + + //--------------------------------------------------------------------------------------------------------------- + + + MarlinKalTestTrack::MarlinKalTestTrack(MarlinKalTest* ktest) + : _ktest(ktest) { + + _kaltrack = new TKalTrack() ; + _kaltrack->SetOwner() ; + + _kalhits = new TObjArray() ; + _kalhits->SetOwner() ; + + _initialised = false ; + _fitDirection = false ; + _smoothed = false ; + + _trackHitAtPositiveNDF = 0; + _hitIndexAtPositiveNDF = 0; + +#ifdef MARLINTRK_DIAGNOSTICS_ON + _ktest->_diagnostics.new_track(this) ; +#endif + } + + + MarlinKalTestTrack::~MarlinKalTestTrack(){ + +#ifdef MARLINTRK_DIAGNOSTICS_ON + _ktest->_diagnostics.end_track() ; +#endif + + delete _kaltrack ; + delete _kalhits ; + } + + + + int MarlinKalTestTrack::addHit( edm4hep::TrackerHit* trkhit) { + + return this->addHit( trkhit, _ktest->findMeasLayer( trkhit )) ; + + } + + int MarlinKalTestTrack::addHit( edm4hep::TrackerHit* trkhit, const ILDVMeasLayer* ml) { + //std::cout << "MarlinKalTestTrack::addHit: trkhit = " << trkhit->id() << " addr: " << trkhit << " ml = " << ml << std::endl ; + if( trkhit && ml ) { + //if(ml){ + return this->addHit( trkhit, ml->ConvertLCIOTrkHit(trkhit), ml) ; + } + else { + std::cout << "MarlinKalTestTrack::addHit: trkhit = " << trkhit->id() << " addr: " << trkhit << " ml = " << ml << std::endl ; + //streamlog_out( ERROR ) << " MarlinKalTestTrack::addHit - bad inputs " << trkhit << " ml : " << ml << std::endl ; + return bad_intputs ; + } + return bad_intputs ; + } + + int MarlinKalTestTrack::addHit( edm4hep::TrackerHit* trkhit, ILDVTrackHit* kalhit, const ILDVMeasLayer* ml) { + //std::cout << "MarlinKalTestTrack::addHit: trkhit = " << trkhit->id() << " ILDVTrackHit: " << kalhit << " ml = " << ml << std::endl ; + if( kalhit && ml ) { + //if(ml){ + _kalhits->Add(kalhit ) ; // Add hit and set surface found + _lcio_hits_to_kaltest_hits[trkhit] = kalhit ; // add hit to map relating lcio and kaltest hits + // _kaltest_hits_to_lcio_hits[kalhit] = trkhit ; // add hit to map relating kaltest and lcio hits + } + else { + //std::cout << "MarlinKalTestTrack::addHit: trkhit = " << trkhit->id() << " ILDVTrackHit: " << kalhit << " ml = " << ml << std::endl ; + if(kalhit) delete kalhit; + return bad_intputs ; + } + //std::cout << "debug: " << "MarlinKalTestTrack::addHit: hit added number of hits for track = " << _kalhits->GetEntries() << std::endl ; + return success ; + } + + + int MarlinKalTestTrack::initialise( bool fitDirection ) {; + //SJA:FIXME: check here if the track is already initialised, and for now don't allow it to be re-initialised + // if the track is going to be re-initialised then we would need to do it directly on the first site + if ( _initialised ) { + throw MarlinTrk::Exception("Track fit already initialised"); + } + + if (_kalhits->GetEntries() < 3) { + std::cout << "Error: <<<<<< MarlinKalTestTrack::initialise: Shortage of Hits! nhits = " + << _kalhits->GetEntries() << " >>>>>>>" << std::endl; + return error ; + } + + _fitDirection = fitDirection ; + + // establish the hit order + Int_t i1, i2, i3; // (i1,i2,i3) = (1st,mid,last) hit to filter + if (_fitDirection == kIterBackward) { + i3 = 0 ; // fg: first index is 0 and not 1 + i1 = _kalhits->GetEntries() - 1; + i2 = i1 / 2; + } else { + i1 = 0 ; + i3 = _kalhits->GetEntries() - 1; + i2 = i3 / 2; + } + + + + TVTrackHit *startingHit = dynamic_cast<TVTrackHit *>(_kalhits->At(i1)); + + // --------------------------- + // Create an initial start site for the track using the first hit + // --------------------------- + // set up a dummy hit needed to create initial site + + TVTrackHit* pDummyHit = 0; + + if ( (pDummyHit = dynamic_cast<ILDCylinderHit *>( startingHit )) ) { + pDummyHit = (new ILDCylinderHit(*static_cast<ILDCylinderHit*>( startingHit ))); + } + else if ( (pDummyHit = dynamic_cast<ILDPlanarHit *>( startingHit )) ) { + pDummyHit = (new ILDPlanarHit(*static_cast<ILDPlanarHit*>( startingHit ))); + } + else if ( ILDPlanarStripHit_DIM == 2 && (pDummyHit = dynamic_cast<ILDPlanarStripHit *>( startingHit )) ) { + pDummyHit = (new ILDPlanarStripHit(*static_cast<ILDPlanarStripHit*>( startingHit ))); + } + else { + std::cout << "Error: <<<<<<<<< MarlinKalTestTrack::initialise: dynamic_cast failed for hit type >>>>>>>" << std::endl; + return error ; + } + + TVTrackHit& dummyHit = *pDummyHit; + + //SJA:FIXME: this constants should go in a header file + // give the dummy hit huge errors so that it does not contribute to the fit + dummyHit(0,1) = 1.e16; // give a huge error to d + dummyHit(1,1) = 1.e16; // give a huge error to z + + // use dummy hit to create initial site + TKalTrackSite& initialSite = *new TKalTrackSite(dummyHit); + + initialSite.SetHitOwner();// site owns hit + initialSite.SetOwner(); // site owns states + + // --------------------------- + // Create initial helix + // --------------------------- + + TVTrackHit &h1 = *dynamic_cast<TVTrackHit *>(_kalhits->At(i1)); // first hit + TVTrackHit &h2 = *dynamic_cast<TVTrackHit *>(_kalhits->At(i2)); // middle hit + TVTrackHit &h3 = *dynamic_cast<TVTrackHit *>(_kalhits->At(i3)); // last hit + TVector3 x1 = h1.GetMeasLayer().HitToXv(h1); + TVector3 x2 = h2.GetMeasLayer().HitToXv(h2); + TVector3 x3 = h3.GetMeasLayer().HitToXv(h3); + + if ( h1.GetDimension() == 1 || h2.GetDimension() == 1 || h3.GetDimension() == 1 ) { + + throw MarlinTrk::Exception("Track fit cannot be initialised from 1 Dimentional hits. Use method MarlinKalTestTrack::initialise( const edm4hep::TrackState& ts, double bfield_z, bool fitDirection )"); + + } + + /* + streamlog_out(DEBUG2) << "MarlinKalTestTrack::initialise Create initial helix from hits: \n " + << "P1 x = " << x1.x() << " y = " << x1.y() << " z = " << x1.z() << " r = " << x1.Perp() << "\n " + << "P2 x = " << x2.x() << " y = " << x2.y() << " z = " << x2.z() << " r = " << x2.Perp() << "\n " + << "P3 x = " << x3.x() << " y = " << x3.y() << " z = " << x3.z() << " r = " << x3.Perp() << "\n " + << "Bz = " << h1.GetBfield() << " direction = " << _fitDirection + << std::endl; + */ + // create helix using 3 global space points + THelicalTrack helstart(x1, x2, x3, h1.GetBfield(), _fitDirection); // initial helix + + // --------------------------- + // Set up initial track state ... could try to use lcio track parameters ... + // --------------------------- + + static TKalMatrix initialState(kSdim,1) ; + initialState(0,0) = 0.0 ; // dr + initialState(1,0) = helstart.GetPhi0() ; // phi0 + initialState(2,0) = helstart.GetKappa() ; // kappa + initialState(3,0) = 0.0 ; // dz + initialState(4,0) = helstart.GetTanLambda() ; // tan(lambda) + if (kSdim == 6) initialState(5,0) = 0.; // t0 + + + // --------------------------- + // Set up initial Covariance Matrix with very large errors + // --------------------------- + + TKalMatrix Cov(kSdim,kSdim); + + // make sure everything is initialised to zero + for (int i=0; i<kSdim*kSdim; ++i) { + Cov.GetMatrixArray()[i] = 0.0; + } + +// for (Int_t i=0; i<kSdim; i++) { +// // fg: if the error is too large the initial helix parameters might be changed extremely by the first three (or so) hits, +// // such that the fit will not work because the helix curls away and does not hit the next layer !!! +// Cov(i,i) = 1.e2 ; // initialise diagonal elements of dummy error matrix +// } + + // prefer translation over rotation of the trackstate early in the fit + + Cov(0,0) = 1.e6 ; // d0 + Cov(1,1) = 1.e2 ; // dphi0 + Cov(2,2) = 1.e2 ; // dkappa + Cov(3,3) = 1.e6 ; // dz + Cov(4,4) = 1.e2 ; // dtanL + if (kSdim == 6) Cov(5,5) = 1.e2; // t0 + + // Add initial states to the site + initialSite.Add(new TKalTrackState(initialState,Cov,initialSite,TVKalSite::kPredicted)); + initialSite.Add(new TKalTrackState(initialState,Cov,initialSite,TVKalSite::kFiltered)); + + // add the initial site to the track: that is, give the track initial parameters and covariance + // matrix at the starting measurement layer + _kaltrack->Add(&initialSite); + + _initialised = true ; + /* + streamlog_out( DEBUG2 ) << " track parameters used for init : " << std::scientific << std::setprecision(6) + << "\t D0 " << 0.0 + << "\t Phi :" << toBaseRange( helstart.GetPhi0() + M_PI/2. ) + << "\t Omega " << 1. /helstart.GetRho() + << "\t Z0 " << 0.0 + << "\t tan(Lambda) " << helstart.GetTanLambda() + + << "\t pivot : [" << helstart.GetPivot().X() << ", " << helstart.GetPivot().Y() << ", " << helstart.GetPivot().Z() + << " - r: " << std::sqrt( helstart.GetPivot().X()*helstart.GetPivot().X()+helstart.GetPivot().Y()*helstart.GetPivot().Y() ) << "]" + << std::endl ; + */ +#ifdef MARLINTRK_DIAGNOSTICS_ON + + // convert to LICO parameters first + + double d0 = 0.0 ; + double phi = toBaseRange( helstart.GetPhi0() + M_PI/2. ); + double omega = 1. /helstart.GetRho() ; + double z0 = 0.0 ; + double tanLambda = helstart.GetTanLambda() ; + +// Cov.Print(); + + _ktest->_diagnostics.set_intial_track_parameters(d0, + phi, + omega, + z0, + tanLambda, + helstart.GetPivot().X(), + helstart.GetPivot().Y(), + helstart.GetPivot().Z(), + Cov); + + + +#endif + + + return success ; + + } + + int MarlinKalTestTrack::initialise( const edm4hep::TrackState& ts, double bfield_z, bool fitDirection ) { + + if (_kalhits->GetEntries() == 0) { + + //streamlog_out( ERROR) << "<<<<<< MarlinKalTestTrack::Initialise: Number of Hits is Zero. Cannot Initialise >>>>>>>" << std::endl; + return error ; + + } + + //SJA:FIXME: check here if the track is already initialised, and for now don't allow it to be re-initialised + // if the track is going to be re-initialised then we would need to do it directly on the first site + if ( _initialised ) { + + throw MarlinTrk::Exception("Track fit already initialised"); + + } + /* + streamlog_out( DEBUG2 ) << "MarlinKalTestTrack::initialise using TrackState: track parameters used for init : " + << "\t D0 " << ts.getD0() + << "\t Phi :" << ts.getPhi() + << "\t Omega " << ts.getOmega() + << "\t Z0 " << ts.getZ0() + << "\t tan(Lambda) " << ts.getTanLambda() + + << "\t pivot : [" << ts.getReferencePoint()[0] << ", " << ts.getReferencePoint()[1] << ", " << ts.getReferencePoint()[2] + << " - r: " << std::sqrt( ts.getReferencePoint()[0]*ts.getReferencePoint()[0]+ts.getReferencePoint()[1]*ts.getReferencePoint()[1] ) << "]" + << std::endl ; + */ + + _fitDirection = fitDirection ; + + // for GeV, Tesla, R in mm + double alpha = bfield_z * 2.99792458E-4 ; + double kappa; + if ( bfield_z == 0.0 ) + kappa = DBL_MAX; + else kappa = ts.omega / alpha ; + + THelicalTrack helix( -ts.D0, + toBaseRange( ts.phi - M_PI/2. ) , + kappa, + ts.Z0, + ts.tanLambda, + ts.referencePoint[0], + ts.referencePoint[1], + ts.referencePoint[2], + bfield_z ); + + TMatrixD cov(5,5) ; + + std::array<float, 15> covLCIO = ts.covMatrix; + + cov( 0 , 0 ) = covLCIO[ 0] ; // d0, d0 + cov( 0 , 1 ) = - covLCIO[ 1] ; // d0, phi + cov( 0 , 2 ) = - covLCIO[ 3] / alpha ; // d0, kappa + cov( 0 , 3 ) = - covLCIO[ 6] ; // d0, z0 + cov( 0 , 4 ) = - covLCIO[10] ; // d0, tanl + + cov( 1 , 0 ) = - covLCIO[ 1] ; // phi, d0 + cov( 1 , 1 ) = covLCIO[ 2] ; // phi, phi + cov( 1 , 2 ) = covLCIO[ 4] / alpha ; // phi, kappa + cov( 1 , 3 ) = covLCIO[ 7] ; // phi, z0 + cov( 1 , 4 ) = covLCIO[11] ; // tanl, phi + + cov( 2 , 0 ) = - covLCIO[ 3] / alpha ; // kappa, d0 + cov( 2 , 1 ) = covLCIO[ 4] / alpha ; // kappa, phi + cov( 2 , 2 ) = covLCIO[ 5] / (alpha * alpha) ; // kappa, kappa + cov( 2 , 3 ) = covLCIO[ 8] / alpha ; // kappa, z0 + cov( 2 , 4 ) = covLCIO[12] / alpha ; // kappa, tanl + + cov( 3 , 0 ) = - covLCIO[ 6] ; // z0, d0 + cov( 3 , 1 ) = covLCIO[ 7] ; // z0, phi + cov( 3 , 2 ) = covLCIO[ 8] / alpha ; // z0, kappa + cov( 3 , 3 ) = covLCIO[ 9] ; // z0, z0 + cov( 3 , 4 ) = covLCIO[13] ; // z0, tanl + + cov( 4 , 0 ) = - covLCIO[10] ; // tanl, d0 + cov( 4 , 1 ) = covLCIO[11] ; // tanl, phi + cov( 4 , 2 ) = covLCIO[12] / alpha ; // tanl, kappa + cov( 4 , 3 ) = covLCIO[13] ; // tanl, z0 + cov( 4 , 4 ) = covLCIO[14] ; // tanl, tanl + +// cov.Print(); + + // move the helix to either the position of the last hit or the first depending on initalise_at_end + + // default case initalise_at_end + int index = _kalhits->GetEntries() - 1 ; + // or initialise at start + if( _fitDirection == IMarlinTrack::forward ){ + index = 0 ; + } + + TVTrackHit* kalhit = dynamic_cast<TVTrackHit *>(_kalhits->At(index)); + + double dphi; + + TVector3 initial_pivot ; + + // Leave the pivot at the origin for a 1-dim hit + if (kalhit->GetDimension() > 1) { + + initial_pivot = kalhit->GetMeasLayer().HitToXv(*kalhit) ; + } + else{ + initial_pivot = TVector3(0.0,0.0,0.0); + } + + + // --------------------------- + // Create an initial start site for the track using the hit + // --------------------------- + // set up a dummy hit needed to create initial site + + TVTrackHit* pDummyHit = 0; + + if ( (pDummyHit = dynamic_cast<ILDCylinderHit *>( kalhit )) ) { + pDummyHit = (new ILDCylinderHit(*static_cast<ILDCylinderHit*>( kalhit ))); + + } + else if ( (pDummyHit = dynamic_cast<ILDPlanarHit *>( kalhit )) ) { + pDummyHit = (new ILDPlanarHit(*static_cast<ILDPlanarHit*>( kalhit ))); + } + else if ( (pDummyHit = dynamic_cast<ILDPlanarStripHit *>( kalhit )) ) { + + pDummyHit = (new ILDPlanarStripHit(*static_cast<ILDPlanarStripHit*>( kalhit ))); + + const TVMeasLayer *ml = &pDummyHit->GetMeasLayer(); + + const TVSurface* surf = dynamic_cast<const TVSurface*>(ml); + + if (surf) { + double phi; + + surf->CalcXingPointWith(helix, initial_pivot, phi); + + } else { + //streamlog_out( ERROR) << "<<<<<<<<< MarlinKalTestTrack::initialise: dynamic_cast failed for TVSurface >>>>>>>" << std::endl; + return error ; + } + + + } + else { + //streamlog_out( ERROR) << "<<<<<<<<< MarlinKalTestTrack::initialise: dynamic_cast failed for hit type >>>>>>>" << std::endl; + return error ; + } + + TVTrackHit& dummyHit = *pDummyHit; + + //SJA:FIXME: this constants should go in a header file + // give the dummy hit huge errors so that it does not contribute to the fit + dummyHit(0,1) = 1.e16; // give a huge error to d + + if(dummyHit.GetDimension()>1) dummyHit(1,1) = 1.e16; // give a huge error to z + + // use dummy hit to create initial site + TKalTrackSite& initialSite = *new TKalTrackSite(dummyHit); + + initialSite.SetHitOwner();// site owns hit + initialSite.SetOwner(); // site owns states + + // --------------------------- + // Set up initial track state + // --------------------------- + + helix.MoveTo( initial_pivot, dphi, 0, &cov ); + + static TKalMatrix initialState(kSdim,1) ; + initialState(0,0) = helix.GetDrho() ; // d0 + initialState(1,0) = helix.GetPhi0() ; // phi0 + initialState(2,0) = helix.GetKappa() ; // kappa + initialState(3,0) = helix.GetDz(); // dz + initialState(4,0) = helix.GetTanLambda() ; // tan(lambda) + if (kSdim == 6) initialState(5,0) = 0.; // t0 + + // make sure that the pivot is in the right place + initialSite.SetPivot(initial_pivot); + + // --------------------------- + // Set up initial Covariance Matrix + // --------------------------- + + TKalMatrix covK(kSdim,kSdim) ; + for(int i=0;i<5;++i) { + for(int j=0;j<5;++j) { + covK[i][j] = cov[i][j] ; + } + } + if (kSdim == 6) covK(5,5) = 1.e6; // t0 + +// covK.Print(); + + // Add initial states to the site + initialSite.Add(new TKalTrackState(initialState,covK,initialSite,TVKalSite::kPredicted)); + initialSite.Add(new TKalTrackState(initialState,covK,initialSite,TVKalSite::kFiltered)); + + // add the initial site to the track: that is, give the track initial parameters and covariance + // matrix at the starting measurement layer + _kaltrack->Add(&initialSite); + + _initialised = true ; + + +#ifdef MARLINTRK_DIAGNOSTICS_ON + + // convert to LICO parameters first + + double d0 = - helix.GetDrho() ; + double phi = toBaseRange( helix.GetPhi0() + M_PI/2. ); + double omega = 1. /helix.GetRho() ; + double z0 = helix.GetDz() ; + double tanLambda = helix.GetTanLambda() ; + + _ktest->_diagnostics.set_intial_track_parameters(d0, + phi, + omega, + z0, + tanLambda, + helix.GetPivot().X(), + helix.GetPivot().Y(), + helix.GetPivot().Z(), + covK); + + + +#endif + + return success ; + + } + + int MarlinKalTestTrack::addAndFit( ILDVTrackHit* kalhit, double& chi2increment, TKalTrackSite*& site, double maxChi2Increment) { + + //streamlog_out(DEBUG1) << "MarlinKalTestTrack::addAndFit called : maxChi2Increment = " << std::scientific << maxChi2Increment << std::endl ; + + if ( ! _initialised ) { + + throw MarlinTrk::Exception("Track fit not initialised"); + + } + + // here do dynamic cast repeatedly in DEBUG statement as this will be stripped out any way for production code + // otherwise we have to do the cast outside of the DEBUG statement and it won't be stripped out + /*streamlog_out( DEBUG1 ) << "Kaltrack::addAndFit : add site to track at index : " + << (dynamic_cast<const ILDVMeasLayer*>( &(kalhit->GetMeasLayer() ) ))->GetIndex() + << " for type " + << dynamic_cast<const ILDVMeasLayer*>( &(kalhit->GetMeasLayer() ) )->GetName() ; + streamlog_out( DEBUG0 ) << " with CellIDs:"; + + for (unsigned int i = 0; i < (dynamic_cast<const ILDVMeasLayer*>( &(kalhit->GetMeasLayer() ) )->getNCellIDs());++i) { + streamlog_out( DEBUG0 ) << " : " + << dynamic_cast<const ILDVMeasLayer*>( &(kalhit->GetMeasLayer() ) )->getCellIDs()[i] ; + + } + + streamlog_out( DEBUG1 ) << std::endl ; + */ + TKalTrackSite* temp_site = new TKalTrackSite(*kalhit); // create new site for this hit + + KalTrackFilter filter( maxChi2Increment ); + filter.resetFilterStatus(); + + temp_site->SetFilterCond( &filter ) ; + + + // this is the only point at which a hit is actually filtered + // and it is here that we can get the GetDeltaChi2 vs the maxChi2Increment + // it will always be possible to get the delta chi2 so long as we have a link to the sites ... + // although calling smooth will natrually update delta chi2. + + + if (!_kaltrack->AddAndFilter(*temp_site)) { + + chi2increment = temp_site->GetDeltaChi2() ; + // get the measurement layer of the current hit + const ILDVMeasLayer* ml = dynamic_cast<const ILDVMeasLayer*>( &(kalhit->GetMeasLayer() ) ) ; + TVector3 pos = ml->HitToXv(*kalhit); + std::cout << "debug: Kaltrack::addAndFit : site discarded! at index : " << ml->GetIndex() + << " for type " << ml->GetName() + << " chi2increment = " << chi2increment + << " maxChi2Increment = " << maxChi2Increment + << " x = " << pos.x() + << " y = " << pos.y() + << " z = " << pos.z() + << " with CellIDs: " << std::endl; + + for (unsigned int i = 0; i < (dynamic_cast<const ILDVMeasLayer*>( &(kalhit->GetMeasLayer() ) )->getNCellIDs());++i) { + std::cout << "debug: CellID = " + << dynamic_cast<const ILDVMeasLayer*>( &(kalhit->GetMeasLayer() ) )->getCellIDs()[i] + << std::endl ; + } + + +#ifdef MARLINTRK_DIAGNOSTICS_ON + _ktest->_diagnostics.record_rejected_site(kalhit, temp_site); +#endif + + delete temp_site; // delete site if filter step failed + + + // compiling the code below with the cmake option CMAKE_BUILD_TYPE=Debug + // and with LDFLAGS=-Wl,--no-undefined + // causes an undefined reference error + // the problem gets fixed using the if/else statement below + + // this fails + //return filter.usedForLastFilterStep() ? site_fails_chi2_cut : site_discarded ; + + // this also fails.. + //bool rc = filter.usedForLastFilterStep() ; + //return (rc ? site_fails_chi2_cut : site_discarded); + + // but this works ?!! + //return ( true ? site_fails_chi2_cut : site_discarded); + + // and this also works.. + //streamlog_out(DEBUG2) << " addAndFit : Site Fails Chi2 cut ? " << filter.passedLastFilterStep() << std::endl; + + if( filter.passedLastFilterStep() == false ) { + return site_fails_chi2_cut ; + } else { + return site_discarded ; + } + + } + + site = temp_site; + chi2increment = site->GetDeltaChi2() ; + +#ifdef MARLINTRK_DIAGNOSTICS_ON + _ktest->_diagnostics.record_site(kalhit, site); +#endif + + return success ; + + } + + int MarlinKalTestTrack::addAndFit( edm4hep::TrackerHit* trkhit, double& chi2increment, double maxChi2Increment) { + + if( ! trkhit ) { + std::cout << "Error: MarlinKalTestTrack::addAndFit(edm4hep::TrackerHit trkhit, double& chi2increment, double maxChi2Increment): trkhit == 0" << std::endl; + return bad_intputs ; + } + + const ILDVMeasLayer* ml = _ktest->findMeasLayer( trkhit ) ; + + if( ml == 0 ){ + // fg: not sure if ml should ever be 0 - but it seems to happen, + // if point is not on surface and more than one surface exists ... + + std::cout << "Error>>>>>>>>>>> no measurment layer found for trkhit cellid0 : " + << decodeILD( trkhit->getCellID() ) << " at " + << trkhit->getPosition() << std::endl ; + + return IMarlinTrack::bad_intputs ; + } + + ILDVTrackHit* kalhit = ml->ConvertLCIOTrkHit(trkhit) ; + + if( kalhit == 0 ){ //fg: ml->ConvertLCIOTrkHit returns 0 if hit not on surface !!! + return IMarlinTrack::bad_intputs ; + } + + TKalTrackSite* site = 0 ; + int error_code = this->addAndFit( kalhit, chi2increment, site, maxChi2Increment); + + if( error_code != success ){ + + delete kalhit; + + // if the hit fails for any reason other than the Chi2 cut record the Chi2 contibution as DBL_MAX + if( error_code != site_fails_chi2_cut ) { + chi2increment = DBL_MAX; + } + + _outlier_chi2_values.push_back(std::make_pair(trkhit, chi2increment)); + + //streamlog_out( DEBUG2 ) << ">>>>>>>>>>> addAndFit Number of Outliers : " + //<< _outlier_chi2_values.size() << std::endl; + + return error_code ; + } + else { + this->addHit(trkhit, kalhit, ml ) ; + _hit_used_for_sites[trkhit] = site ; + _hit_chi2_values.push_back(std::make_pair(trkhit, chi2increment)); + } + + // set the values for the point at which the fit becomes constained + if( _trackHitAtPositiveNDF == 0 && _kaltrack->GetNDF() >= 0){ + + _trackHitAtPositiveNDF = trkhit; + _hitIndexAtPositiveNDF = _kaltrack->IndexOf( site ); + /* + streamlog_out( DEBUG2 ) << ">>>>>>>>>>> Fit is now constrained at : " + << decodeILD( trkhit->getCellID() ) + << " pos " << trkhit->getPosition() + << " trkhit = " << _trackHitAtPositiveNDF + << " index of kalhit = " << _hitIndexAtPositiveNDF + << " NDF = " << _kaltrack->GetNDF() + << std::endl; + */ + } + + return success ; + + } + + + + int MarlinKalTestTrack::testChi2Increment( edm4hep::TrackerHit* trkhit, double& chi2increment ) { + + //if( ! trkhit ) { + // streamlog_out( ERROR) << "MarlinKalTestTrack::addAndFit(edm4hep::TrackerHit trkhit, double& chi2increment, double maxChi2Increment): trkhit == 0" << std::endl; + // return IMarlinTrack::bad_intputs ; + //} + + const ILDVMeasLayer* ml = _ktest->findMeasLayer( trkhit ) ; + + if( ml == 0 ){ + // fg: not sure if ml should ever be 0 - but it seems to happen, + // if point is not on surface and more than one surface exists ... + + std::cout << "Error>>>>>>>>>>> no measurment layer found for trkhit cellid0 : " + << decodeILD( trkhit->getCellID() ) << " at " + << trkhit->getPosition() << std::endl ; + + return IMarlinTrack::bad_intputs ; + + } + + ILDVTrackHit* kalhit = ml->ConvertLCIOTrkHit(trkhit) ; + + if( kalhit == 0 ){ //fg: ml->ConvertLCIOTrkHit returns 0 if hit not on surface !!! + return IMarlinTrack::bad_intputs ; + } + + + TKalTrackSite* site = 0 ; + int error_code = this->addAndFit( kalhit, chi2increment, site, -DBL_MAX); // using -DBL_MAX here ensures the hit will never be added to the fit + + delete kalhit; + + return error_code; + + } + + + + int MarlinKalTestTrack::fit( double maxChi2Increment ) { + + // SJA:FIXME: what do we do about calling fit after we have already added hits and filtered + // I guess this would created new sites when addAndFit is called + // one option would be to remove the sites + // need to check where the sites are stored ... probably in the KalTrackSystem + // + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::fit() called " << std::endl ; + + if ( ! _initialised ) { + + throw MarlinTrk::Exception("Track fit not initialised"); + + } + + // --------------------------- + // Prepare hit iterrator for adding hits to kaltrack + // --------------------------- + + TIter next(_kalhits, _fitDirection); + + // --------------------------- + // Start Kalman Filter + // --------------------------- + + ILDVTrackHit *kalhit = 0; + + while ( (kalhit = dynamic_cast<ILDVTrackHit *>( next() ) ) ) { + + double chi2increment; + TKalTrackSite* site; + int error_code = this->addAndFit( kalhit, chi2increment, site, maxChi2Increment ); + + + edm4hep::TrackerHit* trkhit = kalhit->getLCIOTrackerHit(); + + if( error_code == 0 ){ // add trkhit to map associating trkhits and sites + _hit_used_for_sites[trkhit] = site; + _hit_chi2_values.push_back(std::make_pair(trkhit, chi2increment)); + + // set the values for the point at which the fit becomes constained + if( _trackHitAtPositiveNDF == 0 && _kaltrack->GetNDF() >= 0){ + + _trackHitAtPositiveNDF = trkhit; + _hitIndexAtPositiveNDF = _kaltrack->IndexOf( site ); + /* + streamlog_out( DEBUG2 ) << ">>>>>>>>>>> Fit is now constrained at : " + << decodeILD( trkhit->getCellID() ) + << " pos " << trkhit->getPosition() + << " trkhit = " << _trackHitAtPositiveNDF + << " index of kalhit = " << _hitIndexAtPositiveNDF + << " NDF = " << _kaltrack->GetNDF() + << std::endl; + */ + } + + } + else { // hit rejected by the filter, so store in the list of rejected hits + + // if the hit fails for any reason other than the Chi2 cut record the Chi2 contibution as DBL_MAX + if( error_code != site_fails_chi2_cut ) { + chi2increment = DBL_MAX; + } + + _outlier_chi2_values.push_back(std::make_pair(trkhit, chi2increment)); + //streamlog_out( DEBUG2 ) << ">>>>>>>>>>> fit(): Number of Outliers : " + //<< _outlier_chi2_values.size() << std::endl; + + _hit_not_used_for_sites.push_back(trkhit) ; + + } + + } // end of Kalman filter + + if( _ktest->getOption( MarlinTrk::IMarlinTrkSystem::CFG::useSmoothing ) ){ + //streamlog_out( DEBUG2 ) << "Perform Smoothing for All Previous Measurement Sites " << std::endl ; + int error = this->smooth() ; + + if( error != success ) return error ; + + } + + //return _hit_used_for_sites.empty() == false ? success : all_sites_fail_fit ; + if( _hit_used_for_sites.empty() == false ) + { + return success ; + } + else{ + return all_sites_fail_fit ; + } + + } + + + /** smooth all track states + */ + int MarlinKalTestTrack::smooth(){ + + //streamlog_out( DEBUG2 ) << "MarlinKalTestTrack::smooth() " << std::endl ; + + //fg: we should actually smooth all sites - it is then up to the user which smoothed tracks state to take + // for any furthter extrapolation/propagation ... + + if( !_smoothed ) + _kaltrack->SmoothAll() ; + + //SJA:FIXME: in the current implementation it is only possible to smooth back to the 4th site. + // This is due to the fact that the covariance matrix is not well defined at the first 3 measurement sites filtered. + + // _kaltrack->SmoothBackTo( _hitIndexAtPositiveNDF + 1 ) ; + + _smoothed = true ; + + return success ; + + } + + + /** smooth track states from the last filtered hit back to the measurement site associated with the given hit + */ + int MarlinKalTestTrack::smooth( edm4hep::TrackerHit* trkhit ) { + + //streamlog_out( DEBUG2 ) << "MarlinKalTestTrack::smooth( edm4hep::TrackerHit " << trkhit << " ) " << std::endl ; + + if ( !trkhit ) { + return bad_intputs ; + } + + std::map<edm4hep::TrackerHit*, TKalTrackSite*>::const_iterator it; + + TKalTrackSite* site = 0 ; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + int index = _kaltrack->IndexOf( site ); + + _kaltrack->SmoothBackTo( index ) ; + + _smoothed = true ; + + return success ; + + } + + + int MarlinKalTestTrack::getTrackState( edm4hep::TrackState& ts, double& chi2, int& ndf ) { + + //streamlog_out( DEBUG2 ) << "MarlinKalTestTrack::getTrackState( edm4hep::TrackState& ts ) " << std::endl ; + + // use the last filtered track state + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + + this->ToLCIOTrackState( site, ts, chi2, ndf ); + + return success ; + + + } + + + int MarlinKalTestTrack::getTrackState( edm4hep::TrackerHit* trkhit, edm4hep::TrackState& ts, double& chi2, int& ndf ) { + + //streamlog_out( DEBUG2 ) << "MarlinKalTestTrack::getTrackState(edm4hep::TrackerHit* trkhit, edm4hep::TrackState& ts ) using hit: " << trkhit << " with cellID0 = " << trkhit->getCellID() << std::endl ; + + TKalTrackSite* site = 0 ; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + //streamlog_out( DEBUG1 ) << "MarlinKalTestTrack::getTrackState: site " << site << std::endl; + + this->ToLCIOTrackState( *site, ts, chi2, ndf ); + + return success ; + } + + + int MarlinKalTestTrack::getHitsInFit( std::vector<std::pair<edm4hep::TrackerHit*, double> >& hits ) { + //std::cout << "debug: _hit_chi2_values address= " << &_hit_chi2_values << " " << &(*(_hit_chi2_values.begin())) << " want to copy to hits address=" << &hits << std::endl; + std::copy( _hit_chi2_values.begin() , _hit_chi2_values.end() , std::back_inserter( hits ) ) ; + //hits.resize(_hit_chi2_values.size()); + //std::copy( _hit_chi2_values.begin() , _hit_chi2_values.end() , hits.begin()); + + // this needs more thought. What about when the hits are added using addAndFit? + + // need to check the order so that we can return the list ordered in time + // as they will be added to _hit_chi2_values in the order of fitting + // not in the order of time +// +// if( _fitDirection == IMarlinTrack::backward ){ +// std::reverse_copy( _hit_chi2_values.begin() , _hit_chi2_values.end() , std::back_inserter( hits ) ) ; +// } else { +// std::copy( _hit_chi2_values.begin() , _hit_chi2_values.end() , std::back_inserter( hits ) ) ; +// } + + return success ; + + } + + int MarlinKalTestTrack::getOutliers( std::vector<std::pair<edm4hep::TrackerHit*, double> >& hits ) { + + std::copy( _outlier_chi2_values.begin() , _outlier_chi2_values.end() , std::back_inserter( hits ) ) ; + + // this needs more thought. What about when the hits are added using addAndFit? +// // need to check the order so that we can return the list ordered in time +// // as they will be added to _hit_chi2_values in the order of fitting +// // not in the order of time +// +// if( _fitDirection == IMarlinTrack::backward ){ +// std::reverse_copy( _outlier_chi2_values.begin() , _outlier_chi2_values.end() , std::back_inserter( hits ) ) ; +// } else { +// std::copy( _outlier_chi2_values.begin() , _outlier_chi2_values.end() , std::back_inserter( hits ) ) ; +// } + + return success ; + } + + int MarlinKalTestTrack::getNDF( int& ndf ){ + + if( _initialised == false ) { + return error; + } else { + + ndf = _kaltrack->GetNDF(); + return success; + + } + + } + + int MarlinKalTestTrack::getTrackerHitAtPositiveNDF( edm4hep::TrackerHit*& trkhit ) { + + trkhit = _trackHitAtPositiveNDF; + return success; + + } + + + int MarlinKalTestTrack::extrapolate( const edm4hep::Vector3d& point, edm4hep::TrackState& ts, double& chi2, int& ndf ){ + + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + + return this->extrapolate( point, site, ts, chi2, ndf ) ; + + } + + int MarlinKalTestTrack::extrapolate( const edm4hep::Vector3d& point, edm4hep::TrackerHit* trkhit, edm4hep::TrackState& ts, double& chi2, int& ndf ) { + + TKalTrackSite* site = 0 ; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code; + + return this->extrapolate( point, *site, ts, chi2, ndf ) ; + + } + + int MarlinKalTestTrack::extrapolate( const edm4hep::Vector3d& point, const TKalTrackSite& site ,edm4hep::TrackState& ts, double& chi2, int& ndf ){ + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::extrapolate( const edm4hep::Vector3d& point, edm4hep::TrackState& ts, double& chi2, int& ndf ) called " << std::endl ; + + TKalTrackState& trkState = (TKalTrackState&) site.GetCurState(); // this segfaults if no hits are present + + THelicalTrack helix = trkState.GetHelix() ; + double dPhi ; + + // convert the gear point supplied to TVector3 + const TVector3 tpoint( point.x, point.y, point.z ) ; + + Int_t sdim = trkState.GetDimension(); // dimensions of the track state, it will be 5 or 6 + TKalMatrix sv(sdim,1); + + // now move to the point + TKalMatrix DF(sdim,sdim); + DF.UnitMatrix(); + helix.MoveTo( tpoint , dPhi , &DF , 0) ; // move helix to desired point, and get propagator matrix + + TMatrixD c0(trkState.GetCovMat()); + + TKalMatrix DFt = TKalMatrix(TMatrixD::kTransposed, DF); + c0 = DF * c0 * DFt ; // update the covariance matrix + + this->ToLCIOTrackState( helix, c0, ts, chi2, ndf ); + + return success; + + } + + + int MarlinKalTestTrack::extrapolateToLayer( int layerID, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode ) { + + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + + return this->extrapolateToLayer( layerID, site, ts, chi2, ndf, detElementID, mode ) ; + + } + + + int MarlinKalTestTrack::extrapolateToLayer( int layerID, edm4hep::TrackerHit* trkhit, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode ) { + + TKalTrackSite* site = 0; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + return this->extrapolateToLayer( layerID, *site, ts, chi2, ndf, detElementID, mode ) ; + + } + + + int MarlinKalTestTrack::extrapolateToLayer( int layerID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode ) { + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::extrapolateToLayer( int layerID, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID ) called " << std::endl ; + + edm4hep::Vector3d crossing_point ; + const ILDVMeasLayer* ml = 0; + + int error_code = this->intersectionWithLayer( layerID, site, crossing_point, detElementID, ml, mode ) ; + + if( error_code != 0 ) return error_code ; + + return this->extrapolate( crossing_point, site, ts, chi2, ndf ) ; + + } + + + int MarlinKalTestTrack::extrapolateToDetElement( int detElementID, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode ) { + + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + + return this->extrapolateToDetElement( detElementID, site, ts, chi2, ndf, mode ) ; + + } + + + int MarlinKalTestTrack::extrapolateToDetElement( int detElementID, edm4hep::TrackerHit* trkhit, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode ) { + + TKalTrackSite* site = 0; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + return this->extrapolateToDetElement( detElementID, *site, ts, chi2, ndf, mode ) ; + + } + + + int MarlinKalTestTrack::extrapolateToDetElement( int detElementID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode ) { + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::extrapolateToDetElement( int detElementID, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode ) called " << std::endl ; + + edm4hep::Vector3d crossing_point ; + + const ILDVMeasLayer* ml = 0; + int error_code = this->intersectionWithDetElement( detElementID, site, crossing_point, ml, mode ) ; + + if( error_code != 0 ) return error_code ; + + return this->extrapolate( crossing_point, site, ts, chi2, ndf ) ; + + } + + + + int MarlinKalTestTrack::propagate( const edm4hep::Vector3d& point, edm4hep::TrackState& ts, double& chi2, int& ndf ){ + + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + + // check if the point is inside the beampipe + // SJA:FIXME: really we should also check if the PCA to the point is also less than R + const ILDVMeasLayer* ml = (sqrt(point.x*point.x+point.y*point.y) < _ktest->getIPLayer()->GetR()) ? _ktest->getIPLayer() : 0; + + return this->propagate( point, site, ts, chi2, ndf, ml ) ; + + } + + int MarlinKalTestTrack::propagate( const edm4hep::Vector3d& point, edm4hep::TrackerHit* trkhit, edm4hep::TrackState& ts, double& chi2, int& ndf ){ + + TKalTrackSite* site = 0; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + // check if the point is inside the beampipe + // SJA:FIXME: really we should also check if the PCA to the point is also less than R + + const ILDVMeasLayer* ml = _ktest->getIPLayer(); + + if ( ml ) + if (sqrt(point.x*point.x+point.y*point.y) > _ktest->getIPLayer()->GetR()) ml = NULL; + +// const ILDVMeasLayer* ml = (point.r() < _ktest->getIPLayer()->GetR()) ? _ktest->getIPLayer() : 0; + + return this->propagate( point, *site, ts, chi2, ndf, ml ) ; + + } + + int MarlinKalTestTrack::propagate( const edm4hep::Vector3d& point, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, const ILDVMeasLayer* ml ){ + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::propagate( const edm4hep::Vector3d& point, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf ) called " << std::endl ; + + // convert the gear point supplied to TVector3 + const TVector3 tpoint( point.x, point.y, point.z ) ; + + TKalTrackState& trkState = (TKalTrackState&) site.GetCurState(); // this segfaults if no hits are present + + THelicalTrack helix = trkState.GetHelix() ; + double dPhi = 0.0; + + + Int_t sdim = trkState.GetDimension(); // dimensions of the track state, it will be 5 or 6 + TKalMatrix sv(sdim,1); + + TKalMatrix F(sdim,sdim); // propagator matrix to be returned by transport function + F.UnitMatrix(); // set the propagator matrix to the unit matrix + + TKalMatrix Q(sdim,sdim); // noise matrix to be returned by transport function + Q.Zero(); + TVector3 x0; // intersection point to be returned by transport + + TMatrixD c0(trkState.GetCovMat()); + + // the last layer crossed by the track before point + if( ! ml ){ + ml = _ktest->getLastMeasLayer(helix, tpoint); + } + + if ( ml ) { + + _ktest->_det->Transport(site, *ml, x0, sv, F, Q ) ; // transport to last layer cross before point + + // given that we are sure to have intersected the layer ml as this was provided via getLastMeasLayer, x0 will lie on the layer + // this could be checked with the method isOnSurface + // so F will be the propagation matrix from the current location to the last surface and Q will be the noise matrix up to this point + + + TKalMatrix Ft = TKalMatrix(TMatrixD::kTransposed, F); + c0 = F * c0 * Ft + Q; // update covaraince matrix and add the MS assosiated with moving to tvml + + helix.MoveTo( x0 , dPhi , 0 , 0 ) ; // move the helix to tvml + + + } + else { // the current site is at the last surface before the point to propagate to + + ml = dynamic_cast<const ILDVMeasLayer*>(&(site.GetHit().GetMeasLayer())) ; + + } + + // get whether the track is incomming or outgoing at the last surface + const TVSurface *sfp = dynamic_cast<const TVSurface *>(ml); // last surface + + TMatrixD dxdphi = helix.CalcDxDphi(0); // tangent vector at last surface + TVector3 dxdphiv(dxdphi(0,0),dxdphi(1,0),dxdphi(2,0)); // convert matirix diagonal to vector +// Double_t cpa = helix.GetKappa(); // get pt + + Bool_t isout = -dPhi*dxdphiv.Dot(sfp->GetOutwardNormal(x0)) < 0 ? kTRUE : kFALSE; // out-going or in-coming at the destination surface + + // now move to the point + TKalMatrix DF(sdim,sdim); + DF.UnitMatrix(); + helix.MoveTo( tpoint , dPhi , &DF , 0) ; // move helix to desired point, and get propagator matrix + + TKalMatrix Qms(sdim, sdim); + ml->CalcQms(isout, helix, dPhi, Qms); // calculate MS for the final step through the present material + + TKalMatrix DFt = TKalMatrix(TMatrixD::kTransposed, DF); + c0 = DF * c0 * DFt + Qms ; // update the covariance matrix + + + this->ToLCIOTrackState( helix, c0, ts, chi2, ndf ); + + return success; + + } + + + int MarlinKalTestTrack::propagateToLayer( int layerID, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode ) { + + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + + return this->propagateToLayer( layerID, site, ts, chi2, ndf, detElementID, mode ) ; + + } + + + int MarlinKalTestTrack::propagateToLayer( int layerID, edm4hep::TrackerHit* trkhit, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode ) { + + TKalTrackSite* site = 0; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + return this->propagateToLayer( layerID, *site, ts, chi2, ndf, detElementID, mode ) ; + + } + + + int MarlinKalTestTrack::propagateToLayer( int layerID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode ) { + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::propagateToLayer( int layerID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID ) called " << std::endl; + + edm4hep::Vector3d crossing_point ; + + const ILDVMeasLayer* ml = 0; + + int error_code = this->intersectionWithLayer( layerID, site, crossing_point, detElementID, ml, mode) ; + + if( error_code != success ) return error_code ; + + return this->propagate( crossing_point, site, ts, chi2, ndf , ml) ; + + } + + + int MarlinKalTestTrack::propagateToDetElement( int detElementID, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode ) { + + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + + return this->propagateToDetElement( detElementID, site, ts, chi2, ndf, mode ) ; + + } + + + int MarlinKalTestTrack::propagateToDetElement( int detElementID, edm4hep::TrackerHit* trkhit, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode ) { + + TKalTrackSite* site = 0; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + return this->propagateToDetElement( detElementID, *site, ts, chi2, ndf, mode ) ; + + } + + + int MarlinKalTestTrack::propagateToDetElement( int detElementID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode ) { + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::propagateToDetElement( int detElementID, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode ) called " << std::endl ; + + edm4hep::Vector3d crossing_point ; + + const ILDVMeasLayer* ml = 0; + int error_code = this->intersectionWithDetElement( detElementID, site, crossing_point, ml, mode ) ; + + if( error_code != 0 ) return error_code ; + + return this->propagate( crossing_point, site, ts, chi2, ndf, ml ) ; + + } + + + int MarlinKalTestTrack::intersectionWithDetElement( int detElementID, edm4hep::Vector3d& point, int mode ) { + + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + + const ILDVMeasLayer* ml = 0; + return this->intersectionWithDetElement( detElementID, site, point, ml, mode ) ; + + } + + + int MarlinKalTestTrack::intersectionWithDetElement( int detElementID, edm4hep::TrackerHit* trkhit, edm4hep::Vector3d& point, int mode ) { + + TKalTrackSite* site = 0; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + const ILDVMeasLayer* ml = 0; + return this->intersectionWithDetElement( detElementID, *site, point, ml, mode ) ; + + } + + int MarlinKalTestTrack::intersectionWithDetElement( int detElementID, const TKalTrackSite& site, edm4hep::Vector3d& point, const ILDVMeasLayer*& ml, int mode ) { + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::intersectionWithDetElement( int detElementID, const TKalTrackSite& site, edm4hep::Vector3d& point, const ILDVMeasLayer*& ml, int mode) called " << std::endl; + + std::vector<const ILDVMeasLayer*> meas_modules ; + _ktest->getSensitiveMeasurementModules( detElementID, meas_modules ) ; + + if( meas_modules.size() == 0 ) { + + std::stringstream errorMsg; + errorMsg << "MarlinKalTestTrack::intersectionWithDetElement detector element id unkown: detElementID = " + << decodeILD( detElementID ) << std::endl ; + + throw MarlinTrk::Exception(errorMsg.str()); + + } + + int dummy_detElementID; // not returned here as this is a single element as far as the outside world is concerned. Could check they are equal if we wanted ... + int error_code = this->findIntersection( meas_modules, site, point, dummy_detElementID, ml, mode ) ; + + if( error_code == success ){ + + /* + streamlog_out(DEBUG1) << "MarlinKalTestTrack::intersectionWithDetElement intersection with detElementID = " + << decodeILD( detElementID ) + << ": at x = " << point.x + << " y = " << point.y + << " z = " << point.z + << std::endl ; + */ + } + + else if( error_code == no_intersection ) { + + ml = 0; + /* + streamlog_out(DEBUG1) << "MarlinKalTestTrack::intersectionWithDetElement No intersection with detElementID = " + << decodeILD( detElementID ) + << std::endl ; + */ + } + + return error_code ; + + } + + int MarlinKalTestTrack::intersectionWithLayer( int layerID, edm4hep::Vector3d& point, int& detElementID, int mode ) { + + const TKalTrackSite& site = *(dynamic_cast<const TKalTrackSite*>(_kaltrack->Last())) ; + const ILDVMeasLayer* ml = 0; + return this->intersectionWithLayer( layerID, site, point, detElementID, ml, mode ) ; + + } + + + int MarlinKalTestTrack::intersectionWithLayer( int layerID, edm4hep::TrackerHit* trkhit, edm4hep::Vector3d& point, int& detElementID, int mode ) { + + TKalTrackSite* site = 0; + int error_code = getSiteFromLCIOHit(trkhit, site); + + if( error_code != success ) return error_code ; + + const ILDVMeasLayer* ml = 0; + return this->intersectionWithLayer( layerID, *site, point, detElementID, ml, mode ) ; + + } + + + int MarlinKalTestTrack::intersectionWithLayer( int layerID, const TKalTrackSite& site, edm4hep::Vector3d& point, int& detElementID, const ILDVMeasLayer*& ml, int mode ) { + + //streamlog_out(DEBUG2) << "MarlinKalTestTrack::intersectionWithLayer( int layerID, const TKalTrackSite& site, edm4hep::Vector3d& point, int& detElementID, int mode) called layerID = " << layerID << std::endl; + + std::vector<ILDVMeasLayer const*> meas_modules ; + _ktest->getSensitiveMeasurementModulesForLayer( layerID, meas_modules ) ; + + if( meas_modules.size() == 0 ) { + + //streamlog_out(DEBUG5)<< "MarlinKalTestTrack::intersectionWithLayer layer id unknown: layerID = " << decodeILD( layerID ) << std::endl ; + return no_intersection; + + } + + // int index_of_intersected; + int error_code = this->findIntersection( meas_modules, site, point, detElementID, ml, mode ) ; + + if( error_code == success ){ + + /* + streamlog_out(DEBUG1) << "MarlinKalTestTrack::intersectionWithLayer intersection with layerID = " + << layerID + << ": at x = " << point.x + << " y = " << point.y + << " z = " << point.z + << " r = " << sqrt(point.x*point.x+point.y*point.y) + << " detElementID = " << detElementID + << " " << decodeILD( detElementID ) + << std::endl ; + */ + } + else if( error_code == no_intersection ) { + + ml = 0; + /* + streamlog_out(DEBUG1) << "MarlinKalTestTrack::intersectionWithLayer No intersection with layerID = " + << layerID + << " " << decodeILD( layerID ) + << std::endl ; + */ + } + + return error_code ; + + + } + + + int MarlinKalTestTrack::findIntersection( const ILDVMeasLayer& meas_module, const TKalTrackSite& site, edm4hep::Vector3d& point, double& dphi, int& detElementID, int mode ) { + + + TKalTrackState& trkState = (TKalTrackState&) site.GetCurState(); + + + //--------- DEBUG -------------- + // TKalTrackState* tsSmoothed = ( &((TVKalSite&)site).GetState(TVKalSite::kSmoothed) != 0 ? + // &(TKalTrackState&) ((TVKalSite&)site).GetState( TVKalSite::kSmoothed ) : 0 ) ; + // if( tsSmoothed == &trkState ) + // streamlog_out(DEBUG2) << "************ MarlinKalTestTrack::intersectionWithLayer : using smoothed TrackState !!!!! " << std::endl ; + + // TKalTrackState* tsFiltered = ( &((TVKalSite&)site).GetState(TVKalSite::kFiltered) != 0 ? + // &(TKalTrackState&) ((TVKalSite&)site).GetState( TVKalSite::kFiltered ) : 0 ) ; + // if( tsFiltered == &trkState ) + // streamlog_out(DEBUG2) << "************ MarlinKalTestTrack::intersectionWithLayer : using filtered TrackState !!!!! " << std::endl ; + // //------------------------------ + + + THelicalTrack helix = trkState.GetHelix() ; + + TVector3 xto; // reference point at destination to be returned by CalcXinPointWith + + int crossing_exist = meas_module.getIntersectionAndCellID(helix, xto, dphi, detElementID, mode); + // int crossing_exist = surf->CalcXingPointWith(helix, xto, dphi, mode) ; + + //streamlog_out(DEBUG1) << "MarlinKalTestTrack::intersectionWithLayer crossing_exist = " << crossing_exist << " dphi " << dphi << " with detElementIDs: " << detElementID ; + + //streamlog_out(DEBUG1) << std::endl ; + + + if( crossing_exist == 0 ) { + return no_intersection ; + } + else { + + point.x = xto.X(); + point.y = xto.Y(); + point.z = xto.Z(); + + } + + return success ; + + } + + + + int MarlinKalTestTrack::findIntersection( std::vector<ILDVMeasLayer const*>& meas_modules, const TKalTrackSite& site, edm4hep::Vector3d& point, int& detElementID, const ILDVMeasLayer*& ml, int mode ) { + + unsigned int n_modules = meas_modules.size() ; + + double dphi_min = DBL_MAX; // use to store the min deflection angle found so that can avoid the crossing on the far side of the layer + bool surf_found(false); + + for( unsigned int i = 0 ; i < n_modules ; ++i ){ + + double dphi = 0; + // need to send a temporary point as we may get the crossing point with the layer on the oposite side of the layer + edm4hep::Vector3d point_temp ; + + int temp_detElementID; + + int error_code = findIntersection( *meas_modules[i], site, point_temp, dphi, temp_detElementID, mode ) ; + + if( error_code == success ) { + + // make sure we get the next crossing + if( fabs(dphi) < dphi_min ) { + + dphi_min = fabs(dphi) ; + surf_found = true ; + ml = meas_modules[i]; + detElementID = temp_detElementID; + point = point_temp ; + } + + } + else if( error_code != no_intersection ) { // in which case error_code is an error rather than simply a lack of intersection, so return + + return error_code ; + + } + + } + + // check if the surface was found and return accordingly + if ( surf_found ) { + return success ; + } + else { + return no_intersection ; + } + + + } + + + + void MarlinKalTestTrack::ToLCIOTrackState( const THelicalTrack& helix, const TMatrixD& cov, edm4hep::TrackState& ts, double& chi2, int& ndf) const { + + chi2 = _kaltrack->GetChi2(); + ndf = _kaltrack->GetNDF(); + + //============== convert parameters to LCIO convention ==== + + // fill 5x5 covariance matrix from the 6x6 covariance matrix above + TMatrixD covK(5,5) ; for(int i=0;i<5;++i) for(int j=0;j<5;++j) covK[i][j] = cov[i][j] ; + + // this is for incomming tracks ... + double phi = toBaseRange( helix.GetPhi0() + M_PI/2. ) ; + double omega = 1. /helix.GetRho() ; + double d0 = - helix.GetDrho() ; + double z0 = helix.GetDz() ; + double tanLambda = helix.GetTanLambda() ; + + ts.D0 = d0; + ts.phi = phi; // fi0 - M_PI/2. ) ; + ts.omega = omega; + ts.Z0 = z0; + ts.tanLambda = tanLambda; + + Double_t cpa = helix.GetKappa(); + double alpha = omega / cpa ; // conversion factor for omega (1/R) to kappa (1/Pt) + + std::array<float, 15> covLCIO; + covLCIO[ 0] = covK( 0 , 0 ) ; // d0, d0 + + covLCIO[ 1] = - covK( 1 , 0 ) ; // phi0, d0 + covLCIO[ 2] = covK( 1 , 1 ) ; // phi0, phi + + covLCIO[ 3] = - covK( 2 , 0 ) * alpha ; // omega, d0 + covLCIO[ 4] = covK( 2 , 1 ) * alpha ; // omega, phi + covLCIO[ 5] = covK( 2 , 2 ) * alpha * alpha ; // omega, omega + + covLCIO[ 6] = - covK( 3 , 0 ) ; // z0 , d0 + covLCIO[ 7] = covK( 3 , 1 ) ; // z0 , phi + covLCIO[ 8] = covK( 3 , 2 ) * alpha ; // z0 , omega + covLCIO[ 9] = covK( 3 , 3 ) ; // z0 , z0 + + covLCIO[10] = - covK( 4 , 0 ) ; // tanl, d0 + covLCIO[11] = covK( 4 , 1 ) ; // tanl, phi + covLCIO[12] = covK( 4 , 2 ) * alpha ; // tanl, omega + covLCIO[13] = covK( 4 , 3 ) ; // tanl, z0 + covLCIO[14] = covK( 4 , 4 ) ; // tanl, tanl + + ts.covMatrix = covLCIO; + + float pivot[3] ; + pivot[0] = helix.GetPivot().X() ; + pivot[1] = helix.GetPivot().Y() ; + pivot[2] = helix.GetPivot().Z() ; + ts.referencePoint = pivot; + /* + streamlog_out( DEBUG2 ) << " kaltest track parameters: " + << " chi2/ndf " << chi2 / ndf + << " chi2 " << chi2 + << " ndf " << ndf + << " prob " << TMath::Prob(chi2, ndf) + << std::endl + + << "\t D0 " << d0 << "[+/-" << sqrt( covLCIO[0] ) << "] " + << "\t Phi :" << phi << "[+/-" << sqrt( covLCIO[2] ) << "] " + << "\t Omega " << omega << "[+/-" << sqrt( covLCIO[5] ) << "] " + << "\t Z0 " << z0 << "[+/-" << sqrt( covLCIO[9] ) << "] " + << "\t tan(Lambda) " << tanLambda << "[+/-" << sqrt( covLCIO[14]) << "] " + + << "\t pivot : [" << pivot[0] << ", " << pivot[1] << ", " << pivot[2] + << " - r: " << std::sqrt( pivot[0]*pivot[0]+pivot[1]*pivot[1] ) << "]" + << std::endl ; + */ + + } + + + void MarlinKalTestTrack::ToLCIOTrackState( const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf ) const { + + TKalTrackState& trkState = (TKalTrackState&) site.GetCurState(); // GetCutState will return the last added state to this site + // Assuming everything has proceeded as expected + // this will be Predicted -> Filtered -> Smoothed + + THelicalTrack helix = trkState.GetHelix() ; + + TMatrixD c0(trkState.GetCovMat()); + + this->ToLCIOTrackState( helix, c0, ts, chi2, ndf ); + + } + + + int MarlinKalTestTrack::getSiteFromLCIOHit( edm4hep::TrackerHit* trkhit, TKalTrackSite*& site ) const { + + std::map<edm4hep::TrackerHit*,TKalTrackSite*>::const_iterator it; + + it = _hit_used_for_sites.find(trkhit) ; + + if( it == _hit_used_for_sites.end() ) { // hit not associated with any site + + bool found = false; + + for( unsigned int i = 0; i < _hit_not_used_for_sites.size(); ++i) { + if( trkhit == _hit_not_used_for_sites[i] ) found = true ; + } + + if( found ) { + //streamlog_out( DEBUG2 ) << "MarlinKalTestTrack::getSiteFromLCIOHit: hit was rejected during filtering" << std::endl ; + return site_discarded ; + } + else { + //streamlog_out( DEBUG2 ) << "MarlinKalTestTrack::getSiteFromLCIOHit: hit " << trkhit << " not in list of supplied hits" << std::endl ; + return bad_intputs ; + } + } + + site = it->second; + + + //streamlog_out( DEBUG1 ) << "MarlinKalTestTrack::getSiteFromLCIOHit: site " << site << " found for hit " << trkhit << std::endl ; + return success ; + + } + +} // end of namespace MarlinTrk diff --git a/Service/TrackSystemSvc/src/MarlinKalTestTrack.h b/Service/TrackSystemSvc/src/MarlinKalTestTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..50551db837a399b61fbc9c99907a333b1b41b5e7 --- /dev/null +++ b/Service/TrackSystemSvc/src/MarlinKalTestTrack.h @@ -0,0 +1,360 @@ +#ifndef MarlinKalTestTrack_h +#define MarlinKalTestTrack_h + +#include "TrackSystemSvc/IMarlinTrack.h" +#include "TrackSystemSvc/IMarlinTrkSystem.h" + +#include <TObjArray.h> + +#include <cmath> + +#include "TMatrixD.h" + + +class TKalTrack ; +class THelicalTrack ; +class TKalTrackSite ; +class ILDVTrackHit ; +class ILDVMeasLayer ; + +namespace edm4hep{ + class TrackerHit ; +} + +namespace MarlinTrk{ + class MarlinKalTest; + +/** Implementation of the IMarlinTrack interface, using KalTest and KalDet to provide + * the needed functionality for a Kalman Filter. + * + * @version $Id: MarlinKalTestTrack.h 3641 2012-06-13 13:04:36Z aplin $ + * @author S.Aplin, F. Gaede DESY + */ + + class MarlinKalTestTrack : public MarlinTrk::IMarlinTrack { + public: + MarlinKalTestTrack(MarlinKalTest* ktest) ; + + ~MarlinKalTestTrack() ; + + protected: + + private: + + MarlinKalTestTrack(const MarlinKalTestTrack&) ; // Prevent copy-construction + MarlinKalTestTrack& operator=(const MarlinKalTestTrack&) ; // Prevent assignment + + // make member functions private to force use through interface + + /** add hit to track - the hits have to be added ordered in time ( i.e. typically outgoing ) + * this order will define the direction of the energy loss used in the fit + */ + int addHit(edm4hep::TrackerHit* hit) ; + + /** add hit to track - the hits have to be added ordered in time ( i.e. typically outgoing ) + * this order will define the direction of the energy loss used in the fit + */ + int addHit(edm4hep::TrackerHit* trkhit, const ILDVMeasLayer* ml) ; + + /** add hit to track - the hits have to be added ordered in time ( i.e. typically outgoing ) + * this order will define the direction of the energy loss used in the fit + */ + int addHit( edm4hep::TrackerHit* trkhit, ILDVTrackHit* kalhit, const ILDVMeasLayer* ml) ; + + /** initialise the fit using the hits added up to this point - + * the fit direction has to be specified using IMarlinTrack::backward or IMarlinTrack::forward. + * this is the order wrt the order used in addHit() that will be used in the fit() + */ + int initialise( bool fitDirection ); + + /** initialise the fit with a track state, and z component of the B field in Tesla. + * the fit direction has to be specified using IMarlinTrack::backward or IMarlinTrack::forward. + * this is the order that will be used in the fit(). + * it is the users responsibility that the track state is consistent with the order + * of the hits used in addHit() ( i.e. the direction of energy loss ) + */ + int initialise( const edm4hep::TrackState& ts, double bfield_z, bool fitDirection ) ; + + + /** perform the fit of all current hits, returns error code ( IMarlinTrack::success if no error ) . + * the fit will be performed in the order specified at initialise() wrt the order used in addHit(), i.e. + * IMarlinTrack::backward implies fitting from the outside to the inside for tracks comming from the IP. + */ + int fit( double maxChi2Increment=DBL_MAX ) ; + + + /** smooth all track states + */ + int smooth() ; + + + /** smooth track states from the last filtered hit back to the measurement site associated with the given hit + */ + int smooth( edm4hep::TrackerHit* hit ) ; + + + /** update the current fit using the supplied hit, return code via int. Provides the Chi2 increment to the fit from adding the hit via reference. + * the given hit will not be added if chi2increment > maxChi2Increment. + */ + int addAndFit( edm4hep::TrackerHit* hit, double& chi2increment, double maxChi2Increment=DBL_MAX ) ; + + /** update the current fit using the supplied hit, return code via int. Provides the Chi2 increment to the fit from adding the hit via reference. + * the given hit will not be added if chi2increment > maxChi2Increment. + */ + int addAndFit( ILDVTrackHit* kalhit, double& chi2increment, TKalTrackSite*& site, double maxChi2Increment=DBL_MAX ) ; + + + /** obtain the chi2 increment which would result in adding the hit to the fit. This method will not alter the current fit, and the hit will not be stored in the list of hits or outliers + */ + int testChi2Increment( edm4hep::TrackerHit* hit, double& chi2increment ) ; + + + // Track State Accessesors + + /** get track state, returning TrackState, chi2 and ndf via reference + */ + int getTrackState( edm4hep::TrackState& ts, double& chi2, int& ndf ) ; + + + /** get track state at measurement associated with the given hit, returning TrackState, chi2 and ndf via reference + */ + int getTrackState( edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf ) ; + + + /** get the list of hits included in the fit, together with the chi2 contributions of the hits. + * Pointers to the hits together with their chi2 contribution will be filled into a vector of + * pairs consitining of the pointer as the first part of the pair and the chi2 contribution as + * the second. + */ + int getHitsInFit( std::vector<std::pair<edm4hep::TrackerHit*, double> >& hits ) ; + + /** get the list of hits which have been rejected by from the fit due to the a chi2 increment greater than threshold, + * Pointers to the hits together with their chi2 contribution will be filled into a vector of + * pairs consitining of the pointer as the first part of the pair and the chi2 contribution as + * the second. + */ + int getOutliers( std::vector<std::pair<edm4hep::TrackerHit*, double> >& hits ) ; + + + /** get the current number of degrees of freedom for the fit. + */ + int getNDF( int& ndf ) ; + + /** get TrackeHit at which fit became constrained, i.e. ndf >= 0 + */ + int getTrackerHitAtPositiveNDF( edm4hep::TrackerHit*& trkhit ) ; + + // PROPAGATORS + + /** propagate the fit to the point of closest approach to the given point, returning TrackState, chi2 and ndf via reference + */ + int propagate( const edm4hep::Vector3d& point, edm4hep::TrackState& ts, double& chi2, int& ndf ) ; + + + /** propagate the fit at the measurement site associated with the given hit, to the point of closest approach to the given point, + * returning TrackState, chi2 and ndf via reference + */ + int propagate( const edm4hep::Vector3d& point, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf ) ; + + + /** propagate the fit at the provided measurement site, to the point of closest approach to the given point, + * returning TrackState, chi2 and ndf via reference + */ + int propagate( const edm4hep::Vector3d& point, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, const ILDVMeasLayer* ml = 0 ) ; + + + /** propagate the fit to the numbered sensitive layer, returning TrackState, chi2, ndf and integer ID of sensitive detector element via reference + */ + int propagateToLayer( int layerID, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) ; + + /** propagate the fit at the measurement site associated with the given hit, to numbered sensitive layer, + * returning TrackState, chi2, ndf and integer ID of sensitive detector element via reference + */ + int propagateToLayer( int layerID, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) ; + + /** propagate the fit at the measurement site, to numbered sensitive layer, + * returning TrackState, chi2, ndf and integer ID of sensitive detector element via reference + */ + int propagateToLayer( int layerID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) ; + + /** propagate the fit to sensitive detector element, returning TrackState, chi2 and ndf via reference + */ + int propagateToDetElement( int detElementID, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) ; + + /** propagate the fit at the measurement site associated with the given hit, to sensitive detector element, + * returning TrackState, chi2 and ndf via reference + */ + int propagateToDetElement( int detEementID, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) ; + + /** propagate the fit at the measurement site, to sensitive detector element, + * returning TrackState, chi2, ndf and integer ID of sensitive detector element via reference + */ + int propagateToDetElement( int detEementID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) ; + + + + // EXTRAPOLATORS + + /** extrapolate the fit to the point of closest approach to the given point, returning TrackState, chi2 and ndf via reference + */ + int extrapolate( const edm4hep::Vector3d& point, edm4hep::TrackState& ts, double& chi2, int& ndf ) ; + + /** extrapolate the fit at the measurement site associated with the given hit, to the point of closest approach to the given point, + * returning TrackState, chi2 and ndf via reference + */ + int extrapolate( const edm4hep::Vector3d& point, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf ) ; + + /** extrapolate the fit at the measurement site, to the point of closest approach to the given point, + * returning TrackState, chi2 and ndf via reference + */ + int extrapolate( const edm4hep::Vector3d& point, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf ) ; + + /** extrapolate the fit to numbered sensitive layer, returning TrackState via provided reference + */ + int extrapolateToLayer( int layerID, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site associated with the given hit, to numbered sensitive layer, + * returning TrackState, chi2, ndf and integer ID of sensitive detector element via reference + */ + int extrapolateToLayer( int layerID, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site, to numbered sensitive layer, + * returning TrackState, chi2, ndf and integer ID of sensitive detector element via reference + */ + int extrapolateToLayer( int layerID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int& detElementID, int mode=modeClosest ) ; + + /** extrapolate the fit to sensitive detector element, returning TrackState, chi2 and ndf via reference + */ + int extrapolateToDetElement( int detElementID, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site associated with the given hit, to sensitive detector element, + * returning TrackState, chi2 and ndf via reference + */ + int extrapolateToDetElement( int detEementID, edm4hep::TrackerHit* hit, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site, to sensitive detector element, + * returning TrackState, chi2, ndf and integer ID of sensitive detector element via reference + */ + int extrapolateToDetElement( int detEementID, const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf, int mode=modeClosest ) ; + + + + // INTERSECTORS + + + /** extrapolate the fit to numbered sensitive layer, returning intersection point in global coordinates and integer ID of the + * intersected sensitive detector element via reference + */ + int intersectionWithLayer( int layerID, edm4hep::Vector3d& point, int& detElementID, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site associated with the given hit, to numbered sensitive layer, + * returning intersection point in global coordinates and integer ID of the intersected sensitive detector element via reference + */ + int intersectionWithLayer( int layerID, edm4hep::TrackerHit* hit, edm4hep::Vector3d& point, int& detElementID, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site, to numbered sensitive layer, + * returning intersection point in global coordinates and integer ID of the intersected sensitive detector element via reference + */ + int intersectionWithLayer( int layerID, const TKalTrackSite& site, edm4hep::Vector3d& point, int& detElementID, const ILDVMeasLayer*& ml, int mode=modeClosest ) ; + + + /** extrapolate the fit to numbered sensitive detector element, returning intersection point in global coordinates via reference + */ + int intersectionWithDetElement( int detElementID, edm4hep::Vector3d& point, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site associated with the given hit, to sensitive detector element, + * returning intersection point in global coordinates via reference + */ + int intersectionWithDetElement( int detElementID, edm4hep::TrackerHit* hit, edm4hep::Vector3d& point, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site, to sensitive detector element, + * returning intersection point in global coordinates via reference + */ + int intersectionWithDetElement( int detElementID, const TKalTrackSite& site, edm4hep::Vector3d& point, const ILDVMeasLayer*& ml, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site, to sensitive detector elements contained in the std::vector, + * and return intersection point in global coordinates via reference + */ + int findIntersection( std::vector<ILDVMeasLayer const*>& meas_modules, const TKalTrackSite& site, edm4hep::Vector3d& point, int& detElementID, const ILDVMeasLayer*& ml, int mode=modeClosest ) ; + + /** extrapolate the fit at the measurement site, to the ILDVMeasLayer, + * and return intersection point in global coordinates via reference + */ + int findIntersection( const ILDVMeasLayer& meas_module, const TKalTrackSite& site, edm4hep::Vector3d& point, double& dphi, int& detElementIDconst, int mode=modeClosest ) ; + + + + + //** end of memeber functions from IMarlinTrack interface + + /** fill LCIO Track State with parameters from helix and cov matrix + */ + void ToLCIOTrackState( const TKalTrackSite& site, edm4hep::TrackState& ts, double& chi2, int& ndf ) const ; + + /** fill LCIO Track State with parameters from helix and cov matrix + */ + void ToLCIOTrackState( const THelicalTrack& helix, const TMatrixD& cov, edm4hep::TrackState& ts, double& chi2, int& ndf ) const ; + + /** get the measurement site associated with the given lcio TrackerHit trkhit + */ + int getSiteFromLCIOHit( edm4hep::TrackerHit* trkhit, TKalTrackSite*& site ) const ; + + + + /** helper function to restrict the range of the azimuthal angle to ]-pi,pi]*/ + inline double toBaseRange( double phi) const { + while( phi <= -M_PI ){ phi += 2. * M_PI ; } + while( phi > M_PI ){ phi -= 2. * M_PI ; } + return phi ; + } + + + // memeber variables + + TKalTrack* _kaltrack; + + std::vector<edm4hep::TrackerHit*> _lcioHits ; + + TObjArray* _kalhits; + + MarlinKalTest* _ktest; + + edm4hep::TrackerHit* _trackHitAtPositiveNDF; + int _hitIndexAtPositiveNDF; + + /** used to store whether initial track state has been supplied or created + */ + bool _initialised ; + + /** used to store the fit direction supplied to intialise + */ + bool _fitDirection ; + + + /** used to store whether smoothing has been performed + */ + bool _smoothed ; + + /** map to store relation between lcio hits and measurement sites + */ + std::map<edm4hep::TrackerHit*, TKalTrackSite*> _hit_used_for_sites ; + + /** map to store relation between lcio hits kaltest hits + */ + std::map<edm4hep::TrackerHit*, ILDVTrackHit*> _lcio_hits_to_kaltest_hits ; + + /** vector to store lcio hits rejected for measurement sites + */ + std::vector<edm4hep::TrackerHit*> _hit_not_used_for_sites ; + + /** vector to store the chi-sqaure increment for measurement sites + */ + std::vector< std::pair<edm4hep::TrackerHit*, double> > _hit_chi2_values ; + + /** vector to store the chi-sqaure increment for measurement sites + */ + std::vector< std::pair<edm4hep::TrackerHit*, double> > _outlier_chi2_values ; + + } ; +} +#endif diff --git a/Service/TrackSystemSvc/src/MarlinTrkDiagnostics.cc.remove b/Service/TrackSystemSvc/src/MarlinTrkDiagnostics.cc.remove new file mode 100644 index 0000000000000000000000000000000000000000..46aebfe69d87d0ad4a2c95663cdf96f7b185d8d0 --- /dev/null +++ b/Service/TrackSystemSvc/src/MarlinTrkDiagnostics.cc.remove @@ -0,0 +1,63 @@ + +#include "MarlinTrkDiagnostics.h" + +#include "EVENT/LCObject.h" +#include "UTIL/BitSet32.h" +#include "UTIL/ILDConf.h" + +#ifdef MARLINTRK_DIAGNOSTICS_ON + +namespace MarlinTrk{ + + + void getMCParticlesForTrackerHit(EVENT::TrackerHit* trkhit, std::vector<EVENT::MCParticle*>& mcps){ + + if ( !trkhit ) { + return; + } + + // make sure there is nothing in the vector we wish to return + mcps.clear(); + + // first check if this is a composite space point + if(UTIL::BitSet32( trkhit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ]){ + + const EVENT::LCObjectVec rawObjects = trkhit->getRawHits(); + + for (unsigned iraw = 0; iraw < rawObjects.size(); ++iraw) { + + EVENT::TrackerHit* rawHit = dynamic_cast< EVENT::TrackerHit* >( rawObjects[iraw] ); + + if( rawHit && rawHit->ext<MarlinTrk::MCTruth4HitExt>()){ + + EVENT::MCParticle* mcp = rawHit->ext<MarlinTrk::MCTruth4HitExt>()->simhit->getMCParticle(); + bool found = false; + // check that it is not already in the vector + for (unsigned imcp=0; imcp<mcps.size(); ++imcp) { + if (mcp == mcps[imcp]) { + found = true; + break; + } + } + + if( found == false ) mcps.push_back(mcp); + + } + + + } // end of loop over rawObjects + + // end if COMPOSITE_SPACEPOINT + } else { + + + if( trkhit->ext<MarlinTrk::MCTruth4HitExt>()){ + mcps.push_back(trkhit->ext<MarlinTrk::MCTruth4HitExt>()->simhit->getMCParticle()); + } + + + } + } +} + +#endif diff --git a/Service/TrackSystemSvc/src/MarlinTrkUtils.cc b/Service/TrackSystemSvc/src/MarlinTrkUtils.cc new file mode 100644 index 0000000000000000000000000000000000000000..f28442a27eb1a9e30fde81cbdd5f00c89ff77d55 --- /dev/null +++ b/Service/TrackSystemSvc/src/MarlinTrkUtils.cc @@ -0,0 +1,752 @@ +#include "TrackSystemSvc/MarlinTrkUtils.h" + +#include <vector> +#include <algorithm> + +#include "TrackSystemSvc/IMarlinTrack.h" +#include "TrackSystemSvc/HelixTrack.h" + +#include "DataHelper/Navigation.h" +//#include "lcio.h" +//#include <IMPL/TrackImpl.h> +//#include <IMPL/TrackStateImpl.h> +//#include <EVENT/TrackerHit.h> +#include "edm4hep/TrackerHit.h" +#include "edm4hep/TrackState.h" +#include "edm4hep/Track.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> +#include <UTIL/BitSet32.h> + +//#include "streamlog/streamlog.h" + +#include "TMatrixD.h" + +#define MIN_NDF 6 + +namespace MarlinTrk { + + +// // Check if a square matrix is Positive Definite +// bool Matrix_Is_Positive_Definite(const EVENT::FloatVec& matrix){ +// +// std::cout << "\n MarlinTrk::Matrix_Is_Positive_Definite(EVENT::FloatVec& matrix): " << std::endl; +// +// int icol,irow; +// +// int nrows = 5; +// +// TMatrixD cov(nrows,nrows) ; +// +// bool matrix_is_positive_definite = true; +// +// int icov = 0; +// for(int irow=0; irow<nrows; ++irow ){ +// for(int jcol=0; jcol<irow+1; ++jcol){ +// cov(irow,jcol) = matrix[icov]; +// cov(jcol,irow) = matrix[icov]; +//// std::cout << " " << matrix[icov] ; +// ++icov ; +// } +//// std::cout << std::endl; +// } +// +//// cov.Print(); +// +// double *pU = cov.GetMatrixArray(); +// +// for (icol = 0; icol < nrows; icol++) { +// const int rowOff = icol * nrows; +// +// //Compute fU(j,j) and test for non-positive-definiteness. +// double ujj = pU[rowOff+icol]; +// double diagonal = ujj; +//// std::cout << "ERROR: diagonal = " << diagonal << std::endl; +// +// for (irow = 0; irow < icol; irow++) { +// const int pos_ij = irow*nrows+icol; +// std::cout << " " << pU[pos_ij] ; +// ujj -= pU[pos_ij]*pU[pos_ij]; +// } +// std::cout << " " << diagonal << std::endl; +// +// +// if (ujj <= 0) { +// matrix_is_positive_definite = false; +// } +// } +// +// std::cout << std::endl; +// +// if ( matrix_is_positive_definite == false ) { +// std::cout << "******************************************************" << std::endl; +// std::cout << "** ERROR: matrix shown not to be positive definite **" << std::endl; +// std::cout << "******************************************************" << std::endl; +// } +// +// return matrix_is_positive_definite; +// +// } + + + + int createTrackStateAtCaloFace( IMarlinTrack* marlinTrk, edm4hep::TrackState* track, edm4hep::TrackerHit* trkhit, bool tanL_is_positive ); + + int createFinalisedLCIOTrack( IMarlinTrack* marlinTrk, std::vector<edm4hep::TrackerHit*>& hit_list, edm4hep::Track* track, bool fit_backwards, const std::array<float,15>& initial_cov_for_prefit, float bfield_z, double maxChi2Increment){ + + /////////////////////////////////////////////////////// + // check inputs + /////////////////////////////////////////////////////// + if ( hit_list.empty() ) return IMarlinTrack::bad_intputs ; + + if( track == 0 ){ + throw std::runtime_error( "MarlinTrk::finaliseLCIOTrack: TrackImpl == NULL " ) ; + } + + int return_error = 0; + /////////////////////////////////////////////////////// + // produce prefit parameters + /////////////////////////////////////////////////////// + + edm4hep::TrackState pre_fit ; + + //std::cout << "debug:=====================before createPrefit" << std::endl; + return_error = createPrefit(hit_list, &pre_fit, bfield_z, fit_backwards); + //std::cout << "debug:=====================after createPrefit return code=" << return_error << std::endl; + pre_fit.covMatrix = initial_cov_for_prefit; + + /////////////////////////////////////////////////////// + // use prefit parameters to produce Finalised track + /////////////////////////////////////////////////////// + + if( return_error == 0 ) { + + return_error = createFinalisedLCIOTrack( marlinTrk, hit_list, track, fit_backwards, &pre_fit, bfield_z, maxChi2Increment); + + } else { + //std::cout << "MarlinTrk::createFinalisedLCIOTrack : Prefit failed error = " << return_error << std::endl; + } + return return_error; + } + + int createFinalisedLCIOTrack( IMarlinTrack* marlinTrk, std::vector<edm4hep::TrackerHit*>& hit_list, edm4hep::Track* track, bool fit_backwards, edm4hep::TrackState* pre_fit, float bfield_z, double maxChi2Increment){ + + + /////////////////////////////////////////////////////// + // check inputs + /////////////////////////////////////////////////////// + if ( hit_list.empty() ) return IMarlinTrack::bad_intputs ; + + if( track == 0 ){ + throw std::runtime_error("MarlinTrk::finaliseLCIOTrack: TrackImpl == NULL "); + } + + if( pre_fit == 0 ){ + throw std::runtime_error("MarlinTrk::finaliseLCIOTrack: TrackStateImpl == NULL "); + } + + + int fit_status = createFit(hit_list, marlinTrk, pre_fit, bfield_z, fit_backwards, maxChi2Increment); + + if( fit_status != IMarlinTrack::success ){ + + //std::cout << "MarlinTrk::createFinalisedLCIOTrack fit failed: fit_status = " << fit_status << std::endl; + + return fit_status; + } + + int error = finaliseLCIOTrack(marlinTrk, track, hit_list); + + return error; + } + + + + + int createFit( std::vector<edm4hep::TrackerHit*>& hit_list, IMarlinTrack* marlinTrk, edm4hep::TrackState* pre_fit, float bfield_z, bool fit_backwards, double maxChi2Increment){ + + + /////////////////////////////////////////////////////// + // check inputs + /////////////////////////////////////////////////////// + if ( hit_list.empty() ) return IMarlinTrack::bad_intputs; + + if( marlinTrk == 0 ){ + throw std::runtime_error("MarlinTrk::createFit: IMarlinTrack == NULL "); + } + + if( pre_fit == 0 ){ + throw std::runtime_error("MarlinTrk::createFit: TrackStateImpl == NULL "); + } + + int return_error = 0; + + +// /////////////////////////////////////////////////////// +// // check that the prefit has the reference point at the correct location +// /////////////////////////////////////////////////////// +// +// if (( fit_backwards == IMarlinTrack::backward && pre_fit->getLocation() != lcio::TrackState::AtLastHit ) +// || +// ( fit_backwards == IMarlinTrack::forward && pre_fit->getLocation() != lcio::TrackState::AtFirstHit )) { +// std::stringstream ss ; +// +// ss << "MarlinTrk::createFinalisedLCIOTrack track state must be set at either first or last hit. Location = "; +// ss << pre_fit->getLocation(); +// +// throw EVENT::Exception( ss.str() ); +// +// } + + /////////////////////////////////////////////////////// + // add hits to IMarlinTrk + /////////////////////////////////////////////////////// + + std::vector<edm4hep::TrackerHit*>::iterator it = hit_list.begin(); + + // start by trying to add the hits to the track we want to finally use. + //std::cout << "MarlinTrk::createFit Start Fit: AddHits: number of hits to fit " << hit_list.size() << std::endl; + + std::vector<edm4hep::TrackerHit*> added_hits; + unsigned int ndof_added = 0; + + for( it = hit_list.begin() ; it != hit_list.end() ; ++it ) { + + edm4hep::TrackerHit* trkHit = *it; + bool isSuccessful = false; + //std::cout << "debug: TrackerHit pointer " << trkHit << std::endl; + if( UTIL::BitSet32( trkHit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ){ //it is a composite spacepoint + //Split it up and add both hits to the MarlinTrk + //const EVENT::LCObjectVec rawObjects = trkHit->getRawHits(); + //std::cout << "space point is not still valid! pelease wait updating..." <<std::endl; + //exit(1); + int nRawHit = trkHit->rawHits_size(); + for( unsigned k=0; k< nRawHit; k++ ){ + edm4hep::TrackerHit* rawHit = Navigation::Instance()->GetTrackerHit(trkHit->getRawHits(k)); + if( marlinTrk->addHit( rawHit ) == IMarlinTrack::success ){ + isSuccessful = true; //if at least one hit from the spacepoint gets added + ++ndof_added; +// streamlog_out(DEBUG4) << "MarlinTrk::createFit ndof_added = " << ndof_added << std::endl; + } + } + } + else { // normal non composite hit + if (marlinTrk->addHit( trkHit ) == IMarlinTrack::success ) { + isSuccessful = true; + ndof_added += 2; +// streamlog_out(DEBUG4) << "MarlinTrk::createFit ndof_added = " << ndof_added << std::endl; + } + } + + if (isSuccessful) { + added_hits.push_back(trkHit); + } + else{ + //std::cout << "MarlinTrkUtils::createFit Hit " << it - hit_list.begin() << " Dropped " << std::endl; + } + + } + + if( ndof_added < MIN_NDF ) { + //streamlog_out(DEBUG2) << "MarlinTrk::createFit : Cannot fit less with less than " << MIN_NDF << " degrees of freedom. Number of hits = " << added_hits.size() << " ndof = " << ndof_added << std::endl; + return IMarlinTrack::bad_intputs; + } + + + + /////////////////////////////////////////////////////// + // set the initial track parameters + /////////////////////////////////////////////////////// + + return_error = marlinTrk->initialise( *pre_fit, bfield_z, IMarlinTrack::backward ) ; + if (return_error != IMarlinTrack::success) { + + //streamlog_out(DEBUG5) << "MarlinTrk::createFit Initialisation of track fit failed with error : " << return_error << std::endl; + + return return_error; + + } + + /////////////////////////////////////////////////////// + // try fit and return error + /////////////////////////////////////////////////////// + int status = marlinTrk->fit(maxChi2Increment); + //std::cout << "debug:===================createFit " << status << std::endl; + + return status; + + } + + + + int createPrefit( std::vector<edm4hep::TrackerHit*>& hit_list, edm4hep::TrackState* pre_fit, float bfield_z, bool fit_backwards){ + + /////////////////////////////////////////////////////// + // check inputs + /////////////////////////////////////////////////////// + if ( hit_list.empty() ) return IMarlinTrack::bad_intputs ; + + if( pre_fit == 0 ){ + throw EVENT::Exception( std::string("MarlinTrk::finaliseLCIOTrack: TrackStateImpl == NULL ") ) ; + } + + /////////////////////////////////////////////////////// + // loop over all the hits and create a list consisting only 2D hits + /////////////////////////////////////////////////////// + + std::vector<edm4hep::TrackerHit*> twoD_hits; + + for (unsigned ihit=0; ihit < hit_list.size(); ++ihit) { + + // check if this a space point or 2D hit + if(UTIL::BitSet32( hit_list[ihit]->getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] == false ){ + // then add to the list + twoD_hits.push_back(hit_list[ihit]); + + } + } + + /////////////////////////////////////////////////////// + // check that there are enough 2-D hits to create a helix + /////////////////////////////////////////////////////// + + if (twoD_hits.size() < 3) { // no chance to initialise print warning and return + //streamlog_out(WARNING) << "MarlinTrk::createFinalisedLCIOTrack Cannot create helix from less than 3 2-D hits" << std::endl; + return IMarlinTrack::bad_intputs; + } + + /////////////////////////////////////////////////////// + // make a helix from 3 hits to get a trackstate + /////////////////////////////////////////////////////// + + // SJA:FIXME: this may not be the optimal 3 hits to take in certain cases where the 3 hits are not well spread over the track length + const edm4hep::Vector3d& x1 = twoD_hits[0]->getPosition(); + const edm4hep::Vector3d& x2 = twoD_hits[ twoD_hits.size()/2 ]->getPosition(); + const edm4hep::Vector3d& x3 = twoD_hits.back()->getPosition(); + + HelixTrack helixTrack( x1, x2, x3, bfield_z, HelixTrack::forwards ); + + if ( fit_backwards == IMarlinTrack::backward ) { + pre_fit->location = MarlinTrk::Location::AtLastHit; + helixTrack.moveRefPoint(hit_list.back()->getPosition()[0], hit_list.back()->getPosition()[1], hit_list.back()->getPosition()[2]); + } else { + pre_fit->location = MarlinTrk::Location::AtFirstHit; + helixTrack.moveRefPoint(hit_list.front()->getPosition()[0], hit_list.front()->getPosition()[1], hit_list.front()->getPosition()[2]); + } + + + const float referencePoint[3] = { helixTrack.getRefPointX() , helixTrack.getRefPointY() , helixTrack.getRefPointZ() }; + + pre_fit->D0 = helixTrack.getD0(); + pre_fit->phi = helixTrack.getPhi0(); + pre_fit->omega = helixTrack.getOmega(); + pre_fit->Z0 = helixTrack.getZ0(); + pre_fit->tanLambda = helixTrack.getTanLambda(); + + pre_fit->referencePoint = referencePoint; + + return IMarlinTrack::success; + + } + + int finaliseLCIOTrack( IMarlinTrack* marlintrk, edm4hep::Track* track, std::vector<edm4hep::TrackerHit*>& hit_list, edm4hep::TrackState* atLastHit, edm4hep::TrackState* atCaloFace){ + + /////////////////////////////////////////////////////// + // check inputs + /////////////////////////////////////////////////////// + if( marlintrk == 0 ){ + throw EVENT::Exception( std::string("MarlinTrk::finaliseLCIOTrack: IMarlinTrack == NULL ") ) ; + } + + if( track == 0 ){ + throw EVENT::Exception( std::string("MarlinTrk::finaliseLCIOTrack: TrackImpl == NULL ") ) ; + } + + if( atCaloFace && atLastHit == 0 ){ + throw EVENT::Exception( std::string("MarlinTrk::finaliseLCIOTrack: atLastHit == NULL ") ) ; + } + + if( atLastHit && atCaloFace == 0 ){ + throw EVENT::Exception( std::string("MarlinTrk::finaliseLCIOTrack: atCaloFace == NULL ") ) ; + } + + + + /////////////////////////////////////////////////////// + // error to return if any + /////////////////////////////////////////////////////// + int return_error = 0; + + int ndf = 0; + double chi2 = -DBL_MAX; + + ///////////////////////////////////////////////////////////// + // First check NDF to see if it make any sense to continue. + // The track will be dropped if the NDF is less than 0 + ///////////////////////////////////////////////////////////// + + return_error = marlintrk->getNDF(ndf); + + if ( return_error != IMarlinTrack::success) { + //streamlog_out(DEBUG3) << "MarlinTrk::finaliseLCIOTrack: getNDF returns " << return_error << std::endl; + return return_error; + } else if( ndf < 0 ) { + //streamlog_out(DEBUG2) << "MarlinTrk::finaliseLCIOTrack: number of degrees of freedom less than 0 track dropped : NDF = " << ndf << std::endl; + return IMarlinTrack::error; + } else { + //streamlog_out(DEBUG1) << "MarlinTrk::finaliseLCIOTrack: NDF = " << ndf << std::endl; + } + + + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + // get the list of hits used in the fit + // add these to the track, add spacepoints as long as at least on strip hit is used. + //////////////////////////////////////////////////////////////////////////////////////////////////////// + + std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit; + std::vector<std::pair<edm4hep::TrackerHit*, double> > outliers; + std::vector<edm4hep::TrackerHit*> used_hits; + + hits_in_fit.reserve(300); + outliers.reserve(300); + + marlintrk->getHitsInFit(hits_in_fit); + marlintrk->getOutliers(outliers); + + /////////////////////////////////////////////// + // now loop over the hits provided for fitting + // we do this so that the hits are added in the + // order in which they have been fitted + /////////////////////////////////////////////// + + for ( unsigned ihit = 0; ihit < hit_list.size(); ++ihit) { + + edm4hep::TrackerHit* trkHit = hit_list[ihit]; + + if( UTIL::BitSet32( trkHit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ){ //it is a composite spacepoint + //std::cout << "Error: space point is not still valid! pelease wait updating..." <<std::endl; + //exit(1); + // get strip hits + int nRawHit = trkHit->rawHits_size(); + for( unsigned k=0; k< nRawHit; k++ ){ + edm4hep::TrackerHit* rawHit = Navigation::Instance()->GetTrackerHit(trkHit->getRawHits(k)); + bool is_outlier = false; + // here we loop over outliers as this will be faster than looping over the used hits + for ( unsigned ohit = 0; ohit < outliers.size(); ++ohit) { + if ( rawHit->id() == outliers[ohit].first->id() ) { + is_outlier = true; + break; // break out of loop over outliers + } + } + if (is_outlier == false) { + used_hits.push_back(hit_list[ihit]); + track->addToTrackerHits(*used_hits.back()); + break; // break out of loop over rawObjects + } + } + } else { + bool is_outlier = false; + // here we loop over outliers as this will be faster than looping over the used hits + for ( unsigned ohit = 0; ohit < outliers.size(); ++ohit) { + if ( trkHit == outliers[ohit].first ) { + is_outlier = true; + break; // break out of loop over outliers + } + } + if (is_outlier == false) { + used_hits.push_back(hit_list[ihit]); + track->addToTrackerHits(*used_hits.back()); + } + } + } + + +// /////////////////////////////////////////////////////////////////////////// +// // We now need to find out at which point the fit is constrained +// // and therefore be able to provide well formed (pos. def.) cov. matrices +// /////////////////////////////////////////////////////////////////////////// +// + + + /////////////////////////////////////////////////////// + // first hit + /////////////////////////////////////////////////////// + + edm4hep::TrackState* trkStateAtFirstHit = new edm4hep::TrackState() ; + edm4hep::TrackerHit* firstHit = hits_in_fit.back().first; + + /////////////////////////////////////////////////////// + // last hit + /////////////////////////////////////////////////////// + + edm4hep::TrackState* trkStateAtLastHit = new edm4hep::TrackState() ; + edm4hep::TrackerHit* lastHit = hits_in_fit.front().first; + + edm4hep::TrackerHit* last_constrained_hit = 0 ; + marlintrk->getTrackerHitAtPositiveNDF(last_constrained_hit); + + return_error = marlintrk->smooth(lastHit); + + if ( return_error != IMarlinTrack::success ) { + //streamlog_out(DEBUG4) << "MarlinTrk::finaliseLCIOTrack: return_code for smoothing to " << lastHit << " = " << return_error << " NDF = " << ndf << std::endl; + delete trkStateAtFirstHit; + delete trkStateAtLastHit; + return return_error ; + } + + + /////////////////////////////////////////////////////// + // first create trackstate at IP + /////////////////////////////////////////////////////// + const edm4hep::Vector3d point; // nominal IP + + edm4hep::TrackState* trkStateIP = new edm4hep::TrackState() ; + + + /////////////////////////////////////////////////////// + // make sure that the track state can be propagated to the IP + /////////////////////////////////////////////////////// + + return_error = marlintrk->propagate(point, firstHit, *trkStateIP, chi2, ndf ) ; + + if ( return_error != IMarlinTrack::success ) { + //streamlog_out(DEBUG4) << "MarlinTrk::finaliseLCIOTrack: return_code for propagation = " << return_error << " NDF = " << ndf << std::endl; + delete trkStateIP; + delete trkStateAtFirstHit; + delete trkStateAtLastHit; + + return return_error ; + } + + trkStateIP->location = MarlinTrk::Location::AtIP; + track->addToTrackStates(*trkStateIP); + track->setChi2(chi2); + track->setNdf(ndf); + + + /////////////////////////////////////////////////////// + // set the track states at the first and last hits + /////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////// + // @ first hit + /////////////////////////////////////////////////////// + + //streamlog_out( DEBUG5 ) << " >>>>>>>>>>> create TrackState AtFirstHit" << std::endl ; + + + return_error = marlintrk->getTrackState(firstHit, *trkStateAtFirstHit, chi2, ndf ) ; + + if ( return_error == 0 ) { + trkStateAtFirstHit->location = MarlinTrk::Location::AtFirstHit; + track->addToTrackStates(*trkStateAtFirstHit); + } else { + //streamlog_out( WARNING ) << " >>>>>>>>>>> MarlinTrk::finaliseLCIOTrack: could not get TrackState at First Hit " << firstHit << std::endl ; + delete trkStateAtFirstHit; + } + + double r_first = firstHit->getPosition()[0]*firstHit->getPosition()[0] + firstHit->getPosition()[1]*firstHit->getPosition()[1]; + + track->setRadiusOfInnermostHit(sqrt(r_first)); + + if ( atLastHit == 0 && atCaloFace == 0 ) { + + /////////////////////////////////////////////////////// + // @ last hit + /////////////////////////////////////////////////////// + + //streamlog_out( DEBUG5 ) << " >>>>>>>>>>> create TrackState AtLastHit : using trkhit " << last_constrained_hit << std::endl ; + + edm4hep::Vector3d last_hit_pos(lastHit->getPosition()); + + return_error = marlintrk->propagate(last_hit_pos, last_constrained_hit, *trkStateAtLastHit, chi2, ndf); + +// return_error = marlintrk->getTrackState(lastHit, *trkStateAtLastHit, chi2, ndf ) ; + + if ( return_error == 0 ) { + trkStateAtLastHit->location = MarlinTrk::Location::AtLastHit; + track->addToTrackStates(*trkStateAtLastHit); + } else { + //streamlog_out( DEBUG5 ) << " >>>>>>>>>>> MarlinTrk::finaliseLCIOTrack: could not get TrackState at Last Hit " << last_constrained_hit << std::endl ; + delete trkStateAtLastHit; + } + +// const EVENT::FloatVec& ma = trkStateAtLastHit->getCovMatrix(); +// +// Matrix_Is_Positive_Definite( ma ); + + /////////////////////////////////////////////////////// + // set the track state at Calo Face + /////////////////////////////////////////////////////// + + edm4hep::TrackState trkStateCalo; + bool tanL_is_positive = trkStateIP->tanLambda >0 ; + + return_error = createTrackStateAtCaloFace(marlintrk, &trkStateCalo, last_constrained_hit, tanL_is_positive); +// return_error = createTrackStateAtCaloFace(marlintrk, trkStateCalo, lastHit, tanL_is_positive); + + if ( return_error == 0 ) { + trkStateCalo.location = MarlinTrk::Location::AtCalorimeter; + track->addToTrackStates(trkStateCalo); + } else { + //streamlog_out( WARNING ) << " >>>>>>>>>>> MarlinTrk::finaliseLCIOTrack: could not get TrackState at Calo Face " << std::endl ; + //delete trkStateCalo; + } + } else { + track->addToTrackStates(*atLastHit); + track->addToTrackStates(*atCaloFace); + } + + /////////////////////////////////////////////////////// + // done + /////////////////////////////////////////////////////// + return return_error; + } + + + int createTrackStateAtCaloFace( IMarlinTrack* marlintrk, edm4hep::TrackState* trkStateCalo, edm4hep::TrackerHit* trkhit, bool tanL_is_positive ){ + + //streamlog_out( DEBUG5 ) << " >>>>>>>>>>> createTrackStateAtCaloFace : using trkhit " << trkhit << " tanL_is_positive = " << tanL_is_positive << std::endl ; + + /////////////////////////////////////////////////////// + // check inputs + /////////////////////////////////////////////////////// + if( marlintrk == 0 ){ + throw EVENT::Exception( std::string("MarlinTrk::createTrackStateAtCaloFace: IMarlinTrack == NULL ") ) ; + } + + if( trkStateCalo == 0 ){ + throw EVENT::Exception( std::string("MarlinTrk::createTrackStateAtCaloFace: TrackImpl == NULL ") ) ; + } + + if( trkhit == 0 ){ + throw EVENT::Exception( std::string("MarlinTrk::createTrackStateAtCaloFace: TrackHit == NULL ") ) ; + } + + int return_error = 0; + + double chi2 = -DBL_MAX; + int ndf = 0; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::ECAL ; + encoder[lcio::ILDCellID0::side] = lcio::ILDDetID::barrel; + encoder[lcio::ILDCellID0::layer] = 0 ; + + int detElementID = 0; + + return_error = marlintrk->propagateToLayer(encoder.lowWord(), trkhit, *trkStateCalo, chi2, ndf, detElementID, IMarlinTrack::modeForward ) ; + + if (return_error == IMarlinTrack::no_intersection ) { // try forward or backward + if (tanL_is_positive) { + encoder[lcio::ILDCellID0::side] = lcio::ILDDetID::fwd; + } + else{ + encoder[lcio::ILDCellID0::side] = lcio::ILDDetID::bwd; + } + return_error = marlintrk->propagateToLayer(encoder.lowWord(), trkhit, *trkStateCalo, chi2, ndf, detElementID, IMarlinTrack::modeForward ) ; + } + + if (return_error !=IMarlinTrack::success ) { + //streamlog_out( DEBUG5 ) << " >>>>>>>>>>> createTrackStateAtCaloFace : could not get TrackState at Calo Face: return_error = " << return_error << std::endl ; + } + + + return return_error; + + + } + + void addHitNumbersToTrack(edm4hep::Track* track, std::vector<edm4hep::TrackerHit*>& hit_list, bool hits_in_fit, UTIL::BitField64& cellID_encoder){ + + /////////////////////////////////////////////////////// + // check inputs + /////////////////////////////////////////////////////// + if( track == 0 ){ + throw std::runtime_error( std::string("MarlinTrk::addHitsToTrack: TrackImpl == NULL ") ) ; + } + std::map<int, int> hitNumbers; + + hitNumbers[UTIL::ILDDetID::VXD] = 0; + hitNumbers[UTIL::ILDDetID::SIT] = 0; + hitNumbers[UTIL::ILDDetID::FTD] = 0; + hitNumbers[UTIL::ILDDetID::TPC] = 0; + hitNumbers[UTIL::ILDDetID::SET] = 0; + hitNumbers[UTIL::ILDDetID::ETD] = 0; + + for(unsigned int j=0; j<hit_list.size(); ++j) { + cellID_encoder.setValue(hit_list.at(j)->getCellID()) ; + int detID = cellID_encoder[UTIL::ILDCellID0::subdet]; + ++hitNumbers[detID]; + //std::cout << "debug: " << "Hit from Detector " << detID << std::endl; + } + + int offset = 2 ; + if ( hits_in_fit == false ) { // all hit atributed by patrec + offset = 1 ; + } + track->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::VXD]); + track->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::FTD]); + track->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::SIT]); + track->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::TPC]); + track->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::SET]); + track->addToSubDetectorHitNumbers(hitNumbers[UTIL::ILDDetID::ETD]); + //track->subdetectorHitNumbers().resize(2 * lcio::ILDDetID::ETD); + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::VXD - offset ] = hitNumbers[lcio::ILDDetID::VXD]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::FTD - offset ] = hitNumbers[lcio::ILDDetID::FTD]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::SIT - offset ] = hitNumbers[lcio::ILDDetID::SIT]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::TPC - offset ] = hitNumbers[lcio::ILDDetID::TPC]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::SET - offset ] = hitNumbers[lcio::ILDDetID::SET]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::ETD - offset ] = hitNumbers[lcio::ILDDetID::ETD]; + } + + void addHitNumbersToTrack(edm4hep::Track* track, std::vector<std::pair<edm4hep::TrackerHit* , double> >& hit_list, bool hits_in_fit, UTIL::BitField64& cellID_encoder){ + + /////////////////////////////////////////////////////// + // check inputs + /////////////////////////////////////////////////////// + if( track == 0 ){ + throw std::runtime_error( std::string("MarlinTrk::addHitsToTrack: TrackImpl == NULL ") ) ; + } + + std::map<int, int> hitNumbers; + + hitNumbers[lcio::ILDDetID::VXD] = 0; + hitNumbers[lcio::ILDDetID::SIT] = 0; + hitNumbers[lcio::ILDDetID::FTD] = 0; + hitNumbers[lcio::ILDDetID::TPC] = 0; + hitNumbers[lcio::ILDDetID::SET] = 0; + hitNumbers[lcio::ILDDetID::ETD] = 0; + + for(unsigned int j=0; j<hit_list.size(); ++j) { + cellID_encoder.setValue(hit_list.at(j).first->getCellID()) ; + int detID = cellID_encoder[UTIL::ILDCellID0::subdet]; + ++hitNumbers[detID]; + //std::cout << "debug: Hit from Detector " << detID << std::endl; + } + + int offset = 2 ; + if ( hits_in_fit == false ) { // all hit atributed by patrec + offset = 1 ; + } + track->addToSubDetectorHitNumbers(hitNumbers[lcio::ILDDetID::VXD]); + track->addToSubDetectorHitNumbers(hitNumbers[lcio::ILDDetID::FTD]); + track->addToSubDetectorHitNumbers(hitNumbers[lcio::ILDDetID::SIT]); + track->addToSubDetectorHitNumbers(hitNumbers[lcio::ILDDetID::TPC]); + track->addToSubDetectorHitNumbers(hitNumbers[lcio::ILDDetID::SET]); + track->addToSubDetectorHitNumbers(hitNumbers[lcio::ILDDetID::ETD]); + //track->subdetectorHitNumbers().resize(2 * lcio::ILDDetID::ETD); + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::VXD - offset ] = hitNumbers[lcio::ILDDetID::VXD]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::FTD - offset ] = hitNumbers[lcio::ILDDetID::FTD]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::SIT - offset ] = hitNumbers[lcio::ILDDetID::SIT]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::TPC - offset ] = hitNumbers[lcio::ILDDetID::TPC]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::SET - offset ] = hitNumbers[lcio::ILDDetID::SET]; + //track->subdetectorHitNumbers()[ 2 * lcio::ILDDetID::ETD - offset ] = hitNumbers[lcio::ILDDetID::ETD]; + + } + +} diff --git a/Service/TrackSystemSvc/src/TrackSystemSvc.cpp b/Service/TrackSystemSvc/src/TrackSystemSvc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..78bb2779324d89edf505492d67e566667dcf414e --- /dev/null +++ b/Service/TrackSystemSvc/src/TrackSystemSvc.cpp @@ -0,0 +1,72 @@ +#include "GearSvc/IGearSvc.h" +#include "gear/GearMgr.h" + +#include "MarlinKalTest.h" + +#include "TrackSystemSvc.h" + +DECLARE_COMPONENT(TrackSystemSvc) + +TrackSystemSvc::TrackSystemSvc(const std::string& name, ISvcLocator* svc) + : base_class(name, svc), + m_trackSystem(nullptr){ +} + +TrackSystemSvc::~TrackSystemSvc(){ +} + +MarlinTrk::IMarlinTrkSystem* TrackSystemSvc::getTrackSystem(){ + if(!m_trackSystem){ + auto _gear = service<IGearSvc>("GearSvc"); + if ( !_gear ) { + error() << "Failed to find GearSvc ..." << endmsg; + return 0; + } + gear::GearMgr* mgr = _gear->getGearMgr(); + + auto _geoSvc = service<IGeoSvc>("GeoSvc"); + if ( !_geoSvc ) { + error() << "Failed to find GeoSvc ..." << endmsg; + return 0; + } + m_trackSystem = new MarlinTrk::MarlinKalTest( *mgr, _geoSvc ) ; + } + return m_trackSystem; +} + +StatusCode TrackSystemSvc::initialize(){ + + auto _gear = service<IGearSvc>("GearSvc"); + if ( !_gear ) { + error() << "Failed to find GearSvc ..." << endmsg; + return StatusCode::FAILURE; + } + gear::GearMgr* mgr = _gear->getGearMgr(); + + auto _geoSvc = service<IGeoSvc>("GeoSvc"); + if ( !_geoSvc ) { + error() << "Failed to find GeoSvc ..." << endmsg; + return StatusCode::FAILURE; + } + m_trackSystem = new MarlinTrk::MarlinKalTest( *mgr, _geoSvc ) ; + + return StatusCode::SUCCESS; +} + +void TrackSystemSvc::removeTrackSystem(){ + if ( m_trackSystem ) { + delete m_trackSystem; + m_trackSystem = nullptr; + } + return; +} + +StatusCode TrackSystemSvc::finalize(){ + + // if ( m_trackSystem ) { + // delete m_trackSystem; + // m_trackSystem = nullptr; + // } + + return StatusCode::SUCCESS; +} diff --git a/Service/TrackSystemSvc/src/TrackSystemSvc.h b/Service/TrackSystemSvc/src/TrackSystemSvc.h new file mode 100644 index 0000000000000000000000000000000000000000..45830a4f966682582a380093f22b4fd24a6d0854 --- /dev/null +++ b/Service/TrackSystemSvc/src/TrackSystemSvc.h @@ -0,0 +1,22 @@ +#ifndef TrackSystemSvc_h +#define TrackSystemSvc_h + +#include "TrackSystemSvc/ITrackSystemSvc.h" +#include <GaudiKernel/Service.h> + +class TrackSystemSvc : public extends<Service, ITrackSystemSvc>{ + public: + TrackSystemSvc(const std::string& name, ISvcLocator* svc); + ~TrackSystemSvc(); + + MarlinTrk::IMarlinTrkSystem* getTrackSystem() override; + void removeTrackSystem() override; + + StatusCode initialize() override; + StatusCode finalize() override; + + private: + MarlinTrk::IMarlinTrkSystem* m_trackSystem; +}; + +#endif diff --git a/Utilities/DataHelper/CMakeLists.txt b/Utilities/DataHelper/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7bdae2b719df8dbcd9c327fce6c299cd57196e44 --- /dev/null +++ b/Utilities/DataHelper/CMakeLists.txt @@ -0,0 +1,14 @@ +gaudi_subdir(DataHelper v0r0) + +find_package(EDM4HEP REQUIRED) + +gaudi_depends_on_subdirs() + +set(DataHelperLib_srcs src/*.cc src/*.cpp) + +#gaudi_install_headers(DataHelper) + +gaudi_add_library(DataHelperLib ${DataHelperLib_srcs} + PUBLIC_HEADERS DataHelper + LINK_LIBRARIES EDM4HEP::edm4hep EDM4HEP::edm4hepDict +) diff --git a/Utilities/DataHelper/DataHelper/CaloHitExtended.h b/Utilities/DataHelper/DataHelper/CaloHitExtended.h new file mode 100644 index 0000000000000000000000000000000000000000..07b717ad82de038260b4d93603aaa7f441af7a6f --- /dev/null +++ b/Utilities/DataHelper/DataHelper/CaloHitExtended.h @@ -0,0 +1,72 @@ +#ifndef CaloHitExtended_H +#define CaloHitExtended_H 1 + +//#include "lcio.h" +//#include "EVENT/LCIO.h" +#include "edm4hep/CalorimeterHit.h" +#include "ClusterExtended.h" + +using namespace edm4hep ; + +class ClusterExtended; + +/** + * Class extending native LCIO class CalorimeterHit. <br> + * Class CaloHitExtended is used in TrackwiseClustering <br> + * and Wolf processors. <br> + * @author A. Raspereza (DESY)<br> + * @version $Id: CaloHitExtended.h,v 1.4 2006-02-22 14:53:27 owendt Exp $<br> + */ +class CaloHitExtended { + + public: + + CaloHitExtended(const edm4hep::CalorimeterHit& calhit, int type); + + ~CaloHitExtended(); + + CalorimeterHit * getCalorimeterHit(); + CaloHitExtended * getCaloHitTo(); + CaloHitExtended * getCaloHitFrom(); + ClusterExtended * getClusterExtended(); + int getIndex(); + int getType(); + const float* getDirVec(); + float getYresTo(); + float getYresFrom(); + float getGenericDistance(); + + //void setCalorimeterHit(CalorimeterHit* calhit); + void setCaloHitTo(CaloHitExtended* calhitto); + void setCaloHitFrom(CaloHitExtended* calohitfrom); + void setClusterExtended(ClusterExtended* cluster); + void setIndex(int index); + void setType(int type); + void setDirVec(float* dirVec); + void setYresTo(float yresto); + void setYresFrom(float yresfrom); + void setGenericDistance(float genericDistance); + void setDistanceToCalo(float distanceToCalo); + float getDistanceToCalo(); + void setDistanceToNearestHit(float distanceToNearest); + float getDistanceToNearestHit(); + + + private: + + edm4hep::CalorimeterHit _calohit; + CaloHitExtended * _calohitTo; + CaloHitExtended * _calohitFrom; + ClusterExtended * _clusterAR; + int _index; + int _type; + float _dirVec[3]; + float _yresTo; + float _yresFrom; + float _genericDistance; + float _caloDistance; + float _distanceToNearestHit; + +}; + +#endif diff --git a/Utilities/DataHelper/DataHelper/ClusterExtended.h b/Utilities/DataHelper/DataHelper/ClusterExtended.h new file mode 100644 index 0000000000000000000000000000000000000000..6b38d88758e37ae25b224301e4bf569abaa785c8 --- /dev/null +++ b/Utilities/DataHelper/DataHelper/ClusterExtended.h @@ -0,0 +1,105 @@ +#ifndef ClusterExtended_H +#define ClusterExtended_H 1 + +//#include "CaloHitExtended.h" +//#include "TrackExtended.h" +#include "edm4hep/Cluster.h" +#include "HelixClass.h" + +using namespace edm4hep; + +class TrackExtended; +typedef std::vector<TrackExtended*> TrackExtendedVec; + +class CaloHitExtended; +typedef std::vector<CaloHitExtended*> CaloHitExtendedVec; + +//class ClusterExtended; +//typedef std::vector<ClusterExtended*> ClusterExtendedVec; + +/** + * Class extending native LCIO class Cluster. <br> + * Class ClusterExtended is used in TrackwiseClustering <br> + * and Wolf processors. <br> + * @author A. Raspereza (DESY)<br> + * @version $Id: ClusterExtended.h,v 1.4 2006-02-22 14:41:41 owendt Exp $<br> + */ + +class ClusterExtended { + + public: + + ClusterExtended(); + ClusterExtended( Cluster * cluster ); + ClusterExtended(CaloHitExtended * calohit); + ClusterExtended(TrackExtended * track); + + ~ClusterExtended(); + + CaloHitExtendedVec & getCaloHitExtendedVec(); + TrackExtendedVec & getTrackExtendedVec(); + const float* getStartingPoint(); + const float* getDirection(); + void setStartingPoint(float* sPoint); + void setDirection(float* direct); + void addCaloHitExtended(CaloHitExtended * calohit); + void addTrackExtended(TrackExtended * track); + void setType( int type ); + int getType(); + + void Clear(); + + void setCluster(Cluster * cluster); + Cluster * getCluster(); + + void setAxis(float * axis); + float * getAxis(); + + void setEccentricity( float eccentricity); + float getEccentricity(); + + void setHelix(HelixClass helix); + HelixClass & getHelix(); + + void setHelixChi2R(float helixChi2); + float getHelixChi2R(); + + void setHelixChi2Z(float helixChi2); + float getHelixChi2Z(); + + void setPosition(float * position); + float * getPosition(); + + void setLowEdge(float * lowEdge); + float * getLowEdge(); + void setUpEdge(float * upEdge); + float * getUpEdge(); + + + private: + + TrackExtendedVec _trackVector; + CaloHitExtendedVec _hitVector; + float _startingPoint[3]; + float _direction[3]; + + int _type; + Cluster * _cluster; + + float _axis[3]; + float _position[3]; + float _eccentricity; + + HelixClass _helix; + float _helixChi2R; + float _helixChi2Z; + + float _lowEdge[3]; + float _upEdge[3]; + + +}; + +typedef std::vector<ClusterExtended*> ClusterExtendedVec; + +#endif diff --git a/Utilities/DataHelper/DataHelper/GroupTracks.h b/Utilities/DataHelper/DataHelper/GroupTracks.h new file mode 100644 index 0000000000000000000000000000000000000000..6ae27f1ccc5259b70da9c958d36d51a5791ca549 --- /dev/null +++ b/Utilities/DataHelper/DataHelper/GroupTracks.h @@ -0,0 +1,46 @@ +#ifndef GROUPTRACKS_H +#define GROUPTRACKS_H 1 + +//#include "TrackExtended.h" +//#include "ClusterExtended.h" +#include <vector> + +//fg : forwar declaration needed because of circular include .... +class TrackExtended; +typedef std::vector<TrackExtended*> TrackExtendedVec; +//fg : forward .... + +/** + * Class GroupTracks is needed to group track segments <br> + * with close helix parameters. Needed for Tracking. <br> + * * @author A. Raspereza (DESY)<br> + * @version $Id: GroupTracks.h,v 1.4 2007-09-05 09:39:49 rasp Exp $<br> + */ +//class GroupTracks; + +//typedef std::vector<GroupTracks*> GroupTracksVec; + +class GroupTracks { + + public: + GroupTracks(); + GroupTracks(TrackExtended * track ); + ~GroupTracks(); + + void addTrackExtended( TrackExtended * track ); + void ClearTrackExtendedVec(); + TrackExtendedVec & getTrackExtendedVec(); + void setEdges(float * edges); + float * getEdges(); + + private: + + TrackExtendedVec _trackARVec; + + float _edges[2]; + +}; + +typedef std::vector<GroupTracks*> GroupTracksVec; + +#endif diff --git a/Utilities/DataHelper/DataHelper/HelixClass.h b/Utilities/DataHelper/DataHelper/HelixClass.h new file mode 100644 index 0000000000000000000000000000000000000000..794f8158652a637180cb99de38e35a249c2142d9 --- /dev/null +++ b/Utilities/DataHelper/DataHelper/HelixClass.h @@ -0,0 +1,302 @@ +#ifndef HELIXAR_H +#define HELIXAR_H 1 +#include <vector> +/** + * Utility class to manipulate with different parameterisations <br> + * of helix. Helix can be initialized in a three different <br> + * ways using the following public methods : <br> + * 1) Initialize_VP(float * pos, float * mom, float q, float B) : <br> + * initialization of helix is done using <br> + * - position of the reference point : pos[3]; <br> + * - momentum vector at the reference point : mom[3];<br> + * - particle charge : q;<br> + * - magnetic field (in Tesla) : B;<br> + * 2) Initialize_BZ(float xCentre, float yCentre, float radius, <br> + * float bZ, float phi0, float B, float signPz,<br> + * float zBegin):<br> + * initialization of helix is done according to the following<br> + * parameterization<br> + * x = xCentre + radius*cos(bZ*z + phi0)<br> + * y = yCentre + radius*sin(bZ*z + phi0)<br> + * where (x,y,z) - position of point on the helix<br> + * - (xCentre,yCentre) is the centre of circumference in R-Phi plane<br> + * - radius is the radius of circumference<br> + * - bZ is the helix slope parameter<br> + * - phi0 is the initial phase of circumference<br> + * - B is the magnetic field (in Tesla)<br> + * - signPz is the sign of the z component of momentum vector<br> + * - zBegin is the z coordinate of the reference point;<br> + * 3) void Initialize_Canonical(float phi0, float d0, float z0, float omega,<br> + * float tanlambda, float B) :<br> + * canonical (LEP-wise) parameterisation with the following parameters<br> + * - phi0 - Phi angle of momentum vector at the point of<br> + * closest approach to IP in R-Phi plane; + * - d0 - signed distance of closest approach to IP in R-Phi plane;<br> + * - z0 - z coordinate of the point of closest approach in R-Phi plane;<br> + * - omega - signed curvature;<br> + * - tanlambda - tangent of dip angle;<br> + * - B - magnetic field (in Tesla);<br> + * A set of public methods (getters) provide access to <br> + * various parameters associated with helix. Helix Class contains<br> + * also several utility methods, allowing for calculation of helix<br> + * intersection points with planes parallel and perpendicular to <br> + * z (beam) axis and determination of the distance of closest approach<br> + * from arbitrary 3D point to the helix. <br> + * @author A. Raspereza (DESY)<br> + * @version $Id: HelixClass.h,v 1.16 2008-06-05 13:47:18 rasp Exp $<br> + * + */ + +#include "LineClass.h" +class HelixClass; + +class HelixClass { + public: + +/** + * Constructor. Initializations of constants which are used + * to calculate various parameters associated with helix. + */ + HelixClass(); +/** + * Destructor. + */ + ~HelixClass(); +/** + * Initialization of helix using <br> + * - position of the reference point : pos[3]; <br> + * - momentum vector at the reference point : mom[3];<br> + * - particle charge : q;<br> + * - magnetic field (in Tesla) : B<br> + */ + void Initialize_VP(float * pos, float * mom, float q, float B); + +/** + * Initialization of helix according to the following<br> + * parameterization<br> + * x = xCentre + radius*cos(bZ*z + phi0)<br> + * y = yCentre + radius*sin(bZ*z + phi0)<br> + * where (x,y,z) - position of point on the helix<br> + * - (xCentre,yCentre) is the centre of circumference in R-Phi plane<br> + * - radius is the radius of circumference<br> + * - bZ is the helix slope parameter<br> + * - phi0 is the initial phase of circumference<br> + * - B is the magnetic field (in Tesla)<br> + * - signPz is the sign of the z component of momentum vector<br> + * - zBegin is the z coordinate of the reference point<br> + */ + void Initialize_BZ(float xCentre, float yCentre, float radius, + float bZ, float phi0, float B, float signPz, + float zBegin); +/** + * Canonical (LEP-wise) parameterisation with the following parameters<br> + * - phi0 - Phi angle of momentum vector at the point of<br> + * closest approach to IP in R-Phi plane; + * - d0 - signed distance of closest approach in R-Phi plane;<br> + * - z0 - z coordinate of the point of closest approach to IP + * in R-Phi plane;<br> + * - omega - signed curvature;<br> + * - tanlambda - tangent of dip angle;<br> + * - B - magnetic field (in Tesla)<br> + */ + void Initialize_Canonical(float phi0, float d0, float z0, float omega, + float tanlambda, float B); + /** + * Returns momentum of particle at the point of closest approach <br> + * to IP <br> + */ + const float * getMomentum(); + + /** + * Returns reference point of track <br> + */ + const float * getReferencePoint(); + + /** + * Returns Phi angle of the momentum vector <br> + * at the point of closest approach to IP <br> + */ + float getPhi0(); + + /** + * Returns signed distance of closest approach <br> + * to IP in the R-Phi plane <br> + */ + float getD0(); + + /** + * Returns z coordinate of the point of closest + * approach to IP in the R-Phi plane <br> + */ + float getZ0(); + + /** + * Returns signed curvature of the track <br> + */ + float getOmega(); + + /** + * Returns tangent of dip angle of the track <br> + */ + float getTanLambda(); + + /** + * Returns transverse momentum of the track <br> + */ + float getPXY(); + + + /** + * Returns x coordinate of circumference + */ + float getXC(); + + /** + * Returns y coordinate of circumference + */ + float getYC(); + + + /** + * Returns radius of circumference + */ + float getRadius(); + + + /** + * Returns helix intersection point with the plane <br> + * parallel to z axis. Plane is defined by two coordinates <br> + * of the point belonging to the plane (x0,y0) and normal <br> + * vector (ax,ay). ref[3] is the reference point of the helix. <br> + * point[3] - returned vector holding the coordinates of <br> + * intersection point <br> + */ + float getPointInXY(float x0, float y0, float ax, float ay, + float * ref , float * point); + + /** + * Returns helix intersection point with the plane <br> + * perpendicular to z axis. Plane is defined by z coordinate <br> + * of the plane. ref[3] is the reference point of the helix. <br> + * point[3] - returned vector holding the coordinates of <br> + * intersection point <br> + */ + float getPointInZ(float zLine, float * ref, float * point); + + /** + * Return distance of the closest approach of the helix to <br> + * arbitrary 3D point in space. xPoint[3] - coordinates of <br> + * space point. Distance[3] - vector of distances of helix to <br> + * a given point in various projections : <br> + * Distance[0] - distance in R-Phi plane <br> + * Distance[1] - distance along Z axis <br> + * Distance[2] - 3D distance <br> + */ + float getDistanceToPoint(float * xPoint, float * Distance); + + /** + * Return distance of the closest approach of the helix to <br> + * arbitrary 3D point in space. xPoint[3] - coordinates of <br> + * space point. distCut - limit on the distance between helix <br> + * and the point to reduce calculation time <br> + * If R-Phi is found to be greater than distCut, rPhi distance is returned <br> + * If the R-Phi distance is not too big, than the exact 3D distance is returned <br> + * This function can be used, if the exact distance is not always needed <br> + */ + float getDistanceToPoint(const float* xPoint, float distCut); + float getDistanceToPoint(const std::vector<float>& xPoint, float distCut); + + /** + * This method calculates coordinates of both intersection <br> + * of the helix with a cylinder. <br> + * Rotational symmetry with respect to z axis is assumed, <br> + * meaning that cylinder axis corresponds to the z axis <br> + * of reference frame. <br> + * Inputs : <br> + * Radius - radius of cylinder. <br> + * ref[3] - point of closest approach to the origin of the helix. <br> + * Output : <br> + * point[6] - coordinates of intersection point. <br> + * Method returns also generic time, defined as the <br> + * ratio of helix length from reference point to the intersection <br> + * point to the particle momentum <br> + */ + float getPointOnCircle(float Radius, float * ref, float * point); + + /** Returns distance between two helixes <br> + * Output : <br> + * pos[3] - position of the point of closest approach <br> + * mom[3] - momentum of V0 <br> + */ + float getDistanceToHelix(HelixClass * helix, float * pos, float * mom); + + /** + * Set Edges of helix + */ + void setHelixEdges(float * xStart, float * xEnd); + + /** + * Returns starting point of helix + */ + float * getStartingPoint() {return _xStart;} + + /** + * Returns endpoint of helix + */ + float * getEndPoint() {return _xEnd;} + + /** + * Returns BZ for the second parameterization + */ + float getBz(); + + /** + * Returns Phi for the second parameterization + */ + float getPhiZ(); + + /** + * Returns extrapolated momentum + */ + void getExtrapolatedMomentum(float * pos, float * momentum); + + /** + * Returns charge + */ + float getCharge(); + + private: + float _momentum[3]; // momentum @ ref point + float _referencePoint[3]; // coordinates @ ref point + float _phi0; // phi0 in canonical parameterization + float _d0; // d0 in canonical parameterisation + float _z0; // z0 in canonical parameterisation + float _omega; // signed curvuture in canonical parameterisation + float _tanLambda; // TanLambda + float _pxy; // Transverse momentum + float _charge; // Particle Charge + float _bField; // Magnetic field (assumed to point to Z>0) + float _radius; // radius of circle in XY plane + float _xCentre; // X of circle centre + float _yCentre; // Y of circle centre + float _phiRefPoint; // Phi w.r.t. (X0,Y0) of circle @ ref point + float _phiAtPCA; // Phi w.r.t. (X0,Y0) of circle @ PCA + float _xAtPCA; // X @ PCA + float _yAtPCA; // Y @ PCA + float _pxAtPCA; // PX @ PCA + float _pyAtPCA; // PY @ PCA + float _phiMomRefPoint; // Phi of Momentum vector @ ref point + float _const_pi; // PI + float _const_2pi; // 2*PI + float _const_pi2; // PI/2 + float _FCT; // 2.99792458E-4 + float _xStart[3]; // Starting point of track segment + float _xEnd[3]; // Ending point of track segment + + float _bZ; + float _phiZ; + +}; + + +#endif diff --git a/Utilities/DataHelper/DataHelper/LineClass.h b/Utilities/DataHelper/DataHelper/LineClass.h new file mode 100644 index 0000000000000000000000000000000000000000..98970a263225b5a53ccfded69f33c92ae517d182 --- /dev/null +++ b/Utilities/DataHelper/DataHelper/LineClass.h @@ -0,0 +1,32 @@ +#ifndef LINECLASS_H +#define LINECLASS_H +class LineClass { + + public: + LineClass(float x0, + float y0, + float z0, + float ax, + float ay, + float az); + + LineClass(float *x0, + float *ax); + + ~LineClass(); + + float * getReferencePoint(); + void setReferencePoint(float *x0); + float * getDirectionalVector(); + void setDirectionalVector(float *ax); + float getDistanceToPoint(float * xpoint, float * pos); + + private: + + float _x0[3]; + float _ax[3]; + + +}; + +#endif diff --git a/Utilities/DataHelper/DataHelper/Navigation.h b/Utilities/DataHelper/DataHelper/Navigation.h new file mode 100644 index 0000000000000000000000000000000000000000..238dd30ee280ae938208d4565c0e5231ab7cccff --- /dev/null +++ b/Utilities/DataHelper/DataHelper/Navigation.h @@ -0,0 +1,34 @@ +#ifndef Navigation_h +#define Navigation_h + +//#include "FWCore/DataHandle.h" +//#include "podio/CollectionBase.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include <map> + +class Navigation{ + public: + static Navigation* Instance(); + + Navigation(); + ~Navigation(); + + void Initialize(); + //void AddDataHandle(DataHandle* hdl){if(hdl)m_hdlVec.push_back(hdl);}; + void AddTrackerHitCollection(const edm4hep::TrackerHitCollection* col){m_hitColVec.push_back(col);}; + void AddTrackerAssociationCollection(const edm4hep::MCRecoTrackerAssociationCollection* col){m_assColVec.push_back(col);}; + + edm4hep::TrackerHit* GetTrackerHit(const edm4hep::ObjectID& id, bool delete_by_caller=true); + std::vector<edm4hep::ConstSimTrackerHit> GetRelatedTrackerHit(const edm4hep::ObjectID& id); + std::vector<edm4hep::ConstSimTrackerHit> GetRelatedTrackerHit(const edm4hep::TrackerHit& hit); + + //static Navigation* m_fNavigation; + private: + static Navigation* m_fNavigation; + //DataHandle<edm4hep::MCRecoTrackerAssociationCollection> _inHitAssColHdl{"FTDStripTrackerHitsAssociation", Gaudi::DataHandle::Reader, this}; + std::vector<const edm4hep::TrackerHitCollection*> m_hitColVec; + std::vector<const edm4hep::MCRecoTrackerAssociationCollection*> m_assColVec; + std::map<int, edm4hep::TrackerHit*> m_trkHits; +}; +#endif diff --git a/Utilities/DataHelper/DataHelper/TrackExtended.h b/Utilities/DataHelper/DataHelper/TrackExtended.h new file mode 100644 index 0000000000000000000000000000000000000000..61ff59234a70b999a8e5c02208efab5062fbfd06 --- /dev/null +++ b/Utilities/DataHelper/DataHelper/TrackExtended.h @@ -0,0 +1,130 @@ +#ifndef TRACKAR_H +#define TRACKAR_H 1 + +//#include "lcio.h" +//#include "EVENT/LCIO.h" +#include "edm4hep/Track.h" +#include <vector> +//#include "ClusterExtended.h" +//#include "TrackerHitExtended.h" +#include "GroupTracks.h" + +//using namespace edm4hep; + +class ClusterExtended; +//class GroupTracks; +class TrackerHitExtended; +typedef std::vector<TrackerHitExtended*> TrackerHitExtendedVec; +typedef std::vector<ClusterExtended*> ClusterExtendedVec; + +/** + * Class extending native LCIO class Track. <br> + * Class TrackExtended is used in TrackwiseClustering <br> + * and Wolf processors. <br> + * @author A. Raspereza (DESY)<br> + * @version $Id: TrackExtended.h,v 1.8 2007-09-05 09:39:49 rasp Exp $<br> + */ + +class TrackExtended { + + public: + + + TrackExtended( ); + TrackExtended( TrackerHitExtended * trackerhit ); + TrackExtended( edm4hep::Track * track ); + ~TrackExtended(); + + edm4hep::Track * getTrack(); + const float * getSeedDirection(); + const float * getSeedPosition(); + ClusterExtendedVec & getClusterVec(); + ClusterExtended * getSuperCluster(); + TrackerHitExtendedVec & getTrackerHitExtendedVec(); + void addCluster(ClusterExtended * cluster); + void setSuperCluster(ClusterExtended * superCluster); + void setSeedDirection( float * seedDirection ); + void setSeedPosition( float * seedPosition); + void addTrackerHitExtended( TrackerHitExtended * trackerhit); + void ClearTrackerHitExtendedVec(); + + void setX0(float x0); + void setY0(float y0); + void setR0(float r0); + void setD0(float d0); + void setZ0(float z0); + void setBz(float bz); + void setPhi0(float phi0); + void setPhi(float phi); + void setOmega(float omega); + void setTanLambda(float tanLambda); + + + void setStart(float * xStart); + void setEnd(float * xEnd); + + + float getX0(); + float getY0(); + float getD0(); + float getZ0(); + float getOmega(); + float getTanLambda(); + float getPhi(); + float getR0(); + float getBz(); + float getPhi0(); + + float * getStart(); + float * getEnd(); + + void setGroupTracks( GroupTracks * group ); + GroupTracks * getGroupTracks(); + + float getChi2(); + void setChi2(float chi2); + + int getNDF(); + void setNDF(int ndf); + + float * getCovMatrix(); + void setCovMatrix( float * cov); + + private: + + ClusterExtended *_superCluster; + ClusterExtendedVec _clusterVec; + GroupTracks * _group; + edm4hep::Track * _track; + float _seedDirection[3]; + float _seedPosition[3]; + TrackerHitExtendedVec _trackerHitVector; + + float _x0; + float _y0; + float _r0; + float _bz; + float _phi0; + + float _xStart[3]; + float _xEnd[3]; + + float _d0; // d0 in canonical parameterisation + float _z0; // z0 in canonical parameterisation + float _omega; // omega in canonical parameterisation + float _tanLambda; // tanlambda in canonical parameterisation + float _phi; // phi in canonical parameterisation + + float _chi2; // chi2 of the fit + + float _cov[15]; // covariance matrix + + int _ndf; // NDF + + int _type; // Track type; + +}; + +typedef std::vector<TrackExtended*> TrackExtendedVec; + +#endif diff --git a/Utilities/DataHelper/DataHelper/TrackerHitExtended.h b/Utilities/DataHelper/DataHelper/TrackerHitExtended.h new file mode 100644 index 0000000000000000000000000000000000000000..d625679e387fb6d1627a72421ad9b3d315c93471 --- /dev/null +++ b/Utilities/DataHelper/DataHelper/TrackerHitExtended.h @@ -0,0 +1,84 @@ +#ifndef TRACKERHITAR_H +#define TRACKERHITAR_H 1 + +//#include "lcio.h" +//#include "EVENT/LCIO.h" +#include "edm4hep/TrackerHit.h" +//#include "TrackExtended.h" +#include <vector> + + +//using namespace edm4hep; + +class TrackExtended; +typedef std::vector<TrackExtended*> TrackExtendedVec; + +/** + * Class extending native LCIO class TrackerHit. <br> + * Class TrackerHitExtended is used in TrackwiseClustering <br> + * and Wolf processors. <br> + * @author A. Raspereza (DESY)<br> + * @version $Id: TrackerHitExtended.h,v 1.7 2007-09-05 09:39:49 rasp Exp $<br> + */ +class TrackerHitExtended { + + public: + + TrackerHitExtended(const edm4hep::TrackerHit& trackerhit); + ~TrackerHitExtended(); + void setTrackExtended(TrackExtended * trackAR); + void addTrackExtended(TrackExtended * trackAR); + void setTrackerHitTo(TrackerHitExtended * hitTo); + void setTrackerHitFrom(TrackerHitExtended * hitFrom); + void setGenericDistance(float genericDistance); + //void setTrackerHit(edm4hep::TrackerHit* hit); + void setYresTo(float yresTo); + void setYresFrom(float yresFrom); + void setDirVec(float * dirVec); + void clearTrackVec(); + void setResolutionRPhi(float rphiReso); + void setResolutionZ(float zReso); + void setType(int type); + void setDet(int idet); + void setUsedInFit(bool usedInFit); + + edm4hep::TrackerHit* getTrackerHit(); + TrackExtended * getTrackExtended(); + TrackExtendedVec & getTrackExtendedVec(); + TrackerHitExtended * getTrackerHitFrom(); + TrackerHitExtended * getTrackerHitTo(); + float getGenericDistance(); + float getYresTo(); + float getYresFrom(); + float * getDirVec(); + float getResolutionRPhi(); + float getResolutionZ(); + int getType(); + int getDet(); + bool getUsedInFit(); + + private: + + edm4hep::TrackerHit _trackerHit; + TrackExtended * _trackAR; + TrackerHitExtended * _hitTo; + TrackerHitExtended * _hitFrom; + TrackExtendedVec _trackVecAR; + + float _rphiReso; + float _zReso; + float _yresTo; + float _yresFrom; + float _genericDistance; + float _dirVec[3]; + + int _type; + int _idet; + + bool _usedInFit; + +}; + +typedef std::vector<TrackerHitExtended*> TrackerHitExtendedVec; + +#endif diff --git a/Utilities/DataHelper/src/CaloHitExtended.cc b/Utilities/DataHelper/src/CaloHitExtended.cc new file mode 100644 index 0000000000000000000000000000000000000000..8c608d975201e35181032c23569306a512d3383a --- /dev/null +++ b/Utilities/DataHelper/src/CaloHitExtended.cc @@ -0,0 +1,128 @@ +#include "DataHelper/CaloHitExtended.h" +#include <math.h> + +CaloHitExtended::CaloHitExtended(const edm4hep::CalorimeterHit& calhit, int type) + :_calohit(calhit){ + _type = type; + _index = 0; + _calohitTo = NULL; + _calohitFrom = NULL; +} + +CaloHitExtended::~CaloHitExtended(){ +} + +CalorimeterHit* CaloHitExtended::getCalorimeterHit() { + return &_calohit; +} + +CaloHitExtended* CaloHitExtended::getCaloHitTo() { + return _calohitTo; +} + +CaloHitExtended* CaloHitExtended::getCaloHitFrom() { + return _calohitFrom; +} + +ClusterExtended* CaloHitExtended::getClusterExtended() { + return _clusterAR; +} + +int CaloHitExtended::getIndex() { + return _index; + +} + +int CaloHitExtended::getType() { + return _type; + +} +const float* CaloHitExtended::getDirVec() { + return _dirVec; +} + +float CaloHitExtended::getYresTo() { + return _yresTo; +} + +float CaloHitExtended::getYresFrom() { + return _yresFrom; +} + + + +float CaloHitExtended::getGenericDistance() { + return _genericDistance; +} + +//void CaloHitExtended::setCalorimeterHit(CalorimeterHit* calhit) { +// _calohit = calhit; +//} + +void CaloHitExtended::setCaloHitTo(CaloHitExtended* calhitto) { + _calohitTo = calhitto; +} + +void CaloHitExtended::setCaloHitFrom(CaloHitExtended* calhitfrom) { + _calohitFrom = calhitfrom; +} + +void CaloHitExtended::setClusterExtended(ClusterExtended* cluster) { + _clusterAR = cluster; +} + +void CaloHitExtended::setIndex(int index) { + _index = index; +} + +void CaloHitExtended::setType(int type) { + _type = type; +} + +void CaloHitExtended::setDirVec(float* dirVec) { + float modulus(0.); + for (int i(0); i < 3; ++i) { + modulus += dirVec[i]*dirVec[i]; + } + + modulus = sqrt(modulus); + + if (modulus <= 0.) { + _dirVec[0] = 0.; + _dirVec[1] = 0.; + _dirVec[2] = 1.; + } + else { + _dirVec[0] = dirVec[0] / modulus; + _dirVec[1] = dirVec[1] / modulus; + _dirVec[2] = dirVec[2] / modulus; + } +} + +void CaloHitExtended::setYresTo(float yresto) { + _yresTo = yresto; +} + +void CaloHitExtended::setYresFrom(float yresfrom) { + _yresFrom = yresfrom; +} + +void CaloHitExtended::setGenericDistance(float genericDistance) { + _genericDistance = genericDistance; +} + +void CaloHitExtended::setDistanceToCalo(float caloDistance) { + _caloDistance = caloDistance; +} + +float CaloHitExtended::getDistanceToCalo() { + return _caloDistance; +} + +void CaloHitExtended::setDistanceToNearestHit(float distanceToNearest) { + _distanceToNearestHit = distanceToNearest; +} + +float CaloHitExtended::getDistanceToNearestHit() { + return _distanceToNearestHit; +} diff --git a/Utilities/DataHelper/src/ClusterExtended.cc b/Utilities/DataHelper/src/ClusterExtended.cc new file mode 100644 index 0000000000000000000000000000000000000000..beee779df6f6cad32ba9844ff3ba106bb4d08320 --- /dev/null +++ b/Utilities/DataHelper/src/ClusterExtended.cc @@ -0,0 +1,232 @@ +#include "DataHelper/CaloHitExtended.h" +#include "DataHelper/TrackExtended.h" +#include "DataHelper/ClusterExtended.h" +#include <math.h> + +ClusterExtended::ClusterExtended() { + _hitVector.clear(); + _trackVector.clear(); + + _direction[0] = 0.; + _direction[1] = 0.; + _direction[2] = 0.; + + _startingPoint[0] = 0.; + _startingPoint[1] = 0.; + _startingPoint[2] = 0.; + +} + +ClusterExtended::ClusterExtended( Cluster * cluster ) { + _hitVector.clear(); + _trackVector.clear(); + + _direction[0] = 0.; + _direction[1] = 0.; + _direction[2] = 0.; + + _startingPoint[0] = 0.; + _startingPoint[1] = 0.; + _startingPoint[2] = 0.; + + _cluster = cluster; + +} + + + + +ClusterExtended::ClusterExtended(CaloHitExtended * calohit) { + + _hitVector.clear(); + _hitVector.push_back(calohit); + _trackVector.clear(); + + float rad(0); + + _startingPoint[0] = calohit->getCalorimeterHit()->getPosition().x; + _startingPoint[1] = calohit->getCalorimeterHit()->getPosition().y; + _startingPoint[2] = calohit->getCalorimeterHit()->getPosition().z; + + for (int i(0); i < 3; ++i) { + rad += _startingPoint[i]*_startingPoint[i]; + } + + rad = sqrt(rad); + + _direction[0] = _startingPoint[0]/rad; + _direction[1] = _startingPoint[1]/rad; + _direction[2] = _startingPoint[2]/rad; + +} + +ClusterExtended::ClusterExtended(TrackExtended * track) { + _hitVector.clear(); + _trackVector.clear(); + _trackVector.push_back(track); + for (int i(0); i < 3; ++i) { + _startingPoint[i] = track->getSeedPosition()[i]; + _direction[i] = track->getSeedDirection()[i]; + } +} + + +ClusterExtended::~ClusterExtended() { + _hitVector.clear(); + _trackVector.clear(); +} + +CaloHitExtendedVec& ClusterExtended::getCaloHitExtendedVec() { + return _hitVector; +} + +TrackExtendedVec& ClusterExtended::getTrackExtendedVec() { + return _trackVector; +} + +const float* ClusterExtended::getStartingPoint() { + return _startingPoint; +} + +const float* ClusterExtended::getDirection() { + return _direction; +} + +void ClusterExtended::setStartingPoint(float* sPoint) { + _startingPoint[0] = sPoint[0]; + _startingPoint[1] = sPoint[1]; + _startingPoint[2] = sPoint[2]; + +} + +void ClusterExtended::setDirection(float* direct) { + _direction[0] = direct[0]; + _direction[1] = direct[1]; + _direction[2] = direct[2]; +} + +void ClusterExtended::addCaloHitExtended(CaloHitExtended* calohit) { + _hitVector.push_back(calohit); +} + +void ClusterExtended::addTrackExtended(TrackExtended * track) { + _trackVector.push_back(track); +} + +void ClusterExtended::Clear() { + _hitVector.clear(); + _trackVector.clear(); + +} + +void ClusterExtended::setType( int type ) { + _type = type; +} + +int ClusterExtended::getType() { + return _type; +} + +void ClusterExtended::setCluster(Cluster * cluster) { + _cluster = cluster; +} + +Cluster * ClusterExtended::getCluster() { + return _cluster; +} + +void ClusterExtended::setAxis(float * axis) { + _axis[0] = axis[0]; + _axis[1] = axis[1]; + _axis[2] = axis[2]; +} +float * ClusterExtended::getAxis() { + return _axis; +} + +void ClusterExtended::setEccentricity( float eccentricity) { + _eccentricity = eccentricity; +} +float ClusterExtended::getEccentricity() { + return _eccentricity; +} + +void ClusterExtended::setHelix(HelixClass helix) { + _helix = helix; + int nHits = int(_hitVector.size()); + float timeMax = -1.0e+20; + float timeMin = 1.0e+20; + for (int ihit=0;ihit<nHits;++ihit) { + float pos[3]; + for (int i=0;i<3;++i) + pos[i]=_hitVector[ihit]->getCalorimeterHit()->getPosition()[i]; + + float distance[3]; + float time = _helix.getDistanceToPoint(pos,distance); + if (time > timeMax) { + timeMax = time; + _upEdge[0] = pos[0]; + _upEdge[1] = pos[1]; + _upEdge[2] = pos[2]; + } + if (time < timeMin) { + timeMin = time; + _lowEdge[0] = pos[0]; + _lowEdge[1] = pos[1]; + _lowEdge[2] = pos[2]; + } + + } + +} +HelixClass & ClusterExtended::getHelix() { + return _helix; +} + +void ClusterExtended::setHelixChi2R(float helixChi2) { + _helixChi2R = helixChi2; +} +float ClusterExtended::getHelixChi2R() { + return _helixChi2R; +} + +void ClusterExtended::setHelixChi2Z(float helixChi2) { + _helixChi2Z = helixChi2; +} +float ClusterExtended::getHelixChi2Z() { + return _helixChi2Z; +} + + + +void ClusterExtended::setPosition(float * position) { + _position[0] = position[0]; + _position[1] = position[1]; + _position[2] = position[2]; + +} + +float * ClusterExtended::getPosition() { + return _position; +} + +void ClusterExtended::setUpEdge(float * upEdge) { + _upEdge[0] = upEdge[0]; + _upEdge[1] = upEdge[1]; + _upEdge[2] = upEdge[2]; +} + +void ClusterExtended::setLowEdge(float * lowEdge) { + _lowEdge[0] = lowEdge[0]; + _lowEdge[1] = lowEdge[1]; + _lowEdge[2] = lowEdge[2]; +} + +float * ClusterExtended::getUpEdge() { + return _upEdge; +} + +float * ClusterExtended::getLowEdge() { + return _lowEdge; +} + diff --git a/Utilities/DataHelper/src/GroupTracks.cc b/Utilities/DataHelper/src/GroupTracks.cc new file mode 100644 index 0000000000000000000000000000000000000000..593fe02cb116496cc3bdf2b992c47902aa52eb92 --- /dev/null +++ b/Utilities/DataHelper/src/GroupTracks.cc @@ -0,0 +1,40 @@ +#include "DataHelper/TrackExtended.h" +#include "DataHelper/GroupTracks.h" + +GroupTracks::GroupTracks() { + _trackARVec.clear(); + _edges[0] = 0.0; + _edges[1] = 0.0; +} + +GroupTracks::GroupTracks( TrackExtended * track ) { + _trackARVec.clear(); + _trackARVec.push_back( track ); + _edges[0] = 0.0; + _edges[1] = 0.0; +} + +GroupTracks::~GroupTracks() {} + +void GroupTracks::addTrackExtended( TrackExtended * track ) { + _trackARVec.push_back( track ); +} + +void GroupTracks::ClearTrackExtendedVec() { + _trackARVec.clear(); +} + +TrackExtendedVec & GroupTracks::getTrackExtendedVec() { + return _trackARVec; +} + +void GroupTracks::setEdges(float * edges) { + + _edges[0] = edges[0]; + _edges[1] = edges[1]; + +} + +float * GroupTracks::getEdges() { + return _edges; +} diff --git a/Utilities/DataHelper/src/HelixClass.cc b/Utilities/DataHelper/src/HelixClass.cc new file mode 100644 index 0000000000000000000000000000000000000000..591acc5148ce71b84eb79421cd5c841f423a5f2f --- /dev/null +++ b/Utilities/DataHelper/src/HelixClass.cc @@ -0,0 +1,768 @@ +#include "DataHelper/HelixClass.h" +#include <math.h> +#include <stdlib.h> +#include <iostream> +//#include "ced_cli.h" + +HelixClass::HelixClass() { + _const_2pi = 2.0*M_PI; + _const_pi2 = 0.5*M_PI; + _FCT = 2.99792458E-4; +} + +HelixClass::~HelixClass() {} + +void HelixClass::Initialize_VP(float * pos, float * mom, float q, float B) { + _referencePoint[0] = pos[0]; + _referencePoint[1] = pos[1]; + _referencePoint[2] = pos[2]; + _momentum[0] = mom[0]; + _momentum[1] = mom[1]; + _momentum[2] = mom[2]; + _charge = q; + _bField = B; + _pxy = sqrt(mom[0]*mom[0]+mom[1]*mom[1]); + _radius = _pxy / (_FCT*B); + _omega = q/_radius; + _tanLambda = mom[2]/_pxy; + _phiMomRefPoint = atan2(mom[1],mom[0]); + _xCentre = pos[0] + _radius*cos(_phiMomRefPoint-_const_pi2*q); + _yCentre = pos[1] + _radius*sin(_phiMomRefPoint-_const_pi2*q); + _phiRefPoint = atan2(pos[1]-_yCentre,pos[0]-_xCentre); + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phi0 = -_const_pi2*q + _phiAtPCA; + while (_phi0<0) _phi0+=_const_2pi; + while (_phi0>=_const_2pi) _phi0-=_const_2pi; + _xAtPCA = _xCentre + _radius*cos(_phiAtPCA); + _yAtPCA = _yCentre + _radius*sin(_phiAtPCA); + // _d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0); + double pxy = double(_pxy); + double radius = pxy/double(_FCT*B); + double xCentre = double(pos[0]) + radius*double(cos(_phiMomRefPoint-_const_pi2*q)); + double yCentre = double(pos[1]) + radius*double(sin(_phiMomRefPoint-_const_pi2*q)); + + double d0; + + if (q>0) { + d0 = double(q)*radius - double(sqrt(xCentre*xCentre+yCentre*yCentre)); + } + else { + d0 = double(q)*radius + double(sqrt(xCentre*xCentre+yCentre*yCentre)); + } + + _d0 = float(d0); + +// if (fabs(_d0)>0.001 ) { +// std::cout << "New helix : " << std::endl; +// std::cout << " Position : " << pos[0] +// << " " << pos[1] +// << " " << pos[2] << std::endl; +// std::cout << " Radius = " << _radius << std::endl; +// std::cout << " RC = " << sqrt(_xCentre*_xCentre+_yCentre*_yCentre) << std::endl; +// std::cout << " D0 = " << _d0 << std::endl; +// } + + _pxAtPCA = _pxy*cos(_phi0); + _pyAtPCA = _pxy*sin(_phi0); + float deltaPhi = _phiRefPoint - _phiAtPCA; + float xCircles = -pos[2]*q/(_radius*_tanLambda) - deltaPhi; + xCircles = xCircles/_const_2pi; + int nCircles; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + _z0 = pos[2] + _radius*_tanLambda*q*(deltaPhi + _const_2pi*nCircles); + +} + +void HelixClass::Initialize_Canonical(float phi0, float d0, float z0, + float omega, float tanLambda, float B) { + _omega = omega; + _d0 = d0; + _phi0 = phi0; + _z0 = z0; + _tanLambda = tanLambda; + _charge = omega/fabs(omega); + _radius = 1./fabs(omega); + _xAtPCA = -_d0*sin(_phi0); + _yAtPCA = _d0*cos(_phi0); + _referencePoint[0] = _xAtPCA; + _referencePoint[1] = _yAtPCA; + _referencePoint[2] = _z0; + _pxy = _FCT*B*_radius; + _momentum[0] = _pxy*cos(_phi0); + _momentum[1] = _pxy*sin(_phi0); + _momentum[2] = _tanLambda * _pxy; + _pxAtPCA = _momentum[0]; + _pyAtPCA = _momentum[1]; + _phiMomRefPoint = atan2(_momentum[1],_momentum[0]); + _xCentre = _referencePoint[0] + + _radius*cos(_phi0-_const_pi2*_charge); + _yCentre = _referencePoint[1] + + _radius*sin(_phi0-_const_pi2*_charge); + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phiRefPoint = _phiAtPCA ; + _bField = B; +} + + +void HelixClass::Initialize_BZ(float xCentre, float yCentre, float radius, + float bZ, float phi0, float B, float signPz, + float zBegin) { + + _radius = radius; + _pxy = _FCT*B*_radius; + _charge = -(bZ*signPz)/fabs(bZ*signPz); + _momentum[2] = -_charge*_pxy/(bZ*_radius); + _xCentre = xCentre; + _yCentre = yCentre; + _omega = _charge/radius; + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phi0 = -_const_pi2*_charge + _phiAtPCA; + while (_phi0<0) _phi0+=_const_2pi; + while (_phi0>=_const_2pi) _phi0-=_const_2pi; + _xAtPCA = _xCentre + _radius*cos(_phiAtPCA); + _yAtPCA = _yCentre + _radius*sin(_phiAtPCA); + _d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0); + _pxAtPCA = _pxy*cos(_phi0); + _pyAtPCA = _pxy*sin(_phi0); + _referencePoint[2] = zBegin; + _referencePoint[0] = xCentre + radius*cos(bZ*zBegin+phi0); + _referencePoint[1] = yCentre + radius*sin(bZ*zBegin+phi0); + _phiRefPoint = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + _phiMomRefPoint = -_const_pi2*_charge + _phiRefPoint; + _tanLambda = _momentum[2]/_pxy; + _momentum[0] = _pxy*cos(_phiMomRefPoint); + _momentum[1] = _pxy*sin(_phiMomRefPoint); + + float deltaPhi = _phiRefPoint - _phiAtPCA; + float xCircles = bZ*_referencePoint[2] - deltaPhi; + xCircles = xCircles/_const_2pi; + int nCircles; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + _z0 = _referencePoint[2] - (deltaPhi + _const_2pi*nCircles)/bZ; + _bField = B; + +} + +const float * HelixClass::getMomentum() { + return _momentum; +} +const float * HelixClass::getReferencePoint() { + return _referencePoint; +} +float HelixClass::getPhi0() { + if (_phi0<0.0) + _phi0 += 2*M_PI; + return _phi0; +} +float HelixClass::getD0() { + return _d0; +} +float HelixClass::getZ0() { + return _z0; +} +float HelixClass::getOmega() { + return _omega; +} +float HelixClass::getTanLambda() { + return _tanLambda; +} +float HelixClass::getPXY() { + return _pxy; +} +float HelixClass::getXC() { + return _xCentre; +} + +float HelixClass::getYC() { + return _yCentre; +} + +float HelixClass::getRadius() { + return _radius; +} + +float HelixClass::getBz() { + return _bZ; +} + +float HelixClass::getPhiZ() { + return _phiZ; +} + +float HelixClass::getCharge() { + return _charge; +} + +float HelixClass::getPointInXY(float x0, float y0, float ax, float ay, + float * ref , float * point) { + + float time; + + float AA = sqrt(ax*ax+ay*ay); + + + if (AA <= 0) { + time = -1.0e+20; + return time; + } + + + float BB = ax*(x0-_xCentre) + ay*(y0-_yCentre); + BB = BB / AA; + + float CC = (x0-_xCentre)*(x0-_xCentre) + + (y0-_yCentre)*(y0-_yCentre) - _radius*_radius; + + CC = CC / AA; + + float DET = BB*BB - CC; + float tt1 = 0.; + float tt2 = 0.; + float xx1,xx2,yy1,yy2; + + + if (DET < 0 ) { + time = 1.0e+10; + point[0]=0.0; + point[1]=0.0; + point[2]=0.0; + return time; + } + + + tt1 = - BB + sqrt(DET); + tt2 = - BB - sqrt(DET); + + xx1 = x0 + tt1*ax; + yy1 = y0 + tt1*ay; + xx2 = x0 + tt2*ax; + yy2 = y0 + tt2*ay; + + float phi1 = atan2(yy1-_yCentre,xx1-_xCentre); + float phi2 = atan2(yy2-_yCentre,xx2-_xCentre); + float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre); + + float dphi1 = phi1 - phi0; + float dphi2 = phi2 - phi0; + + if (dphi1 < 0 && _charge < 0) { + dphi1 = dphi1 + _const_2pi; + } + else if (dphi1 > 0 && _charge > 0) { + dphi1 = dphi1 - _const_2pi; + } + + if (dphi2 < 0 && _charge < 0) { + dphi2 = dphi2 + _const_2pi; + } + else if (dphi2 > 0 && _charge > 0) { + dphi2 = dphi2 - _const_2pi; + } + + // Times + tt1 = -_charge*dphi1*_radius/_pxy; + tt2 = -_charge*dphi2*_radius/_pxy; + + if (tt1 < 0. ) + std::cout << "WARNING " << tt1 << std::endl; + if (tt2 < 0. ) + std::cout << "WARNING " << tt2 << std::endl; + + + if (tt1 < tt2) { + point[0] = xx1; + point[1] = yy1; + time = tt1; + } + else { + point[0] = xx2; + point[1] = yy2; + time = tt2; + } + + point[2] = ref[2]+time*_momentum[2]; + + + + return time; + +} + + +float HelixClass::getPointOnCircle(float Radius, float * ref, float * point) { + + float distCenterToIP = sqrt(_xCentre*_xCentre + _yCentre*_yCentre); + + point[0] = 0.0; + point[1] = 0.0; + point[2] = 0.0; + + if ((distCenterToIP+_radius)<Radius) { + float xx = -1.0e+20; + return xx; + } + + if ((_radius+Radius)<distCenterToIP) { + float xx = -1.0e+20; + return xx; + } + + float phiCentre = atan2(_yCentre,_xCentre); + float phiStar = Radius*Radius + distCenterToIP*distCenterToIP + - _radius*_radius; + + phiStar = 0.5*phiStar/fmax(1.0e-20,Radius*distCenterToIP); + + if (phiStar > 1.0) + phiStar = 0.9999999; + + if (phiStar < -1.0) + phiStar = -0.9999999; + + phiStar = acos(phiStar); + + float tt1,tt2,time; + + float xx1 = Radius*cos(phiCentre+phiStar); + float yy1 = Radius*sin(phiCentre+phiStar); + + float xx2 = Radius*cos(phiCentre-phiStar); + float yy2 = Radius*sin(phiCentre-phiStar); + + + float phi1 = atan2(yy1-_yCentre,xx1-_xCentre); + float phi2 = atan2(yy2-_yCentre,xx2-_xCentre); + float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre); + + float dphi1 = phi1 - phi0; + float dphi2 = phi2 - phi0; + + if (dphi1 < 0 && _charge < 0) { + dphi1 = dphi1 + _const_2pi; + } + else if (dphi1 > 0 && _charge > 0) { + dphi1 = dphi1 - _const_2pi; + } + + if (dphi2 < 0 && _charge < 0) { + dphi2 = dphi2 + _const_2pi; + } + else if (dphi2 > 0 && _charge > 0) { + dphi2 = dphi2 - _const_2pi; + } + + // Times + tt1 = -_charge*dphi1*_radius/_pxy; + tt2 = -_charge*dphi2*_radius/_pxy; + + if (tt1 < 0. ) + std::cout << "WARNING " << tt1 << std::endl; + if (tt2 < 0. ) + std::cout << "WARNING " << tt2 << std::endl; + + + float time2; + if (tt1 < tt2) { + point[0] = xx1; + point[1] = yy1; + point[3] = xx2; + point[4] = yy2; + time = tt1; + time2 = tt2; + } + else { + point[0] = xx2; + point[1] = yy2; + point[3] = xx1; + point[4] = yy1; + time = tt2; + time2 = tt1; + } + + point[2] = ref[2]+time*_momentum[2]; + point[5] = ref[2]+time2*_momentum[2]; + + + return time; + +} + + +float HelixClass::getPointInZ(float zLine, float * ref, float * point) { + + float time = zLine - ref[2]; + + if (_momentum[2] == 0.) { + time = -1.0e+20; + point[0] = 0.; + point[1] = 0.; + point[2] = 0.; + return time; + } + + time = time/_momentum[2]; + + float phi0 = atan2(ref[1] - _yCentre , ref[0] - _xCentre); + float phi = phi0 - _charge*_pxy*time/_radius; + float xx = _xCentre + _radius*cos(phi); + float yy = _yCentre + _radius*sin(phi); + + point[0] = xx; + point[1] = yy; + point[2] = zLine; + + return time; + + +} + +float HelixClass::getDistanceToPoint(float * xPoint, float * Distance) { + + float zOnHelix; + float phi = atan2(xPoint[1]-_yCentre,xPoint[0]-_xCentre); + float phi0 = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + //calculate distance to XYprojected centre of Helix, comparing this with distance to radius around centre gives DistXY + float DistXY = (_xCentre-xPoint[0])*(_xCentre-xPoint[0]) + (_yCentre-xPoint[1])*(_yCentre-xPoint[1]); + DistXY = sqrt(DistXY); + DistXY = fabs(DistXY - _radius); + + int nCircles = 0; + + if (fabs(_tanLambda*_radius)>1.0e-20) { + float xCircles = phi0 - phi -_charge*(xPoint[2]-_referencePoint[2])/(_tanLambda*_radius); + xCircles = xCircles/_const_2pi; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + + } + + float DPhi = _const_2pi*((float)nCircles) + phi - phi0; + + zOnHelix = _referencePoint[2] - _charge*_radius*_tanLambda*DPhi; + + float DistZ = fabs(zOnHelix - xPoint[2]); + float Time; + + if (fabs(_momentum[2]) > 1.0e-20) { + Time = (zOnHelix - _referencePoint[2])/_momentum[2]; + } + else { + Time = _charge*_radius*DPhi/_pxy; + } + + Distance[0] = DistXY; + Distance[1] = DistZ; + Distance[2] = sqrt(DistXY*DistXY+DistZ*DistZ); + + return Time; + + +} + +//When we are not interested in the exact distance, we can check if we are +//already far enough away in XY, before we start calculating in Z as the +//distance will only increase +float HelixClass::getDistanceToPoint(const std::vector<float>& xPoint, float distCut) { + //calculate distance to XYprojected centre of Helix, comparing this with distance to radius around centre gives DistXY + float tempx = xPoint[0]-_xCentre; + float tempy = xPoint[1]-_yCentre; + float tempsq = sqrt(tempx*tempx + tempy*tempy); + float tempdf = tempsq - _radius; + float DistXY = fabs( tempdf ); + //If this is bigger than distCut, we dont have to know how much bigger this is + if( DistXY > distCut) { + return DistXY; + } + + int nCircles = 0; + float phi = atan2(tempy,tempx); + float phi0 = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + float phidiff = phi0-phi; + float tempz = xPoint[2] - _referencePoint[2];//Yes referencePoint + float tanradius = _tanLambda*_radius; + if (fabs(tanradius)>1.0e-20) { + float xCircles = (phidiff -_charge*tempz/tanradius)/_const_2pi; + int n1,n2; + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + } + float DistZ = - tempz - _charge*tanradius*(_const_2pi*((float)nCircles) - phidiff); + return sqrt(DistXY*DistXY+DistZ*DistZ); +}//getDistanceToPoint(vector,float) + +float HelixClass::getDistanceToPoint(const float* xPoint, float distCut) { + std::vector<float> xPosition(xPoint, xPoint + 3 );//We are expecting three coordinates, must be +3, last element is excluded! + return getDistanceToPoint(xPosition, distCut); +}//getDistanceToPoint(float*,float) + + + +void HelixClass::setHelixEdges(float * xStart, float * xEnd) { + for (int i=0; i<3; ++i) { + _xStart[i] = xStart[i]; + _xEnd[i] = xEnd[i]; + } + +} + +float HelixClass::getDistanceToHelix(HelixClass * helix, float * pos, float * mom) { + + float x01 = getXC(); + float y01 = getYC(); + + float x02 = helix->getXC(); + float y02 = helix->getYC(); + + float rad1 = getRadius(); + float rad2 = helix->getRadius(); + + float distance = sqrt((x01-x02)*(x01-x02)+(y01-y02)*(y01-y02)); + + bool singlePoint = true; + + float phi1 = 0; + float phi2 = 0; + + if (rad1+rad2<distance) { + phi1 = atan2(y02-y01,x02-x01); + phi2 = atan2(y01-y02,x01-x02); + } + else if (distance+rad2<rad1) { + phi1 = atan2(y02-y01,x02-x01); + phi2 = phi1; + } + else if (distance+rad1<rad2) { + phi1 = atan2(y01-y02,x01-x02); + phi2 = phi1; + } + else { + singlePoint = false; + float cosAlpha = 0.5*(distance*distance+rad2*rad2-rad1*rad1)/(distance*rad2); + float alpha = acos(cosAlpha); + float phi0 = atan2(y01-y02,x01-x02); + phi1 = phi0 + alpha; + phi2 = phi0 - alpha; + } + + + float ref1[3]; + float ref2[3]; + for (int i=0;i<3;++i) { + ref1[i]=_referencePoint[i]; + ref2[i]=helix->getReferencePoint()[i]; + } + + float pos1[3]; + float pos2[3]; + float mom1[3]; + float mom2[3]; + + + if (singlePoint ) { + + float xSect1 = x01 + rad1*cos(phi1); + float ySect1 = y01 + rad1*sin(phi1); + float xSect2 = x02 + rad2*cos(phi2); + float ySect2 = y02 + rad2*sin(phi2); + float R1 = sqrt(xSect1*xSect1+ySect1*ySect1); + float R2 = sqrt(xSect2*xSect2+ySect2*ySect2); + + getPointOnCircle(R1,ref1,pos1); + helix->getPointOnCircle(R2,ref2,pos2); + + } + else { + + float xSect1 = x02 + rad2*cos(phi1); + float ySect1 = y02 + rad2*sin(phi1); + float xSect2 = x02 + rad2*cos(phi2); + float ySect2 = y02 + rad2*sin(phi2); + +// std::cout << "(xSect1,ySect1)=(" << xSect1 << "," << ySect1 << ")" << std::endl; +// std::cout << "(xSect2,ySect2)=(" << xSect2 << "," << ySect2 << ")" << std::endl; + + float temp21[3]; + float temp22[3]; + + float phiI2 = atan2(ref2[1]-y02,ref2[0]-x02); + float phiF21 = atan2(ySect1-y02,xSect1-x02); + float phiF22 = atan2(ySect2-y02,xSect2-x02); + float deltaPhi21 = phiF21 - phiI2; + float deltaPhi22 = phiF22 - phiI2; + float charge2 = helix->getCharge(); + float pxy2 = helix->getPXY(); + float pz2 = helix->getMomentum()[2]; + if (deltaPhi21 < 0 && charge2 < 0) { + deltaPhi21 += _const_2pi; + } + else if (deltaPhi21 > 0 && charge2 > 0) { + deltaPhi21 -= _const_2pi; + } + + if (deltaPhi22 < 0 && charge2 < 0) { + deltaPhi22 += _const_2pi; + } + else if (deltaPhi22 > 0 && charge2 > 0) { + deltaPhi22 -= _const_2pi; + } + + float time21 = -charge2*deltaPhi21*rad2/pxy2; + float time22 = -charge2*deltaPhi22*rad2/pxy2; + + float Z21 = ref2[2] + time21*pz2; + float Z22 = ref2[2] + time22*pz2; + + temp21[0] = xSect1; temp21[1] = ySect1; temp21[2] = Z21; + temp22[0] = xSect2; temp22[1] = ySect2; temp22[2] = Z22; + + +// std::cout << "temp21 = " << temp21[0] << " " << temp21[1] << " " << temp21[2] << std::endl; +// std::cout << "temp22 = " << temp22[0] << " " << temp22[1] << " " << temp22[2] << std::endl; + + + float temp11[3]; + float temp12[3]; + + float phiI1 = atan2(ref1[1]-y01,ref1[0]-x01); + float phiF11 = atan2(ySect1-y01,xSect1-x01); + float phiF12 = atan2(ySect2-y01,xSect2-x01); + float deltaPhi11 = phiF11 - phiI1; + float deltaPhi12 = phiF12 - phiI1; + float charge1 = _charge; + float pxy1 = _pxy; + float pz1 = _momentum[2]; + if (deltaPhi11 < 0 && charge1 < 0) { + deltaPhi11 += _const_2pi; + } + else if (deltaPhi11 > 0 && charge1 > 0) { + deltaPhi11 -= _const_2pi; + } + + if (deltaPhi12 < 0 && charge1 < 0) { + deltaPhi12 += _const_2pi; + } + else if (deltaPhi12 > 0 && charge1 > 0) { + deltaPhi12 -= _const_2pi; + } + + float time11 = -charge1*deltaPhi11*rad1/pxy1; + float time12 = -charge1*deltaPhi12*rad1/pxy1; + + float Z11 = ref1[2] + time11*pz1; + float Z12 = ref1[2] + time12*pz1; + + temp11[0] = xSect1; temp11[1] = ySect1; temp11[2] = Z11; + temp12[0] = xSect2; temp12[1] = ySect2; temp12[2] = Z12; + +// std::cout << "temp11 = " << temp11[0] << " " << temp11[1] << " " << temp11[2] << std::endl; +// std::cout << "temp12 = " << temp12[0] << " " << temp12[1] << " " << temp12[2] << std::endl; + + float Dist1 = 0; + float Dist2 = 0; + + for (int j=0;j<3;++j) { + Dist1 += (temp11[j]-temp21[j])*(temp11[j]-temp21[j]); + Dist2 += (temp12[j]-temp22[j])*(temp12[j]-temp22[j]); + } + + if (Dist1<Dist2) { + for (int l=0;l<3;++l) { + pos1[l] = temp11[l]; + pos2[l] = temp21[l]; + } + } + else { + for (int l=0;l<3;++l) { + pos1[l] = temp12[l]; + pos2[l] = temp22[l]; + } + } + + } + + getExtrapolatedMomentum(pos1,mom1); + helix->getExtrapolatedMomentum(pos2,mom2); + + float helixDistance = 0; + + for (int i=0;i<3;++i) { + helixDistance += (pos1[i] - pos2[i])*(pos1[i] - pos2[i]); + pos[i] = 0.5*(pos1[i]+pos2[i]); + mom[i] = mom1[i]+mom2[i]; + } + helixDistance = sqrt(helixDistance); + + return helixDistance; + +} + +void HelixClass::getExtrapolatedMomentum(float * pos, float * momentum) { + + float phi = atan2(pos[1]-_yCentre,pos[0]-_xCentre); + if (phi <0.) phi += _const_2pi; + phi = phi - _phiAtPCA + _phi0; + momentum[0] = _pxy*cos(phi); + momentum[1] = _pxy*sin(phi); + momentum[2] = _momentum[2]; + + +} diff --git a/Utilities/DataHelper/src/LineClass.cc b/Utilities/DataHelper/src/LineClass.cc new file mode 100644 index 0000000000000000000000000000000000000000..826a0d8f2b74bc038a7bd8bd22dfa353e57727b1 --- /dev/null +++ b/Utilities/DataHelper/src/LineClass.cc @@ -0,0 +1,73 @@ +#include "DataHelper/LineClass.h" +#include <math.h> + +/* + * Constructor + */ + +LineClass::LineClass(float x0, + float y0, + float z0, + float ax, + float ay, + float az) { + _x0[0] = x0; + _x0[1] = y0; + _x0[2] = z0; + _ax[0] = ax; + _ax[1] = ay; + _ax[2] = az; +} + +LineClass::LineClass(float *x0, + float *ax) { + + for (int i=0; i<3; ++i) { + _x0[i] = x0[i]; + _ax[i] = ax[i]; + } +} + +float * LineClass::getReferencePoint() { + return _x0; +} + +float * LineClass::getDirectionalVector() { + return _ax; +} + +void LineClass::setReferencePoint(float *x0) { + for (int i=0; i<3; ++i) + _x0[i] = x0[i]; +} + +void LineClass::setDirectionalVector(float *ax) { + for (int i=0; i<3; ++i) + _ax[i] = ax[i]; + +} + +float LineClass::getDistanceToPoint(float * xpoint, float * pos) { + + float dif[3]; + float prod = 0; + float den = 0; + for (int i=0; i<3; ++i) { + dif[i] = xpoint[i] - _x0[i]; + prod += _ax[i]*dif[i]; + den += _ax[i]*_ax[i]; + } + float time = prod/fmax(1e-10,den); + + float dist = 0.0; + for (int i=0; i<3; ++i) { + pos[i] = _x0[i] + _ax[i]*time; + dist += (xpoint[i]-pos[i])*(xpoint[i]-pos[i]); + } + dist = sqrt(dist); + + return dist; + + + +} diff --git a/Utilities/DataHelper/src/Navigation.cpp b/Utilities/DataHelper/src/Navigation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c220906aab7cc0db0226d74a8a5b1a70d0d77f5 --- /dev/null +++ b/Utilities/DataHelper/src/Navigation.cpp @@ -0,0 +1,81 @@ +#include "DataHelper/Navigation.h" + +#include "edm4hep/SimTrackerHit.h" +#include "edm4hep/TrackerHit.h" + +Navigation* Navigation::m_fNavigation = nullptr; + +Navigation* Navigation::Instance(){ + if(!m_fNavigation) m_fNavigation = new Navigation(); + return m_fNavigation; +} + +Navigation::Navigation(){ +} + +Navigation::~Navigation(){ +} + +void Navigation::Initialize(){ + m_hitColVec.clear(); + m_assColVec.clear(); + for(std::map<int, edm4hep::TrackerHit*>::iterator it=m_trkHits.begin();it!=m_trkHits.end();it++){ + delete it->second; + } + m_trkHits.clear(); +} + +edm4hep::TrackerHit* Navigation::GetTrackerHit(const edm4hep::ObjectID& obj_id, bool delete_by_caller){ + int id = obj_id.collectionID * 10000000 + obj_id.index; + if(!delete_by_caller){ + if(m_trkHits.find(id)!=m_trkHits.end()) return m_trkHits[id]; + } + /* + for(int i=0;i<m_assColVec.size();i++){ + for(auto ass : *m_assColVec[i]){ + edm4hep::ObjectID rec_id = ass.getRec().getObjectID(); + if(rec_id.collectionID!=id.collectionID)break; + else if(rec_id.index==id.index){ + m_trkHits.push_back(ass.getRec()); + return &(m_trkHits.back()); + } + } + } + */ + for(int i=0;i<m_hitColVec.size();i++){ + for(auto hit : *m_hitColVec[i]){ + edm4hep::ObjectID this_id = hit.getObjectID(); + if(this_id.collectionID!=obj_id.collectionID)break; + else if(this_id.index==obj_id.index){ + edm4hep::TrackerHit* hit_copy = new edm4hep::TrackerHit(hit); + if(!delete_by_caller) m_trkHits[id] = hit_copy; + return hit_copy;//&(m_trkHits[id]); + } + } + } + + throw std::runtime_error("Not found TrackerHit"); +} + +std::vector<edm4hep::ConstSimTrackerHit> Navigation::GetRelatedTrackerHit(const edm4hep::ObjectID& id){ + std::vector<edm4hep::ConstSimTrackerHit> hits; + for(int i=0;i<m_assColVec.size();i++){ + for(auto ass : *m_assColVec[i]){ + edm4hep::ObjectID this_id = ass.getRec().getObjectID(); + if(this_id.collectionID!=id.collectionID)break; + else if(this_id.index==id.index) hits.push_back(ass.getSim()); + } + } + return hits; +} + +std::vector<edm4hep::ConstSimTrackerHit> Navigation::GetRelatedTrackerHit(const edm4hep::TrackerHit& hit){ + std::vector<edm4hep::ConstSimTrackerHit> hits; + for(int i=0;i<m_assColVec.size();i++){ + for(auto ass : *m_assColVec[i]){ + if(ass.getRec().getObjectID().collectionID != hit.getObjectID().collectionID) break; + else if(ass.getRec()==hit) hits.push_back(ass.getSim()); + } + } + return hits; +} diff --git a/Utilities/DataHelper/src/TrackExtended.cc b/Utilities/DataHelper/src/TrackExtended.cc new file mode 100644 index 0000000000000000000000000000000000000000..bd5444d7afe6a9df1233a2e6f8a01e904f3b6158 --- /dev/null +++ b/Utilities/DataHelper/src/TrackExtended.cc @@ -0,0 +1,229 @@ +#include "DataHelper/ClusterExtended.h" +#include "DataHelper/TrackerHitExtended.h" +#include "DataHelper/TrackExtended.h" +#include <math.h> + +TrackExtended::TrackExtended( ) { + _track = NULL; + _superCluster = NULL; + _trackerHitVector.clear(); + _clusterVec.clear(); + _group = NULL; +} + +TrackExtended::TrackExtended( Track * track) { + _track = track; + _superCluster = NULL; + _trackerHitVector.clear(); + _clusterVec.clear(); + _group = NULL; + +} + +TrackExtended::TrackExtended( TrackerHitExtended * trackerhit) { + _trackerHitVector.clear(); + _trackerHitVector.push_back(trackerhit); + _track = NULL; + _superCluster = NULL; + _clusterVec.clear(); + _group = NULL; +} + + +TrackExtended::~TrackExtended() {} + +Track * TrackExtended::getTrack() { + return _track; +} + +const float * TrackExtended::getSeedPosition() { + return _seedPosition; +} + +const float * TrackExtended::getSeedDirection() { + return _seedDirection; +} + +ClusterExtendedVec & TrackExtended::getClusterVec() { + return _clusterVec; +} + +ClusterExtended * TrackExtended::getSuperCluster() { + return _superCluster; +} + +TrackerHitExtendedVec & TrackExtended::getTrackerHitExtendedVec() { + return _trackerHitVector; +} + +void TrackExtended::addCluster(ClusterExtended * cluster) { + _clusterVec.push_back(cluster); +} + +void TrackExtended::setSuperCluster(ClusterExtended * superCluster) { + _superCluster = superCluster; +} + +void TrackExtended::setSeedDirection( float * seedDirection ) { + _seedDirection[0] = seedDirection[0]; + _seedDirection[1] = seedDirection[1]; + _seedDirection[2] = seedDirection[2]; +} + +void TrackExtended::setSeedPosition( float * seedPosition) { + _seedPosition[0] = seedPosition[0]; + _seedPosition[1] = seedPosition[1]; + _seedPosition[2] = seedPosition[2]; +} + +void TrackExtended::addTrackerHitExtended( TrackerHitExtended * trackerhit) { + _trackerHitVector.push_back(trackerhit); + +} + +void TrackExtended::ClearTrackerHitExtendedVec() { + _trackerHitVector.clear(); +} + +void TrackExtended::setX0( float x0 ) { + _x0 = x0; +} + +void TrackExtended::setD0( float d0 ) { + _d0 = d0; +} + +void TrackExtended::setZ0( float z0 ) { + _z0 = z0; +} + +void TrackExtended::setY0( float y0 ) { + _y0 = y0; +} + +void TrackExtended::setR0( float r0 ) { + _r0 = r0; +} + +void TrackExtended::setBz( float bz ) { + _bz = bz; +} + +void TrackExtended::setPhi0( float phi0 ) { + _phi0 = phi0; +} + +void TrackExtended::setPhi( float phi ) { + _phi = phi; +} + +void TrackExtended::setOmega( float omega ) { + _omega = omega; +} + +void TrackExtended::setTanLambda( float tanLambda ) { + _tanLambda = tanLambda; +} +void TrackExtended::setNDF( int ndf) { + _ndf = ndf; +} + + +float TrackExtended::getX0() { + return _x0; +} + +float TrackExtended::getY0() { + return _y0; +} + +float TrackExtended::getR0() { + return _r0; +} + +float TrackExtended::getBz() { + return _bz; +} + +float TrackExtended::getD0() { + return _d0; +} + +float TrackExtended::getZ0() { + return _z0; +} + +float TrackExtended::getPhi0() { + return _phi0; +} + +float TrackExtended::getPhi() { + return _phi; +} + +float TrackExtended::getOmega() { + return _omega; +} + +float TrackExtended::getTanLambda() { + return _tanLambda; +} + +int TrackExtended::getNDF() { + return _ndf; +} + +void TrackExtended::setStart(float * xStart) { + _xStart[0] = xStart[0]; + _xStart[1] = xStart[1]; + _xStart[2] = xStart[2]; +} + +void TrackExtended::setEnd(float * xEnd) { + _xEnd[0] = xEnd[0]; + _xEnd[1] = xEnd[1]; + _xEnd[2] = xEnd[2]; +} + +float * TrackExtended::getStart() { + return _xStart; +} + +float * TrackExtended::getEnd() { + return _xEnd; +} + +void TrackExtended::setGroupTracks( GroupTracks * group ) { + _group = group; +} + +GroupTracks * TrackExtended::getGroupTracks() { + return _group; +} + +float TrackExtended::getChi2() { + return _chi2; +} + +void TrackExtended::setChi2(float chi2) { + _chi2 = chi2; +} + +void TrackExtended::setCovMatrix(float * cov) { + for (int i=0; i<15; ++i) + _cov[i] = cov[i]; +} + +float * TrackExtended::getCovMatrix() { + return _cov; +} + +// void TrackExtended::setType(int type) { +// _type = type + +// } + +// int TrackExtended::getType() { +// return _type; + +// } diff --git a/Utilities/DataHelper/src/TrackerHitExtended.cc b/Utilities/DataHelper/src/TrackerHitExtended.cc new file mode 100644 index 0000000000000000000000000000000000000000..d2169bf3661556d98c78899751e0c5c867d7b511 --- /dev/null +++ b/Utilities/DataHelper/src/TrackerHitExtended.cc @@ -0,0 +1,133 @@ +#include "DataHelper/TrackExtended.h" +#include "DataHelper/TrackerHitExtended.h" + +TrackerHitExtended::TrackerHitExtended(const edm4hep::TrackerHit& trackerhit): + _trackerHit(trackerhit){ + _trackAR = NULL; + _trackVecAR.clear(); + _usedInFit = false; +} + +TrackerHitExtended::~TrackerHitExtended() { + +} + +void TrackerHitExtended::setTrackExtended(TrackExtended * trackAR) { + _trackAR = trackAR; + _trackVecAR.clear(); + _trackVecAR.push_back(trackAR); + +} + +void TrackerHitExtended::addTrackExtended(TrackExtended * trackAR) { + _trackVecAR.push_back(trackAR); +} + +TrackExtendedVec & TrackerHitExtended::getTrackExtendedVec() { + return _trackVecAR; +} + + +void TrackerHitExtended::setTrackerHitTo(TrackerHitExtended * hitTo) { + _hitTo = hitTo; +} + +void TrackerHitExtended::setTrackerHitFrom(TrackerHitExtended * hitFrom) { + _hitFrom = hitFrom; + +} + +void TrackerHitExtended::setGenericDistance(float genericDistance) { + _genericDistance = genericDistance; +} + +//void TrackerHitExtended::setTrackerHit(edm4hep::TrackerHit * hit) { +// _trackerHit = hit; +//} + +void TrackerHitExtended::setYresTo(float yresTo) { + _yresTo = yresTo; +} + +void TrackerHitExtended::setYresFrom(float yresFrom) { + _yresFrom = yresFrom; +} + +void TrackerHitExtended::setDirVec(float * dirVec) { + _dirVec[0] = dirVec[0]; + _dirVec[1] = dirVec[1]; + _dirVec[2] = dirVec[2]; +} + +void TrackerHitExtended::setType(int ityp) { + _type = ityp; +} + +void TrackerHitExtended::setDet(int idet) { + _idet = idet; +} + +edm4hep::TrackerHit * TrackerHitExtended::getTrackerHit() { + return &_trackerHit; +} + +TrackExtended * TrackerHitExtended::getTrackExtended() { + return _trackAR; +} + +TrackerHitExtended * TrackerHitExtended::getTrackerHitFrom() { + return _hitFrom; +} +TrackerHitExtended * TrackerHitExtended::getTrackerHitTo() { + return _hitTo; +} +float TrackerHitExtended::getGenericDistance() { + return _genericDistance; +} +float TrackerHitExtended::getYresTo() { + return _yresTo; +} +float TrackerHitExtended::getYresFrom() { + return _yresFrom; +} + +float * TrackerHitExtended::getDirVec() { + return _dirVec; +} + +void TrackerHitExtended::clearTrackVec() { + _trackVecAR.clear(); +} + +float TrackerHitExtended::getResolutionRPhi() { + return _rphiReso; +} + +float TrackerHitExtended::getResolutionZ() { + return _zReso; +} + +void TrackerHitExtended::setResolutionRPhi(float rphiReso) { + _rphiReso = rphiReso; +} + +void TrackerHitExtended::setResolutionZ(float zReso) { + _zReso = zReso; +} + +int TrackerHitExtended::getType() { + return _type; +} + +int TrackerHitExtended::getDet() { + return _idet; +} + +void TrackerHitExtended::setUsedInFit(bool usedInFit) { + _usedInFit = usedInFit; +} + +bool TrackerHitExtended::getUsedInFit() { + return _usedInFit; +} + diff --git a/Utilities/KalDet/CMakeLists.txt b/Utilities/KalDet/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..52b96cf23b79b6c6458ec56803353977aecb70ec --- /dev/null +++ b/Utilities/KalDet/CMakeLists.txt @@ -0,0 +1,58 @@ +############################################################################## +# Package: KalDet +# Desc: import from ILCSoft +############################################################################## + +gaudi_subdir(KalDet v0r0) + +find_package(CLHEP REQUIRED) +find_package(LCIO) +find_package(GEAR) +find_package(ROOT COMPONENTS MathCore) +find_package(EDM4HEP REQUIRED) + +gaudi_depends_on_subdirs( + Detector/DetInterface + Utilities/KalTest +) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +INCLUDE( MyFindROOT ) +INCLUDE( MacroRootDict ) + +SET( ROOT_DICT_CINT_DEFINITIONS "-DHANDLE_DICT_EXCEPTIONS=IGNORED_FOR_CINT" ) + +INCLUDE( ${ROOT_DICT_MACROS_FILE} ) + +SET( lib_input_dirs src/gen src/kern src/lctpc/gearTPC ) + +FOREACH( lib_input_dir ${lib_input_dirs} ) + LIST( APPEND ROOT_DICT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/${lib_input_dir} ) +ENDFOREACH() + +LIST( APPEND ROOT_DICT_INCLUDE_DIRS /workfs/bes/fucd/Key4hep/CEPCSW/Utilities/KalTest ) + +#MESSAGE( STATUS "ROOT_DICT_INCLUDE_DIRS: ${ROOT_DICT_INCLUDE_DIRS}" ) + +FOREACH( lib_input_dir ${lib_input_dirs} ) + AUX_SOURCE_DIRECTORY( ${lib_input_dir} lib_sources ) + PREPARE_ROOT_DICT_HEADERS( ${lib_input_dir} ) + INSTALL(DIRECTORY ${lib_input_dir}/ DESTINATION "include/kaldet" + FILES_MATCHING PATTERN "*.h" PATTERN "LinkDef.h" EXCLUDE + ) + GEN_ROOT_DICT_SOURCES( ${lib_input_dir}Dict.cxx ) + LIST( APPEND lib_sources ${ROOT_DICT_OUTPUT_SOURCES} ) +ENDFOREACH() + +FILE( GLOB_RECURSE ild_sources "src/ild/*.cc" ) +FILE( GLOB_RECURSE lib_headers "src/ild/*.h" ) + +include_directories(src/ild/common) + +set(KalDetLib_srcs ${lib_sources} src/ild/*/*.cc ) + +gaudi_add_library(KalDetLib ${KalDetLib_srcs} + PUBLIC_HEADERS kaldet + LINK_LIBRARIES GaudiKernel ROOT CLHEP LCIO $ENV{GEAR}/lib/libgearsurf.so KalTestLib EDM4HEP::edm4hep EDM4HEP::edm4hepDict +) diff --git a/Utilities/KalDet/cmake/MacroCheckPackageLibs.cmake b/Utilities/KalDet/cmake/MacroCheckPackageLibs.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c4451b3e40839e00dcefe08680a34ef98a3dd2b6 --- /dev/null +++ b/Utilities/KalDet/cmake/MacroCheckPackageLibs.cmake @@ -0,0 +1,164 @@ +############################################################################## +# macro for checkin package libraries in ${PKG_ROOT}/lib +# +# +# macro usage: +# CHECK_PACKAGE_LIBS( PACKAGE_NAME stdlib1 stdlib2 ... stdlibn ) +# only standard libraries should be passed as arguments to the macro +# component libraries are set by cmake in PKG_FIND_COMPONENTS (when +# calling FIND_PACKAGE with COMPONENTS argument) or through the +# variable PKG_USE_COMPONENTS +# +# +# required variables: +# PKG_ROOT : path to PKG root directory +# +# +# returns following variables: +# PKG_LIBRARY_DIRS : list of paths to be used with LINK_DIRECTORIES +# PGK_LIBRARIES : list of STANDARD libraries (NOT including COMPONENTS) +# PKG_COMPONENT_LIBRARIES : list of COMPONENT libraries +# PKG_${COMPONENT}_FOUND : set to TRUE or FALSE for each library +# PKG_${COMPONENT}_LIBRARY : path to each individual library +# +# +# PKG_LIBRARIES and PKG_LIBRARY_DIRS will be empty if any of the standard +# libraries is missing +# +# @author Jan Engels, Desy +############################################################################## + + +SET( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE ) + +MACRO( CHECK_PACKAGE_LIBS _pkgname ) + + SET( _std_lib_missing FALSE ) + SET( _ext_lib_missing FALSE ) + + SET( _std_libnames ${ARGN} ) + SET( _ext_libnames ${${_pkgname}_FIND_COMPONENTS} ${${_pkgname}_USE_COMPONENTS} ) + + IF( _ext_libnames ) + SEPARATE_ARGUMENTS( _ext_libnames ) + LIST( REMOVE_DUPLICATES _ext_libnames ) + ENDIF() + + IF( NOT ${_pkgname}_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ${_pkgname}_LIBRARIES: ${_std_libnames}" ) + IF( _ext_libnames ) + MESSAGE( STATUS "Check for ${_pkgname}_COMPONENT_LIBRARIES: ${_ext_libnames}" ) + ENDIF() + ENDIF() + + SET( ${_pkgname}_LIBRARY_DIRS ) + MARK_AS_ADVANCED( ${_pkgname}_LIBRARY_DIRS ) + + SET( ${_pkgname}_LIBRARIES ) + MARK_AS_ADVANCED( ${_pkgname}_LIBRARIES ) + + SET( ${_pkgname}_COMPONENT_LIBRARIES ) + MARK_AS_ADVANCED( ${_pkgname}_COMPONENT_LIBRARIES ) + + SET( ${_pkgname}_COMPONENT_VARIABLES ) + MARK_AS_ADVANCED( ${_pkgname}_COMPONENT_VARIABLES ) + + FOREACH( _libname ${_std_libnames} ${_ext_libnames} ) + + # flag to check if it is a standard or a component library + LIST( FIND _std_libnames "${_libname}" _aux ) + IF( ${_aux} LESS 0 ) + SET( _is_std_lib FALSE ) + ELSE() + SET( _is_std_lib TRUE ) + ENDIF() + + # libname in upper case + STRING( TOUPPER ${_libname} _ulibname ) + + SET( ${_pkgname}_${_ulibname}_LIBRARY ${_pkgname}_${_ulibname}_LIBRARY-NOTFOUND ) + MARK_AS_ADVANCED( ${_pkgname}_${_ulibname}_LIBRARY ) + + # WARNING: using PATH_SUFFIXES may cause problems when using variable CMAKE_FIND_ROOT_PATH + # this problem does not occur if expanding PATHS + # look in FindMySQL.cmake for more info + #FIND_LIBRARY( ${_pkgname}_${_ulibname}_LIBRARY NAMES ${_libname} PATHS + # ${${_pkgname}_ROOT} ${${_pkgname}_DIR} ${${_pkgname}_LIB_SEARCH_PATH} + # PATH_SUFFIXES lib64 lib + # NO_DEFAULT_PATH + #) + + FIND_LIBRARY( ${_pkgname}_${_ulibname}_LIBRARY NAMES ${_libname} PATHS + ${${_pkgname}_ROOT}/lib64 ${${_pkgname}_ROOT}/lib + ${${_pkgname}_DIR}/lib64 ${${_pkgname}_DIR}/lib + ${${_pkgname}_LIB_SEARCH_PATH} ${${_pkgname}_LIB_SEARCH_PATH}/lib64 ${${_pkgname}_LIB_SEARCH_PATH}/lib + NO_DEFAULT_PATH + ) + + IF( NOT ${_pkgname}_DIR ) + FIND_LIBRARY( ${_pkgname}_${_ulibname}_LIBRARY NAMES ${_libname} ) + ENDIF() + + IF( ${_pkgname}_FIND_REQUIRED ) + LIST( APPEND ${_pkgname}_COMPONENT_VARIABLES ${_pkgname}_${_ulibname}_LIBRARY ) + ENDIF() + + IF( ${_pkgname}_${_ulibname}_LIBRARY ) # if library found + + SET( ${_pkgname}_${_ulibname}_FOUND TRUE ) + + # split libraries in PKG_LIBRARIES and PKG_COMPONENT_LIBRARIES + IF( _is_std_lib ) + LIST( APPEND ${_pkgname}_LIBRARIES ${${_pkgname}_${_ulibname}_LIBRARY} ) + ELSE() + LIST( APPEND ${_pkgname}_COMPONENT_LIBRARIES ${${_pkgname}_${_ulibname}_LIBRARY} ) + ENDIF() + + GET_FILENAME_COMPONENT( _aux ${${_pkgname}_${_ulibname}_LIBRARY} PATH ) + LIST( APPEND ${_pkgname}_LIBRARY_DIRS ${_aux} ) + + IF( NOT ${_pkgname}_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ${_pkgname}_${_ulibname}_LIBRARY: ${${_pkgname}_${_ulibname}_LIBRARY} -- ok" ) + ENDIF() + + ELSE() # library not found + + SET( ${_pkgname}_${_ulibname}_FOUND FALSE ) + + IF( _is_std_lib ) + SET( _std_lib_missing TRUE ) + ELSE() + SET( _ext_lib_missing TRUE ) + ENDIF() + + IF( NOT ${_pkgname}_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ${_pkgname}_${_ulibname}_LIBRARY: ${_libname} -- failed" ) + ENDIF() + + ENDIF() + + ENDFOREACH() + + # clear PKG_LIBRARIES if standard library is missing + IF( _std_lib_missing ) + SET( ${_pkgname}_LIBRARIES ) + ENDIF() + + # clear PKG_COMPONENT_LIBRARIES if a component library is missing and + # FIND_PACKAGE called with REQUIRED argument + IF( _ext_lib_missing AND ${_pkgname}_FIND_REQUIRED ) + SET( ${_pkgname}_COMPONENT_LIBRARIES ) + ENDIF() + + # remove duplicate paths in PKG_LIBRARY_DIRS + IF( ${_pkgname}_LIBRARY_DIRS ) + LIST( REMOVE_DUPLICATES ${_pkgname}_LIBRARY_DIRS ) + ENDIF() + + # debug + #MESSAGE( STATUS "${_pkgname}_LIBRARIES: ${${_pkgname}_LIBRARIES}" ) + #MESSAGE( STATUS "${_pkgname}_COMPONENT_LIBRARIES: ${${_pkgname}_COMPONENT_LIBRARIES}" ) + #MESSAGE( STATUS "${_pkgname}_LIBRARY_DIRS: ${${_pkgname}_LIBRARY_DIRS}" ) + +ENDMACRO( CHECK_PACKAGE_LIBS _pkgname ) + diff --git a/Utilities/KalDet/cmake/MacroCheckPackageVersion.cmake b/Utilities/KalDet/cmake/MacroCheckPackageVersion.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e3ec75d9faa2ee03919d01179636fb1ba843e41e --- /dev/null +++ b/Utilities/KalDet/cmake/MacroCheckPackageVersion.cmake @@ -0,0 +1,108 @@ +############################################################################## +# macro for checking a package version +# +# this macro should be called from your PKGVersion.cmake or from a +# FindPKG.cmake module with the following arguments: +# _pkgname : The package name +# _iversion : The installed version of the package +# +# +# the following conventions are used: +# +# if FIND_PACKAGE is called with EXACT argument than the version has to +# match EXACTLY, i.e.: +# 1.5 == 1.5 +# 1.5 == 1.5.0 +# 1.5 == 1.5.0.0 +# 1.5.2 == 1.5.2.0 +# 1.5.2.1 == 1.5.2.1 +# 1.5.2 != 1.5.2.1 +# 1.5 != 1.5.0.1 +# +# +# otherwise a MINIMUM_REQUIRED version is checked for, i.e. the same +# behavior as with the cmake variable CMAKE_MINIMUM_REQUIRED, e.g.: +# searching: 1.2 --> installed: 1.5.2.2 --> compatible +# searching: 1.5 --> installed: 1.5.2.2 --> compatible +# searching: 1.5.2.1 --> installed: 1.5.2.2 --> compatible +# searching: 1.5.2.3 --> installed: 1.5.2.2 --> unsuitable +# searching: 1.7 --> installed: 1.5.2.2 --> unsuitable +# +# +# following variables are returned (internally to cmake): +# PACKAGE_VERSION_EXACT : set to TRUE if exact version was found +# PACKAGE_VERSION_COMPATIBLE : set to TRUE if version is compatible +# PACKAGE_VERSION_UNSUITABLE : set to TRUE if version found is unsuitable +# +# +# @author Jan Engels, Desy IT +############################################################################## + +# these variables are evaluated internally by the cmake command FIND_PACKAGE to mark this +# package as suitable or not depending on the required version +SET( PACKAGE_VERSION_EXACT FALSE ) +SET( PACKAGE_VERSION_COMPATIBLE TRUE ) +SET( PACKAGE_VERSION_UNSUITABLE FALSE ) + + +# cmake internal variable PACKAGE_FIND_NAME is not defined on FindPKG.cmake +# modules, therefore it is passed as an argument to the macro +# _iversion is the installed version of the package +# _sversion is the version searched by the user with FIND_PACKAGE +#MACRO( CHECK_PACKAGE_VERSION _pkgname _iversion ) +MACRO( CHECK_PACKAGE_VERSION _pkgname ) # left with one argument only for backwards compatibility + + IF( NOT "${ARGV1}" STREQUAL "" ) + SET( _iversion ${ARGV1} ) + ELSE() + SET( _iversion ${${_pkgname}_VERSION_MAJOR}.${${_pkgname}_VERSION_MINOR}.${${_pkgname}_VERSION_PATCH}.${${_pkgname}_VERSION_TWEAK} ) + ENDIF() + + #SET( _sversion_major ${${_pkgname}_FIND_VERSION_MAJOR} ) + #SET( _sversion_minor ${${_pkgname}_FIND_VERSION_MINOR} ) + + SET( _sversion ${${_pkgname}_FIND_VERSION} ) + + IF( NOT ${_pkgname}_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ${_pkgname} (${_iversion})" ) + ENDIF() + + # only do work if FIND_PACKAGE called with a version argument + IF( _sversion ) + + #IF( NOT ${_pkgname}_FIND_QUIETLY ) + # MESSAGE( STATUS "Check for ${_pkgname}: looking for version ${_sversion}" ) + #ENDIF() + + IF( ${_iversion} VERSION_EQUAL ${_sversion} ) # if version matches EXACTLY + #IF( NOT ${_pkgname}_FIND_QUIETLY ) + # MESSAGE( STATUS "Check for ${_pkgname}: exact version found: ${_iversion}" ) + #ENDIF() + SET( PACKAGE_VERSION_EXACT TRUE ) + ELSE() # if version does not match EXACTLY, check if it is compatible/suitable + + # installed version must be greater or equal than version searched by the user, i.e. + # like with the CMAKE_MINIMUM_REQUIRED commando + # if user asks for version 1.2.5 then any version >= 1.2.5 is suitable/compatible + IF( NOT ${_sversion} VERSION_LESS ${_iversion} ) + SET( PACKAGE_VERSION_UNSUITABLE TRUE ) + ENDIF() + # ------------------------------------------------------------------------------------- + + IF( ${_pkgname}_FIND_VERSION_EXACT ) # if exact version was required search must fail!! + #IF( NOT ${_pkgname}_FIND_QUIETLY ) + # MESSAGE( "Check for ${_pkgname}: could not find exact version" ) + #ENDIF() + SET( PACKAGE_VERSION_UNSUITABLE TRUE ) + ENDIF() + + ENDIF() + + IF( PACKAGE_VERSION_UNSUITABLE ) + SET( PACKAGE_VERSION_COMPATIBLE FALSE ) + ENDIF() + + ENDIF( _sversion ) + +ENDMACRO( CHECK_PACKAGE_VERSION ) + diff --git a/Utilities/KalDet/cmake/MacroRootDict.cmake b/Utilities/KalDet/cmake/MacroRootDict.cmake new file mode 100644 index 0000000000000000000000000000000000000000..eb1059ed05176adc07b3252b599872328c98b272 --- /dev/null +++ b/Utilities/KalDet/cmake/MacroRootDict.cmake @@ -0,0 +1,145 @@ +IF(APPLE) + SET( LD_LIBRARY_PATH_VAR DYLD_LIBRARY_PATH ) +ELSE() + SET( LD_LIBRARY_PATH_VAR LD_LIBRARY_PATH ) +ENDIF() +SET( LD_LIBRARY_PATH_CONTENTS $ENV{${LD_LIBRARY_PATH_VAR}} ) +#MESSAGE( STATUS "LD_LIBRARY_PATH_CONTENTS: ${LD_LIBRARY_PATH_CONTENTS}" ) +#MESSAGE( STATUS "ROOT_CINT_EXECUTABLE: ${ROOT_CINT_EXECUTABLE}" ) + +SET( ROOT_CINT_WRAPPER ${LD_LIBRARY_PATH_VAR}=${ROOT_LIBRARY_DIR}:${LD_LIBRARY_PATH_CONTENTS} ${ROOT_CINT_EXECUTABLE} ) + +IF( NOT DEFINED ROOT_DICT_OUTPUT_DIR ) + SET( ROOT_DICT_OUTPUT_DIR "${PROJECT_BINARY_DIR}/rootdict" ) +ENDIF() + +# clean generated header files with 'make clean' +SET_DIRECTORY_PROPERTIES( PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${ROOT_DICT_OUTPUT_DIR}" ) + +IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ROOT_DICT_OUTPUT_DIR: ${PROJECT_BINARY_DIR}/rootdict" ) + MESSAGE( STATUS "Check for ROOT_DICT_CINT_DEFINITIONS: ${ROOT_DICT_CINT_DEFINITIONS}" ) +ENDIF() + + +# ============================================================================ +# helper macro to prepare input headers for GEN_ROOT_DICT_SOURCES +# sorts LinkDef.h to be the last header (required by rootcint) +# +# arguments: +# input_dir - directory to search for headers matching *.h +# +# returns: +# ROOT_DICT_INPUT_HEADERS - all header files found in input_dir with +# LinkDef.h as the last header (if found) +# +# ---------------------------------------------------------------------------- +MACRO( PREPARE_ROOT_DICT_HEADERS _input_dir ) + + FILE( GLOB ROOT_DICT_INPUT_HEADERS "${_input_dir}/*.h" ) + FILE( GLOB _linkdef_hdr "${_input_dir}/LinkDef.h" ) + + #LIST( FIND ROOT_DICT_INPUT_HEADERS ${_linkdef_hdr} _aux ) + #IF( ${_aux} EQUAL 0 OR ${_aux} GREATER 0 ) + # LIST( REMOVE_ITEM ROOT_DICT_INPUT_HEADERS "${_linkdef_hdr}" ) + # LIST( APPEND ROOT_DICT_INPUT_HEADERS "${_linkdef_hdr}" ) + #ENDIF() + + IF( _linkdef_hdr ) + LIST( REMOVE_ITEM ROOT_DICT_INPUT_HEADERS "${_linkdef_hdr}" ) + LIST( APPEND ROOT_DICT_INPUT_HEADERS "${_linkdef_hdr}") + ENDIF() + + #MESSAGE( STATUS "ROOT_DICT_INPUT_HEADERS: ${ROOT_DICT_INPUT_HEADERS}" ) + +ENDMACRO( PREPARE_ROOT_DICT_HEADERS ) + + + +# ============================================================================ +# helper macro to generate Linkdef.h files for rootcint +# +# arguments: +# namespace - prefix used for creating header <namespace>_Linkdef.h +# ARGN - list of sources to be used for generating Linkdef.h +# +# returns: +# ROOT_DICT_INPUT_HEADERS - all header files + <namespace>_LinkDef.h in the +# correct order to be used by macro GEN_ROOT_DICT_SOURCES +# +# ---------------------------------------------------------------------------- +MACRO( GEN_ROOT_DICT_LINKDEF_HEADER _namespace ) + + SET( _input_headers ${ARGN} ) + SET( _linkdef_header "${ROOT_DICT_OUTPUT_DIR}/${_namespace}_Linkdef.h" ) + + FOREACH( _header ${_input_headers} ) + SET( ${_namespace}_file_contents "${${_namespace}_file_contents}\\#pragma link C++ defined_in \\\"${_header}\\\"\\;\\\\n" ) + ENDFOREACH() + + ADD_CUSTOM_COMMAND( + OUTPUT ${_linkdef_header} + COMMAND mkdir -p ${ROOT_DICT_OUTPUT_DIR} + COMMAND printf "${${_namespace}_file_contents}" > ${_linkdef_header} + DEPENDS ${_input_headers} + COMMENT "generating: ${_linkdef_header}" + ) + + SET( ROOT_DICT_INPUT_HEADERS ${_input_headers} ${_linkdef_header} ) + +ENDMACRO() + + +# ============================================================================ +# macro for generating root dict sources with rootcint +# +# arguments: +# dict_src_filename - filename of the dictionary source (to be generated) +# +# requires following variables: +# ROOT_DICT_INPUT_HEADERS - list of headers needed to generate dict source +# * if LinkDef.h is in the list it must be at the end !! +# ROOT_DICT_INCLUDE_DIRS - list of include dirs to pass to rootcint -I.. +# ROOT_DICT_CINT_DEFINITIONS - extra definitions to pass to rootcint +# ROOT_DICT_OUTPUT_DIR - where dictionary source should be generated +# +# returns: +# ROOT_DICT_OUTPUT_SOURCES - list containing generated source and other +# previously generated sources + +# ---------------------------------------------------------------------------- +MACRO( GEN_ROOT_DICT_SOURCE _dict_src_filename ) + + # TODO check for ROOT_CINT_EXECUTABLE + + # need to prefix all include dirs with -I + set( _dict_includes ) + FOREACH( _inc ${ROOT_DICT_INCLUDE_DIRS} ) + SET( _dict_includes "${_dict_includes}\t-I${_inc}") #fg: the \t fixes a wired string expansion + #SET( _dict_includes ${_dict_includes} -I${_inc} ) + ENDFOREACH() + + STRING( REPLACE "/" "_" _dict_src_filename_nosc ${_dict_src_filename} ) + SET( _dict_src_file ${ROOT_DICT_OUTPUT_DIR}/${_dict_src_filename_nosc} ) + STRING( REGEX REPLACE "^(.*)\\.(.*)$" "\\1.h" _dict_hdr_file "${_dict_src_file}" ) + #message("fucd debug: ${_dict_src_file} ${ROOT_DICT_CINT_DEFINITIONS} ${_dict_includes} ${ROOT_DICT_INPUT_HEADERS}") + ADD_CUSTOM_COMMAND( + OUTPUT ${_dict_src_file} ${_dict_hdr_file} + COMMAND mkdir -p ${ROOT_DICT_OUTPUT_DIR} + COMMAND ${ROOT_CINT_WRAPPER} -f "${_dict_src_file}" -c ${ROOT_DICT_CINT_DEFINITIONS} ${_dict_includes} ${ROOT_DICT_INPUT_HEADERS} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DEPENDS ${ROOT_DICT_INPUT_HEADERS} + COMMENT "generating: ${_dict_src_file} ${_dict_hdr_file}" + ) + LIST( APPEND ROOT_DICT_OUTPUT_SOURCES ${_dict_src_file} ) + +ENDMACRO() + +# for backwards compatibility +MACRO( GEN_ROOT_DICT_SOURCES _dict_src_filename ) + #MESSAGE( "USING DEPRECATED GEN_ROOT_DICT_SOURCES. PLEASE USE GEN_ROOT_DICT_SOURCE instead." ) + SET( ROOT_DICT_OUTPUT_SOURCES ) + GEN_ROOT_DICT_SOURCE( ${_dict_src_filename} ) +ENDMACRO() +# ============================================================================ + diff --git a/Utilities/KalDet/cmake/MyFindROOT.cmake b/Utilities/KalDet/cmake/MyFindROOT.cmake new file mode 100644 index 0000000000000000000000000000000000000000..567ce159fc7b846f509fd6c968be7e292a0e98f9 --- /dev/null +++ b/Utilities/KalDet/cmake/MyFindROOT.cmake @@ -0,0 +1,316 @@ +############################################################################### +# cmake module for finding ROOT +# +# requires: +# MacroCheckPackageLibs.cmake for checking package libraries +# +# Following cmake variables are returned by this module: +# +# ROOT_FOUND : set to TRUE if ROOT found +# If FIND_PACKAGE is called with REQUIRED and COMPONENTS arguments +# ROOT_FOUND is only set to TRUE if ALL components are found. +# If REQUIRED is NOT set components may or may not be available +# +# ROOT_LIBRARIES : list of ROOT libraries (NOT including COMPONENTS) +# ROOT_INCLUDE_DIRS : list of paths to be used with INCLUDE_DIRECTORIES +# ROOT_LIBRARY_DIRS : list of paths to be used with LINK_DIRECTORIES +# ROOT_COMPONENT_LIBRARIES : list of ROOT component libraries +# ROOT_${COMPONENT}_FOUND : set to TRUE or FALSE for each library +# ROOT_${COMPONENT}_LIBRARY : path to individual libraries +# +# +# Please note that by convention components should be entered exactly as +# the library names, i.e. the component name equivalent to the library +# $ROOTSYS/lib/libMathMore.so should be called MathMore and NOT: +# mathmore or Mathmore or MATHMORE +# +# However to follow the usual cmake convention it is agreed that the +# ROOT_${COMPONENT}_FOUND and ROOT_${COMPONENT}_LIBRARY variables are ALL +# uppercase, i.e. the MathMore component returns: ROOT_MATHMORE_FOUND and +# ROOT_MATHMORE_LIBRARY NOT ROOT_MathMore_FOUND or ROOT_MathMore_LIBRARY +# +# +# The additional ROOT components should be defined as follows: +# FIND_PACKAGE( ROOT COMPONENTS MathMore Gdml Geom ...) +# +# If components are required use: +# FIND_PACKAGE( ROOT REQUIRED COMPONENTS MathMore Gdml Geom ...) +# +# If only root is required and components are NOT required use: +# FIND_PACKAGE( ROOT REQUIRED ) +# FIND_PACKAGE( ROOT COMPONENTS MathMore Gdml Geom ... QUIET ) +# then you need to check for ROOT_MATHMORE_FOUND, ROOT_GDML_FOUND, etc. +# +# The variable ROOT_USE_COMPONENTS can also be used before calling +# FIND_PACKAGE, i.e.: +# SET( ROOT_USE_COMPONENTS MathMore Gdml Geom ) +# FIND_PACKAGE( ROOT REQUIRED ) # all ROOT_USE_COMPONENTS must also be found +# FIND_PACKAGE( ROOT ) # check for ROOT_FOUND, ROOT_MATHMORE_FOUND, etc. +# +# @author Jan Engels, DESY +############################################################################### + +# ============================================== +# === ROOT_CONFIG_EXECUTABLE === +# ============================================== + +SET( ROOT_CONFIG_EXECUTABLE ROOT_CONFIG_EXECUTABLE-NOTFOUND ) +MARK_AS_ADVANCED( ROOT_CONFIG_EXECUTABLE ) +# FIND_PROGRAM: Once one of the calls succeeds the result variable will be set and stored in the cache so that no call will search again. +FIND_PROGRAM( ROOT_CONFIG_EXECUTABLE root-config PATHS ${ROOT_DIR}/bin NO_DEFAULT_PATH ) +FIND_PROGRAM( ROOT_CONFIG_EXECUTABLE root-config PATHS $ENV{ROOTSYS}/bin NO_DEFAULT_PATH) +FIND_PROGRAM( ROOT_CONFIG_EXECUTABLE root-config PATHS ENV PATH ) +FIND_PROGRAM( ROOT_CONFIG_EXECUTABLE root-config ) + +IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ROOT_CONFIG_EXECUTABLE: ${ROOT_CONFIG_EXECUTABLE}" ) +ENDIF() + +IF( ROOT_CONFIG_EXECUTABLE ) + + + # ============================================== + # === ROOT_VERSION === + # ============================================== + + INCLUDE( MacroCheckPackageVersion ) + + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --version + OUTPUT_VARIABLE _version + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( _exit_code EQUAL 0 ) + + # set required variables for MacroCheckPackageVersion + STRING(REGEX REPLACE "^([0-9]+).*" "\\1" ROOT_VERSION_MAJOR "${_version}") + STRING(REGEX REPLACE "^[0-9]+.([0-9]+).*" "\\1" ROOT_VERSION_MINOR "${_version}") + STRING(REGEX REPLACE "^[0-9]+.[0-9]+.([0-9]+).*" "\\1" ROOT_VERSION_PATCH "${_version}") + + SET( ROOT_VERSION "${ROOT_VERSION_MAJOR}.${ROOT_VERSION_MINOR}.${ROOT_VERSION_PATCH}" ) + ENDIF() + + CHECK_PACKAGE_VERSION( ROOT ${ROOT_VERSION} ) + + + + # ============================================== + # === ROOT_PREFIX === + # ============================================== + + # get root prefix from root-config output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --prefix + OUTPUT_VARIABLE ROOT_PREFIX + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( NOT _exit_code EQUAL 0 ) + # clear variable if root-config exits with error + # it might contain garbage + SET( ROOT_PREFIX ) + ENDIF() + + # PKG_ROOT variables are a cmake standard + # since this package is also called ROOT the variable name + # becomes ROOT_ROOT ... + SET( ROOT_ROOT ${ROOT_PREFIX} ) + + + + # ============================================== + # === ROOT_BIN_DIR === + # ============================================== + + # get bindir from root-config output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --bindir + OUTPUT_VARIABLE ROOT_BIN_DIR + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( NOT _exit_code EQUAL 0 ) + # clear variable if root-config exits with error + # it might contain garbage + SET( ROOT_BIN_DIR ) + ENDIF() + + + + # ============================================== + # === ROOT_EXECUTABLE === + # ============================================== + + + SET( ROOT_EXECUTABLE ROOT_EXECUTABLE-NOTFOUND ) + MARK_AS_ADVANCED( ROOT_EXECUTABLE ) + FIND_PROGRAM( ROOT_EXECUTABLE root PATHS ${ROOT_BIN_DIR} NO_DEFAULT_PATH ) + + IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ROOT_EXECUTABLE: ${ROOT_EXECUTABLE}" ) + ENDIF() + + + + + # ============================================== + # === ROOT_CINT_EXECUTABLE === + # ============================================== + + + # find rootcint + SET( ROOT_CINT_EXECUTABLE ROOT_CINT_EXECUTABLE-NOTFOUND ) + MARK_AS_ADVANCED( ROOT_CINT_EXECUTABLE ) + FIND_PROGRAM( ROOT_CINT_EXECUTABLE rootcint PATHS ${ROOT_BIN_DIR} NO_DEFAULT_PATH ) + + IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ROOT_CINT_EXECUTABLE: ${ROOT_CINT_EXECUTABLE}" ) + ENDIF() + + + + # ============================================== + # === ROOT_INCLUDE_DIR === + # ============================================== + + # get include dir from root-config output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --incdir + OUTPUT_VARIABLE _inc_dir + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( NOT _exit_code EQUAL 0 ) + # clear variable if root-config exits with error + # it might contain garbage + SET( _inc_dir ) + ENDIF() + + + SET( ROOT_INCLUDE_DIRS ROOT_INCLUDE_DIRS-NOTFOUND ) + MARK_AS_ADVANCED( ROOT_INCLUDE_DIRS ) + + FIND_PATH( ROOT_INCLUDE_DIRS + NAMES TH1.h + PATHS ${ROOT_DIR}/include ${_inc_dir} + NO_DEFAULT_PATH + ) + + + + # ============================================== + # === ROOT_LIBRARIES === + # ============================================== + + # get library dir from root-config output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --libdir + OUTPUT_VARIABLE ROOT_LIBRARY_DIR + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( NOT _exit_code EQUAL 0 ) + # clear variable if root-config exits with error + # it might contain garbage + SET( ROOT_LIBRARY_DIR ) + ENDIF() + + + + # ========== standard root libraries ================= + + # standard root libraries (without components) + SET( _root_libnames ) + + # get standard root libraries from 'root-config --libs' output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --noauxlibs --libs + OUTPUT_VARIABLE _aux + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( _exit_code EQUAL 0 ) + + # create a list out of the output + SEPARATE_ARGUMENTS( _aux ) + + # remove first item -L compiler flag + LIST( REMOVE_AT _aux 0 ) + + FOREACH( _lib ${_aux} ) + + # extract libnames from -l compiler flags + STRING( REGEX REPLACE "^-.(.*)$" "\\1" _libname "${_lib}") + + # fix for some root-config versions which export -lz even if using --noauxlibs + IF( NOT _libname STREQUAL "z" ) + + # append all library names into a list + LIST( APPEND _root_libnames ${_libname} ) + + ENDIF() + + ENDFOREACH() + + ENDIF() + + + + # ========== additional root components ================= + + #LIST( APPEND ROOT_FIND_COMPONENTS Minuit2 ) # DEPRECATED !!! + + + # ---------- libraries -------------------------------------------------------- + INCLUDE( MacroCheckPackageLibs ) + + SET( ROOT_LIB_SEARCH_PATH ${ROOT_LIBRARY_DIR} ) + + # only standard libraries should be passed as arguments to CHECK_PACKAGE_LIBS + # additional components are set by cmake in variable PKG_FIND_COMPONENTS + # first argument should be the package name + CHECK_PACKAGE_LIBS( ROOT ${_root_libnames} ) + + + + + # ====== DL LIBRARY ================================================== + # workaround for cmake bug in 64 bit: + # see: http://public.kitware.com/mantis/view.php?id=10813 + IF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) + FIND_LIBRARY( DL_LIB NAMES ${CMAKE_DL_LIBS} dl PATHS /usr/lib64 /lib64 NO_DEFAULT_PATH ) + ENDIF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) + + FIND_LIBRARY( DL_LIB NAMES ${CMAKE_DL_LIBS} dl ) + MARK_AS_ADVANCED( DL_LIB ) + + IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for libdl.so: ${DL_LIB}" ) + ENDIF() + +ENDIF( ROOT_CONFIG_EXECUTABLE ) + +# Threads library +#FIND_PACKAGE( Threads REQUIRED) + + +# ---------- final checking --------------------------------------------------- +INCLUDE( FindPackageHandleStandardArgs ) +# set ROOT_FOUND to TRUE if all listed variables are TRUE and not empty +# ROOT_COMPONENT_VARIABLES will be set if FIND_PACKAGE is called with REQUIRED argument +FIND_PACKAGE_HANDLE_STANDARD_ARGS( ROOT DEFAULT_MSG ROOT_INCLUDE_DIRS ROOT_LIBRARIES ${ROOT_COMPONENT_VARIABLES} PACKAGE_VERSION_COMPATIBLE DL_LIB ) + +IF( ROOT_FOUND ) + LIST( APPEND ROOT_LIBRARIES ${DL_LIB} ) + # FIXME DEPRECATED + SET( ROOT_DEFINITIONS "-DUSEROOT -DUSE_ROOT -DMARLIN_USE_ROOT" ) + MARK_AS_ADVANCED( ROOT_DEFINITIONS ) + + # file including MACROS for generating root dictionary sources + GET_FILENAME_COMPONENT( _aux ${CMAKE_CURRENT_LIST_FILE} PATH ) + SET( ROOT_DICT_MACROS_FILE ${_aux}/MacroRootDict.cmake ) + +ENDIF( ROOT_FOUND ) + +# ---------- cmake bug -------------------------------------------------------- +# ROOT_FIND_REQUIRED is not reset between FIND_PACKAGE calls, i.e. the following +# code fails when geartgeo component not available: (fixed in cmake 2.8) +# FIND_PACKAGE( ROOT REQUIRED ) +# FIND_PACKAGE( ROOT COMPONENTS geartgeo QUIET ) +SET( ROOT_FIND_REQUIRED ) + diff --git a/Utilities/KalDet/kaldet/EXEventGen.h b/Utilities/KalDet/kaldet/EXEventGen.h new file mode 100644 index 0000000000000000000000000000000000000000..bea7bee87b844e42a2a1d2ef97e6f1c4d0d1cb64 --- /dev/null +++ b/Utilities/KalDet/kaldet/EXEventGen.h @@ -0,0 +1,33 @@ +#ifndef __EXEVENTGEN__ +#define __EXEVENTGEN__ + +#include "TKalDetCradle.h" +#include "THelicalTrack.h" +#include "TMath.h" + +class EXEventGen { +public: + EXEventGen(TKalDetCradle const &cradle, TObjArray &kalhits) + : fCradlePtr(&cradle), fHitBufPtr(&kalhits) {} + virtual ~EXEventGen() {} + + THelicalTrack GenerateHelix(Double_t pt, + Double_t cosmin, + Double_t cosmax, + Double_t phimin=0., + Double_t phimax=2*TMath::Pi(), + TVector3 xv0=TVector3(0.,0.,0.)); + void Swim(THelicalTrack &heltrk); + + static void SetT0(Double_t t0) { fgT0 = t0; } + static Double_t GetT0() { return fgT0; } + +private: + TKalDetCradle const *fCradlePtr; // pointer to detector system + TObjArray *fHitBufPtr; // pointer to hit array + + static Double_t fgT0; // t0 + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/EXTPCHit.h b/Utilities/KalDet/kaldet/EXTPCHit.h new file mode 100644 index 0000000000000000000000000000000000000000..8d604c36f5b3120156e030626f293e312aa3dac6 --- /dev/null +++ b/Utilities/KalDet/kaldet/EXTPCHit.h @@ -0,0 +1,54 @@ +#ifndef LCTPC_EXTPCHIT_H +#define LCTPC_EXTPCHIT_H + +#include "GearTPCCylinderHit.h" +#include <kaltest/TVMeasLayer.h> + +/** + * A backward compatibility class for GearTPCCylinderHit. + * Do not use this in new code, but use GearTPCCylinderHit directly. + * This class extends the GearTPCCylinderHit by a side, which is never used anywhere. + * + * \deprecated EXTPCHit + */ + +class EXTPCHit : public kaldet::GearTPCCylinderHit +{ + public: + /// The default constructor. + EXTPCHit(Int_t m = kMdim); + + /// Constructor initialising the original hit as 3D coordinates. + EXTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const TVector3 &xx, + Double_t b, + Int_t m = kMdim); + + /// Constructor initialising the original hit with a reference pointer. + EXTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const void *hitp, + Double_t b, + Int_t m = kMdim); + + /// The destructor. + virtual ~EXTPCHit(); + + /// Get the side value which has been set in the constructor. + inline Int_t GetSide () const { return fSide; } + + private: + Int_t fSide; /// (-1, +1) = (-z side, +z side) + + // ClassDef(EXTPCHit, 1) // EXTPC hit class + +}; + +#endif // LCTPC_EXTPCHIT_H diff --git a/Utilities/KalDet/kaldet/EXTPCKalDetector.h b/Utilities/KalDet/kaldet/EXTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..96025f38d7ac92b6ac795935ca71b793a2b25799 --- /dev/null +++ b/Utilities/KalDet/kaldet/EXTPCKalDetector.h @@ -0,0 +1,45 @@ +#ifndef LCTPC_EXTPCKALDETECTOR_H +#define LCTPC_EXTPCKALDETECTOR_H + +#include "GearTPCKalDetector.h" + +/** + * A backward compatibility class for GearTPCKalDetector. + * It basically provides a static instance of the detector which can be + * accessed via the GetInstance() method. + * In addition it provides the static GetVDrift() and GetBField(), which are used + * in the old code. The use of this class is highly depreciated. + * + * \deprecated EXTPCKalDetector + */ + +class EXTPCKalDetector: public kaldet::GearTPCKalDetector +{ + private: + /// As this this a singleton class the constructor is private. + EXTPCKalDetector(const gear::GearMgr& gearMgr); + +public: + /// The destructor. + virtual ~EXTPCKalDetector(); + + /// Static access function to the singleton instance. + static EXTPCKalDetector * GetInstance(); + + /// Returns the hard coded drift velocity of 76.e-3 mm/ns. + static Double_t GetVdrift() { return fgVdrift; } + + /// Static function to access the magnetic field. + static Double_t GetBfield(); + + private: + static Double_t fgVdrift; //< The drift velocity. + static EXTPCKalDetector * fgInstance; //< The singleton pointer. + + Double_t fBField; //< The magnetic field + + // ClassDef(EXTPCKalDetector, 1) // User defined detector class + +}; + +#endif // LCTPC_EXTPCKALDETECTOR_H diff --git a/Utilities/KalDet/kaldet/EXTPCMeasLayer.h b/Utilities/KalDet/kaldet/EXTPCMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..3557ae56f0f3b46757fc53446cb2707d918b327d --- /dev/null +++ b/Utilities/KalDet/kaldet/EXTPCMeasLayer.h @@ -0,0 +1,83 @@ +#ifndef LCTPC_EXTPCMEASLAYER_H +#define LCTPC_EXTPCMEASLAYER_H + +#include "GearTPCMeasLayer.h" +#include <kaltest/TCylinder.h> + +/** + * A backward compatibility class for GearTPCCylinderMeasLayer. + * It introduces one module and one row, which are associated to the layer. + * This is deprecated, the GearTPCCylinderMeasLayer provides an assiciation of several + * module-row pairs to the layer. + + * This class is an intermediate inheritance class so a GearTPCCylinderMeasLayer can be + * instantiated (as should be in the current code) and the old code can cast the + * TObject pointer, which is delivered by the detector cradle, to an EXTPCMeasLayer. + * + * \attention Do not use any of these function in new code. All new code should still run + * after this class has been removed from the ineritance chain. + * + * \deprecated EXTPCMeasLayer + */ +class EXTPCMeasLayer : public kaldet::GearTPCMeasLayer, public TCylinder +{ + +public: + /// Minimal constructor for this (partially) virtual class. + EXTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Double_t r0, + Double_t lhalf, + TVector3 xc, + Bool_t isPerfect, + Bool_t isActive, + Double_t sigmaX0 = 0., //< the constant part of sigmaX + Double_t sigmaX1 = 0., //< the z-dependent part of sigmaX + Double_t sigmaZ0 = 0., //< the constant part of sigmaZ + Double_t sigmaZ1 = 0.); //< the z-dependent part of sigmaZ + + /// The destructor. + virtual ~EXTPCMeasLayer(); + + /** + * Get the module associated with this layer (deprecated). + * \attention Do not programme against this when using the GearTPC interface. + * This is for backward compatibility only!!! + */ + Int_t GetModuleID() const; + + /** + * Get the layer ID (i.\ e.\ row in the module) associated with this Kalman layer (deprecated). + * + * \attention Do not programme against this when using the GearTPC interface. + * This is for backward compatibility only!!! + */ + Int_t GetLayerID () const; + + /** Deprecated XvToMv which in addition to the position takes a side. + * Side is ignored and XvToMv without the side is called. + * \attention Do not programme against this when using the GearTPC interface. + * This is for backward compatibility only!!! + */ + TKalMatrix XvToMv(const TVector3 &xv, Int_t side) const; + + /** The fully virtual declaration of XvToMv. It is called within the version which also takes + * the side argument, but is implemented in GearTPCCylinderMeasLayer. + */ + virtual TKalMatrix XvToMv(const TVector3 &xv) const = 0; + + /** Smear the incoming hit in the layes measurement surface and place the result into the TObjArray + * which is given as argument. + * From a design point of view this function should not be in the detector class but in a + * simulation extension. It is only put in for compatibility reasons. + * \attention Do not programme against this when using the GearTPC interface. + * This is for backward compatibility only!!! + */ + virtual void ProcessHit(const TVector3 &xx, TObjArray &hits) const; + + //ClassDef(EXTPCMeasLayer, 1) // User defined measurement layer class +}; + +#endif // LCTPC_EXTPCMEASLAYER_H diff --git a/Utilities/KalDet/kaldet/EXVKalDetector.h b/Utilities/KalDet/kaldet/EXVKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..bb1e09cb113920577879dfa220d8017b8f5941ce --- /dev/null +++ b/Utilities/KalDet/kaldet/EXVKalDetector.h @@ -0,0 +1,67 @@ +#ifndef EXVKALDETECTOR_H +#define EXVKALDETECTOR_H +//************************************************************************* +//* ====================== +//* EXVKalDetector Class +//* ====================== +//* +//* (Description) +//* Abstract detector class for Kalman filter +//* (Requires) +//* TVKalDetector +//* (Provides) +//* class EXVKalDetector +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/kern/EXVKalDetector.h +//* +//* $Id: EXVKalDetector.h,v 1.1.1.1 2009-11-24 00:13:59 ikematsu Exp $ +//************************************************************************* +// +#include <TVector3.h> +#include <kaltest/TVKalDetector.h> +#include <kaltest/TAttDrawable.h> + +class TNode; + +/** + * Base class to make a detector drawable, add a magnetic field, + * a power switch (whatever the use may be). + * + * Killenb: I removed the TAttDrawable for the moment. The TNode pointer + * stuff and the implementation of Draw belong to the TAttDrawable anyway. So if + * the drawability is needed move it to TAttDrawable and just inherit from it. + * + * \deprecated EXVKalDetector + */ +class EXVKalDetector : public TVKalDetector, public TAttDrawable { + //class EXVKalDetector : public TVKalDetector { +public: + EXVKalDetector(Double_t bField, Int_t m = 100); + virtual ~EXVKalDetector(); + + /// Return whether the power is on. Currently hard coded to true. + inline virtual Bool_t IsPowerOn() const { return true; } + + /// Turn the power on. Currently ignored. + inline virtual void PowerOn () { fIsPowerOn = kTRUE; } + + /// Turn the power off. Currently ignored. + inline virtual void PowerOff () { fIsPowerOn = kFALSE; } + + /// Returns a single double value with a 3D point as an input. + /// Completely unphysical interface. Either the magnetic field varies with the position, + /// in which case you need a three-dimensional return value, or B can be desrcibed as single + /// value, which means it is homogeneous and thus indepenent from the position. + /// Currently it does the only reasonable thing: It ignores the argument and returns the + /// constant value given in the constructor. + virtual Double_t GetBfield (const TVector3 &xx = TVector3(0.,0.,0.)) const + { return fBfield; } + +protected: + Bool_t fIsPowerOn; // power status + Double_t fBfield; // magnetic field [T] + + ClassDef(EXVKalDetector, 1) // Abstract measurement layer class +}; +#endif diff --git a/Utilities/KalDet/kaldet/EXVMeasLayer.h b/Utilities/KalDet/kaldet/EXVMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..db456868c0886921699599834ace276b7d54d426 --- /dev/null +++ b/Utilities/KalDet/kaldet/EXVMeasLayer.h @@ -0,0 +1,60 @@ +#ifndef EXVMEASLAYER_H +#define EXVMEASLAYER_H +//************************************************************************* +//* ==================== +//* EXVMeasLayer Class +//* ==================== +//* +//* (Description) +//* Abstract measurement layer class used by TVTrackHit +//* (Requires) +//* TVMeasLayer +//* (Provides) +//* class EXVMeasLayer +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/kern/EXVMeasLayer.h +//* +//* $Id: EXVMeasLayer.h,v 1.1.1.1 2009-11-24 00:13:59 ikematsu Exp $ +//************************************************************************* +// +#include <TVector3.h> +#include <kaltest/TKalMatrix.h> +#include <kaltest/TCylinder.h> +#include <kaltest/TVMeasLayer.h> +#include <kaltest/TAttDrawable.h> +#include <kaltest/KalTrackDim.h> +#include <TString.h> + +class TVTrackHit; +#include <TNode.h> + +class EXVMeasLayer : public TVMeasLayer, public TAttDrawable { + +public: + static Bool_t kActive; + static Bool_t kDummy; + + // Ctors and Dtor + + EXVMeasLayer(TMaterial &min, + TMaterial &mout, + Bool_t type = EXVMeasLayer::kActive, + const Char_t *name = "MeasL"); + virtual ~EXVMeasLayer(); + + virtual void ProcessHit(const TVector3 &xx, + TObjArray &hits) const = 0; + + inline TString GetMLName () const { return fName; } + inline TNode *GetNodePtr() const { return fNodePtr; } + + inline void SetNodePtr(TNode *nodep) { fNodePtr = nodep; } + +private: + TString fName; // layer name + TNode *fNodePtr; // node pointer + + ClassDef(EXVMeasLayer, 1) // Abstract measurement layer class +}; +#endif diff --git a/Utilities/KalDet/kaldet/GearTPCCylinderHit.h b/Utilities/KalDet/kaldet/GearTPCCylinderHit.h new file mode 100644 index 0000000000000000000000000000000000000000..109a122019392d6a863696d97f761a2c5e1b1c7b --- /dev/null +++ b/Utilities/KalDet/kaldet/GearTPCCylinderHit.h @@ -0,0 +1,55 @@ +#ifndef GEARTPCCYLINDERHIT_H +#define GEARTPCCYLINDERHIT_H + +#include <KalTrackDim.h> +#include "GearTPCHit.h" +#include <TVMeasLayer.h> + +namespace kaldet{ + +/** The cylindrical implementation of the GearTPCHit. + */ +class GearTPCCylinderHit : public GearTPCHit { + +public: + /// KILLENB What does this constructor do? Best throw it out, it does not + /// properly initialise the class at all, does it? + GearTPCCylinderHit(Int_t m = kMdim); + + /** Constructor to initialise the GearTPCHit using space point coordinates (TVector3) as original hit. + */ + GearTPCCylinderHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const TVector3 &xx, + Double_t b, + Double_t v, + Int_t m = kMdim); + + /** Constructor using a pointer to the original hit as reference. + */ + GearTPCCylinderHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const void *hitp, + Double_t b, + Double_t v, + Int_t m = kMdim); + + /** The dectructor. + */ + virtual ~GearTPCCylinderHit(); + + /** Implementation of the space vector (xv) to measurement vector (mv) calculation + * for a cylindrical hit. + */ + virtual TKalMatrix XvToMv(const TVector3 &xv, Double_t t0) const; + + /** Print some debug output to std err. + */ + virtual void DebugPrint(Option_t *opt = "") const; +}; + +}//namespace kaldet + +#endif //GEARTPCCYLINDERHIT_H diff --git a/Utilities/KalDet/kaldet/GearTPCCylinderMeasLayer.h b/Utilities/KalDet/kaldet/GearTPCCylinderMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..90f7386bbf2bc9e4d9fc5a713f64edc58d9b8a4e --- /dev/null +++ b/Utilities/KalDet/kaldet/GearTPCCylinderMeasLayer.h @@ -0,0 +1,131 @@ +#ifndef GEARTPCCYLINDERMEASLAYER_H +#define GEARTPCCYLINDERMEASLAYER_H +#include <TVector3.h> +#include <TKalMatrix.h> +#include <TCylinder.h> +#include <EXTPCMeasLayer.h> +//#include <KalTrackDim.h> + +#include <TMath.h> + +#include <set> + +class TVTrackHit; + +namespace kaldet +{ + + /** + * A cylindrical measurement layer. + */ + class GearTPCCylinderMeasLayer + : public EXTPCMeasLayer + /* this is the original code which should be reactivated once the EXTPCMeasLayer is phased out: + : public GearTPCMeasLayer, public TCylinder + */ + { + + public: + /** The constructor. + * If the layer is perfect it is always a full circle. The constructor forces + * phiMin and phiMax to +-TMath::Pi(). Differing values will be ignored and a warning is + * printed. + * + * Note: The current implementation forces the layer to be perfect. Segmented layers are + * not supported yet. + * + * Note: for backward compatibility this is derrived from EXTPCMeasLayer. + * After the change to the GearTPC interface this should be changed to GearTPCMeasLayer and + * TCylinder, as EXTPCMeasLayer is inherrited now. + * The current version ensures compatibility for the transition phase. + */ + GearTPCCylinderMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Double_t r0, + Double_t lhalf, + TVector3 xc = TVector3(), + Bool_t isPerfect = true, + Bool_t isActive = true, + Double_t sigmaX0 = 0., + Double_t sigmaX1 = 0., + Double_t sigmaZ0 = 0., + Double_t sigmaZ1 = 0., + Double_t phiMin = -TMath::Pi(), + Double_t phiMax = TMath::Pi()); + + /** + * The desctructor. + */ + virtual ~GearTPCCylinderMeasLayer(); + + // Parent's pure virtuals that must be implemented + + /** Implements kaltest::TVMeasLayer's XvToMv. I have no idea why there are two arguments. + * It ignores ht and just calls XvToMv(xv). + */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const; + + /** Implements the coordinate transformation from the space vector xv to the + * measurement vector (Kalman matrix). + */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Implements the conversion from a Kalman hit (measurement vector) to + * a 3D space point. + */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** + * Implements CalcDhDa, whatever that is. + */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + /** Implements the sorting policy. + * The layers are first sorted by radius + offset. This offset is only + * useful for segments of a cylinder, like the LP1. + * As offsets in this case can be positive or negative, but only make sense in one + * direction (you need a continuous number), we only allow offsets in x. + * This should not be too much of a problem, you should be able to rotate your coordinates + * so the offset is in x. If not you have to extend the sorting policy. (Please thake + * care not to reduce versatility when doing so. You might want to implement your own class?) + * + * For equal radii + offset the layers are sorted by moduleID. As we have to squeeze this + * information into only one number, we multiply the radius + offset by 1e9 and add the moduleID. + * A double has a precision of 53 bits, which is 15.9 digits. So the radius can be up to 1e6.9 mm + * without causing the last digit of the the ModuleID to be cut, and for up to 1000 modules the + * layers can be distinguished down to 1 nm without the two numbers mixing, or down to 1 micron + * with up to 1.000.000 modules. + * + * The additional sorting by module is intended for cylinder segments. Here only one module/row + * per layer is allowed, so we just take the first entry in the set. In case of a perfect layer + * it does not matter because there should only be one layer at this radius, so the sort order + * should not be affected by adding an arbitrary module ID (as long as the module ID is < 1e6, as + * described above). + */ + virtual Double_t GetSortingPolicy() const; + + /** + * Creates a GearTPCCylinderHit and hands over the ownership. + */ + virtual GearTPCHit * createHit(Double_t * meas, + Double_t * dmeas, + void * hitPointer, + Double_t bField, + Double_t vDrift, + Int_t m = kMdim) const; + + + +protected: + Double_t fPhiMin; //< Minimum phi. + Double_t fPhiMax; //< Maximum phi. + +}; + +}//namespace kaldet +#endif diff --git a/Utilities/KalDet/kaldet/GearTPCHit.h b/Utilities/KalDet/kaldet/GearTPCHit.h new file mode 100644 index 0000000000000000000000000000000000000000..aafbb71e7dfd77b43f0f2af28f4d713503512a4c --- /dev/null +++ b/Utilities/KalDet/kaldet/GearTPCHit.h @@ -0,0 +1,94 @@ +#ifndef GEARTPCHIT_H +#define GEARTPCHIT_H + +#include <KalTrackDim.h> +#include <TVTrackHit.h> +#include <TVMeasLayer.h> + +namespace kaldet{ + +/** Base class of a hit for GearTPCKalDetector. It extends the TVTrackHit with the functionality to + * store a space point or a pointer to the original hit for reference. In addition it stores + * the local drift velocity and allows sorting of the hits (according to the distance to the + * origin). + * + * It does not implement the purely virtual functions of the TVTrackHit, which happens in the + * specialisations for cylindrical and planar measurement layers. + */ +class GearTPCHit : public TVTrackHit { + +public: + /// KILLENB What does this constructor do? Best throw it out, it does not + /// properly initialise the class at all, does it? + GearTPCHit(Int_t m = kMdim); + + /** Constructor to initialise the GearTPCHit using space point coordinates (TVector3) as original hit. + */ + GearTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const TVector3 &xx, + Double_t b, + Double_t v, + Int_t m = kMdim); + + /** Constructor using a pointer to the original hit as reference. + */ + GearTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const void *hitp, + Double_t b, + Double_t v, + Int_t m = kMdim); + + /** The dectructor. + */ + virtual ~GearTPCHit(); + + /** + * The sorting policy of hits is implemented as the distance to the origin. + * + * Note: The sorting of hits does not necessarily correspond to the sort order of + * the corresponding Kalman layer! + */ + virtual Double_t GetSortingPolicy() const; + + /** + * Compare two hits according to their sorting policy. + * Returns + * \li -1 if this hits sorting policy is smaller + * \li 0 if both soting policies are equal + * \li 1 if this hits hits sortin policy is larger + * + * Killenb: n.b. Who comes up with this wierd stuff? Ever head of anything like a + * `less than operator` or `comparison operator`? + */ + virtual Int_t Compare(const TObject *obj) const; + + /** + * Returns true. + */ + virtual Bool_t IsSortable() const; + + /// Get the pointer to the reference hit. 0 if the TVector3 has been used for initialisation. + inline const void *GetHitPtr() const { return fHitPtr; } + + /// Get the referece position. (0, 0, 0) if the reference pointer has been used for initialisation. + inline TVector3 GetExactX() const { return *fXXPtr; } + + /// Get the local drift velocity set in the constructor. + inline Double_t GetVdrift() const { return fVDrift; } + +protected: + const TVector3 *fXXPtr; //< pointer to exact hit + const void *fHitPtr; //< pointer to raw Hit object + + Double_t fVDrift; //< the local drift veclocity at this point + + +}; + +}//namespace kaldet + +#endif diff --git a/Utilities/KalDet/kaldet/GearTPCKalDetector.h b/Utilities/KalDet/kaldet/GearTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..800934a5dce925b27ac6460cec8ad011494a662c --- /dev/null +++ b/Utilities/KalDet/kaldet/GearTPCKalDetector.h @@ -0,0 +1,77 @@ +#ifndef GEARTPCKALDETECTOR_H +#define GEARTPCKALDETECTOR_H + +#include "kaltest/TVKalDetector.h" + +#include "GearTPCMeasLayer.h" + +#include <map> + +namespace gear{ + class GearMgr ; +} + +namespace kaldet{ + + /** + * The LCTPC implementation for a TPC which is completely instantiated from GEAR. + * + */ +class GearTPCKalDetector : public TVKalDetector { + +public: + /** + * The constructor. All information to initialise the TPC is taken from GEAR. + * + * As a pragmatic approach to avoid dealing with conditions data and material databases, + * the information about the material budget and the resolution of the layers + * is taken from the GEAR file as user parameters. If the parameters are not found in the + * file the previously hard coded parameters are used as default, which ensures backward + * compatibility. + * + * The gas properties for the matrial budget can be given as user parameters + * for the TPCParameters: + * \param TPCGas_A The mean atomic mass (default 36.2740552) + * \param TPCGas_Z The mean number of protons (default 16.4) + * \param TPCGas_density The density (default 0.749e-3 in which units?) + * \param TPCGas_radlen The radiation length (default 2.392e4 in which units?) + * + * The default gas parameters (are supposed to) correspond to Ar/CH4 90/10. + * N.B.: KILLENB: I think there is a bug in the calculation, the mean A should be + * 37.6 instead of 36.3 (see source code). + * In addition the description as a single TMaterial is not good. + * Using TMixture would be better. + * + * The reslution is calculated as \f$\sigma_x = \sqrt{x_0^2 + x_1^2 \cdot z}\f$. + * This requires z to be proportional to the drift distance, i.\ e. z=0 is at the readout. + + * The resolution of the layers can be given as user parameters in each TPCModule + * section of the GEAR xml file. + * \param sigmax0 The constant part of the x resolution (default 38.3e-3 mm) + * \param sigmax1 The drift distance dependent part of the x resolution + * (default 6.74e-3 mm/sqrt(mm) ) + * \param sigmaz0 The constant part of the z resolution (default 0.5 mm) + * \param sigmaz1 The drift distance dependent part the z resolution + * (default 10.2e-3 mm/sqrt(mm) ) + */ + GearTPCKalDetector(const gear::GearMgr& gearMgr); + + /// The destructor. + virtual ~GearTPCKalDetector(); + + /** + * Get access to the measurement layers using moduleID and row. + * Do not directly access the measurement layers using At() + * because the order depends on the order in the gear file. + * Throws a gear::Exception if the row on the module is not defined. + */ + virtual GearTPCMeasLayer const * GetMeasLayer(int moduleID, int row) const; + +protected: + /// Map which contains the information which measurement layer is stored + /// at which position in the array. + std::map< std::pair<int, int >, Int_t > moduleRowToMeasurementLayerMap; +}; + +}// namespace kaldet +#endif //GEARTPCKALDETECTOR_H diff --git a/Utilities/KalDet/kaldet/GearTPCMeasLayer.h b/Utilities/KalDet/kaldet/GearTPCMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..3e2d0193d14a9e1fdf442a924b1b533d7f3f7eb5 --- /dev/null +++ b/Utilities/KalDet/kaldet/GearTPCMeasLayer.h @@ -0,0 +1,123 @@ +#ifndef GEARTPC_MEASLAYER_H +#define GEARTPC_MEASLAYER_H + +#include "kaltest/TVMeasLayer.h" +#include <set> + +namespace kaldet +{ + + class GearTPCHit; + + /** + * The GearTPCMeasLayer class introduces the z-dependent resolutions sigmaX and sigmaZ + * as well as Gear modules and rows which correspond to this layer. + * + * If the layer is defined as a perfect layer this means all modules are perfectly alligned + * and more than one module/row can be assigned to this layer. You can add them using AddModuleRow. + * The perfect layer should contain all the moduleRows on it, so it is guaranteed that the + * user can access all neighbouring modules this way. + * + * If the layer is not defined as perfect (default) there can only be one module on this layer. + * Calling AddModuleRow will throw an exception. This is the default behaviour because Gear does + * not guarantee that the modules are alligned. Displaced modules do not make up a perfect + * cylinder / plane and have to be treated as separate segments. Finding a neighbouring module/row + * is not trivial and has to be left to the user or a future Gear version. + */ + + class GearTPCMeasLayer + : public TVMeasLayer + { + + public: + /** The constructor. + * The materials and the type (active or passive) are passed on to the + * TVMeasLayer. sigmaX0 [mm] is the constant part of sigmaX, sigmaX1 [mm/sqrt(mm)] + * the z-dependent part, accordingly for sigmaZ. + * + * Module and row have to be specified. They will be added as the first + * module/row pair of this measurement layer. + * For a perfect layer modules can be added with AddModuleRow. + * + * Note: This class cannot be instantiated because the parent's geometry dependent + * purely virtual + * functions like XvToMv are not implemented. This will happen in the cylindrical or planar + * implementations. + * + * For inactive layers you will usually leave the sigmas at 0, they have no useful meaning in + * this case. + */ + GearTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Bool_t isPerfect, + Bool_t isActive, + Double_t sigmaX0 = 0., //< the constant part of sigmaX + Double_t sigmaX1 = 0., //< the z-dependent part of sigmaX + Double_t sigmaZ0 = 0. , //< the constant part of sigmaZ + Double_t sigmaZ1 = 0.); //< the z-dependent part of sigmaZ + + /// The destructor + virtual ~GearTPCMeasLayer(); + + /** + * A perfect measurement layer contains all the modules with rows (row segments) + * that make up the layer. + */ + virtual std::set< std::pair <int, int> > const & GetModuleRows() const; + + /** + * Add another row on another module which lies on the same cylinder. + */ + virtual void AddModuleRow(int module, int row); + + /** + * Get the measurement vector (mv) for this layer from a space point (xv) + */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const = 0; + + /** + * Get the z-depenent resolution in the readout plane + * (usually x or r\f$\phi\f$). + */ + virtual Double_t GetSigmaX(Double_t z) const; + + /** + * Get the z-depenent resolution in z (drift direction). + */ + virtual Double_t GetSigmaZ(Double_t z) const; + + + /** + * Get the flag whether the layer is declared as perfect. + */ + virtual Bool_t IsPerfect() const; + + /** + * A virtual function to create the appropriate hit. Depending on the implementation + * (cylindrical or straight measurement layer) you get the appropriate implementation + * of GearTPCHit. + * It creates a new hit on the heap and hands over the ownership. + */ + virtual GearTPCHit * createHit(Double_t * meas, + Double_t * dmeas, + void * hitPointer, + Double_t bField, + Double_t vDrift, + Int_t m = kMdim) const = 0; + + protected: + Double_t fSigmaX0; // xy resolution + Double_t fSigmaX1; // xy resolution + Double_t fSigmaZ0; // z resolution + Double_t fSigmaZ1; // z resolution + + /// A set to hold all the module/row combinations associated to this layer + std::set< std::pair<int, int> > fModuleRows; + + Bool_t fIsPerfect; + }; + +}// namespace kaldet +#endif // GEARTPC_MEASLAYER_H diff --git a/Utilities/KalDet/kaldet/ILDConeMeasLayer.h b/Utilities/KalDet/kaldet/ILDConeMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..00e9fb0611e760c211a854bbf55cf93b8f1ef25c --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDConeMeasLayer.h @@ -0,0 +1,99 @@ +#ifndef ILDCONEMEASLAYER_H +#define ILDCONEMEASLAYER_H +//************************************************************************* +//* =================== +//* ILDConeMeasLayer Class +//* =================== +//* +//* (Update Recored) +//* 2012/01/19 K.Fujii Original version. (EXBPConeMeasLayer) +//* 2012/01/24 R.Glattauer Adapted to ILD common in KalDet +//* +//************************************************************************* +// +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TCutCone.h" +#include "kaltest/KalTrackDim.h" + +#include "ILDVMeasLayer.h" +#include "iostream" +/* #include "streamlog/streamlog.h" */ +#include "UTIL/ILDConf.h" +#include "edm4hep/TrackerHit.h" + +class ILDConeMeasLayer : public ILDVMeasLayer, public TCutCone { +public: + // Ctors and Dtor + /** Constructor Taking inner and outer materials, z and radius at start and end, B-Field, whether the layer is sensitive, Cell ID, and an optional name */ + ILDConeMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t z1, + Double_t r1, + Double_t z2, + Double_t r2, + Double_t Bz, + Double_t SortingPolicy, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "BPCONEML"); + virtual ~ILDConeMeasLayer(); + + // Parrent's pure virtuals that must be implemented + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const; + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + Bool_t IsOnSurface(const TVector3 &xx) const; + + /** Convert LCIO Tracker Hit to an ILDCylinderHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + + /* streamlog_out( ERROR ) << "Don't use this, it's not implemented!"; */ + return NULL; + } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return this->CalcXingPointWith(hel,xx,phi,0,eps); + + + } + + /** Get sorting policy for this plane */ + virtual double GetSortingPolicy() const { return fsortingPolicy; } + + + + +private: + Double_t fZ1; // z of front face + Double_t fR1; // r of front face + Double_t fZ2; // z of back end + Double_t fR2; // r of back end + Double_t fsortingPolicy; // used for sorting the layers in to out + + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDCylinderHit.h b/Utilities/KalDet/kaldet/ILDCylinderHit.h new file mode 100644 index 0000000000000000000000000000000000000000..9dbe5b73ef225aa41f7b06cf54d5775166073da3 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDCylinderHit.h @@ -0,0 +1,38 @@ +#ifndef ILDCYLINDERHIT_H +#define ILDCYLINDERHIT_H + +/** ILDCylinderHit: User defined KalTest hit class using R and Rphi coordinates, which provides coordinate vector as defined by the MeasLayer + * + * @author S.Aplin DESY + */ + +#include "kaltest/KalTrackDim.h" +#include "ILDVTrackHit.h" + + +class ILDCylinderHit : public ILDVTrackHit { + +public: + + + /** Constructor Taking R and Rphi coordinates and associated measurement layer, with bfield */ + ILDCylinderHit(const TVMeasLayer &ms, Double_t *x, Double_t *dx, + Double_t bfield, edm4hep::TrackerHit* trkhit ) + : ILDVTrackHit(ms, x, dx, bfield, 2, trkhit) + { /* no op */ } + + + // TVTrackHit's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv(const TVector3 &xv, Double_t t0) const; + + /** Print Debug information */ + virtual void DebugPrint(Option_t *opt = "") const; + + +private: + + +}; +#endif diff --git a/Utilities/KalDet/kaldet/ILDCylinderMeasLayer.h b/Utilities/KalDet/kaldet/ILDCylinderMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..04740cc81edde2029bc347dc50a481001a2f2740 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDCylinderMeasLayer.h @@ -0,0 +1,93 @@ +#ifndef ILDCYLINDERMEASLAYER_H +#define ILDCYLINDERMEASLAYER_H + +/** ILDCylinderMeasLayer: User defined KalTest measurement layer class + * + * @author S.Aplin DESY + */ + + +#include "ILDVMeasLayer.h" +#include <iostream> +#include <cmath> +/* #include "streamlog/streamlog.h" */ + + +class ILDCylinderMeasLayer : public ILDVMeasLayer, public TCylinder { + +public: + + /** Constructor Taking inner and outer materials, radius and half length, B-Field, whether the layer is sensitive, Cell ID, and an optional name */ + ILDCylinderMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t r0, + Double_t lhalf, + Double_t x0, + Double_t y0, + Double_t z0, + Double_t Bz, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDCylinderMeasL") + : ILDVMeasLayer(min, mout, Bz, is_active, CellID, name), + TCylinder(r0, lhalf,x0,y0,z0) + { /* no op */ } + + + Bool_t IsOnSurface(const TVector3 &xx) const { + + bool z = (xx.Z() >= GetZmin() && xx.Z() <= GetZmax()); + bool r = std::fabs( (xx-this->GetXc()).Perp() - this->GetR() ) < 1.e-3; // for very short, very stiff tracks this can be poorly defined, so we relax this here a bit to 1 micron + +// streamlog_out(DEBUG0) << "ILDCylinderMeasLayer IsOnSurface for " << this->TVMeasLayer::GetName() << " R = " << this->GetR() << " GetZmin() = " << GetZmin() << " GetZmax() = " << GetZmax() +// << " dr = " << std::fabs( (xx-this->GetXc()).Perp() - this->GetR() ) << " r = " << r << " z = " << z +// << std::endl; + + return r && z; + } + + + + // Parent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + + { return this->XvToMv(xv); } + + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDCylinderHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return this->CalcXingPointWith(hel,xx,phi,0,eps); + + } + + +private: + +}; +#endif diff --git a/Utilities/KalDet/kaldet/ILDDiscMeasLayer.h b/Utilities/KalDet/kaldet/ILDDiscMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..fe3ff82672144da1330120ebe3a8a26d56ae21d4 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDDiscMeasLayer.h @@ -0,0 +1,101 @@ +#ifndef __ILDDISCMEASLAYER__ +#define __ILDDISCMEASLAYER__ + +/** ILDDiscMeasLayer: User defined KalTest Disc measurement layer class used with ILDPLanarTrackHit. + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> + +class TVTrackHit; + + +class ILDDiscMeasLayer : public ILDVMeasLayer, public TPlane { + +public: + + /** Constructor Taking inner and outer materials, center and normal to the plane, B-Field, sorting policy, min and max r, whether the layer is sensitive, Cell ID, and an optional name */ + + ILDDiscMeasLayer(TMaterial &min, + TMaterial &mout, + const TVector3 ¢er, + const TVector3 &normal, + double Bz, + double SortingPolicy, + double rMin, + double rMax, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDDiscMeasL") + : ILDVMeasLayer(min, mout, Bz, is_active, CellID, name), + TPlane(center, normal), + _sortingPolicy(SortingPolicy), _rMin(rMin), _rMax(rMax) + { /* no op */ } + + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps) const; + + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** Check if global point is on surface */ + inline virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + /** Get sorting policy for this plane */ + double GetSortingPolicy() const { return _sortingPolicy; } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return this->CalcXingPointWith(hel,xx,phi,0,eps); + + } + +private: + double _sortingPolicy; + double _rMin; + double _rMax; + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDFTDDiscBasedKalDetector.h b/Utilities/KalDet/kaldet/ILDFTDDiscBasedKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..c8536c6403b54d650ac0418ab2e845ec5f21053b --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDFTDDiscBasedKalDetector.h @@ -0,0 +1,44 @@ +#ifndef __ILDFTDDISCBASEDDETECTOR__ +#define __ILDFTDDISCBASEDDETECTOR__ + +/** Disk based version of the FTD alla LOI +* +* @author S.Aplin DESY +*/ + +#include "kaltest/TVKalDetector.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDFTDDiscBasedKalDetector : public TVKalDetector { +public: + + /** Initialize the FTD from GEAR */ + ILDFTDDiscBasedKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + int _nDisks ; + double _bZ ; + + struct FTD_Disk { + double rInner; + double rOuter; + double senThickness; + double supThickness; + double zPos; + + }; + std::vector<FTD_Disk> _FTDgeo; + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDFTDKalDetector.h b/Utilities/KalDet/kaldet/ILDFTDKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..36cf54b8e5a889a09431635740c3e2c3035d6d6a --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDFTDKalDetector.h @@ -0,0 +1,92 @@ +#ifndef __ILDFTDDETECTOR__ +#define __ILDFTDDETECTOR__ + +/** Petal based FTD to be used for ILD DBD studies + * WARNING: Still very experimental + * + * @author S.Aplin DESY, Robin Glattauer HEPHY + */ + +#include "kaltest/TVKalDetector.h" + +class TNode; +class TVector3; + +namespace gear{ + class GearMgr ; +} + + +class ILDFTDKalDetector : public TVKalDetector { +public: + + /** Initialize the FTD from GEAR */ + ILDFTDKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + struct FTD_Petal { + + int ipetal; + double phi; + double alpha; + double rInner; + double height; + double innerBaseLength; + double outerBaseLength; + double senThickness; + double supThickness; + double senZPos; + bool faces_ip; + + }; + + + struct FTD_Disk { + int nPetals; + double phi0; + double dphi; + + double alpha; + double rInner; + double height; + double innerBaseLength; + double outerBaseLength; + double senThickness; + double supThickness; + + double stripAngle; + + double senZPos_even_front; + double senZPos_odd_front; + + bool isDoubleSided; + bool isStripReadout; + + int nSensors; + + + }; + + + void build_staggered_design(); + + //void create_petal(TVector3 measurement_plane_centre, FTD_Petal petal, int CellID); + /** + * @param zpos the z position of the front measurement surface (middle of front sensitive) + */ + void create_segmented_disk_layers(int idisk, int nsegments, bool even_petals, double phi0, double zpos ); + + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + int _nDisks ; + double _bZ ; + + + std::vector<FTD_Disk> _FTDgeo; + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDMeasurementSurfaceStoreFiller.h b/Utilities/KalDet/kaldet/ILDMeasurementSurfaceStoreFiller.h new file mode 100644 index 0000000000000000000000000000000000000000..79ff8e1ea0aafc6123eed869b85573f5f8580aee --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDMeasurementSurfaceStoreFiller.h @@ -0,0 +1,81 @@ +#ifndef ILDMEASUREMENTSURFACESTOREFILLER_H +#define ILDMEASUREMENTSURFACESTOREFILLER_H + +#include "gearsurf/MeasurementSurfaceStore.h" + +#include <vector> + +namespace gear{ + class GearMgr; + class ZPlanarParameters; + class FTDParameters; +} + +using namespace gear; + +class ILDMeasurementSurfaceStoreFiller : public MeasurementSurfaceStoreFiller{ + + public: + + + ILDMeasurementSurfaceStoreFiller(const gear::GearMgr& gear_mgr) : + _nVTXLayers(0), + _nSITLayers(0), + _nFTDLayers(0), + _nSETLayers(0) { + + this->get_gear_parameters(gear_mgr); + + } + + ~ILDMeasurementSurfaceStoreFiller() { /* no op */ } + + void getMeasurementSurfaces( std::vector<MeasurementSurface*>& surface_list ) const; + + std::string getName() const { return "ILDMeasurementSurfaceStoreFiller" ; } ; + + private: + + /** adds MeasurementSufaces to the store + * @param param: the ZPlanarParameters pointer of the detector, of which the measurement surfaces shall be added + * + * @param det_id: the detector id (as in ILDConf) + */ + void storeZPlanar( const gear::ZPlanarParameters* param , int det_id, std::vector<MeasurementSurface*>& surface_list ) const; + + void storeFTD( const gear::FTDParameters* param, std::vector<MeasurementSurface*>& surface_list ) const; + + + void get_gear_parameters(const gear::GearMgr& gear_mgr); + + /** the strip angles for every layer */ + std::vector< double > _VTXStripAngles; + std::vector< double > _SITStripAngles; + std::vector< double > _SETStripAngles; + + /** the number of sensors for every layer */ + std::vector< int > _VTXNSensors; + std::vector< int > _SITNSensors; + std::vector< int > _SETNSensors; + + + /** the strip angles for every layer and sensor */ + std::vector< std::vector< double > > _FTDStripAngles; + + unsigned _nVTXLayers; + unsigned _nSITLayers; + unsigned _nFTDLayers; + unsigned _nSETLayers; + + + const gear::ZPlanarParameters* _paramVXD; + const gear::ZPlanarParameters* _paramSIT; + const gear::ZPlanarParameters* _paramSET; + const gear::FTDParameters* _paramFTD; + + + +}; + +#endif + diff --git a/Utilities/KalDet/kaldet/ILDParallelPlanarMeasLayer.h b/Utilities/KalDet/kaldet/ILDParallelPlanarMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..7262a3e84e248b8eb03ad0d6afbea283b06750cc --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDParallelPlanarMeasLayer.h @@ -0,0 +1,80 @@ +#ifndef __ILDParallelPlanarMeasLayer__ +#define __ILDParallelPlanarMeasLayer__ + +/** ILDParallelPlanarMeasLayer: User defined KalTest measurement layer class + * + * @author S.Aplin DESY + */ + + +#include "ILDPlanarMeasLayer.h" + +class ILDParallelPlanarMeasLayer : public ILDPlanarMeasLayer { + +public: + + /** Constructor Taking inner and outer materials, distance and phi of plane pca to origin, B-Field, Sorting policy, plane transverse witdth and offset of centre, longitudinal width, whether the layer is sensitive, Cell ID, and an optional name */ + ILDParallelPlanarMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t r, + Double_t phi, + Double_t Bz, + Double_t SortingPolicy, + Double_t xiwidth, + Double_t zetawidth, + Double_t xioffset, + Double_t zoffset, + Double_t UOrigin, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDParallelPlanarMeasLayer") + : + ILDPlanarMeasLayer(min,mout,TVector3(r*cos(phi),r*sin(phi),zoffset),TVector3(cos(phi),sin(phi),0.0),Bz,SortingPolicy,xiwidth,zetawidth,xioffset,UOrigin,is_active,CellID,name), _r(r),_phi(phi),_cos_phi(cos(_phi)),_sin_phi(sin(_phi)) + { /* no op */ } + + + // Parent's pure virtuals that must be implemented + + /** overloaded version of CalcXingPointWith using closed solution */ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + /** overloaded version of CalcXingPointWith using closed solution */ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps = 1.e-8) const{ + + return CalcXingPointWith(hel,xx,phi,0,eps); + + } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return CalcXingPointWith(hel,xx,phi,0,eps); + + } + + +protected: + + Double_t _r; + Double_t _phi; + Double_t _cos_phi; + Double_t _sin_phi; + + +}; + +#endif + diff --git a/Utilities/KalDet/kaldet/ILDParallelPlanarStripMeasLayer.h b/Utilities/KalDet/kaldet/ILDParallelPlanarStripMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..c717f4c13a37397762a9aaf6d63980d8e0dfe61c --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDParallelPlanarStripMeasLayer.h @@ -0,0 +1,62 @@ +#ifndef __ILDParallelPlanarStripMeasLayer__ +#define __ILDParallelPlanarStripMeasLayer__ + +/** ILDParallelPlanarStripMeasLayer: User defined KalTest measurement layer class + * + * @author S.Aplin DESY + */ + +//#include "TKalMatrix.h" +//#include "TVector3.h" +//#include "TVTrackHit.h" + + +#include "ILDParallelPlanarMeasLayer.h" + +class ILDParallelPlanarStripMeasLayer : public ILDParallelPlanarMeasLayer { + +public: + + /** Constructor Taking inner and outer materials, distance and phi of plane pca to origin, B-Field, Sorting policy, plane transverse witdth and offset of centre, longitudinal width, whether the layer is sensitive, Cell ID, and an optional name */ + ILDParallelPlanarStripMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t r, + Double_t phi, + Double_t Bz, + Double_t SortingPolicy, + Double_t xiwidth, + Double_t zetawidth, + Double_t xioffset, + Double_t zoffset, + Double_t UOrigin, + Double_t stripAngle, + Int_t CellID = -1, + const Char_t *name = "ILDParallelPlanarStripMeasLayer") + : + ILDParallelPlanarMeasLayer(min,mout,r,phi,Bz,SortingPolicy,xiwidth,zetawidth,xioffset,zoffset,UOrigin,true,CellID,name), _stripAngle(stripAngle) + + { /* no op */ } + + + // Parent's pure virtuals that must be implemented + + TKalMatrix XvToMv(const TVector3 &xv) const; + + TKalMatrix XvToMv(const TVTrackHit &, const TVector3 &xv) const { + return XvToMv(xv); + } + + TVector3 HitToXv(const TVTrackHit &vht) const ; + + void CalcDhDa(const TVTrackHit &vht, const TVector3 &xxv, const TKalMatrix &dxphiada, TKalMatrix &H) const; + + ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const; + +private: + + double _stripAngle; + +}; + +#endif + diff --git a/Utilities/KalDet/kaldet/ILDPlanarHit.h b/Utilities/KalDet/kaldet/ILDPlanarHit.h new file mode 100644 index 0000000000000000000000000000000000000000..e54f0cf7e053dda87041fd4d9e80fc010b5787fa --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDPlanarHit.h @@ -0,0 +1,41 @@ +#ifndef ILDPLANARHIT_H +#define ILDPLANARHIT_H + +/** ILDPlanarHit: User defined KalTest hit class using u and v coordinates, which provides coordinate vector as defined by the MeasLayer + * + * @author S.Aplin DESY + */ + +#include "kaltest/KalTrackDim.h" + +#include "ILDVTrackHit.h" + +#define ILDPlanarHit_DIM 2 + +class ILDPlanarHit : public ILDVTrackHit { + +public: + + /** Constructor Taking u and v coordinates and associated measurement layer, with bfield */ + ILDPlanarHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Double_t bfield, + edm4hep::TrackerHit* trkhit) + : ILDVTrackHit(ms, x, dx, bfield, ILDPlanarHit_DIM,trkhit) + { /* no op */ } + + // TVTrackHit's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv, Double_t t0) const; + + /** Print Debug information */ + virtual void DebugPrint(Option_t *opt = "") const; + + +private: + + +}; +#endif diff --git a/Utilities/KalDet/kaldet/ILDPlanarMeasLayer.h b/Utilities/KalDet/kaldet/ILDPlanarMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..500f2a233093f6409eb3428fa1f23b82bb45c95b --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDPlanarMeasLayer.h @@ -0,0 +1,84 @@ +#ifndef __ILDPLANARMEASLAYER__ +#define __ILDPLANARMEASLAYER__ +//************************************************************************* +//* =================== +//* ILDPlanarMeasLayer Class +//* =================== +//* +//* (Description) +//* Planar measurement layer class used with ILDPLanarTrackHit. +//* (Requires) +//* ILDVMeasLayer +//* (Provides) +//* class ILDPlanarMeasLayer +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* +//* 2011/06/17 D.Kamai Modified to handle ladder structure. +//************************************************************************* +// +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> + +class TVTrackHit; + +class ILDPlanarMeasLayer : public ILDVMeasLayer, public TPlane { +public: + // Ctors and Dtor + + ILDPlanarMeasLayer(TMaterial &min, + TMaterial &mout, + const TVector3 ¢er, + const TVector3 &normal, + Double_t Bz, + Double_t SortingPolicy, + Double_t xiwidth, + Double_t zetawidth, + Double_t xioffset, + Double_t fUOrigin, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDPlanarMeasL"); + + virtual ~ILDPlanarMeasLayer(); + + // Parrent's pure virtuals that must be implemented + + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const; + + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + Double_t GetSortingPolicy() const { return fSortingPolicy; } + Double_t GetXiwidth() const { return fXiwidth; } + Double_t GetZetawidth() const { return fZetawidth; } + Double_t GetXioffset() const { return fXioffset; } + +protected: + Double_t fSortingPolicy; + Double_t fXiwidth; + Double_t fZetawidth; + Double_t fXioffset; //determines how far the centre of the plane is translated in the direction positive rotation + Double_t fUOrigin; //determines origin of the transverse coordinate + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDPlanarStripHit.h b/Utilities/KalDet/kaldet/ILDPlanarStripHit.h new file mode 100644 index 0000000000000000000000000000000000000000..1103eeda84a5e6729d204ac6385a11b5de909ac3 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDPlanarStripHit.h @@ -0,0 +1,42 @@ +#ifndef ILDPLANARSTRIPHIT_H +#define ILDPLANARSTRIPHIT_H + +/** ILDPlanarStripHit: User defined KalTest hit class using u coordinate, which provides coordinate vector as defined by the MeasLayer + * + * @author S.Aplin DESY + */ + +#include "kaltest/KalTrackDim.h" + +#include "ILDVTrackHit.h" + + +#define ILDPlanarStripHit_DIM 1 // set to 2 if one want to debug strip hits by using the 2nd dimention + +class ILDPlanarStripHit : public ILDVTrackHit { + +public: + + /** Constructor Taking a single coordinate and associated measurement layer, with bfield */ + ILDPlanarStripHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Double_t bfield, + edm4hep::TrackerHit* trkhit) + : ILDVTrackHit(ms, x, dx, bfield, ILDPlanarStripHit_DIM,trkhit) + { /* no op */ } + + // TVTrackHit's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv, Double_t t0) const; + + /** Print Debug information */ + virtual void DebugPrint(Option_t *opt = "") const; + + +private: + + +}; +#endif diff --git a/Utilities/KalDet/kaldet/ILDPolygonBarrelMeasLayer.h b/Utilities/KalDet/kaldet/ILDPolygonBarrelMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..684bb876e7e0be4e48381ca59528c9871b6ffb1d --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDPolygonBarrelMeasLayer.h @@ -0,0 +1,138 @@ +#ifndef __ILDSEGMENTEDDISCMEASLAYER_H__ +#define __ILDSEGMENTEDDISCMEASLAYER_H__ + +/** ILDPolygonBarrelMeasLayer: User defined Polygonal Barrel KalTest measurement layer class to be used only for dead material. Segments are planes parallel to the z axis + * + * NOTE: ALL METHODS INVOLVING HITS ARE DISABLED AND CALL EXIT(1) + * THIS CLASS IS ONLY MEANT FOR DEAD MATERIAL + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TVSurface.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> + +#include "ILDParallelPlanarMeasLayer.h" + +#include <vector> + +class TVTrackHit; + + +class ILDPolygonBarrelMeasLayer : public ILDVMeasLayer, public TVSurface { +public: + // Ctors and Dtor + + + + ILDPolygonBarrelMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double SortingPolicy, + double r0, // min distance to the z-axis + double lhalf, // half length + int nsides, + double zpos, // z of the centre + double phi0, // phi of the first normal following the xaxis positive rotation + std::vector<int> CellIDs, + bool is_active, + const Char_t *name = "ILDPolygonBarrelMeasL"); + + + ~ILDPolygonBarrelMeasLayer(){ delete _enclosing_cylinder;} + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** overloaded version of CalcXingPointWith using closed solution*/ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + /** overloaded version of CalcXingPointWith using closed solution*/ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps = 1.e-8) const{ + + return CalcXingPointWith(hel,xx,phi,0,eps); + + } + + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const ; + + + bool IsOutside(const TVector3 &xx) const; + + double CalcS(const TVector3 &xx) const; + + TMatrixD CalcDSDx(const TVector3 &xx) const; + + /** Check if global point is on surface */ + inline virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + /** Get sorting policy for this plane */ + double GetSortingPolicy() const { return _sortingPolicy; } + +private: + + double angular_range_2PI( double phi ) const; + + unsigned int get_plane_index(double phi) const; + + double _sortingPolicy; + + double _r0; // min distance to the z-axis + double _lhalf; // half length + int _nsides; + double _zpos; // z of the centre + double _phi0; // phi of the first normal following the xaxis positive rotation + + double _segment_dphi; + double _start_phi; + double _rmax; + + std::vector<ILDParallelPlanarMeasLayer> _planes; + TCylinder* _enclosing_cylinder; +}; + + + +#endif diff --git a/Utilities/KalDet/kaldet/ILDRotatedTrapMeaslayer.h b/Utilities/KalDet/kaldet/ILDRotatedTrapMeaslayer.h new file mode 100644 index 0000000000000000000000000000000000000000..8cb7e4e07bd142df53533ca42b88333a818327d1 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDRotatedTrapMeaslayer.h @@ -0,0 +1,106 @@ +#ifndef __ILDPLANARMEASLAYER__ +#define __ILDPLANARMEASLAYER__ +/** ILDRotatedTrapMeaslayer: User defined Rotated Trapezoid Planar KalTest measurement layer class used with ILDPLanarTrackHit. + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> +class TVTrackHit; + +class ILDRotatedTrapMeaslayer : public ILDVMeasLayer, public TPlane { + +public: + + /** Constructor Taking inner and outer materials, centre and normal of the plane, B-Field, sorting policy, height, inner base length, outer base length, tilt angle around axis of symmetry, represents full or half petal, whether the layer is sensitive, Cell ID, and an optional name */ + ILDRotatedTrapMeaslayer(TMaterial &min, + TMaterial &mout, + const TVector3 ¢er, + const TVector3 &normal, + Double_t Bz, + Double_t SortingPolicy, + Double_t height, + Double_t innerBaseLength, + Double_t outerBaseLength, + Double_t alpha, + Int_t half_petal, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDRotatedTrapMeasL"); + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** Check if global point is on surface */ + inline virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + /** Get sorting policy for this plane */ + Double_t GetSortingPolicy() const { return _sortingPolicy; } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return this->CalcXingPointWith(hel,xx,phi,0,eps); + + } + + + +private: + Double_t _sortingPolicy ; + Double_t _signZ ; + Double_t _innerR ; + Double_t _outerR ; + Double_t _innerBaseLength ; + Double_t _outerBaseLength ; + Double_t _cosPhi ; //** cos of the azimuthal angle of the petal + Double_t _sinPhi ; //** sin of the azimuthal angle of the petal + Double_t _cosAlpha ; //** cos of the tilt angle of the petal + Double_t _sinAlpha ; //** sin of the tilt angle of the petal + Double_t _tanBeta ; //** tan of the openning angle of the petal + + // meaning of _halfPetal: + // 0 complete trapezoid + // +1 positive half only, i.e. the side of the petal in which the transverse coordinate, mv(0,0), is positive + // -1 negative half only, i.e. the side of the petal in which the transverse coordinate, mv(0,0), is negative + Int_t _halfPetal ; + + + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDSETKalDetector.h b/Utilities/KalDet/kaldet/ILDSETKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..9327aa8a065e8ff6243df53193df544e37389381 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDSETKalDetector.h @@ -0,0 +1,58 @@ +#ifndef __ILDSETKALDETECTOR__ +#define __ILDSETKALDETECTOR__ + +/** Ladder based SET to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +#include "TMath.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDSETKalDetector : public TVKalDetector { + +public: + + /** Initialize the SET from GEAR */ + ILDSETKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + int _nLayers ; + double _bZ ; + + bool _isStripDetector; + + struct SET_Layer { + int nLadders; + int nSensorsPerLadder; + double phi0; + double dphi; + double senRMin; + double supRMin; + double length; + double width; + double offset; + double senThickness; + double supThickness; + double sensorLength; + double stripAngle; + }; + std::vector<SET_Layer> _SETgeo; + +}; + + + +#endif diff --git a/Utilities/KalDet/kaldet/ILDSITCylinderKalDetector.h b/Utilities/KalDet/kaldet/ILDSITCylinderKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..29f13f6f7cf5eaf3fba067693d475a9c6fa47449 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDSITCylinderKalDetector.h @@ -0,0 +1,44 @@ +#ifndef __ILDSITCYLINDERKALDETECTOR__ +#define __ILDSITCYLINDERKALDETECTOR__ + +/** SIT Cylinder based detector to be used for ILD DBD studies when using the old LOI base SIT + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDSITCylinderKalDetector : public TVKalDetector { +public: + + /** Initialize the TPC from GEAR */ + ILDSITCylinderKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + unsigned int _nLayers ; + double _bZ ; + + struct SIT_Layer { + double radius; + double half_length; + double senThickness; + double supThickness; + + }; + std::vector<SIT_Layer> _SITgeo; + + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDSITKalDetector.h b/Utilities/KalDet/kaldet/ILDSITKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..639e1b27bb76512ad05c8570814b218a9480cb5b --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDSITKalDetector.h @@ -0,0 +1,58 @@ +#ifndef __ILDSITKALDETECTOR__ +#define __ILDSITKALDETECTOR__ + +/** Ladder based SIT to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +#include "TMath.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDSITKalDetector : public TVKalDetector { + +public: + + /** Initialize the SIT from GEAR */ + ILDSITKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + int _nLayers ; + double _bZ ; + + bool _isStripDetector; + + struct SIT_Layer { + int nLadders; + int nSensorsPerLadder; + double phi0; + double dphi; + double senRMin; + double supRMin; + double length; + double width; + double offset; + double senThickness; + double supThickness; + double sensorLength; + double stripAngle; + }; + std::vector<SIT_Layer> _SITgeo; + +}; + + + +#endif diff --git a/Utilities/KalDet/kaldet/ILDSegmentedDiscMeasLayer.h b/Utilities/KalDet/kaldet/ILDSegmentedDiscMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..6133570279f935d889f3e5ed76f3f51ed2f1205b --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDSegmentedDiscMeasLayer.h @@ -0,0 +1,144 @@ +#ifndef __ILDSEGMENTEDDISCMEASLAYER_H__ +#define __ILDSEGMENTEDDISCMEASLAYER_H__ + +/** ILDSegmentedDiscMeasLayer: User defined Segemented Disk Planar KalTest measurement layer class used with ILDPLanarTrackHit. Segments are isosolese trapezoids whose axis of symmetry points to the origin + * WARNING: ONLY IMPLEMENTED FOR X AND Y COORDINATES AT FIXED Z + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> +#include <iostream> + +#include <vector> + +class TVTrackHit; + +class ILDSegmentedDiscMeasLayer : public ILDVMeasLayer, public TPlane { +public: + // Ctors and Dtor + + ILDSegmentedDiscMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double SortingPolicy, + int nsegments, + double zpos, + double phi0, // defined by the axis of symmerty of the first petal + double trap_rmin, + double trap_height, + double trap_innerBaseLength, + double trap_outerBaseLength, + bool is_active, + std::vector<int> CellIDs, + const Char_t *name = "ILDDiscMeasL"); + + ILDSegmentedDiscMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double SortingPolicy, + int nsegments, + double zpos, + double phi0, // defined by the axis of symmerty of the first petal + double trap_rmin, + double trap_height, + double trap_innerBaseLength, + double trap_outerBaseLength, + bool is_active, + const Char_t *name = "ILDDiscMeasL"); + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** overloaded version of CalcXingPointWith using closed solution*/ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + /** overloaded version of CalcXingPointWith using closed solution*/ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps = 1.e-8) const{ + + return CalcXingPointWith(hel,xx,phi,0,eps); + + } + + + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const ; + + + + /** Check if global point is on surface */ + virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + /** Get sorting policy for this plane */ + double GetSortingPolicy() const { return _sortingPolicy; } + +protected: + + double angular_range_2PI( double phi ) const; + unsigned int get_segment_index(double phi) const; + double get_segment_phi(unsigned int index) const; + TVector3 get_segment_centre(unsigned int index) const; + +private: + + double _sortingPolicy; + int _nsegments; + double _trap_rmin; + double _trap_height; + double _trap_inner_base_length; + double _trap_outer_base_length; + double _trap_tan_beta; // tan of the openning angle of the petal + + double _rmax; + double _start_phi; // trailing edge of the first sector + double _segment_dphi; + + + +}; + + + +#endif diff --git a/Utilities/KalDet/kaldet/ILDSegmentedDiscStripMeasLayer.h b/Utilities/KalDet/kaldet/ILDSegmentedDiscStripMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..8bdab6686dcc7ba6d2ac04bcc3e7a7eae1dc84b8 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDSegmentedDiscStripMeasLayer.h @@ -0,0 +1,80 @@ +#ifndef __ILDSEGMENTEDDISCSTRIPMEASLAYER_H__ +#define __ILDSEGMENTEDDISCSTRIPMEASLAYER_H__ + +/** ILDSegmentedDiscStripMeasLayer: User defined Segemented Disk Planar KalTest measurement layer class used with ILDPLanarTrackHit. Segments are isosolese trapezoids whose axis of symmetry points to the origin + * WARNING: ONLY IMPLEMENTED FOR X AND Y COORDINATES AT FIXED Z + * + * @author S.Aplin DESY + */ +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDSegmentedDiscMeasLayer.h" + +#include "TMath.h" +#include <sstream> +#include <iostream> + +#include <vector> + +class TVTrackHit; + +class ILDSegmentedDiscStripMeasLayer : public ILDSegmentedDiscMeasLayer { + +public: + // Ctors and Dtor + + ILDSegmentedDiscStripMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double SortingPolicy, + int nsegments, + double zpos, + double phi0, // defined by the axis of symmerty of the first petal + double trap_rmin, + double trap_height, + double trap_innerBaseLength, + double trap_outerBaseLength, + double stripAngle, + bool is_active, + std::vector<int> CellIDs, + const Char_t *name = "ILDDiscMeasL") + : ILDSegmentedDiscMeasLayer(min,mout,Bz,SortingPolicy,nsegments,zpos,phi0,trap_rmin,trap_height,trap_innerBaseLength,trap_outerBaseLength,is_active,CellIDs,name), + _stripAngle(stripAngle) + { /* no op */ } + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + +private: + + double _stripAngle; + +}; + + + +#endif diff --git a/Utilities/KalDet/kaldet/ILDSupportKalDetector.h b/Utilities/KalDet/kaldet/ILDSupportKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..b7e28fa929884ceadf7755395766d8f75c079c3f --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDSupportKalDetector.h @@ -0,0 +1,37 @@ +#ifndef __ILDSUPPORTDETECTOR__ +#define __ILDSUPPORTDETECTOR__ + +/** Support Material to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} +class IGeoSvc; + +class ILDCylinderMeasLayer; + +class ILDSupportKalDetector : public TVKalDetector { +public: + + /** Initialize the support structures from GEAR */ + ILDSupportKalDetector( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc ); + + /** Returns the special layer inside the Beam Pipe used for propagation to the IP */ + ILDCylinderMeasLayer* getIPLayer() { return _ipLayer; } + +private: + + ILDCylinderMeasLayer* _ipLayer; + + std::vector<std::string> _surface_names; + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDTPCKalDetector.h b/Utilities/KalDet/kaldet/ILDTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..e5ab8db97c723357f2fbd8e964ab319ec7102ca6 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDTPCKalDetector.h @@ -0,0 +1,29 @@ +#ifndef __ILDTPCDETECTOR__ +#define __ILDTPCDETECTOR__ + +/** TPC to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDTPCKalDetector : public TVKalDetector { +public: + + /** Initialize the TPC from GEAR */ + ILDTPCKalDetector( const gear::GearMgr& gearMgr ); + + +private: + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDVMeasLayer.h b/Utilities/KalDet/kaldet/ILDVMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..3d213b3aadcc3f5c3b4ff693462ff2e746e22f53 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDVMeasLayer.h @@ -0,0 +1,88 @@ +#ifndef __ILDVMEASLAYER__ +#define __ILDVMEASLAYER__ + +/** ILDVMeasLayer: Virtual measurement layer class used by ILD[X]MeasLayer Classes. + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" +#include "kaltest/TKalMatrix.h" +#include "kaltest/TCylinder.h" +#include "kaltest/TVMeasLayer.h" +#include "kaltest/TAttDrawable.h" +#include "kaltest/KalTrackDim.h" +#include "TString.h" + +#include <vector> + +class TVTrackHit; +class TNode; +class ILDVTrackHit; + +namespace edm4hep{ + class TrackerHit; +} + +class ILDVMeasLayer : public TVMeasLayer { +public: + + static Bool_t kActive; + static Bool_t kDummy; + + /** Get the layer ID */ + inline int getLayerID() const { return _layerID ; } + + /** Get the Cell ID associated with this measurement layer */ + inline const std::vector<int>& getCellIDs() const { return _cellIDs ; } + + /** Get the number of Cell ID associated with this measurement layer */ + inline unsigned int getNCellIDs() const { return _cellIDs.size() ; } + + /** Get the Magnetic field at the measurement surface */ + inline Double_t GetBz() const { return _Bz; } + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const = 0 ; + + /** Check whether the measurement layer represents a series of detector elements */ + bool isMultilayer() const { return _isMultiLayer; } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const = 0 ; + +protected: + + ILDVMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t Bz, + Bool_t is_active = ILDVMeasLayer::kActive, + int CellID = -1 , + const Char_t *name = "ILDMeasL"); + + ILDVMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t Bz, + const std::vector<int>& cellIDs, + Bool_t is_active = ILDVMeasLayer::kActive, + const Char_t *name = "ILDMeasL"); + + + + Double_t _Bz ; // Magnitude of B-Field in Z + int _layerID ; + std::vector<int> _cellIDs ; + + bool _isMultiLayer; + +private: + + +}; + +#endif diff --git a/Utilities/KalDet/kaldet/ILDVTrackHit.h b/Utilities/KalDet/kaldet/ILDVTrackHit.h new file mode 100644 index 0000000000000000000000000000000000000000..d47be083ee5e2bc1a8871d8ba1578301e8b352f1 --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDVTrackHit.h @@ -0,0 +1,33 @@ +#ifndef ILDVTrackHIT_H +#define ILDVTrackHIT_H + +/** ILDVMeasLayer: Virtual hit class used by ILD[X]Hit Classes, which should provide coordinate vector as defined by the MeasLayer + * + * @author S.Aplin DESY + */ + + +#include "kaltest/TVTrackHit.h" + +#include "ILDVMeasLayer.h" + +#include "edm4hep/TrackerHit.h" + +class ILDVTrackHit : public TVTrackHit { + +public: + + /** Constructor Taking coordinates and associated measurement layer, with bfield and number of measurement dimentions*/ + ILDVTrackHit(const TVMeasLayer &ms, Double_t *x, Double_t *dx, + Double_t bfield , Int_t dim, edm4hep::TrackerHit* trkhit) + : TVTrackHit(ms, x, dx, bfield, dim), _trkhit(trkhit) + { /* no op */ } + + edm4hep::TrackerHit* getLCIOTrackerHit() const { return _trkhit; } + +private: + + edm4hep::TrackerHit* _trkhit; + +}; +#endif diff --git a/Utilities/KalDet/kaldet/ILDVXDKalDetector.h b/Utilities/KalDet/kaldet/ILDVXDKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..c0205e149f55b4ca2340cdfc7549b17fd020cdbc --- /dev/null +++ b/Utilities/KalDet/kaldet/ILDVXDKalDetector.h @@ -0,0 +1,73 @@ +#ifndef __ILDVXDKALDETECTOR__ +#define __ILDVXDKALDETECTOR__ + +/** Ladder based VXD to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +#include "TMath.h" + +class TNode; +class IGeoSvc; + +namespace gear{ + class GearMgr ; +} + + +class ILDVXDKalDetector : public TVKalDetector { + +public: + + ILDVXDKalDetector( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc) ; + + int _nLayers ; + double _bZ ; + + double _relative_position_of_measurement_surface ; + + struct VXD_Layer { + int nLadders; + double phi0; + double dphi; + double senRMin; + double supRMin; + double length; + double width; + double offset; + double senThickness; + double supThickness; + }; + std::vector<VXD_Layer> _VXDgeo; + + + struct VXD_Cryostat { + double alRadius; + double alThickness; + double alInnerR; + double alZEndCap; + double alHalfZ; + double shellRadius; + double shellThickness; + double shellInnerR; + double shellZEndCap; + double shelllHalfZ; + + bool exists; + }; + + VXD_Cryostat _vxd_Cryostat; + +}; + + + +#endif diff --git a/Utilities/KalDet/kaldet/LCTPCKalDetector.h b/Utilities/KalDet/kaldet/LCTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..744793a8a0a6f82e4e16f4cb66c56b4b48acfd54 --- /dev/null +++ b/Utilities/KalDet/kaldet/LCTPCKalDetector.h @@ -0,0 +1,39 @@ +#ifndef LCTPCKALDETECTOR_H +#define LCTPCKALDETECTOR_H + +#include "kaltest/TVKalDetector.h" + +#include "ILDVMeasLayer.h" + +namespace gear{ + class GearMgr ; +} + +namespace kaldet{ + + /** + * The LCTPC implementation for a TPC which is completely instantiated from GEAR. + * + */ +class LCTPCKalDetector : public TVKalDetector { + +public: + + LCTPCKalDetector() {}; + + /** + * The constructor. All information to initialise the TPC is taken from GEAR. + * + * The class has been copied from GearTPCKalDetector class and adopted for the use of MarlinTrk + * You can find comments and necessary information in the original class + * + */ + LCTPCKalDetector(const gear::GearMgr& gearMgr); + + /// The destructor. + virtual ~LCTPCKalDetector(); + +}; + +}// namespace kaldet +#endif //LCTPCKALDETECTOR_H diff --git a/Utilities/KalDet/kaldet/MaterialDataBase.h b/Utilities/KalDet/kaldet/MaterialDataBase.h new file mode 100644 index 0000000000000000000000000000000000000000..d1ed28bf0af03621cfc6dc9a1d7935b6a3833131 --- /dev/null +++ b/Utilities/KalDet/kaldet/MaterialDataBase.h @@ -0,0 +1,76 @@ +#ifndef MaterialDataBase_h +#define MaterialDataBase_h + +/** MaterialDataBase: Class to hold and manage collection of materials + * + * @author S.Aplin DESY + */ + +#include <string> +#include <map> +#include <exception> + +#include "lcio.h" +#include "Exceptions.h" + +class TMaterial; + +namespace gear{ + class GearMgr ; +} +class IGeoSvc; +// fg: define the MaterialDataBaseException as an lcio Exception to allow for +// messages to be printed in what() +typedef lcio::Exception MaterialDataBaseException ; + +class MaterialDataBase { + +public: + + /** Accessor Method */ + static MaterialDataBase& Instance() { + + static MaterialDataBase singleton; + + return singleton; + + } + + // Other non-static member functions + +public: + + /** Destructor */ + ~MaterialDataBase(); + + /** Get Material via name */ + TMaterial* getMaterial(std::string mat_name) ; + + void registerForService(const gear::GearMgr& gearMgr, IGeoSvc* geoSvc=0) ; + + +private: + + void initialise(const gear::GearMgr& gearMgr, IGeoSvc* geoSvc) ; + + MaterialDataBase() { _material_map.clear(); _isInitialised = false ; _gearMgr = 0; } // Private constructor + + + MaterialDataBase(const MaterialDataBase&) ; // Prevent copy-construction + MaterialDataBase& operator=(const MaterialDataBase&) ; // Prevent assignment + + void addMaterial(TMaterial* mat, std::string name); + void createMaterials(const gear::GearMgr& gearMgr, IGeoSvc* geoSvc); + + // private member variables + std::map<std::string,TMaterial* > _material_map; + + bool _isInitialised; + + const gear::GearMgr* _gearMgr; + +}; + + + +#endif diff --git a/Utilities/KalDet/src/gen/EXEventGen.cxx b/Utilities/KalDet/src/gen/EXEventGen.cxx new file mode 100644 index 0000000000000000000000000000000000000000..fa509413209a5710ca377f56802ab7238c128753 --- /dev/null +++ b/Utilities/KalDet/src/gen/EXEventGen.cxx @@ -0,0 +1,140 @@ +#include "EXEventGen.h" +//#include "EXVKalDetector.h" +//#include <EXVMeasLayer.h> +#include "kaldet/EXTPCKalDetector.h" +#include <kaldet/EXTPCMeasLayer.h> +#include <kaltest/TPlane.h> +#include <TRandom.h> +#include <TMath.h> + +#include <iostream> +#include <typeinfo> // needed for std::bad_cast exception + +//----------------------------------- +// Track Parameters +//----------------------------------- + +#define __DR__ 0. +#define __DZ__ 0. + +Double_t EXEventGen::fgT0 = 0.; // [nsec] + +THelicalTrack EXEventGen::GenerateHelix(Double_t pt, + Double_t cosmin, + Double_t cosmax, + Double_t phimin, + Double_t phimax, + TVector3 xv0) +{ + // --------------------------- + // Generate a helical track + // --------------------------- + + Double_t dr = __DR__; + Double_t fi0 = gRandom->Uniform(phimin,phimax); + Double_t cpa = 1. / pt; + Double_t dz = __DZ__; + Double_t cs = gRandom->Uniform(cosmin, cosmax); + Double_t tnl = cs / TMath::Sqrt((1-cs)*(1+cs)); + Double_t x0 = xv0.X(); + Double_t y0 = xv0.Y(); + Double_t z0 = xv0.Z(); + + EXTPCMeasLayer * measLayer = dynamic_cast<EXTPCMeasLayer *>(fCradlePtr->At(0)); + if (measLayer==0) + { + std::cerr << "EXEventGen::GenerateHelix: cast of fCradlePtr->At(0) to EXVMeasLayer * failed" + << std::endl; + std::cerr << "Derive your measurement layer from EXTPCMeasLayer instead of " + << "TVMeasLayer to use EXEventGen." << std::endl; + + throw std::bad_cast(); + } + + EXTPCKalDetector const & kalDetector = dynamic_cast<const EXTPCKalDetector &>(measLayer->GetParent(kFALSE)); + if (measLayer==0) + { + std::cerr << "EXEventGen::GenerateHelix: cast of (measLayer->GetParent(kFALSE) to EXTPCKalDetector * failed" << std::endl; + std::cerr << "Derive your detector from EXTPCKalDetector instead of " + << "TVKalDetector to use EXEventGen." << std::endl; + throw std::bad_cast(); + } + + Double_t b = kalDetector.GetBfield(); + + return THelicalTrack(dr,fi0,cpa,dz,tnl,x0,y0,z0,b); +} + +void EXEventGen::Swim(THelicalTrack &heltrk) +{ + // --------------------------- + // Swim track and Make hits + // --------------------------- + + // killenb: I have no idea what dfi is (delta phi?), but dividing the sorting policy by a + // radius does not make sense. The sorting polily used to return GetR() + GetXc().X(), + // so let's use this. It will onyl work for the LP1, but this class is deprecated anyway. + TCylinder * firstMeasCylinder = dynamic_cast<TCylinder *>(fCradlePtr->At(0)); + if (firstMeasCylinder==0) + { + std::cerr << "Cannot cast first object in the cradle to TCylinder*"<< std::endl; + std::cerr << "EXEventGen only works for cylindrical measuremnt layers, sorry."<< std::endl; + throw std::bad_cast(); + } + Double_t dfi = - (firstMeasCylinder->GetR() + firstMeasCylinder->GetXc().X()) + / heltrk.GetRho(); + + Int_t nLayers = fCradlePtr->GetEntries(); + Int_t dLayer = 1; + Double_t dfisum = 0.; + + for (Int_t layer = 0; layer >= 0; layer += dLayer) { // loop over layers + // change direction if it starts looping back + if (layer == nLayers - 1) dLayer = -1; + + // FIXME: This assumes that the measurement layer implementation is derived from + // TVSurface. This is not ensured by the interface! + EXTPCMeasLayer const * measurementLayer + = dynamic_cast<EXTPCMeasLayer const *>(fCradlePtr->At(layer)); + //check that the object is a measurement layer. It better should be... + if (measurementLayer==0) + { + std::cerr << "EXEventGen::Swim(): fCradlePtr->At(layer) is not an EXVMeasLayer" << std::endl; + throw std::bad_cast(); + } + + TVSurface const * measurementSurface = dynamic_cast<TVSurface const *>(fCradlePtr->At(layer)); + //check that the object is a surface. This part is not ensured by the interface. + if (measurementSurface==0) + { + std::cerr << "EXEventGen::Swim(): fCradlePtr->At(layer) is not a TVSurface" << std::endl; + throw std::bad_cast(); + } + + + TVector3 xx; + Double_t dfis = dfi; + if (!measurementSurface->CalcXingPointWith(heltrk,xx,dfi,1) + || TMath::Abs(dfi) > TMath::Pi() + || TMath::Abs(dfi + dfisum) > TMath::TwoPi()) { + dfi = dfis; + continue; + } + // should use the material behind the surface since dfi is measured + // from the last point to the current surface + // Bool_t dir = dKayer < 0 ? kTRUE : kFALSE; + + dfisum += dfi; + + heltrk.MoveTo(xx,dfi); // move pivot to current hit + + // killenb: seriously: check if the detector is powered? + if (measurementLayer->IsActive() ) + // This has been kickes as true was hard coded anyway + // && dynamic_cast<const EXVKalDetector &>(measurementLayer->GetParent(kFALSE)).IsPowerOn()) + { + measurementLayer->ProcessHit(xx, *fHitBufPtr); // create hit point + } + if (layer == nLayers - 1) break; + } +} diff --git a/Utilities/KalDet/src/gen/EXEventGen.h b/Utilities/KalDet/src/gen/EXEventGen.h new file mode 100644 index 0000000000000000000000000000000000000000..6da2209f8aaa1f56e62b1bbac10e5f29e0ae833b --- /dev/null +++ b/Utilities/KalDet/src/gen/EXEventGen.h @@ -0,0 +1,33 @@ +#ifndef __EXEVENTGEN__ +#define __EXEVENTGEN__ + +#include "kaltest/TKalDetCradle.h" +#include "kaltest/THelicalTrack.h" +#include "TMath.h" + +class EXEventGen { +public: + EXEventGen(TKalDetCradle const &cradle, TObjArray &kalhits) + : fCradlePtr(&cradle), fHitBufPtr(&kalhits) {} + virtual ~EXEventGen() {} + + THelicalTrack GenerateHelix(Double_t pt, + Double_t cosmin, + Double_t cosmax, + Double_t phimin=0., + Double_t phimax=2*TMath::Pi(), + TVector3 xv0=TVector3(0.,0.,0.)); + void Swim(THelicalTrack &heltrk); + + static void SetT0(Double_t t0) { fgT0 = t0; } + static Double_t GetT0() { return fgT0; } + +private: + TKalDetCradle const *fCradlePtr; // pointer to detector system + TObjArray *fHitBufPtr; // pointer to hit array + + static Double_t fgT0; // t0 + +}; + +#endif diff --git a/Utilities/KalDet/src/gen/LinkDef.h b/Utilities/KalDet/src/gen/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..8f90de8e245edab60e2090fed338ca5b5a0d50f6 --- /dev/null +++ b/Utilities/KalDet/src/gen/LinkDef.h @@ -0,0 +1,9 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class EXEventGen+; + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDConeMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDConeMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..7ed8a8269582f00058c947ac1df3a2784d15b613 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDConeMeasLayer.cc @@ -0,0 +1,136 @@ +//************************************************************************* +//* =================== +//* ILDConeMeasLayer Class +//* =================== +//* +//* (Update Recored) +//* 2012/01/19 K.Fujii Original version. (EXBPConeMeasLayer) +//* 2012/01/24 R.Glattauer Adapted to ILD common in KalDet +//* +//************************************************************************* +// + +#include "ILDConeMeasLayer.h" +#include "TMath.h" + + +ILDConeMeasLayer::ILDConeMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t z1, + Double_t r1, + Double_t z2, + Double_t r2, + Double_t Bz, + Double_t SortingPolicy, + Bool_t is_active, + Int_t CellID, + const Char_t *name) + : ILDVMeasLayer(min, mout, Bz, is_active, CellID, name), + TCutCone(r1*(z2-z1)/(r2-r1), + r2*(z2-z1)/(r2-r1), + (r2-r1)/(z2-z1), + 0.,0.,(r2*z1-r1*z2)/(r2-r1)), + fZ1(z1), + fR1(r1), + fZ2(z2), + fR2(r2), + fsortingPolicy(SortingPolicy) +{ +} + +ILDConeMeasLayer::~ILDConeMeasLayer() +{ +} + +TKalMatrix ILDConeMeasLayer::XvToMv(const TVector3 &xxv) const +{ + // Calculate hit coordinate information: + // mv(0,0) = r * phi + // (1,0) = z + + TKalMatrix mv(kMdim,1); + TVector3 xv = xxv - GetXc(); + Double_t r = xv.Z()*GetTanA(); + + mv(0,0) = r * TMath::ATan2(xv.Y(), xv.X()); + mv(1,0) = xv.Z(); + return mv; +} + +TKalMatrix ILDConeMeasLayer::XvToMv(const TVTrackHit &, + const TVector3 &xv) const +{ + return XvToMv(xv); +} + +TVector3 ILDConeMeasLayer::HitToXv(const TVTrackHit &vht) const +{ +// const EXBPConeHit &ht = dynamic_cast<const EXBPConeHit &>(vht); +// +// Double_t r = ht(1,0) * GetTanA(); +// Double_t phi = ht(0,0) / r; +// Double_t x = GetXc().X() + r * TMath::Cos(phi); +// Double_t y = GetXc().Y() + r * TMath::Sin(phi); +// Double_t z = GetXc().Z() + ht(1,0); + + // streamlog_out( ERROR ) << "Don't use this, it's not implemented!"; + + return TVector3(0.,0.,0.); +} + +void ILDConeMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + TVector3 xv = xxv - GetXc(); + Double_t x = xv.X(); + Double_t y = xv.Y(); + Double_t z = xv.Z(); + Double_t xxyy = x * x + y * y; + Double_t phi = TMath::ATan2(y, x); + Double_t tana = GetTanA(); + Double_t r = z * GetTanA(); + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + for (Int_t i=0; i<hdim; i++) { + H(0,i) = - r * (y / xxyy) * dxphiada(0,i) + + r * (x / xxyy) * dxphiada(1,i) + + tana * phi * dxphiada(2,i); + H(1,i) = dxphiada(2,i); + } + if (sdim == 6) { + H(0,sdim-1) = 0.; + H(1,sdim-1) = 0.; + } +} + +Bool_t ILDConeMeasLayer::IsOnSurface(const TVector3 &xx) const +{ + TVector3 xxc = xx - GetXc(); + Double_t r = xxc.Perp(); + Double_t z = xxc.Z(); + Double_t s = (r - GetTanA()*z) * (r + GetTanA()*z); + const Double_t kTol = 1.e-8; + +#if 0 + std::cout << this->TVMeasLayer::GetName() << ":" << this->GetIndex() << ":" << std::endl; + std::cout << "s=" << s << " xx=(" << xx.X() << "," << xx.Y() << "," << xx.Z() << ")" << std::endl; + std::cout << "bool=" << (TMath::Abs(s) < kTol && ((xx.Z()-fZ1)*(xx.Z()-fZ2) <= 0.)) << std::endl; + std::cout << "fZ1=" << fZ1 << " fZ2=" << fZ2 << std::endl; +#endif + + return (TMath::Abs(s) < kTol && ((xx.Z()-fZ1)*(xx.Z()-fZ2) <= 0.)); +} + diff --git a/Utilities/KalDet/src/ild/common/ILDConeMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDConeMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..00e9fb0611e760c211a854bbf55cf93b8f1ef25c --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDConeMeasLayer.h @@ -0,0 +1,99 @@ +#ifndef ILDCONEMEASLAYER_H +#define ILDCONEMEASLAYER_H +//************************************************************************* +//* =================== +//* ILDConeMeasLayer Class +//* =================== +//* +//* (Update Recored) +//* 2012/01/19 K.Fujii Original version. (EXBPConeMeasLayer) +//* 2012/01/24 R.Glattauer Adapted to ILD common in KalDet +//* +//************************************************************************* +// +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TCutCone.h" +#include "kaltest/KalTrackDim.h" + +#include "ILDVMeasLayer.h" +#include "iostream" +/* #include "streamlog/streamlog.h" */ +#include "UTIL/ILDConf.h" +#include "edm4hep/TrackerHit.h" + +class ILDConeMeasLayer : public ILDVMeasLayer, public TCutCone { +public: + // Ctors and Dtor + /** Constructor Taking inner and outer materials, z and radius at start and end, B-Field, whether the layer is sensitive, Cell ID, and an optional name */ + ILDConeMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t z1, + Double_t r1, + Double_t z2, + Double_t r2, + Double_t Bz, + Double_t SortingPolicy, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "BPCONEML"); + virtual ~ILDConeMeasLayer(); + + // Parrent's pure virtuals that must be implemented + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const; + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + Bool_t IsOnSurface(const TVector3 &xx) const; + + /** Convert LCIO Tracker Hit to an ILDCylinderHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + + /* streamlog_out( ERROR ) << "Don't use this, it's not implemented!"; */ + return NULL; + } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return this->CalcXingPointWith(hel,xx,phi,0,eps); + + + } + + /** Get sorting policy for this plane */ + virtual double GetSortingPolicy() const { return fsortingPolicy; } + + + + +private: + Double_t fZ1; // z of front face + Double_t fR1; // r of front face + Double_t fZ2; // z of back end + Double_t fR2; // r of back end + Double_t fsortingPolicy; // used for sorting the layers in to out + + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDCylinderHit.cc b/Utilities/KalDet/src/ild/common/ILDCylinderHit.cc new file mode 100644 index 0000000000000000000000000000000000000000..27f1fc6fd07971b25c45ceb8b9c190eea01a300b --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDCylinderHit.cc @@ -0,0 +1,52 @@ + +#include "ILDCylinderHit.h" +#include "ILDCylinderMeasLayer.h" +#include "TMath.h" + +#include <iostream> +#include <iomanip> + +using std::cerr; +using std::endl; +using std::setw; +using std::setprecision; +using std::ios; +using std::resetiosflags; + +//_________________________________________________________________________ +// -------------------------------- +// Implementation of public methods +// -------------------------------- +// + + +/** Global to Local coordinates */ + +TKalMatrix ILDCylinderHit::XvToMv(const TVector3 &xv, Double_t t0) const +{ + + return this->GetMeasLayer().XvToMv(*(this), xv); + +} + +/** Print Debug information */ + +void ILDCylinderHit::DebugPrint(Option_t *) const +{ + cerr << "------------------- Site Info -------------------------" << endl; + + for (Int_t i = 0; i < GetDimension(); i++) { + Double_t x = (*this)(i, 0); + Double_t dx = (*this)(i, 1); + cerr << " x[" << i << "] = " << setw(8) << setprecision(5) << x + << " " + << "dx[" << i << "] = " << setw(6) << setprecision(2) << dx + << setprecision(7) + << resetiosflags(ios::showpoint) + << endl; + } + cerr << " r of ILDCylinderMeasLayer = " << setw(8) + << static_cast<const ILDCylinderMeasLayer &>(GetMeasLayer()).GetR() << endl; + cerr << "-------------------------------------------------------" << endl; +} + diff --git a/Utilities/KalDet/src/ild/common/ILDCylinderHit.h b/Utilities/KalDet/src/ild/common/ILDCylinderHit.h new file mode 100644 index 0000000000000000000000000000000000000000..9dbe5b73ef225aa41f7b06cf54d5775166073da3 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDCylinderHit.h @@ -0,0 +1,38 @@ +#ifndef ILDCYLINDERHIT_H +#define ILDCYLINDERHIT_H + +/** ILDCylinderHit: User defined KalTest hit class using R and Rphi coordinates, which provides coordinate vector as defined by the MeasLayer + * + * @author S.Aplin DESY + */ + +#include "kaltest/KalTrackDim.h" +#include "ILDVTrackHit.h" + + +class ILDCylinderHit : public ILDVTrackHit { + +public: + + + /** Constructor Taking R and Rphi coordinates and associated measurement layer, with bfield */ + ILDCylinderHit(const TVMeasLayer &ms, Double_t *x, Double_t *dx, + Double_t bfield, edm4hep::TrackerHit* trkhit ) + : ILDVTrackHit(ms, x, dx, bfield, 2, trkhit) + { /* no op */ } + + + // TVTrackHit's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv(const TVector3 &xv, Double_t t0) const; + + /** Print Debug information */ + virtual void DebugPrint(Option_t *opt = "") const; + + +private: + + +}; +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDCylinderMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDCylinderMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..72cb1119747490f57a2ccc61b116108d051c2e76 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDCylinderMeasLayer.cc @@ -0,0 +1,165 @@ +/** User defined KalTest measurement layer class + * + * @author S.Aplin DESY + */ +#include "kaltest/TKalTrack.h" + +#include "ILDCylinderMeasLayer.h" +#include "ILDCylinderHit.h" + +#include <lcio.h> +#include <edm4hep/TrackerHit.h> +//#include <EVENT/TrackerHitZCylinder.h> + +#include "GaudiKernel/CommonMessaging.h" +// #include "streamlog/streamlog.h" + +#include "TMath.h" +#include <cmath> + + +/** Global to Local coordinates */ + +TKalMatrix ILDCylinderMeasLayer::XvToMv(const TVector3 &xv) const +{ + + // Calculate hit coordinate information: + // mv(0, 0) = r * phi + // (1, 0) = drift distance + + // account for cylinder not centered at x=0.0, y=0.0 + TVector3 xxv = xv - GetXc(); + + Double_t phi = TMath::ATan2(xxv.Y(), xxv.X()); + + // bring phi back into +/- Pi range + static Double_t kPi = TMath::Pi(); + static Double_t kTwoPi = 2 * kPi; + while (phi < -kPi) phi += kTwoPi; + while (phi > kPi) phi -= kTwoPi; + + TKalMatrix mv(kMdim, 1); + + mv(0, 0) = GetR() * phi; + + mv(1, 0) = xxv.Z(); + + return mv; +} + + +/** Local to Global coordinates */ + +TVector3 ILDCylinderMeasLayer::HitToXv(const TVTrackHit &vht) const +{ + + Double_t phi = vht(0, 0) / GetR() ; + Double_t z = vht(1, 0); + + // account for cylinder not centered at x=0.0, y=0.0 + Double_t x = GetR() * TMath::Cos(phi) + GetXc().X(); + Double_t y = GetR() * TMath::Sin(phi) + GetXc().Y(); + + return TVector3(x, y, z); +} + + +/** Calculate Projector Matrix */ + +void ILDCylinderMeasLayer::CalcDhDa(const TVTrackHit &vht, // tracker hit not used here + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5, sdim - 1); + + // account for cylinder not centered at x=0.0, y=0.0 + TVector3 xxvc = xxv - GetXc(); + + Double_t xv = xxvc.X(); + Double_t yv = xxvc.Y(); + Double_t xxyy = xv * xv + yv * yv; + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + for (Int_t i = 0; i < hdim; i++) { + H(0, i) = - (yv / xxyy) * dxphiada(0, i) + + (xv / xxyy) * dxphiada(1, i); + H(0, i) *= GetR(); + + H(1, i) = dxphiada(2, i); + } + + if (sdim == 6) { + H(0, sdim - 1) = 0.; + } + +} + + +/** Convert LCIO Tracker Hit to an ILDCylinderHit */ + +ILDVTrackHit* ILDCylinderMeasLayer::ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + if ( ! trkhit) { + // streamlog_out(ERROR) << "ILDCylinderMeasLayer::ConvertLCIOTrkHit trkhit pointer is NULL" << std::endl; + return NULL; + } + + const edm4hep::Vector3d& pos = trkhit->getPosition(); + const TVector3 hit(pos.x, pos.y, pos.z) ; + //SJA:FIXME: this assumes that the cylinder is centred at 0,0 + + // convert to layer coordinates + TKalMatrix h = this->XvToMv(hit); + + Double_t x[2] ; + Double_t dx[2] ; + + x[0] = h(0, 0); + x[1] = h(1, 0); + + + //EVENT::TrackerHitZCylinder* cylinder_hit = dynamic_cast<EVENT::TrackerHitZCylinder*>( trkhit ) ; + if(trkhit->getType()==16){ + //if(cylinder_hit){ + // convert errors + dx[0] = trkhit->getCovMatrix(0); + dx[1] = trkhit->getCovMatrix(1); + } + else { + // convert errors + dx[0] = sqrt(trkhit->getCovMatrix(0) + trkhit->getCovMatrix(2)) ; + dx[1] = sqrt(trkhit->getCovMatrix(5)); + } + + + bool hit_on_surface = IsOnSurface(hit); + + //debug() << "ILDCylinderMeasLayer::ConvertLCIOTrkHit ILDCylinderHit created" + // streamlog_out(DEBUG1) << "ILDCylinderMeasLayer::ConvertLCIOTrkHit ILDCylinderHit created" + // << " R = " << hit.Perp() + // << " Layer R = " << this->GetR() + // << " RPhi = " << x[0] + // << " Z = " << x[1] + // << " dRPhi = " << dx[0] + // << " dZ = " << dx[1] + // << " x = " << pos.x + // << " y = " << pos.y + // << " z = " << pos.z + // << " onSurface = " << hit_on_surface + // << std::endl ; + //<<endmsg; + + return hit_on_surface ? new ILDCylinderHit( *this , x, dx, this->GetBz(), trkhit) : NULL; + +} + diff --git a/Utilities/KalDet/src/ild/common/ILDCylinderMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDCylinderMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..04740cc81edde2029bc347dc50a481001a2f2740 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDCylinderMeasLayer.h @@ -0,0 +1,93 @@ +#ifndef ILDCYLINDERMEASLAYER_H +#define ILDCYLINDERMEASLAYER_H + +/** ILDCylinderMeasLayer: User defined KalTest measurement layer class + * + * @author S.Aplin DESY + */ + + +#include "ILDVMeasLayer.h" +#include <iostream> +#include <cmath> +/* #include "streamlog/streamlog.h" */ + + +class ILDCylinderMeasLayer : public ILDVMeasLayer, public TCylinder { + +public: + + /** Constructor Taking inner and outer materials, radius and half length, B-Field, whether the layer is sensitive, Cell ID, and an optional name */ + ILDCylinderMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t r0, + Double_t lhalf, + Double_t x0, + Double_t y0, + Double_t z0, + Double_t Bz, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDCylinderMeasL") + : ILDVMeasLayer(min, mout, Bz, is_active, CellID, name), + TCylinder(r0, lhalf,x0,y0,z0) + { /* no op */ } + + + Bool_t IsOnSurface(const TVector3 &xx) const { + + bool z = (xx.Z() >= GetZmin() && xx.Z() <= GetZmax()); + bool r = std::fabs( (xx-this->GetXc()).Perp() - this->GetR() ) < 1.e-3; // for very short, very stiff tracks this can be poorly defined, so we relax this here a bit to 1 micron + +// streamlog_out(DEBUG0) << "ILDCylinderMeasLayer IsOnSurface for " << this->TVMeasLayer::GetName() << " R = " << this->GetR() << " GetZmin() = " << GetZmin() << " GetZmax() = " << GetZmax() +// << " dr = " << std::fabs( (xx-this->GetXc()).Perp() - this->GetR() ) << " r = " << r << " z = " << z +// << std::endl; + + return r && z; + } + + + + // Parent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + + { return this->XvToMv(xv); } + + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDCylinderHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return this->CalcXingPointWith(hel,xx,phi,0,eps); + + } + + +private: + +}; +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDDiscMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDDiscMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..d8d476fc30abc2b30711a4cbce25f03104fc28aa --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDDiscMeasLayer.cc @@ -0,0 +1,271 @@ + +#include <iostream> + +#include "ILDDiscMeasLayer.h" +#include "ILDPlanarHit.h" + +#include "kaltest/TVTrack.h" +#include "TVector3.h" +#include "TMath.h" +#include "TRotMatrix.h" +#include "TBRIK.h" +#include "TNode.h" +#include "TString.h" + +#include <edm4hep/TrackerHit.h> + +#include "gearimpl/Vector3D.h" + +// #include "streamlog/streamlog.h" + + +TKalMatrix ILDDiscMeasLayer::XvToMv(const TVector3 &xv) const +{ + + // Calculate measurement vector (hit coordinates) from global coordinates: + + TKalMatrix mv(kMdim,1); + + mv(0,0) = xv.X() ; + + + mv(1,0) = xv.Y() ; + return mv; + +} + + +TVector3 ILDDiscMeasLayer::HitToXv(const TVTrackHit &vht) const +{ + // const ILDPlanarHit &mv = dynamic_cast<const ILDPlanarHit &>(vht); + + double x = vht(0,0) ; + double y = vht(1,0) ; + + double z = GetXc().Z() ; + + return TVector3(x,y,z); +} + +void ILDDiscMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + for (Int_t i=0; i<hdim; i++) { + + H(0,i) = dxphiada(0,i); + H(1,i) = dxphiada(1,i) ; + + } + if (sdim == 6) { + H(0,sdim-1) = 0.; + H(1,sdim-1) = 0.; + } + +} + +Int_t ILDDiscMeasLayer::CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps) const{ + + phi = 0.0; + + xx.SetX(0.0); + xx.SetY(0.0); + xx.SetZ(0.0); + + + // check that direction has one of the correct values + if( !( mode == 0 || mode == 1 || mode == -1) ) return -1 ; + + // get helix parameters + Double_t dr = hel.GetDrho(); + Double_t phi0 = hel.GetPhi0(); // + Double_t kappa = hel.GetKappa(); + Double_t rho = hel.GetRho(); + Double_t omega = 1.0 / rho; + Double_t z0 = hel.GetDz(); + Double_t tanl = hel.GetTanLambda(); + + TVector3 ref_point = hel.GetPivot(); + + + // + // Check if charge is nonzero. + // + + Int_t chg = (Int_t)TMath::Sign(1.1,kappa); + if (!chg) { + // streamlog_out(ERROR) << ">>>> Error >>>> ILDDiscMeasLayer::CalcXingPointWith" << std::endl + // << " Kappa = 0 is invalid for a helix " << std::endl; + return -1; + } + + const double sin_phi0 = sin(phi0); + const double cos_phi0 = cos(phi0); + + const double x_pca = ref_point.x() + dr * cos_phi0 ; + const double y_pca = ref_point.y() + dr * sin_phi0 ; + const double z_pca = ref_point.z() + z0 ; + + const double z = this->GetXc().Z() ; + // get path length to crossing point + + const double s = ( z - z_pca ) / tanl ; + +// streamlog_out(DEBUG0) << "ILDDiscMeasLayer::CalcXingPointWith " +// << " ref_point.z() = " << ref_point.z() +// << " z = " << z +// << " z0 = " << z0 +// << " z_pca = " << z_pca +// << " tanl = " << tanl +// << " z - z_pca = " << z - z_pca +// << std::endl; + +// TVector3 xx_n; +// int cuts = TVSurface::CalcXingPointWith(hel, xx_n, phi, 0, eps); +// streamlog_out(DEBUG0) << "ILDDiscMeasLayer::CalcXingPointWith from Newton: cuts = " << cuts << " x = " << xx_n.x() << " y = "<< xx_n.y() << " z = " << xx_n.z() << " r = " << xx_n.Perp() << " phi = " << xx_n.Phi() << " dphi = " << phi << std::endl; + + + phi = -omega * s; + + const double delta_phi_half = -phi/2.0 ; + + + double x; + double y; + + if( fabs(s) > FLT_MIN ){ // protect against starting on the plane + + x = x_pca - s * ( sin(delta_phi_half) / delta_phi_half ) * sin( phi0 - delta_phi_half ) ; + + y = y_pca + s * ( sin(delta_phi_half) / delta_phi_half ) * cos( phi0 - delta_phi_half ) ; + + } + else{ + // streamlog_out(DEBUG0) << "ILDDiscMeasLayer::CalcXingPointWith Using PCA values " << std::endl; + x = x_pca; + y = y_pca; + phi = 0; + } + + + // check if intersection with plane is within boundaries + + xx.SetXYZ(x, y, z); + + + // streamlog_out(DEBUG0) << "ILDDiscMeasLayer::CalcXingPointWith : cuts = " << (IsOnSurface(xx) ? 1 : 0) << " x = " << xx.x() << " y = "<< xx.y() << " z = " << xx.z() << " r = " << xx.Perp() << " phi = " << xx.Phi() << " dphi = " << phi << " s = " << s << " " << this->TVMeasLayer::GetName() << std::endl; + + if( mode!=0 && fabs(phi)>1.e-10 ){ // (+1,-1) = (fwd,bwd) + if( chg*phi*mode > 0){ + return 0; + } + } + + return (IsOnSurface(xx) ? 1 : 0); + +} + + +Bool_t ILDDiscMeasLayer::IsOnSurface(const TVector3 &xx) const +{ + + bool onSurface = false ; + + TKalMatrix mv = XvToMv(xx); + + // check whether the hit lies in the same plane as the surface + if( TMath::Abs((xx.X()-GetXc().X())*GetNormal().X() + (xx.Y()-GetXc().Y())*GetNormal().Y() + (xx.Z()-GetXc().Z())*GetNormal().Z()) < 1e-4){ + // check whether the hit lies within the boundary of the surface + + double r2 = mv(0,0) * mv(0,0) + mv(1,0) * mv(1,0) ; + + if( r2 <= _rMax*_rMax && r2 >= _rMin*_rMin ) + { + onSurface = true ; + } + } + + return onSurface; + +} + + +ILDVTrackHit* ILDDiscMeasLayer::ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + + //edm4hep::TrackerHitPlane* plane_hit = dynamic_cast<EVENT::TrackerHitPlane*>( trkhit ) ; + //edm4hep::TrackerHitPlane* plane_hit = trkhit; + if((trkhit->getType()&8)!=8) return NULL; + + //edm4hep::TrackerHit* plane_hit = trkhit; + //if( plane_hit == NULL ) return NULL; // SJA:FIXME: should be replaced with an exception + + //gear::Vector3D U(1.0,plane_hit->getU()[1],plane_hit->getU()[0],gear::Vector3D::spherical); + //gear::Vector3D V(1.0,plane_hit->getV()[1],plane_hit->getV()[0],gear::Vector3D::spherical); + gear::Vector3D U(1.0,trkhit->getCovMatrix(1),trkhit->getCovMatrix(0),gear::Vector3D::spherical); + gear::Vector3D V(1.0,trkhit->getCovMatrix(5),trkhit->getCovMatrix(4),gear::Vector3D::spherical); + gear::Vector3D X(1.0,0.0,0.0); + gear::Vector3D Y(0.0,1.0,0.0); + + const float eps = 1.0e-07; + // U must be the global X axis + if( fabs(1.0 - U.dot(X)) > eps ) { + // streamlog_out(ERROR) << "ILDDiscMeasLayer: TrackerHitPlane measurment vectors U is not equal to the global X axis. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << std::endl; + exit(1); + } + + // V must be the global X axis + if( fabs(1.0 - V.dot(Y)) > eps ) { + // streamlog_out(ERROR) << "ILDDiscMeasLayer: TrackerHitPlane measurment vectors V is not equal to the global Y axis. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << std::endl; + exit(1); + } + + const edm4hep::Vector3d& pos=trkhit->getPosition(); + const TVector3 hit(pos.x, pos.y, pos.z); + + // convert to layer coordinates + TKalMatrix h = this->XvToMv(hit); + + double x[2] ; + double dx[2] ; + + x[0] = h(0, 0); + x[1] = h(1, 0); + + //dx[0] = plane_hit->getdU() ; + //dx[1] = plane_hit->getdV() ; + dx[0] = trkhit->getCovMatrix(2); + dx[1] = trkhit->getCovMatrix(5); + + bool hit_on_surface = IsOnSurface(hit); + + // streamlog_out(DEBUG1) << "ILDDiscMeasLayer::ConvertLCIOTrkHit ILDPlanarHit created" + // << " u = " << x[0] + // << " v = " << x[1] + // << " du = " << dx[0] + // << " dv = " << dx[1] + // << " x = " << pos.x + // << " y = " << pos.y + // << " z = " << pos.z + // << " onSurface = " << hit_on_surface + // << std::endl ; + + return hit_on_surface ? new ILDPlanarHit( *this , x, dx, this->GetBz(), trkhit) : NULL; + +} diff --git a/Utilities/KalDet/src/ild/common/ILDDiscMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDDiscMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..fe3ff82672144da1330120ebe3a8a26d56ae21d4 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDDiscMeasLayer.h @@ -0,0 +1,101 @@ +#ifndef __ILDDISCMEASLAYER__ +#define __ILDDISCMEASLAYER__ + +/** ILDDiscMeasLayer: User defined KalTest Disc measurement layer class used with ILDPLanarTrackHit. + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> + +class TVTrackHit; + + +class ILDDiscMeasLayer : public ILDVMeasLayer, public TPlane { + +public: + + /** Constructor Taking inner and outer materials, center and normal to the plane, B-Field, sorting policy, min and max r, whether the layer is sensitive, Cell ID, and an optional name */ + + ILDDiscMeasLayer(TMaterial &min, + TMaterial &mout, + const TVector3 ¢er, + const TVector3 &normal, + double Bz, + double SortingPolicy, + double rMin, + double rMax, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDDiscMeasL") + : ILDVMeasLayer(min, mout, Bz, is_active, CellID, name), + TPlane(center, normal), + _sortingPolicy(SortingPolicy), _rMin(rMin), _rMax(rMax) + { /* no op */ } + + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps) const; + + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** Check if global point is on surface */ + inline virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + /** Get sorting policy for this plane */ + double GetSortingPolicy() const { return _sortingPolicy; } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return this->CalcXingPointWith(hel,xx,phi,0,eps); + + } + +private: + double _sortingPolicy; + double _rMin; + double _rMax; + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDMeasurementSurfaceStoreFiller.cc b/Utilities/KalDet/src/ild/common/ILDMeasurementSurfaceStoreFiller.cc new file mode 100644 index 0000000000000000000000000000000000000000..1d7e527aa65f823abb4cbbb852d549628704334f --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDMeasurementSurfaceStoreFiller.cc @@ -0,0 +1,403 @@ + +#include "ILDMeasurementSurfaceStoreFiller.h" + +#include "UTIL/ILDConf.h" + +#include <gear/ZPlanarParameters.h> +#include <gear/ZPlanarLayerLayout.h> +#include <gear/FTDLayerLayout.h> +#include <gear/FTDParameters.h> +#include <gear/GEAR.h> +#include <gear/GearMgr.h> + +// #include "streamlog/streamlog.h" + + +#include "gear/gearsurf/CartesianCoordinateSystem.h" +#include "gear/gearsurf/MeasurementSurface.h" +#include "gear/gearsurf/BoundaryRectangle.h" +#include "gear/gearsurf/BoundaryTrapezoid.h" + +void ILDMeasurementSurfaceStoreFiller::get_gear_parameters(const gear::GearMgr& gear_mgr) { + + _paramVXD = 0 ; try { _paramVXD = &(gear_mgr.getVXDParameters()); } catch( gear::UnknownParameterException& e){} + _paramSIT = 0 ; try { _paramSIT = &(gear_mgr.getSITParameters()); } catch( gear::UnknownParameterException& e){} + _paramSET = 0 ; try { _paramSET = &(gear_mgr.getSETParameters()); } catch( gear::UnknownParameterException& e){} + _paramFTD = 0 ; try { _paramFTD = &(gear_mgr.getFTDParameters()); } catch( gear::UnknownParameterException& e){} + + + if( _paramVXD ){ + unsigned nVTXLayers = _paramVXD->getZPlanarLayerLayout().getNLayers() ; + + for( unsigned i=0; i<nVTXLayers; i++) { + + _VTXStripAngles.push_back( 0. ); + + //***************************************************************** + // Note currently the VXD is constructed as single sensor ladders + //***************************************************************** + _VTXNSensors.push_back( 1 ); + + } + } + + if( _paramSIT ){ + + unsigned nSITLayers = _paramSIT->getZPlanarLayerLayout().getNLayers(); + + try { + + double strip_angle_deg = _paramSIT->getDoubleVal("strip_angle_deg"); + + for( unsigned i=0; i<nSITLayers; i++) { + + _SITStripAngles.push_back( pow(-1,i) * strip_angle_deg * M_PI/180 ); // alternately + and - 5° + _SITNSensors.push_back(_paramSIT->getIntVals("n_sensors_per_ladder")[i]); + + } + + } catch (gear::UnknownParameterException& e) { + + for( unsigned i=0; i<nSITLayers; i++) { + _SITStripAngles.push_back( 0. ); + _SITNSensors.push_back(_paramSIT->getIntVals("n_sensors_per_ladder")[i]); + } + + } + } + + if( _paramSET ){ + + unsigned nSETLayers = _paramSET->getZPlanarLayerLayout().getNLayers(); + + try { + + double strip_angle_deg = _paramSET->getDoubleVal("strip_angle_deg"); + + for( unsigned i=0; i<nSETLayers; i++) { + + _SETStripAngles.push_back( pow(-1,i) * strip_angle_deg * M_PI/180 ); // alternately + and - 5° + _SETNSensors.push_back(_paramSET->getIntVals("n_sensors_per_ladder")[i]); + + } + + } catch (gear::UnknownParameterException& e) { + + for( unsigned i=0; i<nSETLayers; i++) { + _SETStripAngles.push_back( 0. ); + _SETNSensors.push_back(_paramSET->getIntVals("n_sensors_per_ladder")[i]); + + } + } + } + + + if( _paramFTD ){ + + const gear::FTDLayerLayout& ftdLayers = _paramFTD->getFTDLayerLayout() ; + unsigned nFTDLayers = ftdLayers.getNLayers(); + + for( unsigned layer=0; layer<nFTDLayers; layer++ ){ + + std::vector< double > angles; + + unsigned nSensors = ftdLayers.getNSensors( layer ); + + if (ftdLayers.getSensorType(layer) == gear::FTDParameters::STRIP ){ + + double strip_angle_deg = _paramFTD->getDoubleVal("strip_angle_deg"); + + for( unsigned sensor=1; sensor <= nSensors; sensor++ ){ + + + if ( sensor <= nSensors/2 ) angles.push_back( strip_angle_deg * M_PI/180. ); // the first half of the sensors is in front with one angle, + else angles.push_back( -strip_angle_deg * M_PI/180. ); // the other is in the back with the opposite angle + + } + + } + else{ // a pixel detector, so no stripAngle + + double strip_angle_deg = 0.0 ; + for( unsigned sensor=1; sensor <= nSensors; sensor++ ) angles.push_back(strip_angle_deg); + + } + + _FTDStripAngles.push_back( angles ); + + } + } + //#endif + +} + + + + +void ILDMeasurementSurfaceStoreFiller::getMeasurementSurfaces( std::vector<MeasurementSurface*>& surface_list ) const { + + if( _paramVXD ) + this->storeZPlanar( _paramVXD , UTIL::ILDDetID::VXD, surface_list ); + + if( _paramSIT ) + this->storeZPlanar( _paramSIT , UTIL::ILDDetID::SIT, surface_list ); + + if(_paramSET ) + this->storeZPlanar( _paramSET , UTIL::ILDDetID::SET, surface_list ); + + if( _paramFTD ) + this->storeFTD( _paramFTD , surface_list); + +} + + +void ILDMeasurementSurfaceStoreFiller::storeZPlanar( const gear::ZPlanarParameters* param , int det_id, std::vector<MeasurementSurface*>& surface_list ) const { + + + std::vector< double > angles; + std::vector< int > nsensors; + + if( det_id == UTIL::ILDDetID::VXD ) { + + angles = _VTXStripAngles; + nsensors = _VTXNSensors; + } + else if ( det_id == UTIL::ILDDetID::SIT ){ + angles = _SITStripAngles; + nsensors = _SITNSensors; + } + + else if ( det_id == UTIL::ILDDetID::SET ){ + angles = _SETStripAngles; + nsensors = _SETNSensors; + + } + + else { + return; + } + + + const gear::ZPlanarLayerLayout& layerLayout = param->getZPlanarLayerLayout(); + + unsigned nLayers = layerLayout.getNLayers(); + + for( unsigned layerNumber = 0; layerNumber < nLayers; layerNumber++ ){ + + unsigned nLadders = layerLayout.getNLadders( layerNumber ); + + double ladder_r = layerLayout.getSensitiveDistance(layerNumber); // the distance of the ladders from (0,0,0) + double sensitive_offset = layerLayout.getSensitiveOffset(layerNumber); // the offset, see ZPlanarLayerLayout.h for more details + double deltaPhi = ( 2 * M_PI ) / nLadders ; // the phi difference between two ladders + double phi0 = layerLayout.getPhi0( layerNumber ); + double sensitive_length = layerLayout.getSensitiveLength(layerNumber) * 2.0 ; // note: gear for historical reasons uses the halflength + double sensitive_width = layerLayout.getSensitiveWidth(layerNumber); + double sensitive_thickness = layerLayout.getSensitiveThickness(layerNumber); + + double stripAngle = angles.at(layerNumber); + + for( unsigned ladderNumber = 0; ladderNumber < nLadders; ladderNumber++ ){ + + for( int sensorNumber = 0; sensorNumber < nsensors.at(layerNumber); sensorNumber++ ){ + + // determine the CellID0 for the ladder + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + cellID[ lcio::ILDCellID0::subdet ] = det_id ; + cellID[ lcio::ILDCellID0::side ] = 0 ; + cellID[ lcio::ILDCellID0::layer ] = layerNumber ; + cellID[ lcio::ILDCellID0::module ] = ladderNumber ; + cellID[ lcio::ILDCellID0::sensor ] = sensorNumber ; + int cellID0 = cellID.lowWord(); + + + // ************** + // SJA:FIXME: sensors for now will be placed running from 1 to n will be placed from -z to z + // as is done in the drivers sit_simple_planar and set_simple_planar + double sensor_length = sensitive_length / nsensors.at(layerNumber); + double pos_z = -0.5*sensitive_length + (0.5*sensor_length) + (sensorNumber*sensor_length) ; + // ************** + + // Let's start with the translation T: the new center of coordinates: + // The center of the first sensor (when we ignore an offset and phi0 for now) is (R,0,pos_z) + // If we include the offset, the center gets shifted to (R,offset,pos_z) + CLHEP::Hep3Vector T( ladder_r + sensitive_thickness/2., sensitive_offset, pos_z ); + // Now we have to take into account phi0 and that the number of the ladder. + // Together the center is rotated by phi0 + ladderNumber*deltaPhi around the z axis + CLHEP::HepRotation rot; + rot.rotateZ( deltaPhi * ladderNumber + phi0 ); + + T = rot * T; + + // Next, we want to determinte the rotation matrix R + // We start with u,v,w alligned with x,y,z. + // As u is perpendicular to the strip orientation it looks like this. + // y + // | + // ---|--- + // | | | + // | | | + // <--------|--------> x + // | | | + // | | | + // ---|--- + // | + // To get this sensor in place we have to do a few rotations: + // First we'll rotate around the z axis. With a strip angle of 0, + // we would just rotate by 90°, but with a strip angle by + // 90°-stripAngle in clockwise direction. + CLHEP::HepRotation R; + // printRotation( R ); + R.rotateZ( stripAngle - M_PI/2. ); + // printRotation( R ); + + // Next we rotate 90° clockwise around y, so the strip now points in z direction (if strip angle == 0) + R.rotateY( -M_PI/2. ); + + // Finally we have to get the ladder in place w.r. to its number and the resulting phi angle + R.rotateZ( deltaPhi * ladderNumber + phi0 ); + + CartesianCoordinateSystem* cartesian = new CartesianCoordinateSystem( T, R ); + + BoundaryRectangle* b = new BoundaryRectangle( sensitive_width, sensor_length, 1., -stripAngle ); + MeasurementSurface* ms = new MeasurementSurface( cellID0, cartesian, b ); + surface_list.push_back(ms); + + } + + } + + } + +} + + +void ILDMeasurementSurfaceStoreFiller::storeFTD( const gear::FTDParameters* param, std::vector<MeasurementSurface*>& surface_list ) const { + + const gear::FTDLayerLayout& ftdLayers = param->getFTDLayerLayout() ; + unsigned nLayers = ftdLayers.getNLayers(); + + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + cellID[ lcio::ILDCellID0::subdet ] = UTIL::ILDDetID::FTD ; + + for( unsigned layer = 0; layer < nLayers; layer++ ){ + + + cellID[ lcio::ILDCellID0::layer ] = layer ; + + unsigned nPetals = ftdLayers.getNPetals( layer ); + double deltaPhi = ( 2 * M_PI ) / nPetals; + double phi0 = ftdLayers.getPhi0( layer ); + double lengthMin = ftdLayers.getSensitiveLengthMin( layer ); + double lengthMax = ftdLayers.getSensitiveLengthMax( layer ); + double width = ftdLayers.getSensitiveWidth( layer ); + unsigned nSensors = ftdLayers.getNSensors( layer ); + bool isDoubleSided = ftdLayers.isDoubleSided( layer ); + // Get some information about the petal (a trapezoid, see gear for in depth description) + double distMin = ftdLayers.getSensitiveRinner(layer); // the xy-distance from (0,0) of the center of the inner base + double distMax = distMin + width; // the xy-distance from (0,0) of the center of the outer base + unsigned nSensorsOn1Side = nSensors; + if( isDoubleSided ) nSensorsOn1Side = nSensorsOn1Side / 2; + + for( unsigned petal=0; petal< nPetals; petal++ ){ + + + cellID[ lcio::ILDCellID0::module ] = petal ; + + + for ( unsigned sensor = 1; sensor <=nSensors; sensor++ ){ + + double stripAngle = 0.; + + + stripAngle = _FTDStripAngles[layer][sensor-1]; // NOTE HERE WE ARE COUNTING FROM 1!!!! + + // streamlog_out(DEBUG1) << "FTD layer = " << layer << "\tpetal = " << petal << "\tsensor = " << sensor << " stripAngle = " << stripAngle << "\n"; + + cellID[ lcio::ILDCellID0::side ] = -1 ; + cellID[ lcio::ILDCellID0::sensor ] = sensor ; + int cellID0 = cellID.lowWord(); + + // We start with the Translation Vector T (=origin of new CoordinateSystem ) + // the first petal (if phi0 = 0) sits with its symmetry axis on the x axis. + // It starts at x= rInner (lMin)nand reaches rInner+ width (lMax) on the x axis + // So far the center of Mass will be on the x axis. + // + // Now we have to take into account how many sensors there are on the petal, and where they sit. + double deltaX = (distMax-distMin) / double( nSensorsOn1Side ); //how much delta x one sensor covers + + // The first sensor is the outermost one. Let's calculate its center + double xFirst = distMax - deltaX/2.; + + // From here, all we have to do is go down in steps of deltaX until we reach the right sensor. + // We have to be careful: when there are sensors on the back, they start again at the top. + // If we for example have 6 sensors on a doublesided petal: on the front it is from out to inside: 1,2,3 + // and on the back: 4,5,6. So 1 and 4 will be (apart from z) at the same position. So will 2 and 5, as well + // as 3 and 6 + unsigned steps = (sensor-1)%nSensorsOn1Side; // the number of steps to go deltaX (in negative direction) + // In our example with 6 sensors, this gives sensor 1: 0 steps, 2:1, 3:2, 4:0, 5:1, 6:2 + + double x = xFirst - steps * deltaX; + double y = 0.; + double z = -ftdLayers.getSensitiveZposition( layer, petal, sensor ); // we first calculate for the petals at -z + //(because the imagination of the rotation is easier, as w point the same direction as z) + // later we from the result we can calculate R and T for +z pretty easy. + + // Calculate lengths of the inner and outer base of the trapezoid + double baseOuter = lengthMax - steps * (lengthMax - lengthMin); + double baseInner = baseOuter - (lengthMax - lengthMin) / nSensorsOn1Side; + + CLHEP::Hep3Vector T( x , y, z); + // printVector( T ); + // Now we only have to rotate the petal around the z-axis into its place + CLHEP::HepRotation rot; + rot.rotateZ( petal * deltaPhi + phi0 ); + T = rot * T; + // printVector( T ); + + //On to the rotation matrix + CLHEP::HepRotation R; + // printRotation( R ); + R.rotateZ( petal * deltaPhi + phi0 + stripAngle - M_PI/2. ); + // printRotation( R ); + + BoundaryTrapezoid* b1 = new BoundaryTrapezoid( baseInner, baseOuter, deltaX, 1., -stripAngle); + CartesianCoordinateSystem* cartesian = new CartesianCoordinateSystem( T, R ); + MeasurementSurface* ms = new MeasurementSurface( cellID0, cartesian, b1); + surface_list.push_back(ms); + + + // Once more for the other side + cellID[ lcio::ILDCellID0::side ] = 1 ; + cellID0 = cellID.lowWord(); + + T.setZ( -T.z() ); // switch to -z + + // R is pretty much the same as the strip orientation will be the same, + // but as (by chosen definition) w should point towards the IP, + // we have to flip u around. So we acutally have to rotate 180° around v + // So first we get the vector v + CLHEP::Hep3Vector v = R*CLHEP::Hep3Vector(0,1,0); + // Then we rotate around it + R.rotate( M_PI , v ); + // printRotation( R ); + + BoundaryTrapezoid* b2 = new BoundaryTrapezoid( baseInner, baseOuter, deltaX, 1., stripAngle); + CartesianCoordinateSystem* cartesian2 = new CartesianCoordinateSystem( T, R ); + MeasurementSurface* ms2 = new MeasurementSurface( cellID0, cartesian2, b2); + surface_list.push_back(ms2); + + + } + + } + + } + +} + + + + + + + diff --git a/Utilities/KalDet/src/ild/common/ILDMeasurementSurfaceStoreFiller.h b/Utilities/KalDet/src/ild/common/ILDMeasurementSurfaceStoreFiller.h new file mode 100644 index 0000000000000000000000000000000000000000..79ff8e1ea0aafc6123eed869b85573f5f8580aee --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDMeasurementSurfaceStoreFiller.h @@ -0,0 +1,81 @@ +#ifndef ILDMEASUREMENTSURFACESTOREFILLER_H +#define ILDMEASUREMENTSURFACESTOREFILLER_H + +#include "gearsurf/MeasurementSurfaceStore.h" + +#include <vector> + +namespace gear{ + class GearMgr; + class ZPlanarParameters; + class FTDParameters; +} + +using namespace gear; + +class ILDMeasurementSurfaceStoreFiller : public MeasurementSurfaceStoreFiller{ + + public: + + + ILDMeasurementSurfaceStoreFiller(const gear::GearMgr& gear_mgr) : + _nVTXLayers(0), + _nSITLayers(0), + _nFTDLayers(0), + _nSETLayers(0) { + + this->get_gear_parameters(gear_mgr); + + } + + ~ILDMeasurementSurfaceStoreFiller() { /* no op */ } + + void getMeasurementSurfaces( std::vector<MeasurementSurface*>& surface_list ) const; + + std::string getName() const { return "ILDMeasurementSurfaceStoreFiller" ; } ; + + private: + + /** adds MeasurementSufaces to the store + * @param param: the ZPlanarParameters pointer of the detector, of which the measurement surfaces shall be added + * + * @param det_id: the detector id (as in ILDConf) + */ + void storeZPlanar( const gear::ZPlanarParameters* param , int det_id, std::vector<MeasurementSurface*>& surface_list ) const; + + void storeFTD( const gear::FTDParameters* param, std::vector<MeasurementSurface*>& surface_list ) const; + + + void get_gear_parameters(const gear::GearMgr& gear_mgr); + + /** the strip angles for every layer */ + std::vector< double > _VTXStripAngles; + std::vector< double > _SITStripAngles; + std::vector< double > _SETStripAngles; + + /** the number of sensors for every layer */ + std::vector< int > _VTXNSensors; + std::vector< int > _SITNSensors; + std::vector< int > _SETNSensors; + + + /** the strip angles for every layer and sensor */ + std::vector< std::vector< double > > _FTDStripAngles; + + unsigned _nVTXLayers; + unsigned _nSITLayers; + unsigned _nFTDLayers; + unsigned _nSETLayers; + + + const gear::ZPlanarParameters* _paramVXD; + const gear::ZPlanarParameters* _paramSIT; + const gear::ZPlanarParameters* _paramSET; + const gear::FTDParameters* _paramFTD; + + + +}; + +#endif + diff --git a/Utilities/KalDet/src/ild/common/ILDParallelPlanarMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDParallelPlanarMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..40eb8aebe58bc6efcf49b87470675c4b0e2636d5 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDParallelPlanarMeasLayer.cc @@ -0,0 +1,317 @@ + +#include "ILDParallelPlanarMeasLayer.h" +#include "kaltest/TVTrack.h" + +// #include "streamlog/streamlog.h" + + +Int_t ILDParallelPlanarMeasLayer::CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps) const{ + + + // check that direction has one of the correct values + if( !( mode == 0 || mode == 1 || mode == -1) ) return -1 ; + + + + // This assumes nonzero B field. + // + // Copy helix parameters to local variables. + // + + Double_t dr = hel.GetDrho(); + Double_t phi0 = hel.GetPhi0(); // + Double_t kappa = hel.GetKappa(); + Double_t rho = hel.GetRho(); + Double_t omega = 1.0 / rho; + Double_t r = TMath::Abs(rho); + Double_t z0 = hel.GetDz(); + Double_t tanl = hel.GetTanLambda(); + + TVector3 ref_point = hel.GetPivot(); + + // + // Check if charge is nonzero. + // + + Int_t chg = (Int_t)TMath::Sign(1.1,kappa); + if (!chg) { + // streamlog_out(ERROR) << ">>>> Error >>>> ILDParallelPlanarMeasLayer::CalcXingPointWith" << std::endl + // << " Kappa = 0 is invalid for a helix " << std::endl; + return -1; + } + + // + // Project everything to XY plane and calculate crossing points. + // + // taken from http://paulbourke.net/geometry/sphereline/ + + + const double sin_phi0 = sin(phi0); + const double cos_phi0 = cos(phi0); + + const double x_pca = ref_point.x() + dr * cos_phi0 ; + const double y_pca = ref_point.y() + dr * sin_phi0 ; + const double z_pca = ref_point.z() + z0 ; + + const double x_c = ref_point.x() + ( rho + dr) * cos_phi0 ; + const double y_c = ref_point.y() + ( rho + dr) * sin_phi0 ; + + // get the extreams of the plane in x and y + const double x1 = this->GetXc().x() - 0.5*this->GetXiwidth()*sin(this->GetXc().Phi()) - this->GetXioffset() * sin(this->GetXc().Phi()); + const double x2 = this->GetXc().x() + 0.5*this->GetXiwidth()*sin(this->GetXc().Phi()) - this->GetXioffset() * sin(this->GetXc().Phi()); + + const double y1 = this->GetXc().y() + 0.5*this->GetXiwidth()*cos(this->GetXc().Phi()) + this->GetXioffset() * cos(this->GetXc().Phi()); + const double y2 = this->GetXc().y() - 0.5*this->GetXiwidth()*cos(this->GetXc().Phi()) + this->GetXioffset() * cos(this->GetXc().Phi()); + + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: Xc = " << this->GetXc().x() << " Yc = " << this->GetXc().y() << " Rc = " << this->GetXc().Perp() << " Phi = " << this->GetXc().Phi() << std::endl; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: x1 = " << x1 << " y1 = " << y1 << " R " << TVector3(x1,y1,0).Perp() << " phi = " << TVector3(x1,y1,0).Phi() << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: x2 = " << x2 << " y2 = " << y2 << " R " << TVector3(x2,y2,0).Perp() << " phi = " << TVector3(x2,y2,0).Phi() << std::endl ; + + const double dx = x2 - x1 ; + const double dy = y2 - y1 ; + + const double a = dx * dx + dy * dy ; + + const double b = 2.0 * ( dx * (x1 - x_c) + dy * (y1 - y_c) ) ; + + double c = x_c * x_c + y_c * y_c; + c += x1 * x1 + y1 * y1 ; + + c -= 2.0 * ( x_c * x1 + y_c * y1 ); + c -= rho * rho; + + const double bb4ac = b * b - 4.0 * a * c; + + double u1 ; // first solution + double u2 ; // second solution + + double x_ins = DBL_MAX; + double y_ins = DBL_MAX; + double s_ins = DBL_MAX; + + /* Check for solvability. */ + if (bb4ac + eps < 0.0 ) { // no intersection + return 0; + } + else if(bb4ac - eps < 0.0) { // circle intersects at one point, tangential + return 0; + } + else{ + u1 = (-b + sqrt(bb4ac)) / (2.0 * a); + u2 = (-b - sqrt(bb4ac)) / (2.0 * a); + } + + // test values of u + // case i) ( u1 < 0 && u2 < 0 ) || ( u1 > 1 && u2 > 1 ) + // Line segment doesn't intersect and is on outside of the circle + if ( ( u1 <= 0 && u2 <= 0 ) || ( u1 >= 1 && u2 >= 1 ) ) { + + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: Line segment doesn't intersect and is outside the circle " << std::endl; + // const double x_ins1 = x1 + u1 * (dx) ; + // const double y_ins1 = y1 + u1 * (dy) ; + // + // const double x_ins2 = x1 + u2 * (dx) ; + // const double y_ins2 = y1 + u2 * (dy) ; + // + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 1st solution u = " << u1 << " : " << u1 * dx << " " << u1 * dy << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 2nd solution u = " << u2 << " : " << u2 * dx << " " << u2 * dy << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 1st solution x:y = " << x_ins1 << " : " << y_ins1 << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 2nd solution x:y = " << x_ins2 << " : " << y_ins2 << std::endl ; + + return 0 ; + } + + // case ii) ( u1 < 0 && u2 > 1 ) || ( u1 > 1 && u2 < 0 ) + // Line segment doesn't intersect and is inside the circle + else if ( ( u1 <= 0 && u2 >= 1 ) || ( u1 >= 1 && u2 <= 0 ) ) { + + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: Line segment doesn't intersect and is inside the circle " << std::endl; + // + // const double x_ins1 = x1 + u1 * (dx) ; + // const double y_ins1 = y1 + u1 * (dy) ; + // + // const double x_ins2 = x1 + u2 * (dx) ; + // const double y_ins2 = y1 + u2 * (dy) ; + // + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 1st solution u = " << u1 << " : " << u1 * dx << " " << u1 * dy << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 2nd solution u = " << u2 << " : " << u2 * dx << " " << u2 * dy << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 1st solution x:y = " << x_ins1 << " : " << y_ins1 << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 2nd solution x:y = " << x_ins2 << " : " << y_ins2 << std::endl ; + + + return 0 ; + } + + // case iii) ( u1 > 0 && u1 < 1 && u2 < 0 && u2 > 1 ) || ( u2 > 0 && u2 < 1 && u1 < 0 && u1 > 1 ) + // Line segment intersects at one point + else if ( ( u1 > 0 && u1 < 1 && (u2 <= 0 || u2 >= 1) ) || ( u2 > 0 && u2 < 1 && ( u1 <= 0 || u1 >= 1 )) ) { + + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: Only one possible solution" << std::endl; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 1st solution u = " << u1 << " : " << u1 * dx << " " << u1 * dy << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 2nd solution u = " << u2 << " : " << u2 * dx << " " << u2 * dy << std::endl ; + + if ( u1 > 0 && u1 < 1 ) { // use u1 + + x_ins = x1 + u1 * (dx) ; + y_ins = y1 + u1 * (dy) ; + + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: take 1st solution x:y:z = " << x_ins << " : " << y_ins ; + } + else{ // use u2 + + x_ins = x1 + u2 * (dx) ; + y_ins = y1 + u2 * (dy) ; + + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: take 2nd solution x:y:z = " << x_ins << " : " << y_ins ; + } + + const double delta_x = x_ins - x_pca ; + const double delta_y = y_ins - y_pca ; + + const double sin_delta_phi = omega*delta_x*sin_phi0 - omega*delta_y*cos_phi0 ; + const double cos_delta_phi = 1.0 - omega*delta_x*cos_phi0 - omega*delta_y*sin_phi0 ; + + // const double sin_delta_phi = - omega*delta_x*cos_phi0 - omega*delta_y*sin_phi0 ; + // const double cos_delta_phi = 1.0 - omega*delta_x*sin_phi0 + omega*delta_y*cos_phi0 ; + + s_ins = atan2(-sin_delta_phi,cos_delta_phi) / omega ; + + //SJA:FIXME: do we need to consider the mode here ... + + // streamlog_out(DEBUG0) << " : " << z_pca + s_ins * tanl << std::endl ; + + } + + // case iv) ( u1 > 0 && u1 < 1 && u2 > 0 && u2 < 1 ) + // Line segment intersects at two points + else{ + + const double x_ins1 = x1 + u1 * (dx) ; + const double y_ins1 = y1 + u1 * (dy) ; + + const double x_ins2 = x1 + u2 * (dx) ; + const double y_ins2 = y1 + u2 * (dy) ; + + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 1st solution u = " << u1 << " : " << u1 * dx << " " << u1 * dy << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 2nd solution u = " << u2 << " : " << u2 * dx << " " << u2 * dy << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 1st solution x:y = " << x_ins1 << " : " << y_ins1 << std::endl ; + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: 2nd solution x:y = " << x_ins2 << " : " << y_ins2 << std::endl ; + + // now calculate the path lengths + double s_1 = 0.0 ; + double s_2 = 0.0 ; + + const double delta_x1 = x_ins1 - x_pca ; + const double delta_y1 = y_ins1 - y_pca ; + + // const double sin_delta_phi1 = - omega*delta_x1*cos_phi0 - omega*delta_y1*sin_phi0 ; + // const double cos_delta_phi1 = 1.0 - omega*delta_x1*sin_phi0 + omega*delta_y1*cos_phi0 ; + + const double sin_delta_phi1 = omega*delta_x1*sin_phi0 - omega*delta_y1*cos_phi0 ; + const double cos_delta_phi1 = 1.0 - omega*delta_x1*cos_phi0 - omega*delta_y1*sin_phi0 ; + + s_1 = atan2(-sin_delta_phi1,cos_delta_phi1) / omega ; + + + const double delta_x2 = x_ins2 - x_pca ; + const double delta_y2 = y_ins2 - y_pca ; + + // const double sin_delta_phi2 = - omega*delta_x2*cos_phi0 - omega*delta_y2*sin_phi0 ; + // const double cos_delta_phi2 = 1.0 - omega*delta_x2*sin_phi0 + omega*delta_y2*cos_phi0 ; + + const double sin_delta_phi2 = omega*delta_x2*sin_phi0 - omega*delta_y2*cos_phi0 ; + const double cos_delta_phi2 = 1.0 - omega*delta_x2*cos_phi0 - omega*delta_y2*sin_phi0 ; + + s_2 = atan2(-sin_delta_phi2,cos_delta_phi2) / omega ; + + + if( mode == 0 ) { // take closest intersection + if( TMath::Abs(s_1) < TMath::Abs(s_2) ) { + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: take 1st solution " << std::endl; + x_ins = x_ins1; + y_ins = y_ins1; + s_ins = s_1; + } + else { + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: take 2nd solution " << std::endl; + x_ins = x_ins2; + y_ins = y_ins2; + s_ins = s_2; + } + } + + else{ + + if ( s_1 < 0.0 ) s_1 += TMath::TwoPi() * r ; + if ( s_2 < 0.0 ) s_2 += TMath::TwoPi() * r ; + + if( mode == 1 ){ // take the intersection with smallest s + if( s_1 < s_2 ) { + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: take 1st solution " << std::endl; + x_ins = x_ins1; + y_ins = y_ins1; + s_ins = s_1; + } + else { + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: take 2nd solution " << std::endl; + x_ins = x_ins2; + y_ins = y_ins2; + s_ins = s_2; + } + } + else if( mode == -1 ) { // else take the intersection with largest s + if( s_1 > s_2 ){ + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: take 1st solution " << std::endl; + x_ins = x_ins1; + y_ins = y_ins1; + s_ins = s_1; + } + else{ + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: take 2nd solution " << std::endl; + x_ins = x_ins2; + y_ins = y_ins2; + s_ins = s_2; + } + } + } + } + + + +// streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith mode = " << mode << " dr = " << dr << " dz = " << z0 << " x = " << ref_point.x() << " y = "<< ref_point.y() << " z = " << ref_point.z() << " r = " << ref_point.Perp() << std::endl; + +// TVector3 xx_n; +// int cuts = TVSurface::CalcXingPointWith(hel, xx_n, phi, mode, eps); +// streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith from Newton: cuts = " << cuts << " x = " << xx_n.x() << " y = "<< xx_n.y() << " z = " << xx_n.z() << " r = " << xx_n.Perp() << " phi = " << xx_n.Phi() << " dphi = " << phi << " " << this->TVMeasLayer::GetName() << std::endl; + + xx.SetXYZ(x_ins, y_ins, z_pca + s_ins * tanl); + + phi = -s_ins * omega ; + + // streamlog_out(DEBUG0) << "ILDParallelPlanarMeasLayer::CalcXingPointWith: cuts = " << (IsOnSurface(xx) && (chg*phi*mode)<0) + // << " x = " << xx.X() + // << " y = " << xx.Y() + // << " z = " << xx.Z() + // << " r = " << xx.Perp() + // << " phi = " << xx.Phi() + // << " dphi = " << phi + // << " " << this->TVMeasLayer::GetName() + // << std::endl; + + if( mode!=0 && fabs(phi)>1.e-10){ // (+1,-1) = (fwd,bwd) + if( chg*phi*mode > 0){ + return 0; + } + } + + return (IsOnSurface(xx) ? 1 : 0); + +} + + + + diff --git a/Utilities/KalDet/src/ild/common/ILDParallelPlanarMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDParallelPlanarMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..7262a3e84e248b8eb03ad0d6afbea283b06750cc --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDParallelPlanarMeasLayer.h @@ -0,0 +1,80 @@ +#ifndef __ILDParallelPlanarMeasLayer__ +#define __ILDParallelPlanarMeasLayer__ + +/** ILDParallelPlanarMeasLayer: User defined KalTest measurement layer class + * + * @author S.Aplin DESY + */ + + +#include "ILDPlanarMeasLayer.h" + +class ILDParallelPlanarMeasLayer : public ILDPlanarMeasLayer { + +public: + + /** Constructor Taking inner and outer materials, distance and phi of plane pca to origin, B-Field, Sorting policy, plane transverse witdth and offset of centre, longitudinal width, whether the layer is sensitive, Cell ID, and an optional name */ + ILDParallelPlanarMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t r, + Double_t phi, + Double_t Bz, + Double_t SortingPolicy, + Double_t xiwidth, + Double_t zetawidth, + Double_t xioffset, + Double_t zoffset, + Double_t UOrigin, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDParallelPlanarMeasLayer") + : + ILDPlanarMeasLayer(min,mout,TVector3(r*cos(phi),r*sin(phi),zoffset),TVector3(cos(phi),sin(phi),0.0),Bz,SortingPolicy,xiwidth,zetawidth,xioffset,UOrigin,is_active,CellID,name), _r(r),_phi(phi),_cos_phi(cos(_phi)),_sin_phi(sin(_phi)) + { /* no op */ } + + + // Parent's pure virtuals that must be implemented + + /** overloaded version of CalcXingPointWith using closed solution */ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + /** overloaded version of CalcXingPointWith using closed solution */ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps = 1.e-8) const{ + + return CalcXingPointWith(hel,xx,phi,0,eps); + + } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return CalcXingPointWith(hel,xx,phi,0,eps); + + } + + +protected: + + Double_t _r; + Double_t _phi; + Double_t _cos_phi; + Double_t _sin_phi; + + +}; + +#endif + diff --git a/Utilities/KalDet/src/ild/common/ILDParallelPlanarStripMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDParallelPlanarStripMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..b7064d810dd30f5dd559f3769f58fff65b29a408 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDParallelPlanarStripMeasLayer.cc @@ -0,0 +1,224 @@ + +#include "ILDParallelPlanarStripMeasLayer.h" +#include "ILDPlanarStripHit.h" +#include "kaltest/TVTrack.h" +#include "kaltest/TVTrackHit.h" + +//#include <EVENT/TrackerHitPlane.h> + +#include "gearimpl/Vector3D.h" + +// #include "streamlog/streamlog.h" + + +TKalMatrix ILDParallelPlanarStripMeasLayer::XvToMv(const TVector3 &xv) const +{ + +// streamlog_out(DEBUG0) << "\t ILDParallelPlanarStripMeasLayer::XvToMv: " +// << " x = " << xv.X() +// << " y = " << xv.Y() +// << " z = " << xv.Z() +// << std::endl; + + + double cos_phi = GetNormal().X()/GetNormal().Perp(); + double sin_phi = GetNormal().Y()/GetNormal().Perp(); + + // theta is the strip angle rotation in the plane of the wafer + double cos_theta = cos(_stripAngle); + double sin_theta = sin(_stripAngle); + + double delta_x = xv.X() - GetXc().X(); + double delta_y = xv.Y() - GetXc().Y(); + + double delta_t = (delta_x * sin_phi - delta_y * cos_phi) ; + double delta_z = xv.Z() - GetXc().Z(); + + + TKalMatrix mv(ILDPlanarStripHit_DIM,1); + + mv(0,0) = ( (delta_t + fUOrigin) * cos_theta ) + delta_z * sin_theta ; + + if (ILDPlanarStripHit_DIM == 2) { + mv(1,0) = delta_z * cos_theta - delta_t * sin_theta; + } + +// streamlog_out(DEBUG0) << "\t ILDParallelPlanarStripMeasLayer::XvToMv: " +// << " mv(0,0) = " << mv(0,0) ; +// if (ILDPlanarStripHit_DIM == 2) { +// streamlog_out(DEBUG0) << " mv(1,0) = " << mv(1,0); +// } +// streamlog_out(DEBUG0) << std::endl; + + + return mv; + +} + + +TVector3 ILDParallelPlanarStripMeasLayer::HitToXv(const TVTrackHit &vht) const +{ + +// streamlog_out(DEBUG0) << "\t ILDParallelPlanarStripMeasLayer::HitToXv: " +// << " vht(0,0) = " << vht(0,0); +// if (ILDPlanarStripHit_DIM == 2) { +// streamlog_out(DEBUG0) << " vht(1,0) = " << vht(1,0); +// } +// streamlog_out(DEBUG0) << std::endl; + + double cos_phi = GetNormal().X()/GetNormal().Perp(); + double sin_phi = GetNormal().Y()/GetNormal().Perp(); + + // theta is the strip angle rotation in the plane of the wafer + double cos_theta = cos(_stripAngle); + double sin_theta = sin(_stripAngle); + + double t = (vht(0,0) - fUOrigin ) * cos_theta ; + + double x = t * sin_phi + this->GetXc().X(); + double y = -t * cos_phi + this->GetXc().Y(); + + double dz = 0.0; + + if (ILDPlanarStripHit_DIM == 2) { + dz = vht(1,0) * cos_theta ; + } + + + double z = vht(0,0) * sin_theta + this->GetXc().Z() + dz; + +// streamlog_out(DEBUG0) << "\t ILDParallelPlanarStripMeasLayer::HitToXv: " +// << " x = " << x +// << " y = " << y +// << " z = " << z +// << std::endl; + + + this->IsOnSurface(TVector3(x,y,z)); + + return TVector3(x,y,z); + +} + +void ILDParallelPlanarStripMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + double cos_phi = GetNormal().X()/GetNormal().Perp(); + double sin_phi = GetNormal().Y()/GetNormal().Perp(); + + // theta is the strip angle rotation in the plane of the wafer + double cos_theta = cos(_stripAngle); + double sin_theta = sin(_stripAngle); + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + double dudx = cos_theta * sin_phi; + double dudy = -cos_theta * cos_phi; + double dudz = sin_theta; + + double dvdx = -sin_theta * sin_phi; + double dvdy = sin_theta * cos_phi; + double dvdz = cos_theta; + + +// streamlog_out(DEBUG0) << "\t ILDParallelPlanarStripMeasLayer::CalcDhDa: dudx = " << dudx << " dudy = " << dudy << " dudz = " << dudz << std::endl ; +// if (ILDPlanarStripHit_DIM == 2) streamlog_out(DEBUG0) << "\t ILDParallelPlanarStripMeasLayer::CalcDhDa: dvdx = " << dvdx << " dvdy = " << dvdy << " dvdz = " << dvdz << std::endl ; + + for (Int_t i=0; i<hdim; i++) { + + H(0,i) = dudx * dxphiada(0,i) + dudy * dxphiada(1,i) + dudz * dxphiada(2,i) ; + +// streamlog_out(DEBUG0) << " H(0,"<< i <<") = " << H(0,i) ; + + if (ILDPlanarStripHit_DIM == 2) { + + H(1,i) = dvdx * dxphiada(0,i) + dvdy * dxphiada(1,i) + dvdz * dxphiada(2,i); +// streamlog_out(DEBUG0) << " H(1,"<< i <<") = " << H(1,i); + + } + + } + if (sdim == 6) { + H(0,sdim-1) = 0.; + if (ILDPlanarStripHit_DIM == 2) { + H(1,sdim-1) = 0.; + } + } + +// streamlog_out(DEBUG0) << std::endl; + +} + +ILDVTrackHit* ILDParallelPlanarStripMeasLayer::ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + + //EVENT::TrackerHitPlane* plane_hit = dynamic_cast<EVENT::TrackerHitPlane*>( trkhit ) ; + //if( plane_hit == NULL ) { + if((trkhit->getType()&8)!=8) { + std::cout << "ILDParallelPlanarStripMeasLayer::ConvertLCIOTrkHit dynamic_cast to ILDPlanarStripHit failed " << std::endl; + throw std::logic_error("Invalid invoke ILDParallelPlanarStripMeasLayer by TrackerHit trkhit"); + } + + + // remember here the "position" of the hit in fact defines the origin of the plane it defines so u and v are per definition 0. + // this is still the case for a 1-dimentional measurement, and is then used to calculate the u coordinate according to the origin of the actual measurement plane. + //const TVector3 hit( plane_hit->getPosition()[0], plane_hit->getPosition()[1], plane_hit->getPosition()[2]) ; + const edm4hep::Vector3d& pos=trkhit->getPosition(); + const TVector3 hit(pos.x, pos.y, pos.z); + + // convert to layer coordinates + TKalMatrix h(ILDPlanarStripHit_DIM,1); + h = this->XvToMv(hit); + + Double_t x[ILDPlanarStripHit_DIM] ; + Double_t dx[ILDPlanarStripHit_DIM] ; + + x[0] = h(0, 0); + if(ILDPlanarStripHit_DIM == 2) x[1] = h(1, 0); + + //dx[0] = plane_hit->getdU() ; + //if(ILDPlanarStripHit_DIM == 2) dx[1] = plane_hit->getdV() ; + dx[0] = trkhit->getCovMatrix(2); + if(ILDPlanarStripHit_DIM == 2) dx[1] = trkhit->getCovMatrix(5); + + bool hit_on_surface = IsOnSurface(hit); + /* + std::cout << "ILDParallelPlanarStripMeasLayer::ConvertLCIOTrkHit ILDPlanarStripHit created" + << " for CellID " << trkhit->getCellID() + << " Layer R = " << this->GetXc().Perp() + << " Layer phi = " << this->GetXc().Phi() + << " Layer z0 = " << this->GetXc().Z() + << " u = " << x[0] + << " du = " << dx[0]; + + if(ILDPlanarStripHit_DIM == 2) std::cout << " v = " << x[1] << " dv = " << dx[1]; + + std::cout << " x = " << pos.x + << " y = " << pos.y + << " z = " << pos.z + << " r = " << sqrt(pos.x*pos.x + pos.y*pos.y) + << " onSurface = " << hit_on_surface + << std::endl ; + */ + ILDPlanarStripHit hh( *this , x, dx, this->GetBz(),trkhit); + + this->HitToXv(hh); + + return hit_on_surface ? new ILDPlanarStripHit( *this , x, dx, this->GetBz(),trkhit) : NULL; + + +} + + diff --git a/Utilities/KalDet/src/ild/common/ILDParallelPlanarStripMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDParallelPlanarStripMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..c717f4c13a37397762a9aaf6d63980d8e0dfe61c --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDParallelPlanarStripMeasLayer.h @@ -0,0 +1,62 @@ +#ifndef __ILDParallelPlanarStripMeasLayer__ +#define __ILDParallelPlanarStripMeasLayer__ + +/** ILDParallelPlanarStripMeasLayer: User defined KalTest measurement layer class + * + * @author S.Aplin DESY + */ + +//#include "TKalMatrix.h" +//#include "TVector3.h" +//#include "TVTrackHit.h" + + +#include "ILDParallelPlanarMeasLayer.h" + +class ILDParallelPlanarStripMeasLayer : public ILDParallelPlanarMeasLayer { + +public: + + /** Constructor Taking inner and outer materials, distance and phi of plane pca to origin, B-Field, Sorting policy, plane transverse witdth and offset of centre, longitudinal width, whether the layer is sensitive, Cell ID, and an optional name */ + ILDParallelPlanarStripMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t r, + Double_t phi, + Double_t Bz, + Double_t SortingPolicy, + Double_t xiwidth, + Double_t zetawidth, + Double_t xioffset, + Double_t zoffset, + Double_t UOrigin, + Double_t stripAngle, + Int_t CellID = -1, + const Char_t *name = "ILDParallelPlanarStripMeasLayer") + : + ILDParallelPlanarMeasLayer(min,mout,r,phi,Bz,SortingPolicy,xiwidth,zetawidth,xioffset,zoffset,UOrigin,true,CellID,name), _stripAngle(stripAngle) + + { /* no op */ } + + + // Parent's pure virtuals that must be implemented + + TKalMatrix XvToMv(const TVector3 &xv) const; + + TKalMatrix XvToMv(const TVTrackHit &, const TVector3 &xv) const { + return XvToMv(xv); + } + + TVector3 HitToXv(const TVTrackHit &vht) const ; + + void CalcDhDa(const TVTrackHit &vht, const TVector3 &xxv, const TKalMatrix &dxphiada, TKalMatrix &H) const; + + ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const; + +private: + + double _stripAngle; + +}; + +#endif + diff --git a/Utilities/KalDet/src/ild/common/ILDPlanarHit.cc b/Utilities/KalDet/src/ild/common/ILDPlanarHit.cc new file mode 100644 index 0000000000000000000000000000000000000000..c4fc4ae173a4a42bf80f93ac4ebedc3a5f119f6d --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDPlanarHit.cc @@ -0,0 +1,47 @@ + +#include "ILDPlanarHit.h" +#include "ILDPlanarMeasLayer.h" +#include "ILDSegmentedDiscMeasLayer.h" +#include "ILDDiscMeasLayer.h" +#include "TMath.h" + +#include <iostream> +#include <iomanip> + +using namespace std; + + + +//_____________________________________________________________________ +// ---------------------------------- +// Implementation of public methods +// ---------------------------------- + +/** Global to Local coordinates */ + +TKalMatrix ILDPlanarHit::XvToMv(const TVector3 &xv, Double_t /*t0*/) const +{ + + return this->GetMeasLayer().XvToMv(*(this),xv); + +} + + +/** Print Debug information */ + +void ILDPlanarHit::DebugPrint(Option_t *) const +{ + cerr << "------------------- Site Info -------------------------" << endl; + + for (Int_t i=0; i<GetDimension(); i++) { + Double_t x = (*this)(i,0); + Double_t dx = (*this)(i,1); + cerr << " x[" << i << "] = " << setw(8) << setprecision(5) << x + << " " + << "dx[" << i << "] = " << setw(6) << setprecision(2) << dx + << setprecision(7) + << resetiosflags(ios::showpoint) + << endl; + } + cerr << "-------------------------------------------------------" << endl; +} diff --git a/Utilities/KalDet/src/ild/common/ILDPlanarHit.h b/Utilities/KalDet/src/ild/common/ILDPlanarHit.h new file mode 100644 index 0000000000000000000000000000000000000000..e54f0cf7e053dda87041fd4d9e80fc010b5787fa --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDPlanarHit.h @@ -0,0 +1,41 @@ +#ifndef ILDPLANARHIT_H +#define ILDPLANARHIT_H + +/** ILDPlanarHit: User defined KalTest hit class using u and v coordinates, which provides coordinate vector as defined by the MeasLayer + * + * @author S.Aplin DESY + */ + +#include "kaltest/KalTrackDim.h" + +#include "ILDVTrackHit.h" + +#define ILDPlanarHit_DIM 2 + +class ILDPlanarHit : public ILDVTrackHit { + +public: + + /** Constructor Taking u and v coordinates and associated measurement layer, with bfield */ + ILDPlanarHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Double_t bfield, + edm4hep::TrackerHit* trkhit) + : ILDVTrackHit(ms, x, dx, bfield, ILDPlanarHit_DIM,trkhit) + { /* no op */ } + + // TVTrackHit's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv, Double_t t0) const; + + /** Print Debug information */ + virtual void DebugPrint(Option_t *opt = "") const; + + +private: + + +}; +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDPlanarMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDPlanarMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..ad196d2e6bbefe4ec76f572264ba1b1dd8f2e620 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDPlanarMeasLayer.cc @@ -0,0 +1,310 @@ +//************************************************************************* +//* =================== +//* ILDPlanarMeasLayer Class +//* =================== +//* +//* (Description) +//* Sample measurement layer class used by ILDPlanarHit. +//* (Requires) +//* ILDVMeasLayer +//* (Provides) +//* class ILDPlanarMeasLayer +//* +//************************************************************************* +// +#include <iostream> +#include <cmath> + +#include "ILDPlanarMeasLayer.h" +#include "ILDPlanarHit.h" + +#include "kaltest/TVTrack.h" +#include "TVector3.h" +#include "TMath.h" +#include "TRotMatrix.h" +#include "TBRIK.h" +#include "TNode.h" +#include "TString.h" + +#include "gearimpl/Vector3D.h" + +//#include <EVENT/TrackerHitPlane.h> + +// #include "streamlog/streamlog.h" + +ILDPlanarMeasLayer::ILDPlanarMeasLayer(TMaterial &min, + TMaterial &mout, + const TVector3 ¢er, + const TVector3 &normal, + Double_t Bz, + Double_t SortingPolicy, + Double_t xiwidth, + Double_t zetawidth, + Double_t xioffset, + Double_t UOrigin, + Bool_t is_active, + Int_t CellID, + const Char_t *name) +: ILDVMeasLayer(min, mout, Bz, is_active, CellID, name), +TPlane(center, normal), +fSortingPolicy(SortingPolicy), +fXiwidth(xiwidth), +fZetawidth(zetawidth), +fXioffset(xioffset), +fUOrigin(UOrigin) + +{ + + // streamlog_out(DEBUG0) << "ILDPlanarMeasLayer created" + // << " Layer x0 = " << this->GetXc().X() + // << " y0 = " << this->GetXc().Y() + // << " z0 = " << this->GetXc().Z() + // << " R = " << this->GetXc().Perp() + // << " phi = " << this->GetXc().Phi() + // << " xiwidth = " << fXiwidth + // << " zetawidth = " << fZetawidth + // << " xioffset = " << fXioffset + // << " UOrigin = " << UOrigin + // << " is_active = " << is_active + // << " CellID = " << CellID + // << " name = " << this->ILDVMeasLayer::GetName() + // << std::endl ; + + +} + +ILDPlanarMeasLayer::~ILDPlanarMeasLayer() +{ +} + +TKalMatrix ILDPlanarMeasLayer::XvToMv(const TVector3 &xv) const +{ + // Calculate hit coordinate information: + // mv(0,0) = xi + // (1,0) = zeta + +// streamlog_out(DEBUG0) << "\t ILDPlanarMeasLayer::XvToMv: " +// << " x = " << xv.X() +// << " y = " << xv.Y() +// << " z = " << xv.Z() +// << std::endl; + + TKalMatrix mv(kMdim,1); + + double cos_phi = GetNormal().X()/GetNormal().Perp(); + double sin_phi = GetNormal().Y()/GetNormal().Perp(); + + double delta_x = xv.X() - GetXc().X(); + double delta_y = xv.Y() - GetXc().Y(); + double delta_z = xv.Z() - GetXc().Z(); + + double delta_t = (delta_x * sin_phi - delta_y * cos_phi) ; + + mv(0,0) = delta_t + fUOrigin; + + mv(1,0) = delta_z ; + +// streamlog_out(DEBUG0) << "\t ILDPlanarMeasLayer::XvToMv: " +// << " mv(0,0) = " << mv(0,0) +// << " mv(1,0) = " << mv(1,0) +// << std::endl; + + + return mv; +} + +TKalMatrix ILDPlanarMeasLayer::XvToMv(const TVTrackHit &, + const TVector3 &xv) const +{ + return XvToMv(xv); +} + +TVector3 ILDPlanarMeasLayer::HitToXv(const TVTrackHit &vht) const +{ + + +// streamlog_out(DEBUG0) << "\t ILDPlanarMeasLayer::HitToXv: " +// << " vht(0,0) = " << vht(0,0) +// << " vht(1,0) = " << vht(1,0) +// << std::endl; + + + //const ILDPlanarHit &ht = dynamic_cast<const ILDPlanarHit &>(vht); + + double cos_phi = GetNormal().X()/GetNormal().Perp(); + double sin_phi = GetNormal().Y()/GetNormal().Perp(); + + double delta_t = vht(0,0) - fUOrigin; + + double x = delta_t * sin_phi + this->GetXc().X(); + double y = -delta_t * cos_phi + this->GetXc().Y(); + + double z = vht(1,0) + this->GetXc().Z(); + +// streamlog_out(DEBUG0) << "\t ILDPlanarMeasLayer::HitToXv: " +// << " x = " << x +// << " y = " << y +// << " z = " << z +// << std::endl; + + + return TVector3(x,y,z); +} + +void ILDPlanarMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + double cos_phi = GetNormal().X()/GetNormal().Perp(); + double sin_phi = GetNormal().Y()/GetNormal().Perp(); + + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + for (Int_t i=0; i<hdim; i++) { + + H(0,i) = sin_phi * dxphiada(0,i) - cos_phi * dxphiada(1,i) ; + H(1,i) = dxphiada(2,i); + + } + if (sdim == 6) { + H(0,sdim-1) = 0.; + H(1,sdim-1) = 0.; + } + +} + + +//#define DEBUG_ISONSURFACE 1 +Bool_t ILDPlanarMeasLayer::IsOnSurface(const TVector3 &xx) const +{ + Double_t xi = (xx.Y()-GetXc().Y())*GetNormal().X()/GetNormal().Perp() - (xx.X()-GetXc().X())*GetNormal().Y()/GetNormal().Perp() ; + Double_t zeta = xx.Z() - GetXc().Z(); + + bool onSurface = false ; + + if( (xx.X()-GetXc().X())*GetNormal().X() + (xx.Y()-GetXc().Y())*GetNormal().Y() < 1e-4){ + if( xi <= GetXioffset() + GetXiwidth()/2 && xi >= GetXioffset() - GetXiwidth()/2 && TMath::Abs(zeta) <= GetZetawidth()/2){ + onSurface = true; + } + +#ifdef DEBUG_ISONSURFACE + else{ + // streamlog_out(DEBUG4) << "ILDPlanarMeasLayer::IsOnSurface: Point not within boundary x = " << xx.x() << " y = " << xx.y() << " z = " << xx.z() << " r = " << xx.Perp() << " phi = " << xx.Phi() << std::endl; + // streamlog_out(DEBUG4) << "xi = " << xi << " xi_max = " << GetXioffset() + GetXiwidth()/2 << " xi_min = " << GetXioffset() - GetXiwidth()/2 << " zeta = " << zeta << " zeta_min = " << -GetZetawidth()/2 << " zeta_max " << GetZetawidth()/2 << " Xioffset = " << GetXioffset() << std::endl; + onSurface = false; + // streamlog_out(DEBUG4) << " xi <= GetXioffset() + GetXiwidth()/2 = " << (xi <= GetXioffset() + GetXiwidth()/2) << std::endl ; + // streamlog_out(DEBUG4) << " xi >= GetXioffset() - GetXiwidth()/2 = " << (xi >= GetXioffset() - GetXiwidth()/2) << std::endl; + // streamlog_out(DEBUG4) << " TMath::Abs(zeta) <= GetZetawidth()/2 = " << (TMath::Abs(zeta) <= GetZetawidth()/2) << std::endl; + } +#endif + + } + +#ifdef DEBUG_ISONSURFACE + else{ + // streamlog_out(DEBUG4) << "ILDPlanarMeasLayer::IsOnSurface: Point not on surface x = " << xx.x() << " y = " << xx.y() << " z = " << xx.z() << " r = " << xx.Perp() << " phi = " << xx.Phi() << std::endl; + // streamlog_out(DEBUG4) << "Distance from plane " << (xx.X()-GetXc().X())*GetNormal().X() + (xx.Y()-GetXc().Y())*GetNormal().Y() << std::endl; + } + if( onSurface == false ) { + // streamlog_out(DEBUG) << "x0 " << GetXc().X() << std::endl; + // streamlog_out(DEBUG) << "y0 " << GetXc().Y() << std::endl; + // streamlog_out(DEBUG) << "z0 " << GetXc().Z() << std::endl; + // streamlog_out(DEBUG) << "GetNormal().X() " << GetNormal().X() << std::endl; + // streamlog_out(DEBUG4) << "GetNormal().Y() " << GetNormal().Y() << std::endl; + // streamlog_out(DEBUG4) << "GetNormal().Perp() " << GetNormal().Perp() << std::endl; + // streamlog_out(DEBUG4) << "GetNormal().X()/GetNormal().Perp() " << GetNormal().X()/GetNormal().Perp() << std::endl; + // streamlog_out(DEBUG4) << "GetNormal().Y()/GetNormal().Perp() " << GetNormal().Y()/GetNormal().Perp() << std::endl; + // streamlog_out(DEBUG4) << "xx.X()-GetXc().X() " << xx.X()-GetXc().X() << std::endl; + // streamlog_out(DEBUG4) << "xx.Y()-GetXc().Y() " << xx.Y()-GetXc().Y() << std::endl; + + // streamlog_out(DEBUG4) << "zeta " << zeta << std::endl; + // streamlog_out(DEBUG4) << "xi " << xi << std::endl; + // streamlog_out(DEBUG4) << "zeta half width " << GetZetawidth()/2 << std::endl; + // streamlog_out(DEBUG4) << "xi half width " << GetXiwidth()/2 << std::endl; + // streamlog_out(DEBUG4) << "offset " << GetXioffset() << std::endl; + + // streamlog_out(DEBUG4) << "distance from plane " << (xx.X()-GetXc().X())*GetNormal().X() + (xx.Y()-GetXc().Y())*GetNormal().Y() << std::endl; + } +#endif + + return onSurface; + +} + + +ILDVTrackHit* ILDPlanarMeasLayer::ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + //std::cout << "ILDPlanarMeasLayer::ConvertLCIOTrkHit " << trkhit << " type=" << trkhit->getType() << std::endl; + //EVENT::TrackerHitPlane* plane_hit = dynamic_cast<EVENT::TrackerHitPlane*>( trkhit ) ; + if((trkhit->getType()&8)!=8){ + std::cout << "ILDPlanarMeasLayer::ConvertLCIOTrkHit Warning: type is not 8, but " << (trkhit->getType()&8) << std::endl; + return NULL; + } + //if( plane_hit == NULL ) return NULL; // SJA:FIXME: should be replaced with an exception + + //gear::Vector3D U(1.0,plane_hit->getU()[1],plane_hit->getU()[0],gear::Vector3D::spherical); + //gear::Vector3D V(1.0,plane_hit->getV()[1],plane_hit->getV()[0],gear::Vector3D::spherical); + gear::Vector3D U(1.0,trkhit->getCovMatrix(1),trkhit->getCovMatrix(0),gear::Vector3D::spherical); + gear::Vector3D V(1.0,trkhit->getCovMatrix(4),trkhit->getCovMatrix(3),gear::Vector3D::spherical); + gear::Vector3D Z(0.0,0.0,1.0); + + const float eps = 1.0e-07; + // U must be the global z axis + if( fabs(1.0 - V.dot(Z)) > eps ) { + std::cout << "ILDPlanarMeasLayer: TrackerHitPlane measurment vectors V is not equal to the global Z axis. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << std::endl; + exit(1); + } + + if( fabs(U.dot(Z)) > eps ) { + std::cout << "ILDPlanarMeasLayer: TrackerHitPlane measurment vectors U is not in the global X-Y plane. \n\n exit(1) called from file " << __FILE__ << " and line " << __LINE__ << std::endl; + exit(1); + } + + // remember here the "position" of the hit in fact defines the origin of the plane it defines so u and v are per definition 0. + const edm4hep::Vector3d& pos=trkhit->getPosition(); + const TVector3 hit(pos.x, pos.y, pos.z) ; + + // convert to layer coordinates + TKalMatrix h = this->XvToMv(hit); + + Double_t x[2] ; + Double_t dx[2] ; + + x[0] = h(0, 0); + x[1] = h(1, 0); + + dx[0] = trkhit->getCovMatrix(2); + dx[1] = trkhit->getCovMatrix(5); + + bool hit_on_surface = IsOnSurface(hit); + /* + std::cout << "ILDPlanarMeasLayer::ConvertLCIOTrkHit ILDPlanarHit created" + << " for CellID " << trkhit->getCellID() + << " Layer R = " << this->GetXc().Perp() + << " Layer phi = " << this->GetXc().Phi() + << " Layer z0 = " << this->GetXc().Z() + << " u = " << x[0] + << " v = " << x[1] + << " du = " << dx[0] + << " dv = " << dx[1] + << " x = " << hit.x() + << " y = " << hit.y() + << " z = " << hit.z() + << " r = " << hit.Perp() + << " onSurface = " << hit_on_surface + << std::endl ; + */ + + return hit_on_surface ? new ILDPlanarHit( *this , x, dx, this->GetBz(), trkhit) : NULL; +} diff --git a/Utilities/KalDet/src/ild/common/ILDPlanarMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDPlanarMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..500f2a233093f6409eb3428fa1f23b82bb45c95b --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDPlanarMeasLayer.h @@ -0,0 +1,84 @@ +#ifndef __ILDPLANARMEASLAYER__ +#define __ILDPLANARMEASLAYER__ +//************************************************************************* +//* =================== +//* ILDPlanarMeasLayer Class +//* =================== +//* +//* (Description) +//* Planar measurement layer class used with ILDPLanarTrackHit. +//* (Requires) +//* ILDVMeasLayer +//* (Provides) +//* class ILDPlanarMeasLayer +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* +//* 2011/06/17 D.Kamai Modified to handle ladder structure. +//************************************************************************* +// +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> + +class TVTrackHit; + +class ILDPlanarMeasLayer : public ILDVMeasLayer, public TPlane { +public: + // Ctors and Dtor + + ILDPlanarMeasLayer(TMaterial &min, + TMaterial &mout, + const TVector3 ¢er, + const TVector3 &normal, + Double_t Bz, + Double_t SortingPolicy, + Double_t xiwidth, + Double_t zetawidth, + Double_t xioffset, + Double_t fUOrigin, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDPlanarMeasL"); + + virtual ~ILDPlanarMeasLayer(); + + // Parrent's pure virtuals that must be implemented + + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const; + + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + Double_t GetSortingPolicy() const { return fSortingPolicy; } + Double_t GetXiwidth() const { return fXiwidth; } + Double_t GetZetawidth() const { return fZetawidth; } + Double_t GetXioffset() const { return fXioffset; } + +protected: + Double_t fSortingPolicy; + Double_t fXiwidth; + Double_t fZetawidth; + Double_t fXioffset; //determines how far the centre of the plane is translated in the direction positive rotation + Double_t fUOrigin; //determines origin of the transverse coordinate + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDPlanarStripHit.cc b/Utilities/KalDet/src/ild/common/ILDPlanarStripHit.cc new file mode 100644 index 0000000000000000000000000000000000000000..613e34dfd49c67a5f2ba16f7fc453d998bfcd0b6 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDPlanarStripHit.cc @@ -0,0 +1,47 @@ + +#include "ILDPlanarStripHit.h" +#include "ILDPlanarMeasLayer.h" +#include "ILDSegmentedDiscMeasLayer.h" +#include "ILDDiscMeasLayer.h" +#include "TMath.h" + +#include <iostream> +#include <iomanip> + +using namespace std; + + + +//_____________________________________________________________________ +// ---------------------------------- +// Implementation of public methods +// ---------------------------------- + +/** Global to Local coordinates */ + +TKalMatrix ILDPlanarStripHit::XvToMv(const TVector3 &xv, Double_t /*t0*/) const +{ + + return this->GetMeasLayer().XvToMv(*(this),xv); + +} + + +/** Print Debug information */ + +void ILDPlanarStripHit::DebugPrint(Option_t *) const +{ + cerr << "------------------- Site Info -------------------------" << endl; + + for (Int_t i=0; i<GetDimension(); i++) { + Double_t x = (*this)(i,0); + Double_t dx = (*this)(i,1); + cerr << " x[" << i << "] = " << setw(8) << setprecision(5) << x + << " " + << "dx[" << i << "] = " << setw(6) << setprecision(2) << dx + << setprecision(7) + << resetiosflags(ios::showpoint) + << endl; + } + cerr << "-------------------------------------------------------" << endl; +} diff --git a/Utilities/KalDet/src/ild/common/ILDPlanarStripHit.h b/Utilities/KalDet/src/ild/common/ILDPlanarStripHit.h new file mode 100644 index 0000000000000000000000000000000000000000..1103eeda84a5e6729d204ac6385a11b5de909ac3 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDPlanarStripHit.h @@ -0,0 +1,42 @@ +#ifndef ILDPLANARSTRIPHIT_H +#define ILDPLANARSTRIPHIT_H + +/** ILDPlanarStripHit: User defined KalTest hit class using u coordinate, which provides coordinate vector as defined by the MeasLayer + * + * @author S.Aplin DESY + */ + +#include "kaltest/KalTrackDim.h" + +#include "ILDVTrackHit.h" + + +#define ILDPlanarStripHit_DIM 1 // set to 2 if one want to debug strip hits by using the 2nd dimention + +class ILDPlanarStripHit : public ILDVTrackHit { + +public: + + /** Constructor Taking a single coordinate and associated measurement layer, with bfield */ + ILDPlanarStripHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Double_t bfield, + edm4hep::TrackerHit* trkhit) + : ILDVTrackHit(ms, x, dx, bfield, ILDPlanarStripHit_DIM,trkhit) + { /* no op */ } + + // TVTrackHit's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv, Double_t t0) const; + + /** Print Debug information */ + virtual void DebugPrint(Option_t *opt = "") const; + + +private: + + +}; +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDPolygonBarrelMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDPolygonBarrelMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..c1348fd0fdfd875f91901675ef0c964c3f403334 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDPolygonBarrelMeasLayer.cc @@ -0,0 +1,215 @@ + +#include "ILDPolygonBarrelMeasLayer.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +#include "kaltest/TVTrack.h" +#include "TVector3.h" +#include "TMath.h" +#include "TRotMatrix.h" +#include "TBRIK.h" +#include "TNode.h" +#include "TString.h" + +//#include <EVENT/TrackerHitPlane.h> +#include <edm4hep/TrackerHit.h> + +#include <math.h> +#include <assert.h> +#include <algorithm> + +// #include "streamlog/streamlog.h" + + +ILDPolygonBarrelMeasLayer::ILDPolygonBarrelMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double sortingPolicy, + double r0, // min distance to the z-axis + double lhalf, // half length + int nsides, + double zpos, // z of the centre + double phi0, // phi of the first normal following the xaxis positive rotation + std::vector<int> CellIDs, + bool is_active, + const Char_t *name) : +ILDVMeasLayer(min, mout, Bz, CellIDs, is_active, name), _sortingPolicy(0.), +_r0(r0),_lhalf(lhalf),_nsides(nsides),_zpos(zpos),_phi0(phi0) + +{ + + _segment_dphi = 2.0*M_PI / _nsides; + + phi0 = angular_range_2PI(phi0); + + _start_phi = phi0 - 0.5*_segment_dphi; + + _start_phi = angular_range_2PI(_start_phi); + + for (int i = 0; i < _nsides; ++i) { + + const TVector3 center(r0*cos(phi0),r0*sin(phi0),zpos); + const TVector3 normal(center); + double width = 2*(_r0*tan(_segment_dphi*0.5)); + + double phi = i*_segment_dphi+_start_phi; + + ILDParallelPlanarMeasLayer p(min,mout,r0,phi,Bz,sortingPolicy,width,2*lhalf,0.0,0.0,0.0,false); // NOTE: No Physical Offset or Coordinate Offset allowed + _planes.push_back(p); + + } + + + _rmax = r0*sin((_r0*tan(_segment_dphi*0.5))); + + _enclosing_cylinder = new TCylinder(_rmax, lhalf, 0., 0., 0.); + + +} + + +TKalMatrix ILDPolygonBarrelMeasLayer::XvToMv(const TVector3 &xv) const +{ + + // Calculate measurement vector (hit coordinates) from global coordinates: + int index = this->get_plane_index(xv.Phi()); + + return _planes[index].XvToMv(xv); + +} + + +TVector3 ILDPolygonBarrelMeasLayer::HitToXv(const TVTrackHit &vht) const +{ + + //SJA:FIXME: in order to use real local coordinates we would have to get the CELLID from the ILDPlanarHit, this would tell us in which segment the hit was in + + // streamlog_out(ERROR) << "ILDPolygonBarrelMeasLayer::HitToXv Not implemented: exit(1) called from " << __FILE__ << " line " << __LINE__ << std::endl; + exit(1); + + return TVector3(0.,0.,0.); + +} + +void ILDPolygonBarrelMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + + //SJA:FIXME: in order to use real local coordinates we would have to get the CELLID from the ILDPlanarHit, this would tell us in which segment the hit was in + + // streamlog_out(ERROR) << "ILDPolygonBarrelMeasLayer::CalcDhDa Not implemented: exit(1) called from " << __FILE__ << " line " << __LINE__ << std::endl; + exit(1); + +} + + +Int_t ILDPolygonBarrelMeasLayer::CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps) const{ + + int crosses = _enclosing_cylinder->CalcXingPointWith(hel, xx, phi, mode); + + if (crosses == 0) { + return 0; + } + + int index = this->get_plane_index(xx.Phi()); + + return _planes[index].CalcXingPointWith(hel,xx,phi,mode,eps); + + +} + +Bool_t ILDPolygonBarrelMeasLayer::IsOnSurface(const TVector3 &xx) const +{ + + // streamlog_out(DEBUG0) << "IsOnSurface " << std::endl; + int index = this->get_plane_index(xx.Phi()); + + return _planes[index].IsOnSurface(xx); + +} + + +ILDVTrackHit* ILDPolygonBarrelMeasLayer::ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + + std::cout << "ILDPolygonBarrelMeasLayer::ConvertLCIOTrkHit Not implemented: exit(1) called from " << __FILE__ << " line " << __LINE__ << std::endl; + exit(1); + +} + +bool ILDPolygonBarrelMeasLayer::IsOutside(const TVector3 &xx) const +{ + int index = this->get_plane_index(xx.Phi()); + return _planes[index].IsOutside(xx); +} + +double ILDPolygonBarrelMeasLayer::CalcS(const TVector3 &xx) const { + + int index = this->get_plane_index(xx.Phi()); + return _planes[index].CalcS(xx); + +} + +TMatrixD ILDPolygonBarrelMeasLayer::CalcDSDx(const TVector3 &xx) const { + + int index = this->get_plane_index(xx.Phi()); + return _planes[index].CalcDSDx(xx); + +} + +/** Get the intersection and the CellID, needed for multilayers */ +int ILDPolygonBarrelMeasLayer::getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps) const { + + + int crosses = this->CalcXingPointWith(hel, xx, phi, mode, eps); + + if ( crosses != 0 ) { + + unsigned int plane = this->get_plane_index( xx.Phi() ); + + lcio::BitField64 bf( UTIL::ILDCellID0::encoder_string ) ; + bf.setValue( this->getCellIDs()[0] ) ; // get the first cell_ID, this will have the correct sensor value + + bf[lcio::ILDCellID0::module] = plane; + CellID = bf.lowWord(); + + } + + return crosses; + +} + + +unsigned int ILDPolygonBarrelMeasLayer::get_plane_index(double phi) const { + + phi = angular_range_2PI(phi-_start_phi); + return unsigned(floor(phi/_segment_dphi)); + +} + + +double ILDPolygonBarrelMeasLayer::angular_range_2PI( double phi ) const { + + //bring phi_point into range 0 < phi < +2PI + while (phi < 0) { + phi += 2.0 * M_PI; + } + while (phi >= 2.0*M_PI) { + phi -= 2.0 * M_PI; + } + + return phi; + +} + diff --git a/Utilities/KalDet/src/ild/common/ILDPolygonBarrelMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDPolygonBarrelMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..684bb876e7e0be4e48381ca59528c9871b6ffb1d --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDPolygonBarrelMeasLayer.h @@ -0,0 +1,138 @@ +#ifndef __ILDSEGMENTEDDISCMEASLAYER_H__ +#define __ILDSEGMENTEDDISCMEASLAYER_H__ + +/** ILDPolygonBarrelMeasLayer: User defined Polygonal Barrel KalTest measurement layer class to be used only for dead material. Segments are planes parallel to the z axis + * + * NOTE: ALL METHODS INVOLVING HITS ARE DISABLED AND CALL EXIT(1) + * THIS CLASS IS ONLY MEANT FOR DEAD MATERIAL + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TVSurface.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> + +#include "ILDParallelPlanarMeasLayer.h" + +#include <vector> + +class TVTrackHit; + + +class ILDPolygonBarrelMeasLayer : public ILDVMeasLayer, public TVSurface { +public: + // Ctors and Dtor + + + + ILDPolygonBarrelMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double SortingPolicy, + double r0, // min distance to the z-axis + double lhalf, // half length + int nsides, + double zpos, // z of the centre + double phi0, // phi of the first normal following the xaxis positive rotation + std::vector<int> CellIDs, + bool is_active, + const Char_t *name = "ILDPolygonBarrelMeasL"); + + + ~ILDPolygonBarrelMeasLayer(){ delete _enclosing_cylinder;} + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** overloaded version of CalcXingPointWith using closed solution*/ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + /** overloaded version of CalcXingPointWith using closed solution*/ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps = 1.e-8) const{ + + return CalcXingPointWith(hel,xx,phi,0,eps); + + } + + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const ; + + + bool IsOutside(const TVector3 &xx) const; + + double CalcS(const TVector3 &xx) const; + + TMatrixD CalcDSDx(const TVector3 &xx) const; + + /** Check if global point is on surface */ + inline virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + /** Get sorting policy for this plane */ + double GetSortingPolicy() const { return _sortingPolicy; } + +private: + + double angular_range_2PI( double phi ) const; + + unsigned int get_plane_index(double phi) const; + + double _sortingPolicy; + + double _r0; // min distance to the z-axis + double _lhalf; // half length + int _nsides; + double _zpos; // z of the centre + double _phi0; // phi of the first normal following the xaxis positive rotation + + double _segment_dphi; + double _start_phi; + double _rmax; + + std::vector<ILDParallelPlanarMeasLayer> _planes; + TCylinder* _enclosing_cylinder; +}; + + + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDRotatedTrapMeaslayer.cc b/Utilities/KalDet/src/ild/common/ILDRotatedTrapMeaslayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..c9f855e0bbd9c0257b7501ea8ab0f85b58dcb08b --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDRotatedTrapMeaslayer.cc @@ -0,0 +1,194 @@ +#include <iostream> + +#include "ILDRotatedTrapMeaslayer.h" +#include "ILDPlanarHit.h" + +#include "kaltest/TVTrack.h" +#include "TVector3.h" +#include "TMath.h" +#include "TRotMatrix.h" +#include "TBRIK.h" +#include "TNode.h" +#include "TString.h" + +//#include <EVENT/TrackerHitPlane.h> + +// #include "streamlog/streamlog.h" + +ILDRotatedTrapMeaslayer::ILDRotatedTrapMeaslayer(TMaterial &min, + TMaterial &mout, + const TVector3 ¢er, + const TVector3 &normal, + Double_t Bz, + Double_t SortingPolicy, + Double_t height, + Double_t innerBaseLength, + Double_t outerBaseLength, + Double_t alpha, + Int_t half_petal, + Bool_t is_active, + Int_t CellID, + const Char_t *name) +: ILDVMeasLayer(min, mout, Bz, is_active, CellID, name), +TPlane(center, normal), +_sortingPolicy(SortingPolicy), _innerBaseLength(innerBaseLength), _outerBaseLength(outerBaseLength), _halfPetal(half_petal) +{ + + if( GetXc().Z() >= 0 ) { + _signZ = +1.0 ; + } + else { + _signZ = -1.0 ; + } + + _innerR = GetXc().Perp() - 0.5 * height ; + _outerR = GetXc().Perp() + 0.5 * height ; + _cosPhi = GetXc().X() / GetXc().Perp() ; + _sinPhi = GetXc().Y() / GetXc().Perp() ; + + // alpha should be limited to +/- Pi/2 + _cosAlpha = cos(alpha) ; + _sinAlpha = sin(alpha) ; + + _tanBeta = 0.5 * _outerBaseLength / _outerR ; + +} + +TKalMatrix ILDRotatedTrapMeaslayer::XvToMv(const TVector3 &xv) const +{ + + // Calculate measurement vector (hit coordinates) from global coordinates: + + TKalMatrix mv(kMdim,1); + + // SJA:FIXME: what to do with the -z hits, are they reflective, i.e. that means that the transverse coordinate with be reversed + // transverse coordinate, measured from the centre line of the petal ( the axis of symmetry of the trapizoid ) + mv(0,0) = _cosAlpha * _signZ * ( _cosPhi*xv.Y() - _sinPhi*xv.X() ) + _sinAlpha * ( xv.Z() - GetXc().Z() ) ; + + // radial coordinate, measured from R = 0 ( x=0, y=0) + mv(1,0) = _cosPhi * xv.X() + _sinPhi * xv.Y() ; + return mv; + +} + + +TVector3 ILDRotatedTrapMeaslayer::HitToXv(const TVTrackHit &vht) const +{ + // const ILDPlanarHit &mv = dynamic_cast<const ILDPlanarHit &>(vht); + + Double_t x = vht(1,0) * _cosPhi - _signZ * _cosAlpha * vht(0,0) * _sinPhi ; + Double_t y = vht(1,0) * _sinPhi + _signZ * _cosAlpha * vht(0,0) * _cosPhi ; + + Double_t z = GetXc().Z() + _signZ * vht(0,0) * _sinAlpha; + + return TVector3(x,y,z); +} + +void ILDRotatedTrapMeaslayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + for (Int_t i=0; i<hdim; i++) { + + H(0,i) = _cosAlpha * _signZ * ( _cosPhi*dxphiada(1,i) - _sinPhi*dxphiada(0,i) ) + _sinAlpha*dxphiada(2,i) ; + H(1,i) = _cosPhi * dxphiada(0,i) + _sinPhi*dxphiada(1,i); + + } + if (sdim == 6) { + H(0,sdim-1) = 0.; + H(1,sdim-1) = 0.; + } + +} + + + +Bool_t ILDRotatedTrapMeaslayer::IsOnSurface(const TVector3 &xx) const +{ + + // streamlog_out(DEBUG0) << "IsOnSurface " << std::endl; + + bool onSurface = false ; + + TKalMatrix mv = XvToMv(xx); + + // check whether the hit lies in the same plane as the surface + if( TMath::Abs((xx.X()-GetXc().X())*GetNormal().X() + (xx.Y()-GetXc().Y())*GetNormal().Y() + (xx.Z()-GetXc().Z())*GetNormal().Z()) < 1e-4){ + // check whether the hit lies within the boundary of the surface + if( mv(1,0) <= _outerR && mv(1,0) >= _innerR + && + TMath::Abs(mv(0,0)) <= mv(1,0) * _tanBeta ) + { + + // meaning of _halfPetal: + // 0 complete trapezoid + // +1 positive half only, i.e. the side of the petal in which the transverse coordinate, mv(0,0), is positive + // -1 negative half only, i.e. the side of the petal in which the transverse coordinate, mv(0,0), is negative + + if( _halfPetal == 0 || ( _halfPetal * mv(0,0) ) >= 0) { // check if the point lies in the correct half + onSurface = true ; + } + + } + + else{ + onSurface = false; + } + + } + + return onSurface; + +} + + +ILDVTrackHit* ILDRotatedTrapMeaslayer::ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + + //EVENT::TrackerHitPlane* plane_hit = dynamic_cast<EVENT::TrackerHitPlane*>( trkhit ) ; + if(trkhit->getType()!=8) return NULL; + //if( plane_hit == NULL ) return NULL; // SJA:FIXME: should be replaced with an exception + const edm4hep::Vector3d& pos=trkhit->getPosition(); + const TVector3 hit(pos.x, pos.y, pos.z); + + // convert to layer coordinates + TKalMatrix h = this->XvToMv(hit); + + Double_t x[2] ; + Double_t dx[2] ; + + x[0] = h(0, 0); + x[1] = h(1, 0); + + dx[0] = trkhit->getCovMatrix(2); + dx[1] = trkhit->getCovMatrix(5); + + bool hit_on_surface = IsOnSurface(hit); + + // streamlog_out(DEBUG1) << "ILDRotatedTrapMeaslayer::ConvertLCIOTrkHit ILDPlanarHit created" + // << " u = " << x[0] + // << " v = " << x[1] + // << " du = " << dx[0] + // << " dv = " << dx[1] + // << " x = " << hit.x() + // << " y = " << hit.y() + // << " z = " << hit.z() + // << " onSurface = " << hit_on_surface + // << std::endl ; + + return hit_on_surface ? new ILDPlanarHit( *this , x, dx, this->GetBz(),trkhit) : NULL; + + +} diff --git a/Utilities/KalDet/src/ild/common/ILDRotatedTrapMeaslayer.h b/Utilities/KalDet/src/ild/common/ILDRotatedTrapMeaslayer.h new file mode 100644 index 0000000000000000000000000000000000000000..8cb7e4e07bd142df53533ca42b88333a818327d1 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDRotatedTrapMeaslayer.h @@ -0,0 +1,106 @@ +#ifndef __ILDPLANARMEASLAYER__ +#define __ILDPLANARMEASLAYER__ +/** ILDRotatedTrapMeaslayer: User defined Rotated Trapezoid Planar KalTest measurement layer class used with ILDPLanarTrackHit. + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> +class TVTrackHit; + +class ILDRotatedTrapMeaslayer : public ILDVMeasLayer, public TPlane { + +public: + + /** Constructor Taking inner and outer materials, centre and normal of the plane, B-Field, sorting policy, height, inner base length, outer base length, tilt angle around axis of symmetry, represents full or half petal, whether the layer is sensitive, Cell ID, and an optional name */ + ILDRotatedTrapMeaslayer(TMaterial &min, + TMaterial &mout, + const TVector3 ¢er, + const TVector3 &normal, + Double_t Bz, + Double_t SortingPolicy, + Double_t height, + Double_t innerBaseLength, + Double_t outerBaseLength, + Double_t alpha, + Int_t half_petal, + Bool_t is_active, + Int_t CellID = -1, + const Char_t *name = "ILDRotatedTrapMeasL"); + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** Check if global point is on surface */ + inline virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + /** Get sorting policy for this plane */ + Double_t GetSortingPolicy() const { return _sortingPolicy; } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const { + + CellID = this->getCellIDs()[0]; // not multilayer + return this->CalcXingPointWith(hel,xx,phi,0,eps); + + } + + + +private: + Double_t _sortingPolicy ; + Double_t _signZ ; + Double_t _innerR ; + Double_t _outerR ; + Double_t _innerBaseLength ; + Double_t _outerBaseLength ; + Double_t _cosPhi ; //** cos of the azimuthal angle of the petal + Double_t _sinPhi ; //** sin of the azimuthal angle of the petal + Double_t _cosAlpha ; //** cos of the tilt angle of the petal + Double_t _sinAlpha ; //** sin of the tilt angle of the petal + Double_t _tanBeta ; //** tan of the openning angle of the petal + + // meaning of _halfPetal: + // 0 complete trapezoid + // +1 positive half only, i.e. the side of the petal in which the transverse coordinate, mv(0,0), is positive + // -1 negative half only, i.e. the side of the petal in which the transverse coordinate, mv(0,0), is negative + Int_t _halfPetal ; + + + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDSegmentedDiscMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDSegmentedDiscMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..87cac85cb5b7cb15f1c72a4d57887199be03e437 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDSegmentedDiscMeasLayer.cc @@ -0,0 +1,617 @@ + +#include "ILDSegmentedDiscMeasLayer.h" +#include "ILDPlanarHit.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +#include "kaltest/TVTrack.h" +#include "TVector3.h" +#include "TMath.h" +#include "TRotMatrix.h" +#include "TBRIK.h" +#include "TNode.h" +#include "TString.h" + +//#include <EVENT/TrackerHitPlane.h> + +#include <math.h> +#include <assert.h> +#include <algorithm> + +// #include "streamlog/streamlog.h" + + +ILDSegmentedDiscMeasLayer::ILDSegmentedDiscMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double sortingPolicy, + int nsegments, + double zpos, + double phi0, // defined by the axis of symmerty of the first petal + double trap_rmin, + double trap_height, + double trap_inner_base_length, + double trap_outer_base_length, + bool is_active, + std::vector<int> CellIDs, + const Char_t *name) : +ILDVMeasLayer(min, mout, Bz, CellIDs, is_active, name), +TPlane(TVector3(0.,0.,zpos), TVector3(0.,0.,zpos)), +_sortingPolicy(sortingPolicy),_nsegments(nsegments),_trap_rmin(trap_rmin),_trap_height(trap_height),_trap_inner_base_length(trap_inner_base_length),_trap_outer_base_length(trap_outer_base_length) +{ + + double h = _trap_rmin + _trap_height; + double w = 0.5 * _trap_outer_base_length; + _rmax = sqrt(h*h + w*w); + + _trap_tan_beta = 0.5*(_trap_outer_base_length - _trap_inner_base_length) / _trap_height; + + _segment_dphi = 2.0*M_PI / _nsegments; + + phi0 = angular_range_2PI(phi0); + + _start_phi = phi0 - 0.5*_segment_dphi; + + _start_phi = angular_range_2PI(_start_phi); + + // now check for constistency + double phi_max = std::max( ((0.5 * _trap_outer_base_length) / h ) , ((0.5 * _trap_inner_base_length) / _trap_rmin)); + + if( phi_max > _segment_dphi ) { + // streamlog_out(ERROR) << "ILDSegmentedDiscMeasLayer::ILDSegmentedDiscMeasLayer trapezoids overlaps: exit(1) called from " << __FILE__ << " line " << __LINE__ << std::endl; + exit(1); + } + +} + + + + + + +ILDSegmentedDiscMeasLayer::ILDSegmentedDiscMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double sortingPolicy, + int nsegments, + double zpos, + double phi0, // defined by the axis of symmerty of the first petal + double trap_rmin, + double trap_height, + double trap_inner_base_length, + double trap_outer_base_length, + bool is_active, + const Char_t *name) : +ILDVMeasLayer(min, mout, Bz, is_active, -1, name), +TPlane(TVector3(0.,0.,zpos), TVector3(0.,0.,zpos)), +_sortingPolicy(sortingPolicy),_nsegments(nsegments),_trap_rmin(trap_rmin),_trap_height(trap_height),_trap_inner_base_length(trap_inner_base_length),_trap_outer_base_length(trap_outer_base_length) +{ + + double h = _trap_rmin + _trap_height; + double w = 0.5 * _trap_outer_base_length; + _rmax = sqrt(h*h + w*w); + + _trap_tan_beta = 0.5*(_trap_outer_base_length - _trap_inner_base_length) / _trap_height; + + _segment_dphi = 2.0*M_PI / _nsegments; + + phi0 = angular_range_2PI(phi0); + + _start_phi = phi0 - 0.5*_segment_dphi; + + _start_phi = angular_range_2PI(_start_phi); + + // now check for constistency + double phi_max = std::max( ((0.5 * _trap_outer_base_length) / h ) , ((0.5 * _trap_inner_base_length) / _trap_rmin)); + + if( phi_max > _segment_dphi ) { + // streamlog_out(ERROR) << "ILDSegmentedDiscMeasLayer::ILDSegmentedDiscMeasLayer trapezoids overlaps: exit(1) called from " << __FILE__ << " line " << __LINE__ << std::endl; + exit(1); + } + +} + + +TKalMatrix ILDSegmentedDiscMeasLayer::XvToMv(const TVector3 &xv) const +{ + + // Calculate measurement vector (hit coordinates) from global coordinates: + +// TKalMatrix mv(kMdim,1); +// +// mv(0,0) = xv.X() ; +// +// +// mv(1,0) = xv.Y() ; + /* + std::cout << "\t ILDSegmentedDiscMeasLayer::XvToMv: " + << " x = " << xv.X() + << " y = " << xv.Y() + << " z = " << xv.Z() + << std::endl; + */ + // coordinate matrix to return + TKalMatrix mv(ILDPlanarHit_DIM,1); + + int segmentIndex = get_segment_index(xv.Phi()) ; + + TVector3 XC = this->get_segment_centre(segmentIndex); + + double sensor_x0 = XC.X(); + double sensor_y0 = XC.Y(); + + // here we are assuming that there is no offset of the centre of the sensor in the x-y plane. + + double phi_sensor = XC.Phi(); + + // for ILDSegmentedDiscMeasLayer the Normal is pointing from the IP to the Plane + double sign_z = GetNormal().Z() < 0 ? -1.0 : 1.0 ; + + double phi = phi_sensor + sign_z*M_PI/2 ; + + double cos_phi = cos(phi); + double sin_phi = sin(phi); + + double delta_x = xv.X() - sensor_x0; + double delta_y = xv.Y() - sensor_y0; + + + double cos_theta = -sign_z; + + double u = delta_x * cos_phi + delta_y * sin_phi ; + mv(0,0) = u ; + + double v = ( cos_theta * delta_y * cos_phi - cos_theta * delta_x * sin_phi) ; + mv(1,0) = v ; + + /* + std::cout << "\t ILDSegmentedDiscMeasLayer::XvToMv: phi_sensor = " << phi_sensor << " phi = " << phi << " sign_z = " << sign_z<< std::endl; + + std::cout << "\t ILDSegmentedDiscMeasLayer::XvToMv: " + << " mv(0,0) = " << mv(0,0) + << " mv(1,0) = " << mv(1,0) + << std::endl; + */ + return mv; + +} + + +TVector3 ILDSegmentedDiscMeasLayer::HitToXv(const TVTrackHit &vht) const { + + //std::cout << "\t ILDSegmentedDiscMeasLayer::HitToXv: " + // << " vht(0,0) = " << vht(0,0) << " vht(1,0) = " << vht(1,0) << std::endl; + + const ILDPlanarHit &mv = dynamic_cast<const ILDPlanarHit &>(vht); + +// double x = mv(0,0) ; +// double y = mv(1,0) ; +// +// double z = this->GetXc().Z() ; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + edm4hep::TrackerHit* hit = mv.getLCIOTrackerHit(); + encoder.setValue(hit->getCellID()); + int segmentIndex = encoder[lcio::ILDCellID0::module] / 2 ; + + + TVector3 XC = this->get_segment_centre(segmentIndex); + + double sensor_x0 = XC.X(); + double sensor_y0 = XC.Y(); + double sensor_z0 = XC.Z(); + + double phi_sensor = XC.Phi(); + // for ILDSegmentedDiscMeasLayer the Normal is pointing from the IP to the Plane + double sign_z = GetNormal().Z() < 0 ? -1.0 : 1.0 ;; + + double phi = phi_sensor + sign_z*M_PI/2 ; + + double cos_phi = cos(phi); + double sin_phi = sin(phi); + + double cos_theta = -sign_z; + + double u = mv(0,0); + double v = mv(1,0); + + double delta_x = (u * cos_phi - cos_theta * v * sin_phi) ; + double delta_y = (u * sin_phi + cos_theta * v * cos_phi) ; + + double x = delta_x + sensor_x0; + double y = delta_y + sensor_y0; + + double z = sensor_z0 ; + /* + std::cout << "\t ILDSegmentedDiscMeasLayer::HitToXv: " + << " x = " << x + << " y = " << y + << " z = " << z + << std::endl; + */ + return TVector3(x,y,z); + +} + +void ILDSegmentedDiscMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + +// Int_t sdim = H.GetNcols(); +// Int_t hdim = TMath::Max(5,sdim-1); +// +// // Set H = (@h/@a) = (@d/@a, @z/@a)^t +// +// for (Int_t i=0; i<hdim; i++) { +// +// H(0,i) = dxphiada(0,i); +// H(1,i) = dxphiada(1,i) ; +// +// } +// if (sdim == 6) { +// H(0,sdim-1) = 0.; +// H(1,sdim-1) = 0.; +// } + + + int segmentIndex = get_segment_index(xxv.Phi()) ; + + TVector3 XC = this->get_segment_centre(segmentIndex); + + double phi_sensor = XC.Phi(); + // for ILDSegmentedDiscMeasLayer the Normal is pointing from the IP to the Plane + double sign_z = GetNormal().Z() < 0 ? -1.0 : 1.0 ; + + double phi = phi_sensor + sign_z*M_PI/2 ; + + double cos_phi = cos(phi); + double sin_phi = sin(phi); + + double cos_theta = -sign_z; + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + double dudx = cos_phi; + double dudy = sin_phi; + + double dvdx = -cos_theta * sin_phi; + double dvdy = cos_theta * cos_phi; + /* + std::cout << "\t ILDSegmentedDiscMeasLayer::CalcDhDa: " + << " dudx = " << dudx + << " dudy = " << dudy + << " dvdx = " << dvdx + << " dvdy = " << dvdy + << std::endl; + */ + for (Int_t i=0; i<hdim; i++) { + + H(0,i) = dudx * dxphiada(0,i) + dudy * dxphiada(1,i) ; + H(1,i) = dvdx * dxphiada(0,i) + dvdy * dxphiada(1,i) ; + + } + if (sdim == 6) { + + H(0,sdim-1) = 0.0; + H(1,sdim-1) = 0.; + + } +} + + +Int_t ILDSegmentedDiscMeasLayer::CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps) const{ + + // streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::CalcXingPointWith" << std::endl; + + phi = 0.0; + + xx.SetX(0.0); + xx.SetY(0.0); + xx.SetZ(0.0); + + // check that direction has one of the correct values + if( !( mode == 0 || mode == 1 || mode == -1) ) return -1 ; + +// + + // get helix parameters + Double_t dr = hel.GetDrho(); + Double_t phi0 = hel.GetPhi0(); // + Double_t kappa = hel.GetKappa(); + Double_t rho = hel.GetRho(); + Double_t omega = 1.0 / rho; + Double_t z0 = hel.GetDz(); + Double_t tanl = hel.GetTanLambda(); + + TVector3 ref_point = hel.GetPivot(); + + // + // Check if charge is nonzero. + // + + Int_t chg = (Int_t)TMath::Sign(1.1,kappa); + if (!chg) { + // streamlog_out(ERROR) << ">>>> Error >>>> ILDSegmentedDiscMeasLayer::CalcXingPointWith" << std::endl + // << " Kappa = 0 is invalid for a helix " << std::endl; + return -1; + } + + const double sin_phi0 = sin(phi0); + const double cos_phi0 = cos(phi0); + + const double x_pca = ref_point.x() + dr * cos_phi0 ; + const double y_pca = ref_point.y() + dr * sin_phi0 ; + const double z_pca = ref_point.z() + z0 ; + + const double z = this->GetXc().Z() ; + // get path length to crossing point + + const double s = ( z - z_pca ) / tanl ; + + +// streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::CalcXingPointWith " +// << " ref_point.z() = " << ref_point.z() +// << " z = " << z +// << " z0 = " << z0 +// << " z_pca = " << z_pca +// << " tanl = " << tanl +// << " z - z_pca = " << z - z_pca +// << std::endl; +// +// TVector3 xx_n; +// int cuts = TVSurface::CalcXingPointWith(hel, xx_n, phi, mode, eps); +// streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::CalcXingPointWith from Newton: cuts = " << cuts << " x = " << xx_n.x() << " y = "<< xx_n.y() << " z = " << xx_n.z() << " r = " << xx_n.Perp() << " phi = " << xx_n.Phi() << " dphi = " << phi << std::endl; + + + phi = -omega * s; + + const double delta_phi_half = -phi/2.0 ; + + double x; + double y; + + if( fabs(s) > FLT_MIN ){ // protect against starting on the plane + + x = x_pca - s * ( sin(delta_phi_half) / delta_phi_half ) * sin( phi0 - delta_phi_half ) ; + + y = y_pca + s * ( sin(delta_phi_half) / delta_phi_half ) * cos( phi0 - delta_phi_half ) ; + + } + else{ + // streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::CalcXingPointWith Using PCA values " << std::endl; + x = x_pca; + y = y_pca; + phi = 0.0; + } + + + xx.SetXYZ(x, y, z); + + + // streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::CalcXingPointWith : cuts = " << (IsOnSurface(xx) && (chg*phi*mode)<0) << " x = " << xx.x() << " y = "<< xx.y() << " z = " << xx.z() << " r = " << xx.Perp() << " phi = " << xx.Phi() << " dphi = " << phi << " s = " << s << " " << this->TVMeasLayer::GetName() << std::endl; +// +// streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::CalcXingPointWith : xdiff = " << xx.x() - xx_n.x() << " ydiff = "<< xx.y() - xx_n.y() << " zdiff = " << xx.z() - xx_n.z() << std::endl; + + // check if intersection with plane is within boundaries + + if( mode!=0 && fabs(phi)>1.e-10 ){ // (+1,-1) = (fwd,bwd) + if( chg*phi*mode > 0){ + return 0; + } + } + + + return (IsOnSurface(xx) ? 1 : 0); + + +} + +Bool_t ILDSegmentedDiscMeasLayer::IsOnSurface(const TVector3 &xx) const +{ + + // streamlog_out(DEBUG0) << "IsOnSurface " << std::endl; + + bool onSurface = false ; + + // TKalMatrix mv = XvToMv(xx); + + // check whether the hit lies in the same plane as the surface, here we are resticted to planes perpendicular to z + + // streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::IsOnSurface Xc.Z = " << GetXc().Z() << std::endl; + + if (TMath::Abs(xx.Z()-GetXc().Z()) < 1e-4) { + // streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::IsOnSurface z passed " << std::endl; + double r2 = xx.Perp2(); + + // quick check to see weather the hit lies inside the min max r + if( r2 <= _rmax*_rmax && r2 >= _trap_rmin*_trap_rmin ) { + // streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::IsOnSurface r2 passed " << std::endl; + + double phi_point = angular_range_2PI(xx.Phi()); + + // get the angle in the local system + double gamma = angular_range_2PI(phi_point - _start_phi); + + // the angle local to the sector + double local_phi = fmod(gamma, _segment_dphi) - (0.5*_segment_dphi) ; + + double dist_along_centre_line = xx.Perp()*cos(local_phi); + + // check if the point projected onto the centre line is within the limits of the trapezoid + if( dist_along_centre_line > _trap_rmin && dist_along_centre_line < _trap_rmin + _trap_height){ + // streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::IsOnSurface dist_along_centre_line passed " << std::endl; + + double adj = dist_along_centre_line - _trap_rmin ; + + double dist_from_centre_line = fabs(xx.Perp()*sin(local_phi)); + + double opp = dist_from_centre_line - 0.5*_trap_inner_base_length; + + double tan_delta_angle = opp/adj; + + // check if the point is within the angular limits of the trapezoid + if (tan_delta_angle < _trap_tan_beta) { + // streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::IsOnSurface tan_delta_angle passed " << std::endl; + onSurface = true ; + + } + } + } + } + + return onSurface; + +} + + +ILDVTrackHit* ILDSegmentedDiscMeasLayer::ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + //EVENT::TrackerHitPlane* plane_hit = dynamic_cast<EVENT::TrackerHitPlane*>( trkhit ) ; + //if( plane_hit == NULL ) { + // streamlog_out(ERROR) << "ILDSegmentedDiscMeasLayer::ConvertLCIOTrkHit dynamic_cast to TrackerHitPlane failed " << std::endl; + //return NULL; // SJA:FIXME: should be replaced with an exception + //} + if((trkhit->getType()&8)!=8) { + std::cout << "ILDSegmentedDiscMeasLayer::ConvertLCIOTrkHit dynamic_cast to ILDPlanarHit failed " << std::endl; + throw std::logic_error("Invalid invoke ILDSegmentedDiscMeasLayer by TrackerHit trkhit"); + } + + // remember here the "position" of the hit in fact defines the origin of the plane it defines so u and v are per definition 0. + const edm4hep::Vector3d& pos=trkhit->getPosition(); + const TVector3 hit(pos.x, pos.y, pos.z) ; + + // convert to layer coordinates + TKalMatrix h(ILDPlanarHit_DIM,1); + + h = this->XvToMv(hit); + + double x[ILDPlanarHit_DIM] ; + double dx[ILDPlanarHit_DIM] ; + + x[0] = h(0, 0); + x[1] = h(1, 0); + + dx[0] = trkhit->getCovMatrix(2); + dx[1] = trkhit->getCovMatrix(5); + + bool hit_on_surface = IsOnSurface(hit); + /* + std::cout << "ILDSegmentedDiscMeasLayer::ConvertLCIOTrkHit: ILDPlanarHit created" + << " for CellID " << trkhit->getCellID() + << " u = " << x[0] + << " v = " << x[1] + << " du = " << dx[0] + << " dv = " << dx[1] + << " x = " << pos.x + << " y = " << pos.y + << " z = " << pos.z + << " onSurface = " << hit_on_surface + << std::endl ; + */ + ILDPlanarHit hh( *this , x, dx, this->GetBz(),trkhit); + + this->HitToXv(hh); + + return hit_on_surface ? new ILDPlanarHit( *this , x, dx, this->GetBz(),trkhit) : NULL; + +} + + +/** Get the intersection and the CellID, needed for multilayers */ +int ILDSegmentedDiscMeasLayer::getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps) const { + + + int crosses = this->CalcXingPointWith(hel, xx, phi, mode, eps); + + if ( crosses != 0 ) { + + unsigned int segment = this->get_segment_index( xx.Phi() ); + + const std::vector<int>& cellIds = this->getCellIDs(); + + lcio::BitField64 bf( UTIL::ILDCellID0::encoder_string ) ; + bf.setValue( this->getCellIDs()[0] ) ; // get the first cell_ID, this will have the correct sensor value + + bf[lcio::ILDCellID0::module] = cellIds.at(segment); + CellID = bf.lowWord(); + + } + + + return crosses; + +} + +unsigned int ILDSegmentedDiscMeasLayer::get_segment_index(double phi) const { + + phi = angular_range_2PI(phi-_start_phi); + return unsigned(floor(phi/_segment_dphi)); + +} + +double ILDSegmentedDiscMeasLayer::get_segment_phi(unsigned int index) const{ + + return angular_range_2PI(_start_phi + 0.5*_segment_dphi + index * _segment_dphi); + +} + + +TVector3 ILDSegmentedDiscMeasLayer::get_segment_centre(unsigned int index) const{ + +// streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::get_segment_centre index = " << index << std::endl; + + double phi = this->get_segment_phi(index); + +// streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::get_segment_centre phi = " << phi << std::endl; + + + double rc = _trap_rmin + _trap_height/2; + +// streamlog_out(DEBUG0) << "ILDSegmentedDiscMeasLayer::get_segment_centre rc = " << rc << std::endl; + + double xc = rc * cos(phi); + double yc = rc * sin(phi);; + + double zc = this->GetXc().Z(); + + TVector3 XC(xc,yc,zc); + + + return XC; + +} + +double ILDSegmentedDiscMeasLayer::angular_range_2PI( double phi ) const { + + //bring phi_point into range 0 < phi < +2PI + while (phi < 0) { + phi += 2.0 * M_PI; + } + while (phi >= 2.0*M_PI) { + phi -= 2.0 * M_PI; + } + + return phi; + +} + diff --git a/Utilities/KalDet/src/ild/common/ILDSegmentedDiscMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDSegmentedDiscMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..6133570279f935d889f3e5ed76f3f51ed2f1205b --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDSegmentedDiscMeasLayer.h @@ -0,0 +1,144 @@ +#ifndef __ILDSEGMENTEDDISCMEASLAYER_H__ +#define __ILDSEGMENTEDDISCMEASLAYER_H__ + +/** ILDSegmentedDiscMeasLayer: User defined Segemented Disk Planar KalTest measurement layer class used with ILDPLanarTrackHit. Segments are isosolese trapezoids whose axis of symmetry points to the origin + * WARNING: ONLY IMPLEMENTED FOR X AND Y COORDINATES AT FIXED Z + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDVMeasLayer.h" + +#include "TMath.h" +#include <sstream> +#include <iostream> + +#include <vector> + +class TVTrackHit; + +class ILDSegmentedDiscMeasLayer : public ILDVMeasLayer, public TPlane { +public: + // Ctors and Dtor + + ILDSegmentedDiscMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double SortingPolicy, + int nsegments, + double zpos, + double phi0, // defined by the axis of symmerty of the first petal + double trap_rmin, + double trap_height, + double trap_innerBaseLength, + double trap_outerBaseLength, + bool is_active, + std::vector<int> CellIDs, + const Char_t *name = "ILDDiscMeasL"); + + ILDSegmentedDiscMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double SortingPolicy, + int nsegments, + double zpos, + double phi0, // defined by the axis of symmerty of the first petal + double trap_rmin, + double trap_height, + double trap_innerBaseLength, + double trap_outerBaseLength, + bool is_active, + const Char_t *name = "ILDDiscMeasL"); + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + + /** overloaded version of CalcXingPointWith using closed solution*/ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + /** overloaded version of CalcXingPointWith using closed solution*/ + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps = 1.e-8) const{ + + return CalcXingPointWith(hel,xx,phi,0,eps); + + } + + + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const ; + + + + /** Check if global point is on surface */ + virtual Bool_t IsOnSurface (const TVector3 &xx) const; + + /** Get sorting policy for this plane */ + double GetSortingPolicy() const { return _sortingPolicy; } + +protected: + + double angular_range_2PI( double phi ) const; + unsigned int get_segment_index(double phi) const; + double get_segment_phi(unsigned int index) const; + TVector3 get_segment_centre(unsigned int index) const; + +private: + + double _sortingPolicy; + int _nsegments; + double _trap_rmin; + double _trap_height; + double _trap_inner_base_length; + double _trap_outer_base_length; + double _trap_tan_beta; // tan of the openning angle of the petal + + double _rmax; + double _start_phi; // trailing edge of the first sector + double _segment_dphi; + + + +}; + + + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDSegmentedDiscStripMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDSegmentedDiscStripMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..590032d20c53e5c4fc058f32293f6a4b88fa751a --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDSegmentedDiscStripMeasLayer.cc @@ -0,0 +1,299 @@ + +#include "ILDSegmentedDiscStripMeasLayer.h" + +#include "ILDPlanarStripHit.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +#include "kaltest/TVTrack.h" +#include "TVector3.h" +#include "TMath.h" +#include "TRotMatrix.h" +#include "TBRIK.h" +#include "TNode.h" +#include "TString.h" + +//#include <EVENT/TrackerHitPlane.h> + +#include <math.h> +#include <assert.h> +#include <algorithm> + +// #include "streamlog/streamlog.h" + + +TKalMatrix ILDSegmentedDiscStripMeasLayer::XvToMv(const TVector3 &xv) const +{ + + // Calculate measurement vector (hit coordinates) from global coordinates: + /* + std::cout << "\t ILDSegmentedDiscStripMeasLayer::XvToMv: " + << " x = " << xv.X() + << " y = " << xv.Y() + << " z = " << xv.Z() + << std::endl; + */ + // let's start with the sensor whose axis of symmetry is + // aligned with the y-axis and whose sensitive face is facing towards the IP. + // For a zero strip angle then: + // u = -x + // v = y + // w = -z + + // coordinate matrix to return + TKalMatrix mv(ILDPlanarStripHit_DIM,1); + + int segmentIndex = get_segment_index(xv.Phi()) ; + + TVector3 XC = this->get_segment_centre(segmentIndex); + + double sensor_x0 = XC.X(); + double sensor_y0 = XC.Y(); + + // here we are assuming that there is no offset of the centre of the sensor in the x-y plane. + // SJA:FIXME: We need to get the segment we are in to get phi + + double phi_sensor = XC.Phi(); + + // for ILDSegmentedDiscMeasLayer the Normal is pointing from the IP to the Plane + double sign_z = GetNormal().Z() < 0 ? -1.0 : 1.0 ; + + double phi = phi_sensor + sign_z*M_PI/2 ; + + phi += _stripAngle; // the strip rotation is around the w vector which is pointing at the IP + + double cos_phi = cos(phi); + double sin_phi = sin(phi); + + double delta_x = xv.X() - sensor_x0; + double delta_y = xv.Y() - sensor_y0; + + // is the sensitive facing the IP (+1) or facing away from it (-1) + // const double sign_z = GetNormal().Z() < 0 ? 1.0 : -1.0 ; + + // double u = sign_z * (delta_y * cos_phi - delta_x * sin_phi) ; + + double cos_theta = -sign_z; + + // double u = delta_x * cos_phi - cos_theta * delta_y * sin_phi ; + double u = delta_x * cos_phi + delta_y * sin_phi ; + + mv(0,0) = u ; + + if (ILDPlanarStripHit_DIM == 2) { + // double v = (delta_x * sin_phi + cos_theta * delta_y * cos_phi) ; + double v = ( cos_theta * delta_y * cos_phi - cos_theta * delta_x * sin_phi) ; + mv(1,0) = v ; + } + + /* + std::cout << "\t ILDSegmentedDiscStripMeasLayer::XvToMv: phi_sensor = " << phi_sensor << " phi = " << phi << " stripAngle = " << _stripAngle << " sign_z = " << sign_z<< std::endl; + + std::cout << "\t ILDSegmentedDiscStripMeasLayer::XvToMv: " + << " mv(0,0) = " << mv(0,0) ; + if (ILDPlanarStripHit_DIM == 2) { + std::cout << " mv(1,0) = " << mv(1,0); + } + std::cout << std::endl; + */ + return mv; + +} + +TVector3 ILDSegmentedDiscStripMeasLayer::HitToXv(const TVTrackHit &vht) const { + /* + std::cout << "\t ILDSegmentedDiscStripMeasLayer::HitToXv: " + << " vht(0,0) = " << vht(0,0); + if (ILDPlanarStripHit_DIM == 2) { + std::cout << " vht(1,0) = " << vht(1,0); + } + std::cout << std::endl; + */ + const ILDPlanarStripHit &mv = dynamic_cast<const ILDPlanarStripHit &>(vht); + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + edm4hep::TrackerHit* hit = mv.getLCIOTrackerHit(); + encoder.setValue(hit->getCellID()); + int segmentIndex = encoder[lcio::ILDCellID0::module] / 2 ; + + + TVector3 XC = this->get_segment_centre(segmentIndex); + + double sensor_x0 = XC.X(); + double sensor_y0 = XC.Y(); + double sensor_z0 = XC.Z(); + + ////std::cout << "\t ILDSegmentedDiscStripMeasLayer::HitToXv: segmentIndex = " << segmentIndex << " x0 = " << sensor_x0 << " y0 = " << sensor_y0 << " z0 = " << sensor_z0 << " segment Phi = " << XC.Phi() << std::endl; + + // here we are assuming that there is no offset of the centre of the sensor in the x-y plane. + // SJA:FIXME: We need to get the segment we are in to get phi + + double phi_sensor = XC.Phi(); + // for ILDSegmentedDiscMeasLayer the Normal is pointing from the IP to the Plane + double sign_z = GetNormal().Z() < 0 ? -1.0 : 1.0 ;; + + double phi = phi_sensor + sign_z*M_PI/2 ; + + phi += _stripAngle; // the strip rotation is around the w vector which is pointing at the IP + + double cos_phi = cos(phi); + double sin_phi = sin(phi); + + double cos_theta = -sign_z; + + double u = mv(0,0); + double v = 0.0; + + if (ILDPlanarStripHit_DIM == 2) { + v = mv(1,0); + } + +// double delta_x = (u * cos_phi - cos_theta * v * sin_phi) ; +// double delta_y = (u * sin_phi + cos_theta * v * cos_phi) ; + + double delta_x = (u * cos_phi - cos_theta * v * sin_phi) ; + double delta_y = (u * sin_phi + cos_theta * v * cos_phi) ; + + double x = delta_x + sensor_x0; + double y = delta_y + sensor_y0; + + double z = sensor_z0 ; + /* + std::cout << "\t ILDSegmentedDiscStripMeasLayer::HitToXv: " + << " x = " << x + << " y = " << y + << " z = " << z + << std::endl; + */ + return TVector3(x,y,z); +} + +void ILDSegmentedDiscStripMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + int segmentIndex = get_segment_index(xxv.Phi()) ; + + TVector3 XC = this->get_segment_centre(segmentIndex); + + + double phi_sensor = XC.Phi(); + // for ILDSegmentedDiscMeasLayer the Normal is pointing from the IP to the Plane + double sign_z = GetNormal().Z() < 0 ? -1.0 : 1.0 ; + + double phi = phi_sensor + sign_z*M_PI/2 ; + + phi += _stripAngle; // the strip rotation is around the w vector which is pointing at the IP + + double cos_phi = cos(phi); + double sin_phi = sin(phi); + + double cos_theta = -sign_z; + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + + double dudx = cos_phi; + double dudy = sin_phi; + + double dvdx = -cos_theta * sin_phi; + double dvdy = cos_theta * cos_phi; + /* + std::cout << "\t ILDSegmentedDiscStripMeasLayer::CalcDhDa: " + << " dudx = " << dudx + << " dudy = " << dudy + << " dvdx = " << dvdx + << " dvdy = " << dvdy + << std::endl; + */ + for (Int_t i=0; i<hdim; i++) { + + H(0,i) = dudx * dxphiada(0,i) + dudy * dxphiada(1,i) ; + + if (ILDPlanarStripHit_DIM == 2) { + H(1,i) = dvdx * dxphiada(0,i) + dvdy * dxphiada(1,i) ; + } + + } + if (sdim == 6) { + H(0,sdim-1) = 0.0; + if (ILDPlanarStripHit_DIM == 2) { + H(1,sdim-1) = 0.; + } + + } + +} + + + +ILDVTrackHit* ILDSegmentedDiscStripMeasLayer::ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const { + + //EVENT::TrackerHitPlane* plane_hit = dynamic_cast<EVENT::TrackerHitPlane*>( trkhit ) ; + //if( plane_hit == NULL ) { + // streamlog_out(ERROR) << "ILDSegmentedDiscStripMeasLayer::ConvertLCIOTrkHit dynamic_cast to TrackerHitPlane failed " << std::endl; + //return NULL; // SJA:FIXME: should be replaced with an exception + //} + if((trkhit->getType()&8)!=8) { + std::cout << "ILDSegmentedDiscStripMeasLayer::ConvertLCIOTrkHit dynamic_cast to ILDPlanarStripHit failed " << std::endl; + throw std::logic_error("Invalid invoke ILDSegmentedDiscStripMeasLayer by TrackerHit trkhit"); + } + + // remember here the "position" of the hit in fact defines the origin of the plane it defines so u and v are per definition 0. + // this is still the case for a 1-dimentional measurement, and is then used to calculate the u coordinate according to the origin of the actual measurement plane. + const edm4hep::Vector3d& pos=trkhit->getPosition(); + const TVector3 hit(pos[0], pos[1], pos[2]) ; + + // convert to layer coordinates + TKalMatrix h(ILDPlanarStripHit_DIM,1); + + h = this->XvToMv(hit); + + double x[ILDPlanarStripHit_DIM] ; + double dx[ILDPlanarStripHit_DIM] ; + + x[0] = h(0, 0); + if(ILDPlanarStripHit_DIM == 2) x[1] = h(1, 0); + + dx[0] = trkhit->getCovMatrix(2); + if(ILDPlanarStripHit_DIM == 2) dx[1] = trkhit->getCovMatrix(5); + + bool hit_on_surface = IsOnSurface(hit); + /* + std::cout << "ILDSegmentedDiscStripMeasLayer::ConvertLCIOTrkHit ILDPlanarStripHit created" + << " for CellID " << trkhit->getCellID() + << " Disc Z = " << this->GetXc().Z() + << " u = " << x[0] + << " du = " << dx[0]; + + if(ILDPlanarStripHit_DIM == 2) std::cout << " v = " << x[1] << " dv = " << dx[1]; + + std::cout << " x = " << hit.x() + << " y = " << hit.y() + << " z = " << hit.z() + << " r = " << hit.Perp() + << " onSurface = " << hit_on_surface + << std::endl ; + */ + ILDPlanarStripHit hh( *this , x, dx, this->GetBz(),trkhit); + + this->HitToXv(hh); + + return hit_on_surface ? new ILDPlanarStripHit( *this , x, dx, this->GetBz(),trkhit) : NULL; + +} + + + diff --git a/Utilities/KalDet/src/ild/common/ILDSegmentedDiscStripMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDSegmentedDiscStripMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..8bdab6686dcc7ba6d2ac04bcc3e7a7eae1dc84b8 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDSegmentedDiscStripMeasLayer.h @@ -0,0 +1,80 @@ +#ifndef __ILDSEGMENTEDDISCSTRIPMEASLAYER_H__ +#define __ILDSEGMENTEDDISCSTRIPMEASLAYER_H__ + +/** ILDSegmentedDiscStripMeasLayer: User defined Segemented Disk Planar KalTest measurement layer class used with ILDPLanarTrackHit. Segments are isosolese trapezoids whose axis of symmetry points to the origin + * WARNING: ONLY IMPLEMENTED FOR X AND Y COORDINATES AT FIXED Z + * + * @author S.Aplin DESY + */ +#include "TVector3.h" + +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "ILDSegmentedDiscMeasLayer.h" + +#include "TMath.h" +#include <sstream> +#include <iostream> + +#include <vector> + +class TVTrackHit; + +class ILDSegmentedDiscStripMeasLayer : public ILDSegmentedDiscMeasLayer { + +public: + // Ctors and Dtor + + ILDSegmentedDiscStripMeasLayer(TMaterial &min, + TMaterial &mout, + double Bz, + double SortingPolicy, + int nsegments, + double zpos, + double phi0, // defined by the axis of symmerty of the first petal + double trap_rmin, + double trap_height, + double trap_innerBaseLength, + double trap_outerBaseLength, + double stripAngle, + bool is_active, + std::vector<int> CellIDs, + const Char_t *name = "ILDDiscMeasL") + : ILDSegmentedDiscMeasLayer(min,mout,Bz,SortingPolicy,nsegments,zpos,phi0,trap_rmin,trap_height,trap_innerBaseLength,trap_outerBaseLength,is_active,CellIDs,name), + _stripAngle(stripAngle) + { /* no op */ } + + + // Parrent's pure virtuals that must be implemented + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const + { return this->XvToMv(xv); } + + + /** Global to Local coordinates */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Local to Global coordinates */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** Calculate Projector Matrix */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const ; + +private: + + double _stripAngle; + +}; + + + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDVMeasLayer.cc b/Utilities/KalDet/src/ild/common/ILDVMeasLayer.cc new file mode 100644 index 0000000000000000000000000000000000000000..6770585173502a72f0490f8a1db7a446309a3587 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDVMeasLayer.cc @@ -0,0 +1,62 @@ + +#include "ILDVMeasLayer.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +// #include "streamlog/streamlog.h" + +Bool_t ILDVMeasLayer::kActive = kTRUE; +Bool_t ILDVMeasLayer::kDummy = kFALSE; + +//ClassImp(ILDVMeasLayer) + +ILDVMeasLayer::ILDVMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t Bz, + Bool_t is_active, + int cellID , + const Char_t *name) +: TVMeasLayer(min, mout, is_active, name), +_Bz(Bz), +_isMultiLayer(false) +{ + _cellIDs.push_back(cellID); + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + encoder.setValue(cellID); + encoder[lcio::ILDCellID0::module] = 0; + encoder[lcio::ILDCellID0::sensor] = 0; + + _layerID = encoder.lowWord(); + +} + + +ILDVMeasLayer::ILDVMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t Bz, + const std::vector<int>& cellIDs, + Bool_t is_active, + const Char_t *name) +: TVMeasLayer(min, mout, is_active, name), +_Bz(Bz), +_cellIDs(cellIDs), +_isMultiLayer(true) +{ + + if (cellIDs.size() == 0 ) { + // streamlog_out(ERROR) << __FILE__ << " line " << __LINE__ << " size of cellIDs == 0" << std::endl; + } + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + encoder.setValue(cellIDs.at(0)); + encoder[lcio::ILDCellID0::module] = 0; + encoder[lcio::ILDCellID0::sensor] = 0; + + _layerID = encoder.lowWord(); + +} + + + diff --git a/Utilities/KalDet/src/ild/common/ILDVMeasLayer.h b/Utilities/KalDet/src/ild/common/ILDVMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..3d213b3aadcc3f5c3b4ff693462ff2e746e22f53 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDVMeasLayer.h @@ -0,0 +1,88 @@ +#ifndef __ILDVMEASLAYER__ +#define __ILDVMEASLAYER__ + +/** ILDVMeasLayer: Virtual measurement layer class used by ILD[X]MeasLayer Classes. + * + * @author S.Aplin DESY + */ + +#include "TVector3.h" +#include "kaltest/TKalMatrix.h" +#include "kaltest/TCylinder.h" +#include "kaltest/TVMeasLayer.h" +#include "kaltest/TAttDrawable.h" +#include "kaltest/KalTrackDim.h" +#include "TString.h" + +#include <vector> + +class TVTrackHit; +class TNode; +class ILDVTrackHit; + +namespace edm4hep{ + class TrackerHit; +} + +class ILDVMeasLayer : public TVMeasLayer { +public: + + static Bool_t kActive; + static Bool_t kDummy; + + /** Get the layer ID */ + inline int getLayerID() const { return _layerID ; } + + /** Get the Cell ID associated with this measurement layer */ + inline const std::vector<int>& getCellIDs() const { return _cellIDs ; } + + /** Get the number of Cell ID associated with this measurement layer */ + inline unsigned int getNCellIDs() const { return _cellIDs.size() ; } + + /** Get the Magnetic field at the measurement surface */ + inline Double_t GetBz() const { return _Bz; } + + /** Convert LCIO Tracker Hit to an ILDPLanarTrackHit */ + virtual ILDVTrackHit* ConvertLCIOTrkHit(edm4hep::TrackerHit* trkhit) const = 0 ; + + /** Check whether the measurement layer represents a series of detector elements */ + bool isMultilayer() const { return _isMultiLayer; } + + /** Get the intersection and the CellID, needed for multilayers */ + virtual int getIntersectionAndCellID(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t &CellID, + Int_t mode, + Double_t eps = 1.e-8) const = 0 ; + +protected: + + ILDVMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t Bz, + Bool_t is_active = ILDVMeasLayer::kActive, + int CellID = -1 , + const Char_t *name = "ILDMeasL"); + + ILDVMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t Bz, + const std::vector<int>& cellIDs, + Bool_t is_active = ILDVMeasLayer::kActive, + const Char_t *name = "ILDMeasL"); + + + + Double_t _Bz ; // Magnitude of B-Field in Z + int _layerID ; + std::vector<int> _cellIDs ; + + bool _isMultiLayer; + +private: + + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/common/ILDVTrackHit.h b/Utilities/KalDet/src/ild/common/ILDVTrackHit.h new file mode 100644 index 0000000000000000000000000000000000000000..d47be083ee5e2bc1a8871d8ba1578301e8b352f1 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/ILDVTrackHit.h @@ -0,0 +1,33 @@ +#ifndef ILDVTrackHIT_H +#define ILDVTrackHIT_H + +/** ILDVMeasLayer: Virtual hit class used by ILD[X]Hit Classes, which should provide coordinate vector as defined by the MeasLayer + * + * @author S.Aplin DESY + */ + + +#include "kaltest/TVTrackHit.h" + +#include "ILDVMeasLayer.h" + +#include "edm4hep/TrackerHit.h" + +class ILDVTrackHit : public TVTrackHit { + +public: + + /** Constructor Taking coordinates and associated measurement layer, with bfield and number of measurement dimentions*/ + ILDVTrackHit(const TVMeasLayer &ms, Double_t *x, Double_t *dx, + Double_t bfield , Int_t dim, edm4hep::TrackerHit* trkhit) + : TVTrackHit(ms, x, dx, bfield, dim), _trkhit(trkhit) + { /* no op */ } + + edm4hep::TrackerHit* getLCIOTrackerHit() const { return _trkhit; } + +private: + + edm4hep::TrackerHit* _trkhit; + +}; +#endif diff --git a/Utilities/KalDet/src/ild/common/MaterialDataBase.cc b/Utilities/KalDet/src/ild/common/MaterialDataBase.cc new file mode 100644 index 0000000000000000000000000000000000000000..2911317f7990c2ec2deb56eadabaab5ab7ce787b --- /dev/null +++ b/Utilities/KalDet/src/ild/common/MaterialDataBase.cc @@ -0,0 +1,239 @@ + +#include "MaterialDataBase.h" + +#include <stdexcept> +#include <vector> +#include <algorithm> + +#include <gear/GEAR.h> +#include "gearimpl/Util.h" +#include <gear/SimpleMaterial.h> +#include <gearimpl/GearParametersImpl.h> +#include "DetInterface/IGeoSvc.h" + +#include "TMaterial.h" + +MaterialDataBase::~MaterialDataBase(){ + + std::map<std::string,TMaterial* >::iterator it = _material_map.begin(); + std::vector<TMaterial*> deleted_objects; + + for( /**/; it!=_material_map.end(); ++it) + + if( std::find( deleted_objects.begin(), deleted_objects.end(), (*it).second ) != deleted_objects.end() ) { + delete (*it).second ; + deleted_objects.push_back((*it).second) ; + } +} + +TMaterial* MaterialDataBase::getMaterial(std::string mat_name){ + + if (_isInitialised == false) { + MaterialDataBaseException exp ( mat_name ) ; + + + throw exp; + } + + std::map<std::string,TMaterial* >::iterator it = _material_map.find(mat_name) ; + + if ( it == _material_map.end() ) { + MaterialDataBaseException exp( mat_name ) ; + throw exp ; + } + else { + return (*it).second ; + } + +} + +void MaterialDataBase::initialise( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc ){ + + if( !_isInitialised ){ + this->createMaterials(gearMgr, geoSvc); + _isInitialised = true ; + _gearMgr = &gearMgr; + } + +} + +void MaterialDataBase::registerForService(const gear::GearMgr& gearMgr, IGeoSvc* geoSvc ) { + + if( !_isInitialised ){ + //std::cout << "debug fucd: " << "--------------------" << std::endl; + this->initialise(gearMgr, geoSvc); + } + + else { + if ( _gearMgr != &gearMgr ) { + MaterialDataBaseException exp( " MaterialDataBase::registerForService : _gearMgr != &gearMgr ! " ) ; + throw exp; + } + } + +} + + +void MaterialDataBase::addMaterial(TMaterial* mat, std::string name) { + std::map<std::string, TMaterial*>::iterator it = _material_map.find(name) ; + //std::cout << name << " " << mat << std::endl; + std::string what( name ) ; + what += " - already exists [MaterialDataBase::addMaterial() ] " ; + MaterialDataBaseException exp( what ) ; + + if ( it != _material_map.end() ) { + //std::cout << what << std::endl; + throw exp; + } + else { + _material_map[name] = mat ; + } +} + + +void MaterialDataBase::createMaterials(const gear::GearMgr& gearMgr, IGeoSvc* geoSvc ){ + + Double_t A, Z, density, radlen ; + std::string name; + + // Beam + A = 14.00674 * 0.7 + 15.9994 * 0.3 ; + Z = 7.3 ; + density = 1.0e-25 ; // density set to very low value + radlen = 1.0e25 ; // give huge radiation length + name = "beam" ; + + TMaterial& beam = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.) ; + this->addMaterial(&beam, name); + + // Air + A = 14.00674 * 0.7 + 15.9994 * 0.3 ; + Z = 7.3 ; + density = 1.205e-3 ; // g/cm^3 + radlen = 3.42e4 ; // cm // SJA:FIXME using the standard formular for the radiation length and the above values gives 3.06e4 + name = "air" ; + + TMaterial &air = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.) ; + this->addMaterial(&air, name) ; + + // Si + A = 28.09 ; + Z = 14.0 ; + density = 2.33 ; // g/cm^3 + radlen = 9.36607 ; // cm + name = "silicon"; + + TMaterial &silicon = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.) ; + this->addMaterial(&silicon, name); + + // C + A = 12.01 ; + Z = 6.0 ; + density = 2.00 ; // g/cm^3 + radlen = 21.3485 ; // cm + name = "carbon" ; + + TMaterial &carbon = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.) ; + this->addMaterial(&carbon, name); + + // Aluminium + A = 26.9815 ; + Z = 13.0 ; + density = 2.699 ; // g/cm^3 + radlen = 8.9 ; // cm + name = "aluminium" ; + + TMaterial &aluminium = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.) ; + this->addMaterial(&aluminium, name); + + // Beryllium + A = 9.012 ; + Z = 4.0 ; + density = 1.85 ; // g/cm^3 + radlen = 35.28 ; // cm + name = "beryllium" ; + + TMaterial &beryllium = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.) ; + this->addMaterial(&beryllium, name); + + + // TPC Gas + A = 39.948*0.9+(12.011*0.2+1.00794*0.8)*0.1; + Z = 16.4; + density = 1.749e-3 ; +// radlen = 1.196e4*2; + radlen = 0.5*1.196e4*2; // SJA:FIXME: reduce by a factor of 10% + name = "tpcgas" ; + + TMaterial &tpcgas = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.); + this->addMaterial(&tpcgas, name); + + // TPC Field Cage + A = air.GetA()*0.97 + aluminium.GetA()*0.03 ; // SJA:FIXME just use this simple approximation for now + Z = air.GetZ()*0.97 + aluminium.GetZ()*0.03 ; // SJA:FIXME just use this simple approximation for now + density = 0.0738148 ; + radlen = 489.736 * 0.5 ; // SJA:FIXME just use factor of two for now as the amount differs by ~ factor of 2 from observation in GEANT4 + name = "tpcinnerfieldcage" ; + + TMaterial &tpcinnerfieldcage = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.); + this->addMaterial(&tpcinnerfieldcage, name); + + // TPC Field Cage + A = air.GetA()*0.97 + aluminium.GetA()*0.03 ; // SJA:FIXME just use this simple approximation for now + Z = air.GetZ()*0.97 + aluminium.GetZ()*0.03 ; // SJA:FIXME just use this simple approximation for now + density = 0.0738148 ; + radlen = 489.736 ; + name = "tpcouterfieldcage" ; + + TMaterial &tpcouterfieldcage = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.); + this->addMaterial(&tpcouterfieldcage, name); + + + // FTD Support Material + // Needed because of the lack of space frame in the Tracking Geometry description + // Carbon with density and rad-length changed by a factor of 2 + + A = 12.01 ; + Z = 6.0 ; + density = 0.5 * 2.00 ; // g/cm^3 + radlen = 2.0 * 21.3485 ; // cm + name = "FTDSupportMaterial" ; + + TMaterial &ftdsupport = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.) ; + this->addMaterial(&ftdsupport, name); + + + // VXD Support Material + + try{ + + //const gear::SimpleMaterial& vxd_sup_mat = gearMgr.getSimpleMaterial("VXDSupportMaterial"); + /* + const gear::GearParametersImpl* vxd_sup_mat = geoSvc->getDetParameters("VXDSupportMaterial"); + + A = vxd_sup_mat->getDoubleVal("A"); + Z = vxd_sup_mat->getDoubleVal("Z"); + density = vxd_sup_mat->getDoubleVal("Density"); + radlen = vxd_sup_mat->getDoubleVal("RadL"); + name = vxd_sup_mat->getStringVal("Name"); + */ + //A = vxd_sup_mat.getA(); + //Z = vxd_sup_mat.getZ(); + //density = vxd_sup_mat.getDensity() * (1000.0/ 1000000.0); // kg/m^3 -> g/cm^3 + //radlen = vxd_sup_mat.getRadLength() / 10.0 ; // mm -> cm + //name = vxd_sup_mat.getName() ; + //std::cout << "debug fucd: " << "==================" << geoSvc << std::endl; + //TMaterial &vxdsupport = *new TMaterial(name.c_str(), "", A, Z, density, radlen, 0.); + //this->addMaterial(&vxdsupport, name); + TMaterial* vxdsupport = geoSvc->getMaterial("VXDSupportMaterial"); + //std::cout << "debug fucd: " << "==================" << std::endl; + if(vxdsupport) this->addMaterial(vxdsupport, "VXDSupportMaterial"); + else std::cout << "Material VXDSupportMaterial not found" << std::endl; + } + catch( gear::UnknownParameterException& e){ + std::cout << "Error while read material from GeoSvc!" << std::endl; + } + + +} + diff --git a/Utilities/KalDet/src/ild/common/MaterialDataBase.h b/Utilities/KalDet/src/ild/common/MaterialDataBase.h new file mode 100644 index 0000000000000000000000000000000000000000..d1ed28bf0af03621cfc6dc9a1d7935b6a3833131 --- /dev/null +++ b/Utilities/KalDet/src/ild/common/MaterialDataBase.h @@ -0,0 +1,76 @@ +#ifndef MaterialDataBase_h +#define MaterialDataBase_h + +/** MaterialDataBase: Class to hold and manage collection of materials + * + * @author S.Aplin DESY + */ + +#include <string> +#include <map> +#include <exception> + +#include "lcio.h" +#include "Exceptions.h" + +class TMaterial; + +namespace gear{ + class GearMgr ; +} +class IGeoSvc; +// fg: define the MaterialDataBaseException as an lcio Exception to allow for +// messages to be printed in what() +typedef lcio::Exception MaterialDataBaseException ; + +class MaterialDataBase { + +public: + + /** Accessor Method */ + static MaterialDataBase& Instance() { + + static MaterialDataBase singleton; + + return singleton; + + } + + // Other non-static member functions + +public: + + /** Destructor */ + ~MaterialDataBase(); + + /** Get Material via name */ + TMaterial* getMaterial(std::string mat_name) ; + + void registerForService(const gear::GearMgr& gearMgr, IGeoSvc* geoSvc=0) ; + + +private: + + void initialise(const gear::GearMgr& gearMgr, IGeoSvc* geoSvc) ; + + MaterialDataBase() { _material_map.clear(); _isInitialised = false ; _gearMgr = 0; } // Private constructor + + + MaterialDataBase(const MaterialDataBase&) ; // Prevent copy-construction + MaterialDataBase& operator=(const MaterialDataBase&) ; // Prevent assignment + + void addMaterial(TMaterial* mat, std::string name); + void createMaterials(const gear::GearMgr& gearMgr, IGeoSvc* geoSvc); + + // private member variables + std::map<std::string,TMaterial* > _material_map; + + bool _isInitialised; + + const gear::GearMgr* _gearMgr; + +}; + + + +#endif diff --git a/Utilities/KalDet/src/ild/ftd/ILDFTDDiscBasedKalDetector.cc b/Utilities/KalDet/src/ild/ftd/ILDFTDDiscBasedKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..db2b578d211ff0dc8f80f5a0aa5198eb43be0907 --- /dev/null +++ b/Utilities/KalDet/src/ild/ftd/ILDFTDDiscBasedKalDetector.cc @@ -0,0 +1,174 @@ + +#include "ILDFTDDiscBasedKalDetector.h" + +#include "kaldet/MaterialDataBase.h" + +#include <sstream> + +#include "gear/GEAR.h" +#include "gear/BField.h" +#include "gearimpl/Util.h" +#include "gear/FTDLayerLayout.h" + +#include "kaldet/ILDDiscMeasLayer.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +// #include "streamlog/streamlog.h" + +#include "TVector3.h" + +ILDFTDDiscBasedKalDetector::ILDFTDDiscBasedKalDetector( const gear::GearMgr& gearMgr ) : +TVKalDetector(30), _nDisks(0) // SJA:FIXME initial size, 300 looks reasonable for ILD, though this would be better stored as a const somewhere +{ + + // streamlog_out(DEBUG1) << "ILDFTDDiscBasedKalDetector building Simple Disc Based FTD detector using GEAR " << std::endl ; + + MaterialDataBase::Instance().registerForService(gearMgr); + setupGearGeom( gearMgr ) ; + + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air") ; + TMaterial & silicon = *MaterialDataBase::Instance().getMaterial("silicon") ; + TMaterial & carbon = *MaterialDataBase::Instance().getMaterial("carbon") ; + + + Bool_t active = true ; + Bool_t dummy = false ; + + std::string name = "FTD" ; + + double eps1 = 1.0e-04 ; // disk + double eps3 = 1.0e-06 ; // layer in disk + double eps4 = 1.0e-08 ; // forward or backwards + + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + for (int idisk = 0; idisk < _nDisks; ++idisk) { + + + double rOuter = _FTDgeo[idisk].rOuter ; + double rInner = _FTDgeo[idisk].rInner ; + double senThickness = _FTDgeo[idisk].senThickness ; + double supThickness = _FTDgeo[idisk].supThickness ; + double zPos = _FTDgeo[idisk].zPos; + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::FTD ; + encoder[lcio::ILDCellID0::side] = 1 ; + encoder[lcio::ILDCellID0::layer] = idisk ; + encoder[lcio::ILDCellID0::module] = 0 ; + encoder[lcio::ILDCellID0::sensor] = 0 ; + + int CellID_FWD = encoder.lowWord() ; + + encoder[lcio::ILDCellID0::side] = -1 ; + + int CellID_BWD = encoder.lowWord() ; + + // note the z position given in gear is actually the mid point (z) of the sensitive i.e. the z of the measurement plane + TVector3 sen_front_face_centre_fwd( 0.0, 0.0, zPos - senThickness*0.5); // for +z + + TVector3 measurement_plane_centre_fwd( sen_front_face_centre_fwd.X(), + sen_front_face_centre_fwd.Y(), + sen_front_face_centre_fwd.Z() + senThickness*0.5 ); + + TVector3 sen_rear_face_centre_fwd( sen_front_face_centre_fwd.X(), + sen_front_face_centre_fwd.Y(), + sen_front_face_centre_fwd.Z() + senThickness ); + + TVector3 sup_rear_face_centre_fwd( sen_rear_face_centre_fwd.X(), + sen_rear_face_centre_fwd.Y(), + sen_rear_face_centre_fwd.Z() + supThickness ); + + TVector3 normal_fwd(sen_front_face_centre_fwd) ; + normal_fwd.SetMag(1.0) ; + + + double sort_policy = rOuter + eps1 * idisk ; + + + sort_policy += eps3 * 1; + Add(new ILDDiscMeasLayer( air, silicon, sen_front_face_centre_fwd, normal_fwd, _bZ, sort_policy, rInner, rOuter, dummy ) ); + + sort_policy += eps3 * 2; + Add(new ILDDiscMeasLayer( silicon, silicon, measurement_plane_centre_fwd, normal_fwd, _bZ, sort_policy, rInner, rOuter, active, CellID_FWD ) ); + + sort_policy += eps3 * 3; + Add(new ILDDiscMeasLayer( silicon, carbon, sen_rear_face_centre_fwd, normal_fwd, _bZ, sort_policy, rInner, rOuter, dummy ) ); + + sort_policy += eps3 * 4; + Add(new ILDDiscMeasLayer( carbon, air, sup_rear_face_centre_fwd, normal_fwd, _bZ, sort_policy, rInner, rOuter, dummy ) ); + + + // note the z position given in gear is actually the mid point (z) of the sensitive i.e. the z of the measurement plane + TVector3 sen_front_face_centre_bwd( 0.0, 0.0, -zPos + senThickness*0.5 ); // for -z + + TVector3 measurement_plane_centre_bwd( sen_front_face_centre_bwd.X(), + sen_front_face_centre_bwd.Y(), + sen_front_face_centre_bwd.Z() - senThickness*0.5 ); + + TVector3 sen_rear_face_centre_bwd( sen_front_face_centre_bwd.X(), + sen_front_face_centre_bwd.Y(), + sen_front_face_centre_bwd.Z() - senThickness ); + + TVector3 sup_rear_face_centre_bwd( sen_rear_face_centre_bwd.X(), + sen_rear_face_centre_bwd.Y(), + sen_rear_face_centre_bwd.Z() - supThickness ); + + TVector3 normal_bwd(sen_front_face_centre_bwd) ; + normal_bwd.SetMag(1.0) ; + + + sort_policy += eps4 ; // for backward + + sort_policy += eps3 * 1; + Add(new ILDDiscMeasLayer( air, silicon, sen_front_face_centre_bwd, normal_bwd, _bZ, sort_policy, rInner, rOuter, dummy ) ); + + sort_policy += eps3 * 2; + Add(new ILDDiscMeasLayer( silicon, silicon, measurement_plane_centre_bwd, normal_bwd, _bZ, sort_policy, rInner, rOuter, active, CellID_BWD ) ); + + sort_policy += eps3 * 3; + Add(new ILDDiscMeasLayer( silicon, carbon, sen_rear_face_centre_bwd, normal_bwd, _bZ, sort_policy, rInner, rOuter, dummy ) ); + + sort_policy += eps3 * 4; + Add(new ILDDiscMeasLayer( carbon, air, sup_rear_face_centre_bwd, normal_bwd, _bZ, sort_policy, rInner, rOuter, dummy ) ); + + + } + + SetOwner(); + +} + + + +void ILDFTDDiscBasedKalDetector::setupGearGeom( const gear::GearMgr& gearMgr ){ + + + const gear::GearParameters& pFTD = gearMgr.getGearParameters("FTD"); + + _bZ = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + const std::vector<double>& FTD_si = pFTD.getDoubleVals("FTDDiskSiThickness" ) ; + const std::vector<double>& FTD_sp = pFTD.getDoubleVals("FTDDiskSupportThickness" ) ; + const std::vector<double>& FTD_ri = pFTD.getDoubleVals("FTDInnerRadius" ) ; + const std::vector<double>& FTD_ro = pFTD.getDoubleVals("FTDOuterRadius" ) ; + const std::vector<double>& FTD_z = pFTD.getDoubleVals("FTDZCoordinate" ) ; + + _nDisks = FTD_si.size() ; + _FTDgeo.resize(_nDisks); + + for(int disk=0; disk< _nDisks; ++disk){ + + _FTDgeo[disk].rInner = FTD_ri[disk]; + _FTDgeo[disk].rOuter = FTD_ro[disk]; + _FTDgeo[disk].senThickness = FTD_si[disk]; + _FTDgeo[disk].supThickness = FTD_sp[disk]; + _FTDgeo[disk].zPos = FTD_z[disk]; + + + } + + +} diff --git a/Utilities/KalDet/src/ild/ftd/ILDFTDDiscBasedKalDetector.h b/Utilities/KalDet/src/ild/ftd/ILDFTDDiscBasedKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..c8536c6403b54d650ac0418ab2e845ec5f21053b --- /dev/null +++ b/Utilities/KalDet/src/ild/ftd/ILDFTDDiscBasedKalDetector.h @@ -0,0 +1,44 @@ +#ifndef __ILDFTDDISCBASEDDETECTOR__ +#define __ILDFTDDISCBASEDDETECTOR__ + +/** Disk based version of the FTD alla LOI +* +* @author S.Aplin DESY +*/ + +#include "kaltest/TVKalDetector.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDFTDDiscBasedKalDetector : public TVKalDetector { +public: + + /** Initialize the FTD from GEAR */ + ILDFTDDiscBasedKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + int _nDisks ; + double _bZ ; + + struct FTD_Disk { + double rInner; + double rOuter; + double senThickness; + double supThickness; + double zPos; + + }; + std::vector<FTD_Disk> _FTDgeo; + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/ftd/ILDFTDKalDetector.cc b/Utilities/KalDet/src/ild/ftd/ILDFTDKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..3ac020812669ae175d17c9f9df6c983ce506790e --- /dev/null +++ b/Utilities/KalDet/src/ild/ftd/ILDFTDKalDetector.cc @@ -0,0 +1,501 @@ + +#include "ILDFTDKalDetector.h" + +#include "kaldet/MaterialDataBase.h" + +#include <sstream> + +#include "gear/GEAR.h" +#include "gear/BField.h" +#include "gearimpl/Util.h" +#include "gear/FTDLayerLayout.h" + +#include "kaldet/ILDRotatedTrapMeaslayer.h" +#include "kaldet/ILDSegmentedDiscMeasLayer.h" +#include "kaldet/ILDSegmentedDiscStripMeasLayer.h" +#include "kaldet/ILDDiscMeasLayer.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +// #include "streamlog/streamlog.h" + +#include "TVector3.h" + +ILDFTDKalDetector::ILDFTDKalDetector( const gear::GearMgr& gearMgr ) : +TVKalDetector(300), _nDisks(0) // SJA:FIXME initial size, 300 looks reasonable for ILD, though this would be better stored as a const somewhere +{ + + // streamlog_out(DEBUG1) << "ILDFTDKalDetector building FTD detector using GEAR " << std::endl ; + + MaterialDataBase::Instance().registerForService(gearMgr); + setupGearGeom( gearMgr ) ; + + this->build_staggered_design(); + + + SetOwner(); + +} + + + + +void ILDFTDKalDetector::build_staggered_design() { + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::build_staggered_design " << std::endl; + + + std::string name = "FTD" ; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + + + for (int idisk = 0; idisk < _nDisks; ++idisk) { + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::build_staggered_design build disk " << idisk << std::endl; + + int npetals = _FTDgeo[idisk].nPetals ; + double phi0 = _FTDgeo[idisk].phi0 ; + + double senZPos_even_front = _FTDgeo[idisk].senZPos_even_front; + double senZPos_odd_front = _FTDgeo[idisk].senZPos_odd_front; + + + // check that the number of petals is divisible by 2 + int nsegments = npetals/2; + + // even segments forward + this->create_segmented_disk_layers(idisk, nsegments, true, phi0, senZPos_even_front ); + + // even segments backwards + this->create_segmented_disk_layers(idisk, nsegments, true, phi0, -senZPos_even_front ); + + + // odd segements + // update phi0 by the angular distance of one petal + phi0 += 2.0 * M_PI / npetals; + + // odd segments forward + this->create_segmented_disk_layers(idisk, nsegments, false, phi0, senZPos_odd_front ); + + // odd segments backward + this->create_segmented_disk_layers(idisk, nsegments, false, phi0, -senZPos_odd_front ); + + + + + // make the air disks + + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air") ; + + Bool_t dummy = false ; + + // place air discs to help transport during track extrapolation + if( idisk < _nDisks-1 ){ + + // place the disc half way between the two discs + double z = ( _FTDgeo[idisk].senZPos_even_front + _FTDgeo[idisk+1].senZPos_even_front ) * 0.5 ; + + TVector3 xc_fwd(0.0, 0.0, z) ; + TVector3 normal_fwd(xc_fwd) ; + normal_fwd.SetMag(1.0) ; + + double eps1 = 1.0e-04 ; // offset for disk number + double eps2 = 1.0e-05 ; // odd or even + double eps4 = 1.0e-08 ; // offset for forwards and backwards + + double height = _FTDgeo[idisk].height ; + double rInner = _FTDgeo[idisk].rInner ; + + + double sort_policy = rInner+height + eps1 * idisk + eps2 * 2 ; // we need to be after the even and odd + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create air support disk at " << xc_fwd.z() << " sort_policy = " << sort_policy << std::endl; + + Add(new ILDDiscMeasLayer( air, air, xc_fwd, normal_fwd, _bZ, sort_policy, + rInner, rInner+height, dummy,-1, "FTDAirSupportDiscFront" ) ); + + TVector3 xc_bwd(0.0, 0.0, -z) ; + TVector3 normal_bwd(xc_bwd) ; + normal_bwd.SetMag(1.0) ; + + // offset needed for rear disks + sort_policy += eps4 ; + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create air support disk at " << xc_bwd.z() << " sort_policy = " << sort_policy << std::endl; + Add(new ILDDiscMeasLayer( air, air, xc_bwd, normal_bwd, _bZ, sort_policy, + rInner, rInner+height, dummy,-1, "FTDAirSupportDiscRear" ) ); + + + + } + + } + +} + + + + + + +void ILDFTDKalDetector::create_segmented_disk_layers( int idisk, int nsegments, bool even_petals, double phi0, double zpos ){ + + Bool_t active = true ; + Bool_t dummy = false ; + + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air") ; + TMaterial & silicon = *MaterialDataBase::Instance().getMaterial("silicon") ; + TMaterial & carbon = *MaterialDataBase::Instance().getMaterial("carbon") ; + TMaterial & stripsupport = *MaterialDataBase::Instance().getMaterial("FTDSupportMaterial") ; + + double senThickness = _FTDgeo[idisk].senThickness ; + double supThickness = _FTDgeo[idisk].supThickness ; + double innerBaseLength = _FTDgeo[idisk].innerBaseLength ; + double outerBaseLength = _FTDgeo[idisk].outerBaseLength ; + double height = _FTDgeo[idisk].height ; + double rInner = _FTDgeo[idisk].rInner ; + bool isDoubleSided = _FTDgeo[idisk].isDoubleSided ; + int nSensors = _FTDgeo[idisk].nSensors ; + int zsign = zpos > 0 ? +1 : -1 ; + double stripAngle = _FTDgeo[idisk].stripAngle ; + bool isStripReadout = _FTDgeo[idisk].isStripReadout ; + + //SJA:FIXME: due to the space frame design of the strip layers there is far too much support so just leave it out for now ... + TMaterial & support = isStripReadout == false ? carbon : stripsupport; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::FTD ; + encoder[lcio::ILDCellID0::side] = zsign ; + encoder[lcio::ILDCellID0::layer] = idisk ; + + int start_index = even_petals ? 0 : 1 ; + std::vector<int> sensors_front; + std::vector<int> sensors_back; + std::vector<int> module_ids_front; + std::vector<int> module_ids_back; + + if( isDoubleSided ){ // sensors on front and back double supZPos_odd_front = _FTDgeo[idisk].supZPos_odd; + + // first half is on the front, second half on the back, sensors start with sensor number 1 + for( int iSensor=1; iSensor <= nSensors/2; iSensor++ ) sensors_front.push_back( iSensor ); + for( int iSensor=nSensors/2 + 1; iSensor <= nSensors; iSensor++ ) sensors_back.push_back( iSensor ); + + } + else{ // only sensors on the front + + for( int iSensor=1; iSensor <= nSensors; iSensor++ ) sensors_front.push_back( iSensor ); + + } + + for (int i=0; i<nsegments; ++i) { + + encoder[lcio::ILDCellID0::module] = start_index + i*2 ; + + for( unsigned j=0; j<sensors_front.size(); j++ ){ + + encoder[lcio::ILDCellID0::sensor] = sensors_front[j]; + module_ids_front.push_back( encoder.lowWord() ); + + } + + for( unsigned j=0; j<sensors_back.size(); j++ ){ + + encoder[lcio::ILDCellID0::sensor] = sensors_back[j]; + module_ids_back.push_back( encoder.lowWord() ); + + } + + } + + // create segmented disk + + // front face of sensitive + double z = zpos - zsign*0.5*(senThickness) ; + // double sort_policy = fabs(z) ; + double eps1 = 1.0e-04 ; // disk + double eps2 = 1.0e-05 ; // odd or even + double eps3 = 1.0e-06 ; // layer in disk + double eps4 = 1.0e-08 ; // forward or backwards + + double sort_policy = rInner+height + eps1 * idisk + eps3 * 1 ; + if ( ! even_petals ) sort_policy += eps2; + + // if this is the negative z disk add epsilon to the policy + if( z < 0 ) sort_policy += eps4 ; + const char *name1 = z > 0 ? "FTDSenFrontPositiveZ" : "FTDSenFrontNegativeZ"; + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add front face of sensitive at " << z << " sort_policy = " << sort_policy << std::endl; + Add( new ILDSegmentedDiscMeasLayer(air, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, dummy,name1) ); + + // measurement plane + + z += zsign*0.5*senThickness; + //sort_policy = fabs(z) ; + sort_policy = rInner+height + eps1 * idisk + eps3 * 2 ; + if( z < 0 ) sort_policy += eps4 ; + + if ( ! even_petals ) { + sort_policy += eps2; + + const char *name2 = z > 0 ? "FTDMeasLayerFrontPositiveZOdd" : "FTDMeasLayerFrontNegativeZOdd"; + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add measurement plane at " << z << " sort_policy = " << sort_policy << " Strip Readout = " << isStripReadout << " number of module_ids = " << module_ids_front.size(); + if (isStripReadout) { + Add( new ILDSegmentedDiscStripMeasLayer(silicon, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, stripAngle, active, module_ids_front,name2)); + // streamlog_out(DEBUG) << " stripAngle = " << stripAngle ; + + } else { + Add( new ILDSegmentedDiscMeasLayer(silicon, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, active, module_ids_front,name2)); + } + // streamlog_out(DEBUG) << std::endl; + } + else{ + const char *name2 = z > 0 ? "FTDMeasLayerFrontPositiveZEven" : "FTDMeasLayerFrontNegativeZEven"; + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add measurement plane at " << z << " sort_policy = " << sort_policy << " Strip Readout = " << isStripReadout << " number of module_ids = " << module_ids_front.size(); + if (isStripReadout) { + Add( new ILDSegmentedDiscStripMeasLayer(silicon, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, stripAngle, active, module_ids_front,name2)); + // streamlog_out(DEBUG) << " stripAngle = " << stripAngle ; + } else { + Add( new ILDSegmentedDiscMeasLayer(silicon, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, active, module_ids_front,name2)); + } + // streamlog_out(DEBUG) << std::endl; + } + + // interface between sensitive and support + z += zsign*0.5*senThickness; + // sort_policy = fabs(z) ; + sort_policy = rInner+height + eps1 * idisk + eps3 * 3 ; + if( z < 0 ) sort_policy += eps4 ; + if ( ! even_petals ) sort_policy += eps2; + + const char *name3 = z > 0 ? "FTDSenSupportIntfPositiveZ" : "FTDSenSupportIntfNegativeZ"; + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add interface between sensitive and support at " << z << " sort_policy = " << sort_policy << std::endl; + Add( new ILDSegmentedDiscMeasLayer(silicon, support, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, dummy,name3)); + + if( isDoubleSided ){ + + // interface between support and sensitive + z += zsign*supThickness; + // sort_policy = fabs(z) ; + sort_policy = rInner+height + eps1 * idisk + eps3 * 4 ; + if( z < 0 ) sort_policy += eps4 ; + if ( ! even_petals ) sort_policy += eps2; + + const char *name4 = z > 0 ? "FTDSupportSenIntfPositiveZ" : "FTDSupportSenIntfNegativeZ"; + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add interface between support and sensitive at " << z << " sort_policy = " << sort_policy << std::endl; + Add( new ILDSegmentedDiscMeasLayer(support, silicon , _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, dummy,name4)); + + + // measurement plane at the back + z += zsign*0.5*senThickness; + // sort_policy = fabs(z) ; + sort_policy = rInner+height + eps1 * idisk + eps3 * 5 ; + if( z < 0 ) sort_policy += eps4 ; + if ( ! even_petals ){ + + sort_policy += eps2; + + const char *name5 = z > 0 ? "FTDMeasLayerBackPositiveZOdd" : "FTDMeasLayerBackNegativeZOdd"; + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add measurement plane at " << z << " sort_policy = " << sort_policy << " Strip Readout = " << isStripReadout << " number of module_ids = " << module_ids_back.size() ; + if (isStripReadout) { + Add( new ILDSegmentedDiscStripMeasLayer(silicon, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, -stripAngle,active, module_ids_back,name5)); + // streamlog_out(DEBUG) << " stripAngle = " << -stripAngle ; + + } else { + Add( new ILDSegmentedDiscMeasLayer(silicon, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, active, module_ids_back,name5)); + } + // streamlog_out(DEBUG) << std::endl; + + } + else{ + const char *name5 = z > 0 ? "FTDMeasLayerBackPositiveZEven" : "FTDMeasLayerBackNegativeZEven"; + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add measurement plane at " << z << " sort_policy = " << sort_policy<< " Strip Readout = " << isStripReadout << " number of module_ids = " << module_ids_back.size(); + if (isStripReadout) { + Add( new ILDSegmentedDiscStripMeasLayer(silicon, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, -stripAngle,active, module_ids_back,name5)); + // streamlog_out(DEBUG) << " stripAngle = " << -stripAngle ; + } else { + Add( new ILDSegmentedDiscMeasLayer(silicon, silicon, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, active, module_ids_back,name5)); + } + // streamlog_out(DEBUG) << std::endl; + } + + // rear face of sensitive + z += zsign*0.5*senThickness; + // sort_policy = fabs(z) ; + sort_policy = rInner+height + eps1 * idisk + eps3 * 6 ; + if( z < 0 ) sort_policy += eps4 ; + if ( ! even_petals ) sort_policy += eps2; + + const char *name6 = z > 0 ? "FTDSenRearPositiveZ" : "FTDSenRearNegativeZ"; + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add rear face of sensitive at " << z << " sort_policy = " << sort_policy << std::endl; + Add( new ILDSegmentedDiscMeasLayer(silicon, air, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, dummy,name6)); + + + + } + else{ + + // rear face of support + z += zsign*supThickness; + // sort_policy = fabs(z) ; + sort_policy = rInner+height + eps1 * idisk + eps3 * 4 ; + if( z < 0 ) sort_policy += eps4 ; + if ( ! even_petals ) sort_policy += eps2; + + const char *name4 = z > 0 ? "FTDSupRearPositiveZ" : "FTDSupRearNegativeZ"; + + // streamlog_out(DEBUG) << "ILDFTDKalDetector::create_segmented_disk_layers add rear face of support at " << z << " sort_policy = " << sort_policy << std::endl; + Add( new ILDSegmentedDiscMeasLayer(support, air, _bZ, sort_policy, nsegments, z, phi0, rInner, height, innerBaseLength, outerBaseLength, dummy,name4)); + + } + +} + + + +void ILDFTDKalDetector::setupGearGeom( const gear::GearMgr& gearMgr ){ + + const gear::FTDParameters& ftdParams = gearMgr.getFTDParameters() ; + const gear::FTDLayerLayout& ftdlayers = ftdParams.getFTDLayerLayout() ; + + _bZ = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + double strip_angle_deg = 0.0; + bool strip_angle_present = true; + + try { + + strip_angle_deg = ftdParams.getDoubleVal("strip_angle_deg"); + + } catch (gear::UnknownParameterException& e) { + + strip_angle_present = false; + + } + + + _nDisks = ftdlayers.getNLayers() ; // just do the first disk for now + _FTDgeo.resize(_nDisks); + + //SJA:FIXME: for now the support is taken as the same size the sensitive + // if this is not done then the exposed areas of the support would leave a carbon - air boundary, + // which if traversed in the reverse direction to the next boundary then the track be propagated through carbon + // for a significant distance + + double eps = 1.0e-08; + + for(int disk=0; disk< _nDisks; ++disk){ + + // numbers taken from the ILD_01 gear file for the sensitive part + _FTDgeo[disk].nPetals = ftdlayers.getNPetals(disk) ; + _FTDgeo[disk].dphi = 2*M_PI / _FTDgeo[disk].nPetals ; + _FTDgeo[disk].phi0 = ftdlayers.getPhi0(disk) ; + _FTDgeo[disk].alpha = ftdlayers.getAlpha(disk) ; + _FTDgeo[disk].rInner = ftdlayers.getSensitiveRinner(disk) ; + _FTDgeo[disk].height = ftdlayers.getSensitiveWidth(disk) ; + _FTDgeo[disk].innerBaseLength = ftdlayers.getSensitiveLengthMin(disk) ; + _FTDgeo[disk].outerBaseLength = ftdlayers.getSensitiveLengthMax(disk) ; + _FTDgeo[disk].senThickness = ftdlayers.getSensitiveThickness(disk) ; + _FTDgeo[disk].supThickness = ftdlayers.getSupportThickness(disk) ; + + _FTDgeo[disk].senZPos_even_front = ftdlayers.getSensitiveZposition(disk, 0, 1) ; + _FTDgeo[disk].senZPos_odd_front = ftdlayers.getSensitiveZposition(disk, 1, 1) ; + + _FTDgeo[disk].isDoubleSided = ftdlayers.isDoubleSided( disk ); + _FTDgeo[disk].isStripReadout = ftdlayers.getSensorType(disk) == gear::FTDParameters::STRIP ? true : false; + _FTDgeo[disk].nSensors = ftdlayers.getNSensors( disk ); + + + if (strip_angle_present) { + _FTDgeo[disk].stripAngle = strip_angle_deg * M_PI/180 ; + } else { + _FTDgeo[disk].stripAngle = 0.0 ; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + // Assertions //////////////////////////////////////////////////////////////////////////////////// + + // there should be an even number of petals per disk + assert( _FTDgeo[disk].nPetals%2 == 0 ); + + // support and sensitive should have the same size an position in xy + assert( fabs( ftdlayers.getSupportLengthMin(disk) - ftdlayers.getSensitiveLengthMin(disk) ) < eps ); + assert( fabs( ftdlayers.getSupportLengthMax(disk) - ftdlayers.getSensitiveLengthMax(disk) ) < eps ); + assert( fabs( ftdlayers.getSupportWidth(disk) - ftdlayers.getSensitiveWidth(disk) ) < eps ); + assert( fabs( ftdlayers.getSupportRinner(disk) - ftdlayers.getSensitiveRinner(disk) ) < eps ); + + // double sided petals should have as many sensors on the front as on the back + if( _FTDgeo[disk].isDoubleSided ) assert( _FTDgeo[disk].nSensors%2 == 0 ); + + + // petals should not be rotated around their symmetry axis + assert( fabs( ftdlayers.getAlpha( disk ) ) < eps ); + + + // the z positions of the sensors should be all the same on one side of the petal + // and in case of double sided petals, the second half of the sensors should be behind the first half + + if( _FTDgeo[disk].isDoubleSided ){ // double sided: first half of sensors should have one z value, and second half as well + + for( int iPetal=0; iPetal< _FTDgeo[disk].nPetals; iPetal++){ + + int sensors1Side = _FTDgeo[disk].nSensors/2; + + //check first half + for( int iSensor=2; iSensor <= sensors1Side; iSensor++ ){ + + assert( fabs( ftdlayers.getSensitiveZposition( disk, iPetal, iSensor) - ftdlayers.getSensitiveZposition( disk, iPetal, iSensor-1) ) < eps ); + + } + + // check second half + for( int iSensor=sensors1Side + 2; iSensor <= _FTDgeo[disk].nSensors; iSensor++ ){ + + assert( fabs( ftdlayers.getSensitiveZposition( disk, iPetal, iSensor) - ftdlayers.getSensitiveZposition( disk, iPetal, iSensor-1) ) < eps ); + + // also check if the sensors on the back are farther away from the origin: + assert( fabs( ftdlayers.getSensitiveZposition( disk, iPetal, iSensor) ) - fabs( ftdlayers.getSensitiveZposition( disk, iPetal, iSensor-sensors1Side ) ) >= 0. ); + } + } + } + else{ // single sided: all sensors should have the same z + + for( int iPetal=0; iPetal< _FTDgeo[disk].nPetals; iPetal++){ + + for(int iSensor=2; iSensor <= _FTDgeo[disk].nSensors; iSensor++ ){ + + assert( fabs( ftdlayers.getSensitiveZposition( disk, iPetal, iSensor) - ftdlayers.getSensitiveZposition( disk, iPetal, iSensor-1) ) < eps ); + + } + } + } + + // there should be no gap between support and sensitive + + for( int iPetal=0; iPetal< _FTDgeo[disk].nPetals; iPetal++){ + + + int side = ftdlayers.getSupportZposition( disk, iPetal ) > 0? 1 : -1; + + double endSensitive = ftdlayers.getSensitiveZposition( disk, iPetal, 1) + side * _FTDgeo[disk].senThickness/2.; + double endSupport = ftdlayers.getSupportZposition( disk, iPetal ) -side * _FTDgeo[disk].supThickness/2.; + + assert( fabs( endSensitive- endSupport ) < eps ); + + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + } + + +} diff --git a/Utilities/KalDet/src/ild/ftd/ILDFTDKalDetector.h b/Utilities/KalDet/src/ild/ftd/ILDFTDKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..36cf54b8e5a889a09431635740c3e2c3035d6d6a --- /dev/null +++ b/Utilities/KalDet/src/ild/ftd/ILDFTDKalDetector.h @@ -0,0 +1,92 @@ +#ifndef __ILDFTDDETECTOR__ +#define __ILDFTDDETECTOR__ + +/** Petal based FTD to be used for ILD DBD studies + * WARNING: Still very experimental + * + * @author S.Aplin DESY, Robin Glattauer HEPHY + */ + +#include "kaltest/TVKalDetector.h" + +class TNode; +class TVector3; + +namespace gear{ + class GearMgr ; +} + + +class ILDFTDKalDetector : public TVKalDetector { +public: + + /** Initialize the FTD from GEAR */ + ILDFTDKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + struct FTD_Petal { + + int ipetal; + double phi; + double alpha; + double rInner; + double height; + double innerBaseLength; + double outerBaseLength; + double senThickness; + double supThickness; + double senZPos; + bool faces_ip; + + }; + + + struct FTD_Disk { + int nPetals; + double phi0; + double dphi; + + double alpha; + double rInner; + double height; + double innerBaseLength; + double outerBaseLength; + double senThickness; + double supThickness; + + double stripAngle; + + double senZPos_even_front; + double senZPos_odd_front; + + bool isDoubleSided; + bool isStripReadout; + + int nSensors; + + + }; + + + void build_staggered_design(); + + //void create_petal(TVector3 measurement_plane_centre, FTD_Petal petal, int CellID); + /** + * @param zpos the z position of the front measurement surface (middle of front sensitive) + */ + void create_segmented_disk_layers(int idisk, int nsegments, bool even_petals, double phi0, double zpos ); + + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + int _nDisks ; + double _bZ ; + + + std::vector<FTD_Disk> _FTDgeo; + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/lctpc/LCTPCKalDetector.cc b/Utilities/KalDet/src/ild/lctpc/LCTPCKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..18fa3a853a7d1238f89b9e275527e30d5241657d --- /dev/null +++ b/Utilities/KalDet/src/ild/lctpc/LCTPCKalDetector.cc @@ -0,0 +1,226 @@ +// STL +#include <vector> + +// GEAR +#include <gear/GEAR.h> +#include <gear/TPCParameters.h> +#include <gear/PadRowLayout2D.h> +#include <gear/BField.h> +#include <gearimpl/TPCModuleImpl.h> +#include <gearxml/GearXML.h> + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +// #include <streamlog/streamlog.h> + +#include "kaldet/LCTPCKalDetector.h" +#include "kaldet/ILDCylinderMeasLayer.h" + +namespace kaldet +{ + +LCTPCKalDetector::LCTPCKalDetector(const gear::GearMgr& gearMgr) + : TVKalDetector(210) +{ + gear::TPCParameters const & tpcParameters = gearMgr.getTPCParameters(); + + // Try to read the material properties from the GEAR file. + // If it cannot be found use an Argon based mixture instead. + Double_t A, Z, density, radlen; + + try{ + // One try/catch block for all. + // It does not make sense to only replace part of the parameters, + // they all have to be there. + A = tpcParameters.getDoubleVal("TPCGas_A"); + Z = tpcParameters.getDoubleVal("TPCGas_Z"); + density = tpcParameters.getDoubleVal("TPCGas_density"); + radlen = tpcParameters.getDoubleVal("TPCGas_radlen"); + } + catch( gear::UnknownParameterException & ) + { + // streamlog_out(MESSAGE) << "LCTPCKalDetector: No TPCGas parameters found in the gear file." + // << " Using Ar/CH4 90/10." << std::endl; + + // Is this supposed to be Ar/CH4 90/10? + // I think it's wrong. A CH4 module does not consist of 0.2 carbon + // and 0.8 hydrogen atoms, but 1 C and 4 H, so it should be + // A = 39.948 * 0.9 + (12.011 + 1.00794 * 4) * 0.1; + A = 39.948 * 0.9 + (12.011 * 0.2 + 1.00794 * 0.8) * 0.1; + Z = 16.4; // now how does this calculate? + density = 0.749e-3; // in which units? + radlen = 1.196e4 * 2; // in which units? + } + + TMaterial &gas = *new TMaterial("TPCGas", "", A, Z, density, radlen, 0.); + + // FIXME: what about the cathode tickness. Sensitivity gap in the middle? + // And what about the LP? There it's not the half length... + Double_t lhalf + = tpcParameters.getMaxDriftLength(); // half length + + // FIXME:: needed more careful B calculation ?? + const Double_t bz = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + +// gear::BField const & bField = gearMgr.getBField(); +// // get the BField at 0,0,0. Check that there are no transverse components +// // FIXME: Event though there are no transverse components at 0, 0, 0 does not mean +// // there are no transverse components somewhere else. +// gear::Vector3D bFieldVector = bField.at(gear::Vector3D(0., 0., 0.)); +// if (bFieldVector[0]!=0 || bFieldVector[1]!=0) +// { +// streamlog_out(ERROR) << "B-field has transverse components." +// << " LCTPCKalDetector only works with homogeneous B-field" +// << " in z direction" << std::endl; +// throw gear::Exception("Magnetic field not homogeneous"); +// } + + // set the protected member variable of EXVKalDetector + // fBfield = bFieldVector[2]; + + // FIXME: Just don't put dummy modules into the gear file? + // No, we might need the radiation length + // Damn it, the description in GEAR is not complete, grrrr. + // Bool_t active = GearTPCMeasLayer::kActive; + // Bool_t dummy = GearTPCMeasLayer::kDummy; + + // The index where in the TObjectArray the next element will be stored. Unfortunately we have to + // do the bookkeeping manually :-( + Int_t arrayIndex = 0; + + // ILD-type Encoder + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + // A map to store if a layer, which is a full cylinder, already exists. If it has the same + // offset and the same radius, this is the case. Then to not add a Kalman layer but add the module + // to the layer. + std::map< std::pair<double, double> , Int_t > uniqueLayerMap;// <offset, r>, LayerIndex + + for (std::vector<gear::TPCModule *>::const_iterator moduleIter = tpcParameters.getModules().begin(); + moduleIter < tpcParameters.getModules().end(); ++moduleIter) + { + gear::TPCModule *module = *moduleIter; + + // FIXME: Implementation for RectangularPadRowLayout missing + switch (module->getLocalPadLayout().getCoordinateType()) + { + case gear::PadRowLayout2D::POLAR : + //Unfortunately cylinder segments are not implemented in KalDet yet. + //Perhaps in a future implementation... + // Get the phi min and phi max of the module, plus the right rotation + // in the global coordinate system. This is not the global angle because it is + // relative to the origin of the module, which has a shift in global coordinates. + //Double_t phimin = module->getLocalModuleExtent()[2] + module->getAngle(); + //Double_t phimax = module->getLocalModuleExtent()[3] + module->getAngle(); + + // the offset is either in r/phi or in x/y, depending on the global coordinate system + double xOffset, yOffset; + switch (module->getCoordinateType()) + { + case gear::PadRowLayout2D::POLAR : + xOffset=module->getOffset()[0]*cos(module->getOffset()[1]); + yOffset=module->getOffset()[0]*sin(module->getOffset()[1]); + break; + case gear::PadRowLayout2D::CARTESIAN : + xOffset=module->getOffset()[0]; + yOffset=module->getOffset()[1]; + break; + default: + throw gear::UnknownParameterException("Unknown global coordinate system in LCTPCKalDetector"); + + } + + if (yOffset!=0) + { + // streamlog_out(ERROR) << "yOffset not 0. The current implementation of LCTPCKalDetector" + // << "only allows an offset in x direction." << std::endl; + throw gear::UnknownParameterException("Offset in y is not 0."); + } + + // Loop the pad rows and place one cylinder segment each + for (int row = 0; row < module->getNRows(); ++row) + { + // To get the radius we have to ask for the center of one one the pads, + // just take pad 0 in this row. + int padIndex = module->getPadIndex(row, 0); + + // The radius only makes sense in local module coordinates. + // So we have to ask the local pad layout. The module always answers in global coordinates. + Double_t r = module->getLocalPadLayout().getPadCenter(padIndex)[0]; + + std::map< std::pair<double, double> , Int_t >::iterator uniqueLayerIterator= + uniqueLayerMap.find( std::pair<double, double>(xOffset, r) ); + + if ( uniqueLayerIterator==uniqueLayerMap.end() ) + { + // streamlog_out(DEBUG2) << "adding new layer "<<arrayIndex<< " (xOffset="<<xOffset + // <<", r="<<r + // <<") with module "<< module->getModuleID() + // <<" and row "<<row << std::endl; + // add the measurement layer to this object, and remember where we put it + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::TPC ; + + int mod = module -> getModuleID() ; + int row_global = + // Modules 0 and 1 get the same row index + ( mod==0 || mod==1 ) ? row : + /* For modules 2, 3 and 4 the row gets increased + * by the number of rows in modules 0/1 + */ + ( ( mod==2 || mod==3 || mod==4) ? tpcParameters.getModule(0).getNRows() + row : + /* For modules 5 and 6 the row gets increased + * by the number of rows in modules 0/1 and 2/3/4 + */ + tpcParameters.getModule(0).getNRows() + tpcParameters.getModule(2).getNRows() + row ); + + encoder[lcio::ILDCellID0::layer] = row_global ; + + // encoder[lcio::ILDCellID0::module] = mod ; + + int CellID = encoder.lowWord() ; + + Add(new ILDCylinderMeasLayer(gas, gas, + r, lhalf, + xOffset, yOffset, 0, // FIXME: cathode thickness? + bz, + true, // active + CellID, + "ILDCylinderMeasLayer")); + + // add the layer to the uniqueLayerMap + uniqueLayerMap[std::pair<double, double>(xOffset, r)] = arrayIndex; + + // count up the array index + ++arrayIndex; + } + else // layer already exists + { + // streamlog_out(DEBUG2) + // << "A new layer will not be added as the layer with the same parameters already exist"<< std::endl; + } + + }// loop rows in module + break; + + case gear::PadRowLayout2D::CARTESIAN : + throw gear::NotImplementedException("Cartesian local coordinates not yet supported by LCTPCKalDetector"); + + default: + throw gear::UnknownParameterException("Unknown local coordinate system in LCTPCKalDetector"); + }//switch coordinate type + + } + + SetOwner();// make the KalDetector (TObjectArry) owner of the measurement layers so they are + // deleted when the detector is deleted + +} + +LCTPCKalDetector::~LCTPCKalDetector() +{ +} + +}//namespace kaldet diff --git a/Utilities/KalDet/src/ild/lctpc/LCTPCKalDetector.h b/Utilities/KalDet/src/ild/lctpc/LCTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..452aaaad178e497f5ffdbe9e0520c9e5fe2718d6 --- /dev/null +++ b/Utilities/KalDet/src/ild/lctpc/LCTPCKalDetector.h @@ -0,0 +1,39 @@ +#ifndef LCTPCKALDETECTOR_H +#define LCTPCKALDETECTOR_H + +#include "kaltest/TVKalDetector.h" + +#include "kaldet/ILDVMeasLayer.h" + +namespace gear{ + class GearMgr ; +} + +namespace kaldet{ + + /** + * The LCTPC implementation for a TPC which is completely instantiated from GEAR. + * + */ +class LCTPCKalDetector : public TVKalDetector { + +public: + + LCTPCKalDetector() {}; + + /** + * The constructor. All information to initialise the TPC is taken from GEAR. + * + * The class has been copied from GearTPCKalDetector class and adopted for the use of MarlinTrk + * You can find comments and necessary information in the original class + * + */ + LCTPCKalDetector(const gear::GearMgr& gearMgr); + + /// The destructor. + virtual ~LCTPCKalDetector(); + +}; + +}// namespace kaldet +#endif //LCTPCKALDETECTOR_H diff --git a/Utilities/KalDet/src/ild/set/ILDSETKalDetector.cc b/Utilities/KalDet/src/ild/set/ILDSETKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..a8ae3eda05e97f1c3b659f9213e505a67f1db102 --- /dev/null +++ b/Utilities/KalDet/src/ild/set/ILDSETKalDetector.cc @@ -0,0 +1,286 @@ + +#include "kaldet/ILDSETKalDetector.h" + +#include "kaldet/MaterialDataBase.h" + +#include "kaldet/ILDParallelPlanarStripMeasLayer.h" + + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +#include <gear/GEAR.h> +#include "gear/BField.h" +#include <gear/ZPlanarParameters.h> +#include <gear/ZPlanarLayerLayout.h> +#include "gearimpl/Util.h" + +#include "TMath.h" + +#include "math.h" +#include <sstream> + +// #include "streamlog/streamlog.h" + +ILDSETKalDetector::ILDSETKalDetector( const gear::GearMgr& gearMgr ) +: TVKalDetector(300) // SJA:FIXME initial size, 300 looks reasonable for ILD, though this would be better stored as a const somewhere +{ + + + // streamlog_out(DEBUG4) << "ILDSETKalDetector building SET detector using GEAR " << std::endl ; + + MaterialDataBase::Instance().registerForService(gearMgr); + + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air"); + TMaterial & silicon = *MaterialDataBase::Instance().getMaterial("silicon"); + TMaterial & carbon = *MaterialDataBase::Instance().getMaterial("carbon"); + + this->setupGearGeom(gearMgr) ; + + if (_isStripDetector) { + // streamlog_out(DEBUG4) << "\t\t building SET detector as STRIP Detector." << std::endl ; + } else { + // streamlog_out(DEBUG4) << "\t\t building SET detector as PIXEL Detector." << std::endl ; + } + + + //--The Ladder structure (realistic ladder)-- + int nLadders; + +// Bool_t active = true; + Bool_t dummy = false; + + static const double eps_layer = 1e-6; + static const double eps_sensor = 1e-8; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + for (int layer=0; layer<_nLayers; ++layer) { + + double offset = _SETgeo[layer].offset ; + + if( offset!=0.0 ) { + std::cerr << "SET can not have offsets using the current implementation: exit(1)" << std::endl ; + exit(1) ; + } + + nLadders = _SETgeo[layer].nLadders ; + + const double phi0 = _SETgeo[layer].phi0 ; + + const double ladder_distance = _SETgeo[layer].supRMin ; + const double ladder_thickness = _SETgeo[layer].supThickness ; + + const double sensitive_distance = _SETgeo[layer].senRMin ; + const double sensitive_thickness = _SETgeo[layer].senThickness ; + + const double width = _SETgeo[layer].width ; + const double length = _SETgeo[layer].length; + + double currPhi; + const double dphi = _SETgeo[layer].dphi ; + + const double stripAngle = pow(-1,layer) *_SETgeo[layer].stripAngle; + + const int nsensors = _SETgeo[layer].nSensorsPerLadder; + + const double sensor_length = _SETgeo[layer].sensorLength; + + + for (int ladder=0; ladder<nLadders; ++ladder) { + + + currPhi = phi0 + (dphi * ladder); + + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::SET ; + encoder[lcio::ILDCellID0::side] = 0 ; + encoder[lcio::ILDCellID0::layer] = layer ; + encoder[lcio::ILDCellID0::module] = ladder ; + + double z_centre_support = 0.0; + + // check if the sensitive is inside or outside for the support + if( sensitive_distance < ladder_distance ) { + + double sen_front_sorting_policy = sensitive_distance + (4 * ladder+0) * eps_layer ; + double sen_back_sorting_policy = sensitive_distance + (4 * ladder+2) * eps_layer ; + double sup_back_sorting_policy = ladder_distance + (4 * ladder+3) * eps_layer ; + + // air - sensitive boundary + Add(new ILDParallelPlanarMeasLayer(air, silicon, sensitive_distance, currPhi, _bZ, sen_front_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SETSenFront")) ; + + for (int isensor=0; isensor<nsensors; ++isensor) { + + encoder[lcio::ILDCellID0::sensor] = isensor ; + int CellID = encoder.lowWord() ; + + double measurement_plane_sorting_policy = sensitive_distance + (4 * ladder+1) * eps_layer + eps_sensor * isensor ; + + double z_centre_sensor = -0.5*length + (0.5*sensor_length) + (isensor*sensor_length) ; + + + if (_isStripDetector) { + + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarStripMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*0.5, currPhi, _bZ, measurement_plane_sorting_policy, width, sensor_length, offset, z_centre_sensor, offset, stripAngle, CellID, "SETMeaslayer" )) ; + + } else { + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*0.5, currPhi, _bZ, measurement_plane_sorting_policy, width, sensor_length, offset, z_centre_sensor, offset, true, CellID, "SETMeaslayer" )) ; + } + + + // streamlog_out(DEBUG0) << "ILDSETKalDetector add surface with CellID = " + // << CellID + // << std::endl ; + + } + + + // sensitive - support boundary + Add(new ILDParallelPlanarMeasLayer(silicon, carbon, sensitive_distance+sensitive_thickness, currPhi, _bZ, sen_back_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SETSenSupportIntf" )) ; + + // support - air boundary + Add(new ILDParallelPlanarMeasLayer(carbon, air, ladder_distance+ladder_thickness, currPhi, _bZ, sup_back_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SETSupRear" )) ; + } + else { + + double sup_front_sorting_policy = ladder_distance + (4 * ladder+0) * eps_layer ; + double sen_front_sorting_policy = sensitive_distance + (4 * ladder+1) * eps_layer ; + double sen_back_sorting_policy = sensitive_distance + (4 * ladder+3) * eps_layer ; + + // air - support boundary + Add(new ILDParallelPlanarMeasLayer(air, carbon, ladder_distance, currPhi, _bZ, sup_front_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SETSupFront")) ; + + // support boundary - sensitive + Add(new ILDParallelPlanarMeasLayer(carbon, silicon, sensitive_distance, currPhi, _bZ, sen_front_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SETSenSupportIntf" )) ; + + + for (int isensor=0; isensor<nsensors; ++isensor) { + + encoder[lcio::ILDCellID0::sensor] = isensor ; + int CellID = encoder.lowWord() ; + + double measurement_plane_sorting_policy = sensitive_distance + (4 * ladder+2) * eps_layer + eps_sensor * isensor ; + + double z_centre_sensor = -0.5*length + (0.5*sensor_length) + (isensor*sensor_length) ; + + + if (_isStripDetector) { + + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarStripMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*0.5, currPhi, _bZ, measurement_plane_sorting_policy, width, sensor_length, offset, z_centre_sensor, offset, stripAngle, CellID, "SETMeaslayer" )) ; + + } else { + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*0.5, currPhi, _bZ, measurement_plane_sorting_policy, width, sensor_length, offset, z_centre_sensor, offset, true, CellID, "SETMeaslayer" )) ; + } + + + // streamlog_out(DEBUG0) << "ILDSETKalDetector add surface with CellID = " + // << CellID + // << std::endl ; + + + } + + + // support - air boundary + Add(new ILDParallelPlanarMeasLayer(silicon, air, sensitive_distance+sensitive_thickness, currPhi, _bZ, sen_back_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SETSenRear" )) ; + } + + + } + + } + + SetOwner(); +} + + + +void ILDSETKalDetector::setupGearGeom( const gear::GearMgr& gearMgr ){ + + const gear::ZPlanarParameters& pSETDetMain = gearMgr.getSETParameters(); + const gear::ZPlanarLayerLayout& pSETLayerLayout = pSETDetMain.getZPlanarLayerLayout(); + + _bZ = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + _nLayers = pSETLayerLayout.getNLayers(); + _SETgeo.resize(_nLayers); + + bool n_sensors_per_ladder_present = true; + + try { + + std::vector<int> v = pSETDetMain.getIntVals("n_sensors_per_ladder"); + + } catch (gear::UnknownParameterException& e) { + + n_sensors_per_ladder_present = false; + + } + + double strip_angle_deg = 0.0; + + try { + + strip_angle_deg = pSETDetMain.getDoubleVal("strip_angle_deg"); + _isStripDetector = true; + + } catch (gear::UnknownParameterException& e) { + + _isStripDetector = false; + + } + + + //SJA:FIXME: for now the support is taken as the same size the sensitive + // if this is not done then the exposed areas of the support would leave a carbon - air boundary, + // which if traversed in the reverse direction to the next boundary then the track would be propagated through carbon + // for a significant distance + + for( int layer=0; layer < _nLayers; ++layer){ + + + _SETgeo[layer].nLadders = pSETLayerLayout.getNLadders(layer); + _SETgeo[layer].phi0 = pSETLayerLayout.getPhi0(layer); + _SETgeo[layer].dphi = 2*M_PI / _SETgeo[layer].nLadders; + _SETgeo[layer].senRMin = pSETLayerLayout.getSensitiveDistance(layer); + _SETgeo[layer].supRMin = pSETLayerLayout.getLadderDistance(layer); + _SETgeo[layer].length = pSETLayerLayout.getSensitiveLength(layer)*2.0; // note: gear for historical reasons uses the halflength + _SETgeo[layer].width = pSETLayerLayout.getSensitiveWidth(layer); + _SETgeo[layer].offset = pSETLayerLayout.getSensitiveOffset(layer); + _SETgeo[layer].senThickness = pSETLayerLayout.getSensitiveThickness(layer); + _SETgeo[layer].supThickness = pSETLayerLayout.getLadderThickness(layer); + + if (n_sensors_per_ladder_present) { + _SETgeo[layer].nSensorsPerLadder = pSETDetMain.getIntVals("n_sensors_per_ladder")[layer]; + } + else{ + _SETgeo[layer].nSensorsPerLadder = 1 ; + } + + _SETgeo[layer].sensorLength = _SETgeo[layer].length / _SETgeo[layer].nSensorsPerLadder; + + + if (_isStripDetector) { + _SETgeo[layer].stripAngle = strip_angle_deg * M_PI/180 ; + } else { + _SETgeo[layer].stripAngle = 0.0 ; + } + + // streamlog_out(DEBUG0) << " layer = " << layer << std::endl; + // streamlog_out(DEBUG0) << " nSensorsPerLadder = " << _SETgeo[layer].nSensorsPerLadder << std::endl; + // streamlog_out(DEBUG0) << " sensorLength = " << _SETgeo[layer].sensorLength << std::endl; + // streamlog_out(DEBUG0) << " stripAngle = " << _SETgeo[layer].stripAngle << std::endl; + // streamlog_out(DEBUG0) << " _isStripDetector = " << _isStripDetector << std::endl; + + } + + + + +} diff --git a/Utilities/KalDet/src/ild/set/ILDSETKalDetector.h b/Utilities/KalDet/src/ild/set/ILDSETKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..9327aa8a065e8ff6243df53193df544e37389381 --- /dev/null +++ b/Utilities/KalDet/src/ild/set/ILDSETKalDetector.h @@ -0,0 +1,58 @@ +#ifndef __ILDSETKALDETECTOR__ +#define __ILDSETKALDETECTOR__ + +/** Ladder based SET to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +#include "TMath.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDSETKalDetector : public TVKalDetector { + +public: + + /** Initialize the SET from GEAR */ + ILDSETKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + int _nLayers ; + double _bZ ; + + bool _isStripDetector; + + struct SET_Layer { + int nLadders; + int nSensorsPerLadder; + double phi0; + double dphi; + double senRMin; + double supRMin; + double length; + double width; + double offset; + double senThickness; + double supThickness; + double sensorLength; + double stripAngle; + }; + std::vector<SET_Layer> _SETgeo; + +}; + + + +#endif diff --git a/Utilities/KalDet/src/ild/sit/ILDSITCylinderKalDetector.cc b/Utilities/KalDet/src/ild/sit/ILDSITCylinderKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..5cbc808f582932fd9086dd06a1b005618c821890 --- /dev/null +++ b/Utilities/KalDet/src/ild/sit/ILDSITCylinderKalDetector.cc @@ -0,0 +1,133 @@ + +#include "kaldet/ILDSITCylinderKalDetector.h" +#include "kaldet/ILDCylinderMeasLayer.h" +#include "kaldet/ILDCylinderHit.h" + +#include "kaldet/MaterialDataBase.h" + +#include <sstream> +#include <cstdlib> + +#include "gear/GEAR.h" +#include "gear/BField.h" +#include "gearimpl/Util.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +// #include "streamlog/streamlog.h" + + +ILDSITCylinderKalDetector::ILDSITCylinderKalDetector( const gear::GearMgr& gearMgr ) : +TVKalDetector(100) +{ + + // streamlog_out(DEBUG1) << "ILDSITCylinderKalDetector building SIT Simple Cylinder Based Detector using GEAR " << std::endl ; + + ; + + this->setupGearGeom(gearMgr); + + MaterialDataBase::Instance().registerForService(gearMgr); + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air"); + TMaterial & silicon = *MaterialDataBase::Instance().getMaterial("silicon"); + TMaterial & carbon = *MaterialDataBase::Instance().getMaterial("carbon"); + + Bool_t active = true; + Bool_t dummy = false; + + std::string name = "SIT"; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + for ( unsigned int ilayer = 0 ; ilayer<_nLayers ; ++ilayer) { + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::SIT ; + encoder[lcio::ILDCellID0::layer] = ilayer ; + encoder[lcio::ILDCellID0::module] = 0 ; + encoder[lcio::ILDCellID0::sensor] = 0 ; + + int CellID = encoder.lowWord() ; + + double rad = _SITgeo[ilayer].radius - 0.5 * _SITgeo[ilayer].senThickness; + double lhalf = _SITgeo[ilayer].half_length; + + const double x0 = 0.0; + const double y0 = 0.0; + const double z0 = 0.0; + + Add( new ILDCylinderMeasLayer(air, silicon , rad, lhalf, x0, y0, z0, _bZ, dummy,-1,"SITSenFront" ) ); + + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Front face Measurement layer at R = " << rad << " and half length = " << lhalf + // << " X0_in = " << air.GetRadLength() << " X0_out = " << silicon.GetRadLength() + // << std::endl ; + + rad += 0.5 * _SITgeo[ilayer].senThickness; + + Add( new ILDCylinderMeasLayer(silicon , silicon, rad, lhalf, x0, y0, z0, _bZ, active,CellID,"SITMeaslayer" ) ); + + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: " << CellID << " at R = " << rad << " and half length = " << lhalf + // << " X0_in = " << silicon.GetRadLength() << " X0_out = " << silicon.GetRadLength() + // << std::endl ; + + rad += 0.5 * _SITgeo[ilayer].senThickness; + + Add( new ILDCylinderMeasLayer(silicon , carbon, rad, lhalf, x0, y0, z0, _bZ, dummy, -1,"SITSenSupInterFace" ) ); + + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Interface between senstive and support Measurement layer at R = " << rad << " and half length = " << lhalf + // << " X0_in = " << silicon.GetRadLength() << " X0_out = " << carbon.GetRadLength() + // << std::endl ; + + rad += _SITgeo[ilayer].supThickness; + + Add( new ILDCylinderMeasLayer(carbon , air, rad, lhalf, x0, y0, z0, _bZ, dummy, -1,"SITSupRear" ) ); + + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Rear face Measurement layer using at R = " << rad << " and half length = " << lhalf + // << " X0_in = " << carbon.GetRadLength() << " X0_out = " << air.GetRadLength() + // << std::endl ; + + + + } + + SetOwner(); +} + + +void ILDSITCylinderKalDetector::setupGearGeom( const gear::GearMgr& gearMgr ){ + + + const gear::GearParameters& pSIT = gearMgr.getGearParameters("SIT"); + + _bZ = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + double SIT_si = pSIT.getDoubleVal("SITLayerThickness" ) ; + double SIT_sp = pSIT.getDoubleVal("SITSupportLayerThickness" ) ; + const std::vector<double>& SIT_r = pSIT.getDoubleVals("SITLayerRadius" ) ; + const std::vector<double>& SIT_hl = pSIT.getDoubleVals("SITSupportLayerHalfLength" ) ; + + _nLayers = SIT_r.size() ; + _SITgeo.resize(_nLayers); + + + if (_nLayers != SIT_r.size() || _nLayers != SIT_hl.size()) { + + // streamlog_out( ERROR ) << "ILDSITCylinderKalDetector miss-match between DoubleVec and nlayers exit(1) called from file " << __FILE__ << " line " << __LINE__ << std::endl ; + exit(1); + + } + + + for(unsigned int layer=0; layer< _nLayers; ++layer){ + + _SITgeo[layer].senThickness = SIT_si; + _SITgeo[layer].supThickness = SIT_sp; + _SITgeo[layer].radius = SIT_r[layer]; + _SITgeo[layer].half_length = SIT_hl[layer]; + + + } + + +} + diff --git a/Utilities/KalDet/src/ild/sit/ILDSITCylinderKalDetector.h b/Utilities/KalDet/src/ild/sit/ILDSITCylinderKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..29f13f6f7cf5eaf3fba067693d475a9c6fa47449 --- /dev/null +++ b/Utilities/KalDet/src/ild/sit/ILDSITCylinderKalDetector.h @@ -0,0 +1,44 @@ +#ifndef __ILDSITCYLINDERKALDETECTOR__ +#define __ILDSITCYLINDERKALDETECTOR__ + +/** SIT Cylinder based detector to be used for ILD DBD studies when using the old LOI base SIT + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDSITCylinderKalDetector : public TVKalDetector { +public: + + /** Initialize the TPC from GEAR */ + ILDSITCylinderKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + unsigned int _nLayers ; + double _bZ ; + + struct SIT_Layer { + double radius; + double half_length; + double senThickness; + double supThickness; + + }; + std::vector<SIT_Layer> _SITgeo; + + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/sit/ILDSITKalDetector.cc b/Utilities/KalDet/src/ild/sit/ILDSITKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..e58b9d6e773e9afabad21e3179be18e2891f4f69 --- /dev/null +++ b/Utilities/KalDet/src/ild/sit/ILDSITKalDetector.cc @@ -0,0 +1,286 @@ + +#include "ILDSITKalDetector.h" + +#include "MaterialDataBase.h" + +#include "ILDParallelPlanarStripMeasLayer.h" + + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +#include <gear/GEAR.h> +#include "gear/BField.h" +#include <gear/ZPlanarParameters.h> +#include <gear/ZPlanarLayerLayout.h> +#include "gearimpl/Util.h" + +#include "TMath.h" + +#include "math.h" +#include <sstream> + +// #include "streamlog/streamlog.h" + +ILDSITKalDetector::ILDSITKalDetector( const gear::GearMgr& gearMgr ) +: TVKalDetector(300) // SJA:FIXME initial size, 300 looks reasonable for ILD, though this would be better stored as a const somewhere +{ + + + // streamlog_out(DEBUG4) << "ILDSITKalDetector building SIT detector using GEAR " << std::endl ; + + MaterialDataBase::Instance().registerForService(gearMgr); + + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air"); + TMaterial & silicon = *MaterialDataBase::Instance().getMaterial("silicon"); + TMaterial & carbon = *MaterialDataBase::Instance().getMaterial("carbon"); + + this->setupGearGeom(gearMgr) ; + + if (_isStripDetector) { + // streamlog_out(DEBUG4) << "\t\t building SIT detector as STRIP Detector." << std::endl ; + } else { + // streamlog_out(DEBUG4) << "\t\t building SIT detector as PIXEL Detector." << std::endl ; + } + + + //--The Ladder structure (realistic ladder)-- + int nLadders; + + // Bool_t active = true; + Bool_t dummy = false; + + static const double eps_layer = 1e-6; + static const double eps_sensor = 1e-8; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + for (int layer=0; layer<_nLayers; ++layer) { + + double offset = _SITgeo[layer].offset ; + + if( offset!=0.0 ) { + std::cerr << "SIT can not have offsets using the current implementation: exit(1)" << std::endl ; + exit(1) ; + } + + nLadders = _SITgeo[layer].nLadders ; + + const double phi0 = _SITgeo[layer].phi0 ; + + const double ladder_distance = _SITgeo[layer].supRMin ; + const double ladder_thickness = _SITgeo[layer].supThickness ; + + const double sensitive_distance = _SITgeo[layer].senRMin ; + const double sensitive_thickness = _SITgeo[layer].senThickness ; + + const double width = _SITgeo[layer].width ; + const double length = _SITgeo[layer].length; + + double currPhi; + const double dphi = _SITgeo[layer].dphi ; + + const double stripAngle = pow(-1,layer) *_SITgeo[layer].stripAngle; + + const int nsensors = _SITgeo[layer].nSensorsPerLadder; + + const double sensor_length = _SITgeo[layer].sensorLength; + + + for (int ladder=0; ladder<nLadders; ++ladder) { + + + currPhi = phi0 + (dphi * ladder); + + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::SIT ; + encoder[lcio::ILDCellID0::side] = 0 ; + encoder[lcio::ILDCellID0::layer] = layer ; + encoder[lcio::ILDCellID0::module] = ladder ; + + double z_centre_support = 0.0; + + // check if the sensitive is inside or outside for the support + if( sensitive_distance < ladder_distance ) { + + double sen_front_sorting_policy = sensitive_distance + (4 * ladder+0) * eps_layer ; + double sen_back_sorting_policy = sensitive_distance + (4 * ladder+2) * eps_layer ; + double sup_back_sorting_policy = ladder_distance + (4 * ladder+3) * eps_layer ; + + // air - sensitive boundary + Add(new ILDParallelPlanarMeasLayer(air, silicon, sensitive_distance, currPhi, _bZ, sen_front_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SITSenFront")) ; + + for (int isensor=0; isensor<nsensors; ++isensor) { + + encoder[lcio::ILDCellID0::sensor] = isensor ; + int CellID = encoder.lowWord() ; + + double measurement_plane_sorting_policy = sensitive_distance + (4 * ladder+1) * eps_layer + eps_sensor * isensor ; + + double z_centre_sensor = -0.5*length + (0.5*sensor_length) + (isensor*sensor_length) ; + + + if (_isStripDetector) { + + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarStripMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*0.5, currPhi, _bZ, measurement_plane_sorting_policy, width, sensor_length, offset, z_centre_sensor, offset, stripAngle, CellID, "SITMeaslayer" )) ; + + } else { + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*0.5, currPhi, _bZ, measurement_plane_sorting_policy, width, sensor_length, offset, z_centre_sensor, offset, true, CellID, "SITMeaslayer" )) ; + } + + + // streamlog_out(DEBUG0) << "ILDSITKalDetector add surface with CellID = " + // << CellID + // << std::endl ; + + } + + + // sensitive - support boundary + Add(new ILDParallelPlanarMeasLayer(silicon, carbon, sensitive_distance+sensitive_thickness, currPhi, _bZ, sen_back_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SITSenSupportIntf" )) ; + + // support - air boundary + Add(new ILDParallelPlanarMeasLayer(carbon, air, ladder_distance+ladder_thickness, currPhi, _bZ, sup_back_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SITSupRear" )) ; + } + else { + + double sup_front_sorting_policy = ladder_distance + (4 * ladder+0) * eps_layer ; + double sen_front_sorting_policy = sensitive_distance + (4 * ladder+1) * eps_layer ; + double sen_back_sorting_policy = sensitive_distance + (4 * ladder+3) * eps_layer ; + + // air - support boundary + Add(new ILDParallelPlanarMeasLayer(air, carbon, ladder_distance, currPhi, _bZ, sup_front_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SITSupFront")) ; + + // support boundary - sensitive + Add(new ILDParallelPlanarMeasLayer(carbon, silicon, sensitive_distance, currPhi, _bZ, sen_front_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SITSenSupportIntf" )) ; + + + for (int isensor=0; isensor<nsensors; ++isensor) { + + encoder[lcio::ILDCellID0::sensor] = isensor ; + int CellID = encoder.lowWord() ; + + double measurement_plane_sorting_policy = sensitive_distance + (4 * ladder+2) * eps_layer + eps_sensor * isensor ; + + double z_centre_sensor = -0.5*length + (0.5*sensor_length) + (isensor*sensor_length) ; + + + if (_isStripDetector) { + + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarStripMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*0.5, currPhi, _bZ, measurement_plane_sorting_policy, width, sensor_length, offset, z_centre_sensor, offset, stripAngle, CellID, "SITMeaslayer" )) ; + + } else { + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*0.5, currPhi, _bZ, measurement_plane_sorting_policy, width, sensor_length, offset, z_centre_sensor, offset, true, CellID, "SITMeaslayer" )) ; + } + + + // streamlog_out(DEBUG0) << "ILDSITKalDetector add surface with CellID = " + // << CellID + // << std::endl ; + + + } + + + // support - air boundary + Add(new ILDParallelPlanarMeasLayer(silicon, air, sensitive_distance+sensitive_thickness, currPhi, _bZ, sen_back_sorting_policy, width, length, offset,z_centre_support, offset, dummy,-1,"SITSenRear" )) ; + } + + + } + + } + + SetOwner(); +} + + + +void ILDSITKalDetector::setupGearGeom( const gear::GearMgr& gearMgr ){ + + const gear::ZPlanarParameters& pSITDetMain = gearMgr.getSITParameters(); + const gear::ZPlanarLayerLayout& pSITLayerLayout = pSITDetMain.getZPlanarLayerLayout(); + + _bZ = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + _nLayers = pSITLayerLayout.getNLayers(); + _SITgeo.resize(_nLayers); + + bool n_sensors_per_ladder_present = true; + + try { + + std::vector<int> v = pSITDetMain.getIntVals("n_sensors_per_ladder"); + + } catch (gear::UnknownParameterException& e) { + + n_sensors_per_ladder_present = false; + + } + + double strip_angle_deg = 0.0; + + try { + + strip_angle_deg = pSITDetMain.getDoubleVal("strip_angle_deg"); + _isStripDetector = true; + + } catch (gear::UnknownParameterException& e) { + + _isStripDetector = false; + + } + + + //SJA:FIXME: for now the support is taken as the same size the sensitive + // if this is not done then the exposed areas of the support would leave a carbon - air boundary, + // which if traversed in the reverse direction to the next boundary then the track would be propagated through carbon + // for a significant distance + + for( int layer=0; layer < _nLayers; ++layer){ + + + _SITgeo[layer].nLadders = pSITLayerLayout.getNLadders(layer); + _SITgeo[layer].phi0 = pSITLayerLayout.getPhi0(layer); + _SITgeo[layer].dphi = 2*M_PI / _SITgeo[layer].nLadders; + _SITgeo[layer].senRMin = pSITLayerLayout.getSensitiveDistance(layer); + _SITgeo[layer].supRMin = pSITLayerLayout.getLadderDistance(layer); + _SITgeo[layer].length = pSITLayerLayout.getSensitiveLength(layer)*2.0; // note: gear for historical reasons uses the halflength + _SITgeo[layer].width = pSITLayerLayout.getSensitiveWidth(layer); + _SITgeo[layer].offset = pSITLayerLayout.getSensitiveOffset(layer); + _SITgeo[layer].senThickness = pSITLayerLayout.getSensitiveThickness(layer); + _SITgeo[layer].supThickness = pSITLayerLayout.getLadderThickness(layer); + + if (n_sensors_per_ladder_present) { + _SITgeo[layer].nSensorsPerLadder = pSITDetMain.getIntVals("n_sensors_per_ladder")[layer]; + } + else{ + _SITgeo[layer].nSensorsPerLadder = 1 ; + } + + _SITgeo[layer].sensorLength = _SITgeo[layer].length / _SITgeo[layer].nSensorsPerLadder; + + + if (_isStripDetector) { + _SITgeo[layer].stripAngle = strip_angle_deg * M_PI/180 ; + } else { + _SITgeo[layer].stripAngle = 0.0 ; + } + + // streamlog_out(DEBUG0) << " layer = " << layer << std::endl; + // streamlog_out(DEBUG0) << " nSensorsPerLadder = " << _SITgeo[layer].nSensorsPerLadder << std::endl; + // streamlog_out(DEBUG0) << " sensorLength = " << _SITgeo[layer].sensorLength << std::endl; + // streamlog_out(DEBUG0) << " stripAngle = " << _SITgeo[layer].stripAngle << std::endl; + // streamlog_out(DEBUG0) << " _isStripDetector = " << _isStripDetector << std::endl; + + } + + + + +} diff --git a/Utilities/KalDet/src/ild/sit/ILDSITKalDetector.h b/Utilities/KalDet/src/ild/sit/ILDSITKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..639e1b27bb76512ad05c8570814b218a9480cb5b --- /dev/null +++ b/Utilities/KalDet/src/ild/sit/ILDSITKalDetector.h @@ -0,0 +1,58 @@ +#ifndef __ILDSITKALDETECTOR__ +#define __ILDSITKALDETECTOR__ + +/** Ladder based SIT to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +#include "TMath.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDSITKalDetector : public TVKalDetector { + +public: + + /** Initialize the SIT from GEAR */ + ILDSITKalDetector( const gear::GearMgr& gearMgr ); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr ) ; + + int _nLayers ; + double _bZ ; + + bool _isStripDetector; + + struct SIT_Layer { + int nLadders; + int nSensorsPerLadder; + double phi0; + double dphi; + double senRMin; + double supRMin; + double length; + double width; + double offset; + double senThickness; + double supThickness; + double sensorLength; + double stripAngle; + }; + std::vector<SIT_Layer> _SITgeo; + +}; + + + +#endif diff --git a/Utilities/KalDet/src/ild/support/ILDSupportKalDetector.cc b/Utilities/KalDet/src/ild/support/ILDSupportKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..3b59a6af44c926aaa2d88a9b8217b8e98bdec813 --- /dev/null +++ b/Utilities/KalDet/src/ild/support/ILDSupportKalDetector.cc @@ -0,0 +1,329 @@ + +#include "ILDSupportKalDetector.h" +#include "ILDCylinderMeasLayer.h" +#include "ILDConeMeasLayer.h" +#include "ILDPolygonBarrelMeasLayer.h" +#include "ILDDiscMeasLayer.h" + +#include "TMath.h" +#include "TTUBE.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +#include "MaterialDataBase.h" + +#include <sstream> +#include <cmath> + +#include "gear/GEAR.h" +#include "gear/BField.h" +#include "gearimpl/Util.h" +#include "gear/CalorimeterParameters.h" +// #include "streamlog/streamlog.h" +#include "DetInterface/IGeoSvc.h" + +ILDSupportKalDetector::ILDSupportKalDetector( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc ) : +TVKalDetector(10) +{ + + // streamlog_out(DEBUG1) << "ILDSupportKalDetector building beampipe using GEAR " << std::endl ; + + const gear::GearParameters& pBeamPipe = gearMgr.getGearParameters("BeamPipe"); + const Double_t bz = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + // switch gear to dd4hep::rec, once validated, gear will been removed. + const dd4hep::rec::ConicalSupportData* pBeamPipeData = geoSvc->getBeamPipeData(); + const std::vector<dd4hep::rec::ConicalSupportData::Section>& sections = pBeamPipeData->sections; + std::cout << "======================BeamPipe===================" << std::endl; + for(int i=0;i<sections.size();i++){ + std::cout << sections[i].zPos << " " << sections[i].rInner << " " << sections[i].rOuter << std::endl; + } + std::cout << "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" << std::endl; + // the beampipe is supposed to be a chain of cut cones (cut, that means the spike is cut off, also called a cone frustum). + // as they are connected, RStart[i] == REnd[i-1]. With this all we need are the z values and the radii at the place. + const std::vector<double> z = pBeamPipe.getDoubleVals("Z"); + const std::vector<double> rInner = pBeamPipe.getDoubleVals("RInner"); //inner radius of the cone + const std::vector<double> rOuter = pBeamPipe.getDoubleVals("ROuter"); //outer radius of the cone + for(int i=0;i<sections.size();i++){ + std::cout << z[i] << " " << rInner[i] << " " << rOuter[i] << std::endl; + } + MaterialDataBase::Instance().registerForService(gearMgr, geoSvc); + TMaterial & beam = *MaterialDataBase::Instance().getMaterial("beam"); + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air"); + // TMaterial & aluminium = *MaterialDataBase::Instance().getMaterial("aluminium"); + TMaterial & beryllium = *MaterialDataBase::Instance().getMaterial("beryllium"); + + Bool_t dummy = false; + + double eps_side = 1.0e-8; + double eps_section = 1.0e-6; + + // first check the sizes of the beam-pipe values r_in r_out and z + + if ( ( z.size() != rInner.size() ) || ( z.size() != rOuter.size() ) ) { + // streamlog_out(ERROR) << "ILDSupportKalDetector::ILDSupportKalDetector miss-match in number of double values for beam-pipe: Z = " << z.size() << " RInner = " << rInner.size() << " ROuter = " << rOuter.size() << " exit(1) called from "<< __FILE__ << " line " << __LINE__ << std::endl; + exit(1); + } + + double epsilon = 1.e-6; + + double rInnerStart_last = -DBL_MAX; + double rInnerEnd_last = -DBL_MAX; + double rOuterStart_last = -DBL_MAX; + double rOuterEnd_last = -DBL_MAX; + + // add beam pipe cones + for( unsigned i=0; i<z.size()-1; i++){ + + double zStart = z[i]; + double zEnd = z[i+1]; + double rInnerStart = rInner[i]; + double rInnerEnd = rInner[i+1]; + double rOuterStart = rOuter[i]; + double rOuterEnd = rOuter[i+1]; + + + //SJA:FIXME: HERE WE NEED TO MAKE SURE THAT THE BEAM PIPE IS NEVER DECREASING IN RADII OTHERWISE THE SORTING GOES WRONG + if ( rInnerStart < rInnerStart_last ) rInnerStart = rInnerStart_last; rInnerStart_last = rInnerStart; + if ( rInnerEnd < rInnerEnd_last ) rInnerEnd = rInnerEnd_last ; rInnerEnd_last = rInnerEnd; + if ( rOuterStart < rOuterStart_last ) rOuterStart = rOuterStart_last; rOuterStart_last = rOuterStart; + if ( rOuterEnd < rOuterEnd_last ) rOuterEnd = rOuterEnd_last; rOuterEnd_last = rOuterEnd; + + + std::stringstream sname; + + const double x0 = 0.0; + const double y0 = 0.0; + const double z0 = 0.0; + + + // central part has to be treated separately as it should not be composed of two halves but a single section. + if (i==0) { + // check that z values start a zero + if (fabs(zStart) > epsilon) { + // streamlog_out(ERROR) << "ILDSupportKalDetector::ILDSupportKalDetector first z value for beam-pipe must equal zero: Z = " << zStart << " exit(1) called from "<< __FILE__ << " line " << __LINE__ << std::endl; + exit(1); + } + + // just make a minimal beam pipe (tube) no cone for now as the sorting policy does not works as expected + + double zhalf = zEnd; + + + sname << "BeamPipeInnerWallCentralSection_" << i; + _surface_names.push_back(sname.str()); + + + Add( new ILDCylinderMeasLayer(beam, beryllium , rInnerStart , zhalf, x0, y0, z0, bz, dummy,-1, _surface_names.back().c_str() )); + + // streamlog_out( DEBUG0 ) << " *** adding " << _surface_names.back() << " Measurement layer using CellID: [ beampipe ] at R = " << rInnerStart + // << " zHalf = " << zhalf << " X0_in = " << beam.GetRadLength() << " X0_out = " << beryllium.GetRadLength() + // << std::endl ; + + sname.str(std::string()); + sname << "BeamPipeOuterWallCentralSection_" << i; + _surface_names.push_back(sname.str()); + + Add( new ILDCylinderMeasLayer(beryllium, air , rOuterStart , zhalf, x0, y0, z0, bz, dummy,-1, _surface_names.back().c_str() )); + + // streamlog_out( DEBUG0 ) << " *** adding " << _surface_names.back() << " Measurement layer using CellID: [ beampipe ] at R = " << rOuterStart + // << " zHalf = " << zhalf << " X0_in = " << beryllium.GetRadLength() << " X0_out = " << air.GetRadLength() + // << std::endl ; + + + + } else { + + + if( fabs( zEnd-zStart ) > epsilon ){ + + + double SortingPolicy = rInnerStart+i*eps_section; + + if (fabs(rInnerEnd-rInnerStart) > epsilon) { // use cone + + sname.str(std::string()); + sname << "BeamPipeConeInnerFwd" << i; + _surface_names.push_back(sname.str()); + + Add( new ILDConeMeasLayer(beam, beryllium , zStart, rInnerStart, zEnd, rInnerEnd, bz, SortingPolicy, dummy,-1, _surface_names.back().c_str() ) ); + + sname.str(std::string()); + sname << "BeamPipeConeInnerBwd" << i; + _surface_names.push_back(sname.str()); + + Add( new ILDConeMeasLayer(beam, beryllium , -zStart, rInnerStart, -zEnd, rInnerEnd, bz, SortingPolicy+eps_side, dummy,-1, _surface_names.back().c_str() ) ); + + } else { // use cylinder + + sname.str(std::string()); + sname << "BeamPipeCylindeInnerFwd" << i; + _surface_names.push_back(sname.str()); + + const double zhalf = fabs(zEnd-zStart); + + const double zoffset = zStart + zhalf; + + Add( new ILDCylinderMeasLayer(beam, beryllium , rInnerStart+i*eps_section , zhalf, x0, y0, zoffset, bz, dummy,-1, _surface_names.back().c_str() )); + + sname.str(std::string()); + sname << "BeamPipeCylindeInnerBwd" << i; + _surface_names.push_back(sname.str()); + + Add( new ILDCylinderMeasLayer(beam, beryllium , rInnerStart+i*eps_section+eps_side , zhalf, x0, y0, -zoffset, bz, dummy,-1, _surface_names.back().c_str() )); + + + } + + + // streamlog_out( DEBUG0 ) << " *** adding inner " << _surface_names[_surface_names.size()-2] << " and " << _surface_names.back() << " Measurement layer using CellID: [ beampipe ] at" + // << " z1 = +-" << zStart + // << " z2 = +-" << zEnd + // << " r1 = " << rInnerStart + // << " r2 = " << rInnerEnd + // << " X0_in = " << beam.GetRadLength() << " X0_out = " << beryllium.GetRadLength() + // << std::endl ; + + SortingPolicy = rOuterStart+i*eps_section; + + if (fabs(rOuterEnd-rOuterStart) > epsilon) { // use cone + + sname.str(std::string()); + sname << "BeamPipeConeOuterFwd" << i; + _surface_names.push_back(sname.str()); + + Add( new ILDConeMeasLayer(beryllium , air , zStart, rOuterStart, zEnd, rOuterEnd, bz, SortingPolicy, dummy,-1, _surface_names.back().c_str() ) ); + + sname.str(std::string()); + sname << "BeamPipeConeOuterBwd" << i; + _surface_names.push_back(sname.str()); + + Add( new ILDConeMeasLayer(beryllium , air , -zStart, rOuterStart, -zEnd, rOuterEnd, bz, SortingPolicy+eps_side, dummy,-1, _surface_names.back().c_str() ) ); + + + } else { // use cylinder + + sname.str(std::string()); + sname << "BeamPipeCylindeOuterFwd" << i; + _surface_names.push_back(sname.str()); + + const double zhalf = fabs(zEnd-zStart); + + const double zoffset = zStart + zhalf; + + Add( new ILDCylinderMeasLayer(beryllium, air , rOuterStart+i*eps_section , zhalf, x0, y0, zoffset, bz, dummy,-1, _surface_names.back().c_str() )); + + sname.str(std::string()); + sname << "BeamPipeCylindeOuterBwd" << i; + _surface_names.push_back(sname.str()); + + Add( new ILDCylinderMeasLayer(beryllium, air , rOuterStart+i*eps_section+eps_side , zhalf, x0, y0, -zoffset, bz, dummy,-1, _surface_names.back().c_str() )); + + } + + + // streamlog_out( DEBUG0 ) << " *** adding outer " << _surface_names[_surface_names.size()-2] << " and " << _surface_names.back() << " Measurement layer using CellID: [ beampipe ] at" + // << " z1 = +-" << zStart + // << " z2 = +-" << zEnd + // << " r1 = " << rOuterStart + // << " r2 = " << rOuterEnd + // << " X0_in = " << beryllium.GetRadLength() << " X0_out = " << air.GetRadLength() + // << std::endl ; + + } + + } + + } + + + // add vacuum layer 1mm inside the beam pipe to assist propagation to the IP + // therefore make a cylinder that is 1mm smaller than the lowest RInner value of the cones + // and make it so long that it gets as long as the beamtube + const double rvacuum = *min_element(rInner.begin(), rInner.end()) - 1.0; + const double zHalfVacuum = z.back(); + + const double x0 = 0.0; + const double y0 = 0.0; + const double z0 = 0.0; + + + _ipLayer = new ILDCylinderMeasLayer(beam, beam , rvacuum , zHalfVacuum, x0, y0, z0, bz, dummy,-1,"IPLayer" ); + + Add( _ipLayer ); + // streamlog_out( DEBUG0 ) << " *** adding " << "IPLayer" << " Measurement layer using CellID: [ beampipe ] at R = " << rvacuum + // << " zHalf = " << zHalfVacuum << " X0_in = " << beam.GetRadLength() << " X0_out = " << beam.GetRadLength() + // << std::endl ; + + + // add calo bounding inner surface as ILDPolygonBarrelMeasLayer and two planes at the inner z of the calo endcaps with ILDDiscMeasLayer + + // SJA:FIXME: OK for now we will just use a set of planes as there is not yet an implementation to propagate to a multilayer + + const gear::CalorimeterParameters& ecalB = gearMgr.getEcalBarrelParameters(); + const gear::CalorimeterParameters& ecalE = gearMgr.getEcalEndcapParameters(); + + if (ecalB.getSymmetryOrder()!=8) { + // streamlog_out(ERROR) << "ILDSupportKalDetector::ILDSupportKalDetector ECal barrel is not eightfold symmetry: exit(1) called from " << __FILE__ << " line " << __LINE__ << std::endl; + exit(1); + + } + + double phi0 = ecalB.getPhi0(); + double r_min_ecal_bar = ecalB.getExtent()[0]; + double z_max_ecal_bar = ecalB.getExtent()[3]; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::ECAL ; + encoder[lcio::ILDCellID0::side] = lcio::ILDDetID::barrel; + encoder[lcio::ILDCellID0::layer] = 0 ; + + std::vector<int> module_ids; + + for (int i=0; i<8; ++i) { + + encoder[lcio::ILDCellID0::module] = i; + module_ids.push_back(encoder.lowWord()); + + double segment_dphi = 2.0*M_PI / 8; + double phi = i*segment_dphi+phi0; + double width = 2.0*(r_min_ecal_bar*tan(segment_dphi*0.5)); + double length = 2.0*z_max_ecal_bar; + Add ( new ILDParallelPlanarMeasLayer(air,air,r_min_ecal_bar,phi,bz,r_min_ecal_bar+i*1.0e-06,width,length,0.0,0.0,0.0,true,encoder.lowWord(),"ECalBarrelFace")); + + } + + // Add ( new ILDPolygonBarrelMeasLayer(air,air,bz,r_min_ecal_bar,r_min_ecal_bar,z_max_ecal_bar*0.5,8,0.0,phi0,module_ids,"ECalBarrelFace")); + + // streamlog_out( DEBUG0 ) << " *** adding ECalBarrelFace Measurement layer at Rmin = " << r_min_ecal_bar << std::endl ; + + double r_max_ecal_ecap = ecalE.getExtent()[1]; + double z_min_ecal_ecap = ecalE.getExtent()[2]; + + encoder[lcio::ILDCellID0::module] = 0; + + encoder[lcio::ILDCellID0::side] = lcio::ILDDetID::fwd; + + TVector3 front_face_centre_fwd( 0.0, 0.0, z_min_ecal_ecap); // for +z + TVector3 front_face_normal_fwd(front_face_centre_fwd); + front_face_normal_fwd.SetMag(1.0); + + Add (new ILDDiscMeasLayer(air, air, front_face_centre_fwd,front_face_normal_fwd, bz, z_min_ecal_ecap, 0., r_max_ecal_ecap/cos(M_PI/8.0), true, encoder.lowWord(),"ECalEndcapFace+Z") ); + + // streamlog_out( DEBUG0 ) << " *** adding ECalEndcapFace+Z Measurement layer at Zmin = " << front_face_centre_fwd.z() << " and Rmax = " << r_max_ecal_ecap/cos(M_PI/8.0) << std::endl ; + + encoder[lcio::ILDCellID0::side] = lcio::ILDDetID::bwd; + TVector3 front_face_centre_bwd( -front_face_centre_fwd ); // for -z + TVector3 front_face_normal_bwd(front_face_centre_bwd); + front_face_normal_bwd.SetMag(1.0); + + Add (new ILDDiscMeasLayer(air, air, front_face_centre_bwd,front_face_normal_bwd, bz, z_min_ecal_ecap+1.0e-06, 0., r_max_ecal_ecap/cos(M_PI/8.0), true, encoder.lowWord(),"ECalEndcapFace-Z")); + + // streamlog_out( DEBUG0 ) << " *** adding ECalEndcapFace-Z Measurement layer at Zmin = " << front_face_centre_bwd.z() << " and Rmax = " << r_max_ecal_ecap/cos(M_PI/8.0) << std::endl ; + + SetOwner(); +} + diff --git a/Utilities/KalDet/src/ild/support/ILDSupportKalDetector.h b/Utilities/KalDet/src/ild/support/ILDSupportKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..b7e28fa929884ceadf7755395766d8f75c079c3f --- /dev/null +++ b/Utilities/KalDet/src/ild/support/ILDSupportKalDetector.h @@ -0,0 +1,37 @@ +#ifndef __ILDSUPPORTDETECTOR__ +#define __ILDSUPPORTDETECTOR__ + +/** Support Material to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} +class IGeoSvc; + +class ILDCylinderMeasLayer; + +class ILDSupportKalDetector : public TVKalDetector { +public: + + /** Initialize the support structures from GEAR */ + ILDSupportKalDetector( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc ); + + /** Returns the special layer inside the Beam Pipe used for propagation to the IP */ + ILDCylinderMeasLayer* getIPLayer() { return _ipLayer; } + +private: + + ILDCylinderMeasLayer* _ipLayer; + + std::vector<std::string> _surface_names; + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.cc b/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..cb41bf467d2a208fbc8b6ff0587f08bf5aca2ba7 --- /dev/null +++ b/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.cc @@ -0,0 +1,137 @@ + +#include "ILDTPCKalDetector.h" +#include "ILDCylinderMeasLayer.h" +#include "ILDCylinderHit.h" + +#include "TMath.h" +#include "TTUBE.h" + +#include "MaterialDataBase.h" + +#include <sstream> + +#include "gear/GEAR.h" +#include "gear/BField.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gearimpl/Util.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +// #include "streamlog/streamlog.h" + + +ILDTPCKalDetector::ILDTPCKalDetector( const gear::GearMgr& gearMgr ) : +TVKalDetector(250) // SJA:FIXME initial size, 250 looks reasonable for ILD, though this would be better stored as a const somewhere +{ + + // streamlog_out(DEBUG1) << "ILDTPCKalDetector building TPC detector using GEAR " << std::endl ; + + const gear::TPCParameters& tpcParams = gearMgr.getTPCParameters(); + + const gear::PadRowLayout2D& pL = tpcParams.getPadLayout() ; + + // streamlog_out(DEBUG1) << "ILDTPCKalDetector - got padlayout with nLayers = " << pL.getNRows() << std::endl ; + + const Double_t bz = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + static const Int_t nlayers = pL.getNRows() ; // n rows + static const Double_t lhalf = tpcParams.getMaxDriftLength() ; // half length + + static const Double_t rstep = pL.getRowHeight(0) ; // step length of radius + + // assuming that this is the radius of the first measurment layer .... + static const Double_t rmin = tpcParams.getPlaneExtent()[0] + rstep/2. ; // minimum radius + + // streamlog_out( DEBUG0 ) << tpcParams << std::endl ; + + static const Double_t rtub = tpcParams.getDoubleVal("tpcInnerRadius") ; // inner r of support tube + static const Double_t outerr = tpcParams.getDoubleVal("tpcOuterRadius") ; // outer radius of TPC + + static const Double_t inthick = tpcParams.getDoubleVal("tpcInnerWallThickness") ; // thickness of inner shell + static const Double_t outthick = tpcParams.getDoubleVal("tpcOuterWallThickness") ; // thickness of outer shell + + MaterialDataBase::Instance().registerForService(gearMgr); + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air"); + TMaterial & tpcgas = *MaterialDataBase::Instance().getMaterial("tpcgas"); + // TMaterial & aluminium = *MaterialDataBase::Instance().getMaterial("aluminium"); + TMaterial & tpcinnerfieldcage = *MaterialDataBase::Instance().getMaterial("tpcinnerfieldcage"); + TMaterial & tpcouterfieldcage = *MaterialDataBase::Instance().getMaterial("tpcouterfieldcage"); + + Bool_t active = true; + Bool_t dummy = false; + + std::string name = "TPC"; + + const double x0 = 0.0; + const double y0 = 0.0; + const double z0 = 0.0; + + + // add inner field cage + Add( new ILDCylinderMeasLayer(air, tpcinnerfieldcage , rtub, lhalf, x0, y0, z0, bz, dummy,-1,"TPCInnerFCInr" ) ); + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [ inner field cage ] at R = " << rtub + // << " X0_in = " << air.GetRadLength() << " X0_out = " << tpcinnerfieldcage.GetRadLength() + // << std::endl ; + + Add( new ILDCylinderMeasLayer(tpcinnerfieldcage , tpcgas, rtub+inthick, lhalf, x0, y0, z0, bz, dummy,-1,"TPCInnerFCOtr" ) ); + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [ inner field cage ] at R = " << rtub+inthick + // << " X0_in = " << tpcinnerfieldcage.GetRadLength() << " X0_out = " << tpcgas.GetRadLength() + // << std::endl ; + + + // streamlog_out( DEBUG0 ) << " *** Inner Field Cage = " << int( (inthick/(tpcinnerfieldcage.GetRadLength()*10.0) /*cm*/ )*1000) / 10.0 << "% of a radiation length " << std::endl ; + + // create measurement layers + Double_t r = rmin; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + for (Int_t layer = 0; layer < nlayers; layer++) { + + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::TPC ; + encoder[lcio::ILDCellID0::layer] = layer ; + + int CellID = encoder.lowWord() ; + + ILDCylinderMeasLayer* tpcL = new ILDCylinderMeasLayer(tpcgas, tpcgas, r, lhalf, x0, y0, z0, bz, active, CellID, "TPCMeasLayer") ; + + Add( tpcL ) ; + + int nth_layers(10) ; + + if( layer % nth_layers == 0 ){ + + // streamlog_out( DEBUG0 ) << " *** for TPC Gas printing only every " << nth_layers << "th layer" << std::endl ; + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [" << CellID << "] at R = " << r + // << " X0_in = " << tpcgas.GetRadLength() << " X0_out = " << tpcgas.GetRadLength() + // << std::endl ; + } + + r += rstep; + + } + + // add outer field cage + Add( new ILDCylinderMeasLayer(tpcgas, tpcouterfieldcage, outerr-outthick, lhalf, x0, y0, z0, bz, dummy,-1,"TPCOuterFCInr") ) ; + + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [ outer field cage ] at R = " << outerr-outthick + // << " X0_in = " << tpcgas.GetRadLength() << " X0_out = " << tpcouterfieldcage.GetRadLength() + // << std::endl ; + + Add( new ILDCylinderMeasLayer(tpcouterfieldcage, air, outerr, lhalf, x0, y0, z0, bz, dummy,-1,"TPCOuterFCOtr") ) ; + + // streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [ outer field cage ] at R = " << outerr + // << " X0_in = " << tpcouterfieldcage.GetRadLength() << " X0_out = " << air.GetRadLength() + // << std::endl ; + + // streamlog_out( DEBUG0 ) << " *** Outer Field Cage = " << int( (outthick/(tpcouterfieldcage.GetRadLength()*10.0) /*cm*/ )*1000) / 10.0 << "% of a radiation length " << std::endl ; + + + SetOwner(); +} + + diff --git a/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.cc.remove b/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.cc.remove new file mode 100644 index 0000000000000000000000000000000000000000..dc6101e5ee7acee641647a3563dd5c5c1ba5e016 --- /dev/null +++ b/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.cc.remove @@ -0,0 +1,139 @@ + +#include "ILDTPCKalDetector.h" +#include "ILDCylinderMeasLayer.h" +#include "ILDCylinderHit.h" + +#include "TMath.h" +#include "TTUBE.h" + +#include "MaterialDataBase.h" + +#include <sstream> + +#include "gear/GEAR.h" +#include "gear/BField.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gearimpl/Util.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +#include "streamlog/streamlog.h" + +namespace kaldet{ + +ILDTPCKalDetector::ILDTPCKalDetector( const gear::GearMgr& gearMgr ) : +TVKalDetector(250) // SJA:FIXME initial size, 250 looks reasonable for ILD, though this would be better stored as a const somewhere +{ + + streamlog_out(DEBUG1) << "ILDTPCKalDetector building TPC detector using GEAR " << std::endl ; + + const gear::TPCParameters& tpcParams = gearMgr.getTPCParameters(); + + const gear::PadRowLayout2D& pL = tpcParams.getPadLayout() ; + + streamlog_out(DEBUG1) << "ILDTPCKalDetector - got padlayout with nLayers = " << pL.getNRows() << std::endl ; + + const Double_t bz = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + static const Int_t nlayers = pL.getNRows() ; // n rows + static const Double_t lhalf = tpcParams.getMaxDriftLength() ; // half length + + static const Double_t rstep = pL.getRowHeight(0) ; // step length of radius + + // assuming that this is the radius of the first measurment layer .... + static const Double_t rmin = tpcParams.getPlaneExtent()[0] + rstep/2. ; // minimum radius + + streamlog_out( DEBUG0 ) << tpcParams << std::endl ; + + static const Double_t rtub = tpcParams.getDoubleVal("tpcInnerRadius") ; // inner r of support tube + static const Double_t outerr = tpcParams.getDoubleVal("tpcOuterRadius") ; // outer radius of TPC + + static const Double_t inthick = tpcParams.getDoubleVal("tpcInnerWallThickness") ; // thickness of inner shell + static const Double_t outthick = tpcParams.getDoubleVal("tpcOuterWallThickness") ; // thickness of outer shell + + MaterialDataBase::Instance().registerForService(gearMgr); + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air"); + TMaterial & tpcgas = *MaterialDataBase::Instance().getMaterial("tpcgas"); + // TMaterial & aluminium = *MaterialDataBase::Instance().getMaterial("aluminium"); + TMaterial & tpcinnerfieldcage = *MaterialDataBase::Instance().getMaterial("tpcinnerfieldcage"); + TMaterial & tpcouterfieldcage = *MaterialDataBase::Instance().getMaterial("tpcouterfieldcage"); + + Bool_t active = true; + Bool_t dummy = false; + + std::string name = "TPC"; + + const double x0 = 0.0; + const double y0 = 0.0; + const double z0 = 0.0; + + + // add inner field cage + Add( new ILDCylinderMeasLayer(air, tpcinnerfieldcage , rtub, lhalf, x0, y0, z0, bz, dummy,-1,"TPCInnerFCInr" ) ); + streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [ inner field cage ] at R = " << rtub + << " X0_in = " << air.GetRadLength() << " X0_out = " << tpcinnerfieldcage.GetRadLength() + << std::endl ; + + Add( new ILDCylinderMeasLayer(tpcinnerfieldcage , tpcgas, rtub+inthick, lhalf, x0, y0, z0, bz, dummy,-1,"TPCInnerFCOtr" ) ); + streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [ inner field cage ] at R = " << rtub+inthick + << " X0_in = " << tpcinnerfieldcage.GetRadLength() << " X0_out = " << tpcgas.GetRadLength() + << std::endl ; + + + streamlog_out( DEBUG0 ) << " *** Inner Field Cage = " << int( (inthick/(tpcinnerfieldcage.GetRadLength()*10.0) /*cm*/ )*1000) / 10.0 << "% of a radiation length " << std::endl ; + + // create measurement layers + Double_t r = rmin; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + for (Int_t layer = 0; layer < nlayers; layer++) { + + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::TPC ; + encoder[lcio::ILDCellID0::layer] = layer ; + + int CellID = encoder.lowWord() ; + + ILDCylinderMeasLayer* tpcL = new ILDCylinderMeasLayer(tpcgas, tpcgas, r, lhalf, x0, y0, z0, bz, active, CellID, "TPCMeasLayer") ; + + Add( tpcL ) ; + + int nth_layers(10) ; + + if( layer % nth_layers == 0 ){ + + streamlog_out( DEBUG0 ) << " *** for TPC Gas printing only every " << nth_layers << "th layer" << std::endl ; + streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [" << CellID << "] at R = " << r + << " X0_in = " << tpcgas.GetRadLength() << " X0_out = " << tpcgas.GetRadLength() + << std::endl ; + } + + r += rstep; + + } + + // add outer field cage + Add( new ILDCylinderMeasLayer(tpcgas, tpcouterfieldcage, outerr-outthick, lhalf, x0, y0, z0, bz, dummy,-1,"TPCOuterFCInr") ) ; + + streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [ outer field cage ] at R = " << outerr-outthick + << " X0_in = " << tpcgas.GetRadLength() << " X0_out = " << tpcouterfieldcage.GetRadLength() + << std::endl ; + + Add( new ILDCylinderMeasLayer(tpcouterfieldcage, air, outerr, lhalf, x0, y0, z0, bz, dummy,-1,"TPCOuterFCOtr") ) ; + + streamlog_out( DEBUG0 ) << " *** adding " << name << " Measurement layer using CellID: [ outer field cage ] at R = " << outerr + << " X0_in = " << tpcouterfieldcage.GetRadLength() << " X0_out = " << air.GetRadLength() + << std::endl ; + + streamlog_out( DEBUG0 ) << " *** Outer Field Cage = " << int( (outthick/(tpcouterfieldcage.GetRadLength()*10.0) /*cm*/ )*1000) / 10.0 << "% of a radiation length " << std::endl ; + + + SetOwner(); +} + + +} diff --git a/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.h b/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..e5ab8db97c723357f2fbd8e964ab319ec7102ca6 --- /dev/null +++ b/Utilities/KalDet/src/ild/tpc/ILDTPCKalDetector.h @@ -0,0 +1,29 @@ +#ifndef __ILDTPCDETECTOR__ +#define __ILDTPCDETECTOR__ + +/** TPC to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +class TNode; + +namespace gear{ + class GearMgr ; +} + + +class ILDTPCKalDetector : public TVKalDetector { +public: + + /** Initialize the TPC from GEAR */ + ILDTPCKalDetector( const gear::GearMgr& gearMgr ); + + +private: + +}; + +#endif diff --git a/Utilities/KalDet/src/ild/vxd/ILDVXDKalDetector.cc b/Utilities/KalDet/src/ild/vxd/ILDVXDKalDetector.cc new file mode 100644 index 0000000000000000000000000000000000000000..a820db54985ae8936acecc432c08577a3f9324de --- /dev/null +++ b/Utilities/KalDet/src/ild/vxd/ILDVXDKalDetector.cc @@ -0,0 +1,406 @@ + +#include "ILDVXDKalDetector.h" + +#include "MaterialDataBase.h" + +#include "ILDParallelPlanarMeasLayer.h" +#include "ILDCylinderMeasLayer.h" +#include "ILDDiscMeasLayer.h" + +#include <UTIL/BitField64.h> +#include <UTIL/ILDConf.h> + +#include <gear/GEAR.h> +#include "gear/BField.h" +#include <gearimpl/ZPlanarParametersImpl.h> +#include <gear/VXDParameters.h> +#include <gear/VXDLayerLayout.h> +#include "gearimpl/Util.h" +#include "DetInterface/IGeoSvc.h" + +#include "TMath.h" + +#include "math.h" +#include <sstream> + +// #include "streamlog/streamlog.h" + +ILDVXDKalDetector::ILDVXDKalDetector( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc ) +: TVKalDetector(300) // SJA:FIXME initial size, 300 looks reasonable for ILD, though this would be better stored as a const somewhere +{ + + // streamlog_out(DEBUG1) << "ILDVXDKalDetector building VXD detector using GEAR " << std::endl ; + + MaterialDataBase::Instance().registerForService(gearMgr, geoSvc); + + TMaterial & air = *MaterialDataBase::Instance().getMaterial("air"); + TMaterial & silicon = *MaterialDataBase::Instance().getMaterial("silicon"); + TMaterial & carbon = *MaterialDataBase::Instance().getMaterial("VXDSupportMaterial"); + TMaterial & beryllium = *MaterialDataBase::Instance().getMaterial("beryllium"); + + // needed for cryostat + + TMaterial & aluminium = *MaterialDataBase::Instance().getMaterial("aluminium"); + + _vxd_Cryostat.exists = false; + + this->setupGearGeom(gearMgr, geoSvc) ; + + //--The Ladder structure (realistic ladder)-- + int nLadders; + + Bool_t active = true; + Bool_t dummy = false; + + static const double eps = 1e-6; + + UTIL::BitField64 encoder( lcio::ILDCellID0::encoder_string ) ; + + for (int layer=0; layer<_nLayers; ++layer) { + + nLadders = _VXDgeo[layer].nLadders ; + + double phi0 = _VXDgeo[layer].phi0 ; + + double ladder_distance = _VXDgeo[layer].supRMin ; + double ladder_thickness = _VXDgeo[layer].supThickness ; + + double sensitive_distance = _VXDgeo[layer].senRMin ; + double sensitive_thickness = _VXDgeo[layer].senThickness ; + + double width = _VXDgeo[layer].width ; + double length = _VXDgeo[layer].length; + double offset = _VXDgeo[layer].offset; + + double pos_xi_nonoverlap_width = (2.0 * (( width / 2.0 ) - fabs(offset))); + + double currPhi; + double dphi = _VXDgeo[layer].dphi ; + + static const double z_offset = 0.0; // all VXD planes are centred at zero + + for (int ladder=0; ladder<nLadders; ++ladder) { + + currPhi = phi0 + (dphi * ladder); + + encoder.reset() ; // reset to 0 + + encoder[lcio::ILDCellID0::subdet] = lcio::ILDDetID::VXD ; + encoder[lcio::ILDCellID0::side] = 0 ; + encoder[lcio::ILDCellID0::layer] = layer ; + encoder[lcio::ILDCellID0::module] = ladder ; + encoder[lcio::ILDCellID0::sensor] = 0 ; + + int CellID = encoder.lowWord() ; + + // even layers have the senstive side facing the IP + if(layer%2 == 0 ){ // overlap section of ladder0 is defined after the last ladder, + + + double sen_front_sorting_policy = sensitive_distance + (4 * ladder+0) * eps ; + double measurement_plane_sorting_policy = sensitive_distance + (4 * ladder+1) * eps ; + double sen_back_sorting_policy = sensitive_distance + (4 * ladder+2) * eps ; + double sup_back_sorting_policy = sensitive_distance + (4 * ladder+3) * eps ; + + + if(ladder==0){ // bacause overlap section of ladder0 is further outer than the last ladder. + + // streamlog_out(DEBUG0) << "ILDVXDKalDetector add surface with CellID = " + // << CellID + // << std::endl ; + + // non overlapping region + // air - sensitive boundary + Add(new ILDParallelPlanarMeasLayer(air, silicon, sensitive_distance, currPhi, _bZ, sen_front_sorting_policy, pos_xi_nonoverlap_width, length, 0.0, z_offset, offset, dummy,-1,"VXDSenFront_non_overlap_even" )) ; + + // measurement plane defined as the middle of the sensitive volume - unless "relative_position_of_measurement_surface" parameter given in GEAR + Add(new ILDParallelPlanarMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*_relative_position_of_measurement_surface, currPhi, _bZ, measurement_plane_sorting_policy, pos_xi_nonoverlap_width, length, 0.0, z_offset, offset, active, CellID, "VXDMeasLayer_non_overlap_even" )) ; + + // sensitive - support boundary + Add(new ILDParallelPlanarMeasLayer(silicon, carbon, sensitive_distance+sensitive_thickness, currPhi, _bZ, sen_back_sorting_policy, pos_xi_nonoverlap_width, length, 0.0, z_offset, offset, dummy,-1,"VXDSenSuppportIntf_non_overlap_even" )) ; + + // support - air boundary + Add(new ILDParallelPlanarMeasLayer(carbon, air, ladder_distance+ladder_thickness, currPhi, _bZ, sup_back_sorting_policy, pos_xi_nonoverlap_width, length, 0.0, z_offset, offset, dummy,-1,"VXDSupRear_non_overlap_even" )) ; + + + // overlapping region + double overlap_region_width = width - pos_xi_nonoverlap_width ; + double overlap_region_offset = -(overlap_region_width/2.0) - (pos_xi_nonoverlap_width)/2.0 ; + + + // overlap sorting policy uses nLadders as the overlapping "ladder" is the order i.e. there will now be nLadders+1 + double overlap_front_sorting_policy = sensitive_distance + (4* nLadders+0) * eps; + double overlap_measurement_plane_sorting_policy = sensitive_distance + (4* nLadders+1) * eps; + double overlap_back_sorting_policy = sensitive_distance + (4* nLadders+2) * eps; + double overlap_sup_back_sorting_policy = sensitive_distance + (4* nLadders+3) * eps; + + // streamlog_out(DEBUG0) << "ILDVXDKalDetector add surface with CellID = " + // << CellID + // << std::endl ; + + // air - sensitive boundary + Add(new ILDParallelPlanarMeasLayer(air, silicon, sensitive_distance, currPhi, _bZ, overlap_front_sorting_policy, overlap_region_width, length, overlap_region_offset, z_offset, offset, dummy,-1,"VXDSenFront_overlap_even")) ; + + // measurement plane defined as the middle of the sensitive volume - unless "relative_position_of_measurement_surface" parameter given in GEAR + Add(new ILDParallelPlanarMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*_relative_position_of_measurement_surface, currPhi, _bZ, overlap_measurement_plane_sorting_policy, overlap_region_width, length, overlap_region_offset, z_offset, offset, active, CellID, "VXDMeasLayer_overlap_even" )) ; + + + // sensitive - support boundary + Add(new ILDParallelPlanarMeasLayer(silicon, carbon, sensitive_distance+sensitive_thickness, currPhi, _bZ, overlap_back_sorting_policy, overlap_region_width, length, overlap_region_offset, z_offset, offset, dummy,-1,"VXDSenSuppportIntf_overlap_even")) ; + + // support - air boundary + Add(new ILDParallelPlanarMeasLayer(carbon, air, ladder_distance+ladder_thickness, currPhi, _bZ, overlap_sup_back_sorting_policy, overlap_region_width, length, overlap_region_offset, z_offset, offset, dummy,-1,"VXDSupRear_overlap_even")) ; + + } + else{ + + // streamlog_out(DEBUG0) << "ILDVXDKalDetector (ILDParallelPlanarMeasLayer) add surface with CellID = " + // << CellID + // << std::endl ; + + + // air - sensitive boundary + Add(new ILDParallelPlanarMeasLayer(air, silicon, sensitive_distance, currPhi, _bZ, sen_front_sorting_policy, width, length, offset, z_offset, offset, dummy,-1, "VXDSenFront_even")) ; + + + // measurement plane defined as the middle of the sensitive volume - unless "relative_position_of_measurement_surface" parameter given in GEAR - even layers face outwards ! + Add(new ILDParallelPlanarMeasLayer(silicon, silicon, sensitive_distance+sensitive_thickness*( 1.-_relative_position_of_measurement_surface ), currPhi, _bZ, measurement_plane_sorting_policy, width, length, offset, z_offset, offset, active, CellID, "VXDMeaslayer_even" )) ; + + // sensitive - support boundary + Add(new ILDParallelPlanarMeasLayer(silicon, carbon, sensitive_distance+sensitive_thickness, currPhi, _bZ, sen_back_sorting_policy, width, length, offset, z_offset, offset, dummy,-1,"VXDSenSuppportIntf_even" )) ; + + // support - air boundary + Add(new ILDParallelPlanarMeasLayer(carbon, air, ladder_distance+ladder_thickness, currPhi, _bZ, sup_back_sorting_policy, width, length, offset, z_offset, offset, dummy,-1,"VXDSupRear_even" )) ; + + } + } + else{ // counting from 0, odd numbered layers are placed with the support closer to the IP than the sensitive + + + + double sup_forward_sorting_policy = ladder_distance + (4 * ladder+0) * eps ; + double sup_back_sorting_policy = ladder_distance + (4 * ladder+1) * eps ; + double measurement_plane_sorting_policy = ladder_distance + (4 * ladder+2) * eps ; + double sen_back_sorting_policy = ladder_distance + (4 * ladder+3) * eps ; + + // streamlog_out(DEBUG0) << "ILDVXDKalDetector (ILDPlanarMeasLayer) add surface with CellID = " + // << CellID + // << std::endl ; + + // air - support boundary + Add(new ILDParallelPlanarMeasLayer(air, carbon, ladder_distance, currPhi, _bZ, sup_forward_sorting_policy, width, length, offset, z_offset, offset, dummy,-1,"VXDSupFront_odd" )) ; + + // support - sensitive boundary + Add(new ILDParallelPlanarMeasLayer(carbon, silicon, (ladder_distance+ladder_thickness), currPhi, _bZ, sup_back_sorting_policy, width, length, offset, z_offset, offset, dummy,-1,"VXDSenSuppportIntf_odd")) ; + + // measurement plane defined as the middle of the sensitive volume + Add(new ILDParallelPlanarMeasLayer(silicon, silicon, (sensitive_distance+sensitive_thickness*0.5), currPhi, _bZ, measurement_plane_sorting_policy, width, length, offset, z_offset, offset, active, CellID, "VXDMeaslayer_odd")) ; + + // sensitive air - sensitive boundary + Add(new ILDParallelPlanarMeasLayer(silicon, air, (sensitive_distance+sensitive_thickness), currPhi, _bZ, sen_back_sorting_policy, width, length, offset, z_offset, offset, dummy,-1,"VXDSenRear_odd")) ; + + + } + } + } + + if (_vxd_Cryostat.exists) { + // build Cryostat according to mokka driver vxd04.cc + + // beryllium shell + + double rtub = _vxd_Cryostat.shellInnerR; + double halfz = _vxd_Cryostat.shelllHalfZ; + + const double x0 = 0.0; + const double y0 = 0.0; + const double z0 = 0.0; + + + // beryllium cylinder inner wall + Add( new ILDCylinderMeasLayer(air, beryllium , rtub, halfz, x0, y0, z0, _bZ, dummy,-1,"VXDShellInnerWall" ) ); + + // streamlog_out( DEBUG0 ) << " *** adding " << "VXDShellInnerWall" << " Measurement layer using CellID: [ VXDShellInnerWall ] at R = " << rtub + // << " X0_in = " << air.GetRadLength() << " X0_out = " << beryllium.GetRadLength() + // << std::endl; + + + rtub += _vxd_Cryostat.shellThickness; + + // beryllium cylinder outer wall + Add( new ILDCylinderMeasLayer(beryllium, air , rtub, halfz, x0, y0, z0, _bZ, dummy,-1,"VXDShellOuterWall" ) ); + + // streamlog_out( DEBUG0 ) << " *** adding " << "VXDShellOuterWall" << " Measurement layer using CellID: [ VXDShellOuterWall ] at R = " << rtub + // << " X0_in = " << beryllium.GetRadLength() << " X0_out = " << air.GetRadLength() + // << std::endl; + + + rtub = _vxd_Cryostat.alRadius; + halfz = _vxd_Cryostat.alHalfZ; + + + // aluminum cylinder inner wall + Add( new ILDCylinderMeasLayer(air, aluminium , _vxd_Cryostat.alRadius, halfz, x0, y0, z0, _bZ, dummy,-1,"VXDCryoAlInnerWall" ) ); + + + // streamlog_out( DEBUG0 ) << " *** adding " << "VXDCryoAlInnerWall" << " Measurement layer using CellID: [ VXDCryoAlInnerWall ] at R = " << rtub + // << " X0_in = " << air.GetRadLength() << " X0_out = " << aluminium.GetRadLength() + // << std::endl; + + rtub += 1.1 * _vxd_Cryostat.alThickness; // SJA:FIXME: increase the thickness as we don't have the information on the foam in the GEAR file. + + // aluminum cylinder outer wall + Add( new ILDCylinderMeasLayer(aluminium, air , rtub, halfz, x0, y0, z0, _bZ, dummy,-1,"VXDCryoAlOuterWall" ) ); + + + // streamlog_out( DEBUG0 ) << " *** adding " << "VXDCryoAlOuterWall" << " Measurement layer using CellID: [ VXDCryoAlOuterWall ] at R = " << rtub + // << " X0_in = " << aluminium.GetRadLength() << " X0_out = " << air.GetRadLength() + // << std::endl; + + + // aluminum endcaps + + + const double z_front_face = _vxd_Cryostat.alZEndCap; + const double z_rear_face = z_front_face + _vxd_Cryostat.alThickness; + + double rOuter = _vxd_Cryostat.alRadius - 0.1 ; // make sure we don't collide with the aluminium cryostat cylinder + double rInner = _vxd_Cryostat.alInnerR ; + + + double eps_face = 1.0e-06 ; // offset for forwards and backwards + double eps_side = 1.0e-08 ; // offset for forwards and backwards + + double sort_policy = rOuter ; + + + TVector3 xc_fwd(0.0, 0.0, z_front_face) ; + TVector3 normal_fwd(xc_fwd) ; + normal_fwd.SetMag(1.0) ; + + // streamlog_out(DEBUG) << "VXDCryoAleEndCap created disk at " << xc_fwd.z() << " sort_policy = " << sort_policy << std::endl; + + Add(new ILDDiscMeasLayer( air, aluminium, xc_fwd, normal_fwd, _bZ, sort_policy, + rInner, rOuter, dummy,-1, "VXDCryoAleEndCapDiscFrontFwd" ) ); + + sort_policy += eps_face; + xc_fwd.SetZ(z_rear_face); + + Add(new ILDDiscMeasLayer( aluminium, air, xc_fwd, normal_fwd, _bZ, sort_policy, + rInner, rOuter, dummy,-1, "VXDCryoAleEndCapDiscBackFwd" ) ); + + + TVector3 xc_bwd(0.0, 0.0, -z_front_face) ; + TVector3 normal_bwd(xc_bwd) ; + normal_bwd.SetMag(1.0) ; + + // offset needed for rear disks + sort_policy = rOuter + eps_side ; + + // streamlog_out(DEBUG) << "VXDCryoAleEndCap created disk at " << xc_bwd.z() << " sort_policy = " << sort_policy << std::endl; + + Add(new ILDDiscMeasLayer( air, aluminium, xc_bwd, normal_bwd, _bZ, sort_policy, + rInner, rOuter, dummy,-1, "VXDCryoAleEndCapDiscFrontBwd" ) ); + + sort_policy += eps_face; + xc_fwd.SetZ(-z_rear_face); + + Add(new ILDDiscMeasLayer( aluminium, air, xc_bwd, normal_bwd, _bZ, sort_policy, + rInner, rOuter, dummy,-1, "VXDCryoAleEndCapDiscFrontBwd" ) ); + + + + } + + SetOwner(); +} + + + + +void ILDVXDKalDetector::setupGearGeom( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc){ + + const gear::VXDParameters& pVXDDetMainObject = gearMgr.getVXDParameters(); + const gear::VXDParameters* pVXDDetMain2 = &pVXDDetMainObject; + const gear::ZPlanarParametersImpl* pVXDDetMain = geoSvc->getVXDParameters(); + const gear::VXDLayerLayout& pVXDLayerLayout = pVXDDetMain->getVXDLayerLayout(); + const gear::VXDLayerLayout& pVXDLayerLayout2 = pVXDDetMain2->getVXDLayerLayout(); + + _bZ = gearMgr.getBField().at( gear::Vector3D( 0.,0.,0.) ).z() ; + + _nLayers = pVXDLayerLayout.getNLayers(); + _VXDgeo.resize(_nLayers); + + //SJA:FIXME: for now the support is taken as the same size the sensitive + // if this is not done then the exposed areas of the support would leave a carbon - air boundary, + // which if traversed in the reverse direction to the next boundary then the track will be propagated through carbon + // for a significant distance + + for( int layer=0; layer < _nLayers; ++layer){ + _VXDgeo[layer].nLadders = pVXDLayerLayout.getNLadders(layer); + _VXDgeo[layer].phi0 = pVXDLayerLayout.getPhi0(layer); + _VXDgeo[layer].dphi = 2*M_PI / _VXDgeo[layer].nLadders; + _VXDgeo[layer].senRMin = pVXDLayerLayout.getSensitiveDistance(layer); + _VXDgeo[layer].supRMin = pVXDLayerLayout.getLadderDistance(layer); + _VXDgeo[layer].length = pVXDLayerLayout.getSensitiveLength(layer) * 2.0 ; // note: gear for historical reasons uses the halflength + _VXDgeo[layer].width = pVXDLayerLayout.getSensitiveWidth(layer); + _VXDgeo[layer].offset = pVXDLayerLayout.getSensitiveOffset(layer); + _VXDgeo[layer].senThickness = pVXDLayerLayout.getSensitiveThickness(layer); + _VXDgeo[layer].supThickness = pVXDLayerLayout.getLadderThickness(layer); + std::cout << layer << ": " << _VXDgeo[layer].nLadders << " " << _VXDgeo[layer].phi0 << " " << _VXDgeo[layer].dphi << " " << _VXDgeo[layer].senRMin + << " " << _VXDgeo[layer].supRMin << " " << _VXDgeo[layer].length << " " << _VXDgeo[layer].width << " " << _VXDgeo[layer].offset + << " " << _VXDgeo[layer].senThickness << " " << _VXDgeo[layer].supThickness << std::endl; + std::cout << layer << ": " << pVXDLayerLayout2.getNLadders(layer) << " " << pVXDLayerLayout2.getPhi0(layer) << " " << 2*M_PI/pVXDLayerLayout2.getNLadders(layer) + << " " << pVXDLayerLayout2.getSensitiveDistance(layer) << " " << pVXDLayerLayout2.getLadderDistance(layer) + << " " << pVXDLayerLayout2.getSensitiveLength(layer)*2 << " " << pVXDLayerLayout2.getSensitiveWidth(layer) + << " " << pVXDLayerLayout2.getSensitiveOffset(layer) << " " << pVXDLayerLayout2.getSensitiveThickness(layer) + << " " << pVXDLayerLayout2.getLadderThickness(layer) << std::endl; + } + // by default, we put the measurement surface in the middle of the sensitive + // layer, this can optionally be changed, e.g. in the case of the FPCCD where the + // epitaxial layer is 15 mu thick (in a 50 mu wafer) + _relative_position_of_measurement_surface = 0.5 ; + + try { + + _relative_position_of_measurement_surface = pVXDDetMain->getDoubleVal( "relative_position_of_measurement_surface" ); + + // streamlog_out(DEBUG) << " ILDVXDKalDetector::setupGearGeom: relative_position_of_measurement_surface parameter is provided : " << _relative_position_of_measurement_surface << std::endl ; + + } catch (gear::UnknownParameterException& e) {} + + // Cryostat + try { + + //const gear::GearParameters& pVXDInfraObject = gearMgr.getGearParameters("VXDInfra"); + //const gear::GearParameters* pVXDInfra = &pVXDInfraObject; + //change Gear to GeoSvc + //const gear::GearParametersImpl* pVXDInfra = geoSvc->getDetParameters("VXDInfra"); + //_vxd_Cryostat.alRadius = pVXDInfra->getDoubleVal( "CryostatAlRadius" ); + //_vxd_Cryostat.alThickness = pVXDInfra->getDoubleVal( "CryostatAlThickness" ); + //_vxd_Cryostat.alInnerR = pVXDInfra->getDoubleVal( "CryostatAlInnerR" ); + //_vxd_Cryostat.alZEndCap = pVXDInfra->getDoubleVal( "CryostatAlZEndCap" ); + //_vxd_Cryostat.alHalfZ = pVXDInfra->getDoubleVal( "CryostatAlHalfZ" ); + //change GearParametersImpl to get directly + //const std::map<std::string,double>& vxdInfra = geoSvc->getDetParameters("VXDInfra"); + _vxd_Cryostat.alRadius = geoSvc->getDetParameter("VXDInfra","CryostatAlRadius"); + _vxd_Cryostat.alThickness = geoSvc->getDetParameter("VXDInfra","CryostatAlThickness"); + _vxd_Cryostat.alInnerR = geoSvc->getDetParameter("VXDInfra","CryostatAlInnerR"); + _vxd_Cryostat.alZEndCap = geoSvc->getDetParameter("VXDInfra","CryostatAlZEndCap"); + _vxd_Cryostat.alHalfZ = geoSvc->getDetParameter("VXDInfra","CryostatAlHalfZ"); + + _vxd_Cryostat.shellInnerR = pVXDDetMain->getShellInnerRadius(); + _vxd_Cryostat.shellThickness = pVXDDetMain->getShellOuterRadius() - _vxd_Cryostat.shellInnerR; + _vxd_Cryostat.shelllHalfZ = pVXDDetMain->getShellHalfLength(); + + _vxd_Cryostat.exists = true; + } + //catch (gear::UnknownParameterException& e) { + catch (std::runtime_error& e) { + //streamlog_out( WARNING ) << "ILDVXDKalDetector Cryostat values not found in GEAR file " << std::endl ; + std::cout << e.what() << std::endl ; + _vxd_Cryostat.exists = false; + + } + +} diff --git a/Utilities/KalDet/src/ild/vxd/ILDVXDKalDetector.h b/Utilities/KalDet/src/ild/vxd/ILDVXDKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..c0205e149f55b4ca2340cdfc7549b17fd020cdbc --- /dev/null +++ b/Utilities/KalDet/src/ild/vxd/ILDVXDKalDetector.h @@ -0,0 +1,73 @@ +#ifndef __ILDVXDKALDETECTOR__ +#define __ILDVXDKALDETECTOR__ + +/** Ladder based VXD to be used for ILD DBD studies + * + * @author S.Aplin DESY + */ + +#include "kaltest/TVKalDetector.h" + +#include "TMath.h" + +class TNode; +class IGeoSvc; + +namespace gear{ + class GearMgr ; +} + + +class ILDVXDKalDetector : public TVKalDetector { + +public: + + ILDVXDKalDetector( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc); + + +private: + + void setupGearGeom( const gear::GearMgr& gearMgr, IGeoSvc* geoSvc) ; + + int _nLayers ; + double _bZ ; + + double _relative_position_of_measurement_surface ; + + struct VXD_Layer { + int nLadders; + double phi0; + double dphi; + double senRMin; + double supRMin; + double length; + double width; + double offset; + double senThickness; + double supThickness; + }; + std::vector<VXD_Layer> _VXDgeo; + + + struct VXD_Cryostat { + double alRadius; + double alThickness; + double alInnerR; + double alZEndCap; + double alHalfZ; + double shellRadius; + double shellThickness; + double shellInnerR; + double shellZEndCap; + double shelllHalfZ; + + bool exists; + }; + + VXD_Cryostat _vxd_Cryostat; + +}; + + + +#endif diff --git a/Utilities/KalDet/src/kern/EXVKalDetector.cxx b/Utilities/KalDet/src/kern/EXVKalDetector.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d65bb32c2ea32d5fa073e3412e4ed032e6d546ba --- /dev/null +++ b/Utilities/KalDet/src/kern/EXVKalDetector.cxx @@ -0,0 +1,34 @@ +//************************************************************************* +//* ====================== +//* EXVKalDetector Class +//* ====================== +//* +//* (Description) +//* Abstract detector class for Kalman filter +//* (Requires) +//* TVKalDetector +//* (Provides) +//* class EXVKalDetector +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/kern/EXVKalDetector.cxx +//* 2010/11/17 K.Fujii Changed unit system to (mm, nsec, T) +//* from (cm, nsec, kG) +//* +//* $Id: EXVKalDetector.cxx,v 1.1.1.1 2009-11-24 00:13:59 ikematsu Exp $ +//************************************************************************* +// +#include "EXVKalDetector.h" + +ClassImp(EXVKalDetector) + +EXVKalDetector::EXVKalDetector(Double_t bField, Int_t m) + : TVKalDetector(m), + fIsPowerOn(kTRUE), + fBfield(bField) +{ +} + +EXVKalDetector::~EXVKalDetector() +{ +} diff --git a/Utilities/KalDet/src/kern/EXVKalDetector.h b/Utilities/KalDet/src/kern/EXVKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..f7a8413a462bf37f1f51da528a521537d815bf34 --- /dev/null +++ b/Utilities/KalDet/src/kern/EXVKalDetector.h @@ -0,0 +1,68 @@ +#ifndef EXVKALDETECTOR_H +#define EXVKALDETECTOR_H +//************************************************************************* +//* ====================== +//* EXVKalDetector Class +//* ====================== +//* +//* (Description) +//* Abstract detector class for Kalman filter +//* (Requires) +//* TVKalDetector +//* (Provides) +//* class EXVKalDetector +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/kern/EXVKalDetector.h +//* +//* $Id: EXVKalDetector.h,v 1.1.1.1 2009-11-24 00:13:59 ikematsu Exp $ +//************************************************************************* +// +#include <TVector3.h> +#include <kaltest/TVKalDetector.h> +#include <kaltest/TAttDrawable.h> + +class TNode; + +/** + * Base class to make a detector drawable, add a magnetic field, + * a power switch (whatever the use may be). + * + * Killenb: I removed the TAttDrawable for the moment. The TNode pointer + * stuff and the implementation of Draw belong to the TAttDrawable anyway. So if + * the drawability is needed move it to TAttDrawable and just inherit from it. + * + * \deprecated EXVKalDetector + */ +//class EXVKalDetector : public TVKalDetector, public TAttDrawable { +class EXVKalDetector : public TVKalDetector { + +public: + EXVKalDetector(Double_t bField, Int_t m = 100); + virtual ~EXVKalDetector(); + + /// Return whether the power is on. Currently hard coded to true. + inline virtual Bool_t IsPowerOn() const { return true; } + + /// Turn the power on. Currently ignored. + inline virtual void PowerOn () { fIsPowerOn = kTRUE; } + + /// Turn the power off. Currently ignored. + inline virtual void PowerOff () { fIsPowerOn = kFALSE; } + + /// Returns a single double value with a 3D point as an input. + /// Completely unphysical interface. Either the magnetic field varies with the position, + /// in which case you need a three-dimensional return value, or B can be desrcibed as single + /// value, which means it is homogeneous and thus indepenent from the position. + /// Currently it does the only reasonable thing: It ignores the argument and returns the + /// constant value given in the constructor. + virtual Double_t GetBfield (const TVector3 &xx = TVector3(0.,0.,0.)) const + { return fBfield; } + +protected: + Bool_t fIsPowerOn; // power status + Double_t fBfield; // magnetic field [T] + + ClassDef(EXVKalDetector, 1) // Abstract measurement layer class +}; +#endif diff --git a/Utilities/KalDet/src/kern/EXVMeasLayer.cxx b/Utilities/KalDet/src/kern/EXVMeasLayer.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3ce17f2d16d4b02833da68da3489b1b585ed492b --- /dev/null +++ b/Utilities/KalDet/src/kern/EXVMeasLayer.cxx @@ -0,0 +1,39 @@ +//************************************************************************* +//* ==================== +//* EXVMeasLayer Class +//* ==================== +//* +//* (Description) +//* Abstract measurement layer class used by TVTrackHit +//* (Requires) +//* TVMeasLayer +//* (Provides) +//* class EXVMeasLayer +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/kern/EXVMeasLayer.cxx +//* +//* $Id: EXVMeasLayer.cxx,v 1.1.1.1 2009-11-24 00:13:59 ikematsu Exp $ +//************************************************************************* +// +#include "EXVMeasLayer.h" +#include <TNode.h> + +Bool_t EXVMeasLayer::kActive = kTRUE; +Bool_t EXVMeasLayer::kDummy = kFALSE; + +ClassImp(EXVMeasLayer) + +EXVMeasLayer::EXVMeasLayer(TMaterial &min, + TMaterial &mout, + Bool_t isactive, + const Char_t *name) + : TVMeasLayer(min, mout, isactive), + fName(name), + fNodePtr(0) +{ +} + +EXVMeasLayer::~EXVMeasLayer() +{ +} diff --git a/Utilities/KalDet/src/kern/EXVMeasLayer.h b/Utilities/KalDet/src/kern/EXVMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..db456868c0886921699599834ace276b7d54d426 --- /dev/null +++ b/Utilities/KalDet/src/kern/EXVMeasLayer.h @@ -0,0 +1,60 @@ +#ifndef EXVMEASLAYER_H +#define EXVMEASLAYER_H +//************************************************************************* +//* ==================== +//* EXVMeasLayer Class +//* ==================== +//* +//* (Description) +//* Abstract measurement layer class used by TVTrackHit +//* (Requires) +//* TVMeasLayer +//* (Provides) +//* class EXVMeasLayer +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/kern/EXVMeasLayer.h +//* +//* $Id: EXVMeasLayer.h,v 1.1.1.1 2009-11-24 00:13:59 ikematsu Exp $ +//************************************************************************* +// +#include <TVector3.h> +#include <kaltest/TKalMatrix.h> +#include <kaltest/TCylinder.h> +#include <kaltest/TVMeasLayer.h> +#include <kaltest/TAttDrawable.h> +#include <kaltest/KalTrackDim.h> +#include <TString.h> + +class TVTrackHit; +#include <TNode.h> + +class EXVMeasLayer : public TVMeasLayer, public TAttDrawable { + +public: + static Bool_t kActive; + static Bool_t kDummy; + + // Ctors and Dtor + + EXVMeasLayer(TMaterial &min, + TMaterial &mout, + Bool_t type = EXVMeasLayer::kActive, + const Char_t *name = "MeasL"); + virtual ~EXVMeasLayer(); + + virtual void ProcessHit(const TVector3 &xx, + TObjArray &hits) const = 0; + + inline TString GetMLName () const { return fName; } + inline TNode *GetNodePtr() const { return fNodePtr; } + + inline void SetNodePtr(TNode *nodep) { fNodePtr = nodep; } + +private: + TString fName; // layer name + TNode *fNodePtr; // node pointer + + ClassDef(EXVMeasLayer, 1) // Abstract measurement layer class +}; +#endif diff --git a/Utilities/KalDet/src/kern/LinkDef.h b/Utilities/KalDet/src/kern/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..e4f3a1c5692a6c07b66ae8a68e810783672a6ea4 --- /dev/null +++ b/Utilities/KalDet/src/kern/LinkDef.h @@ -0,0 +1,10 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class EXVKalDetector+; +#pragma link C++ class EXVMeasLayer+; + +#endif diff --git a/Utilities/KalDet/src/lctpc/doc/Doxyfile_html b/Utilities/KalDet/src/lctpc/doc/Doxyfile_html new file mode 100644 index 0000000000000000000000000000000000000000..5d8d0456bda50333081f240ce26fc53a21ce4f55 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/doc/Doxyfile_html @@ -0,0 +1,1790 @@ +# Doxyfile 1.7.5.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = GearTPC + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../gearTPC \ + GearTPC_mainpage.h + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to directory from which doxygen is run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is adviced to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/Utilities/KalDet/src/lctpc/doc/Doxyfile_latex b/Utilities/KalDet/src/lctpc/doc/Doxyfile_latex new file mode 100644 index 0000000000000000000000000000000000000000..26eb34dc728b9001365f38c4cdfe4db230b05e60 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/doc/Doxyfile_latex @@ -0,0 +1,1790 @@ +# Doxyfile 1.7.5.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = GearTPC + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../gearTPC \ + GearTPC_mainpage.h + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to directory from which doxygen is run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = NO + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is adviced to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/Utilities/KalDet/src/lctpc/doc/GearTPC_mainpage.h b/Utilities/KalDet/src/lctpc/doc/GearTPC_mainpage.h new file mode 100644 index 0000000000000000000000000000000000000000..b6793715ca22da768de1841a8cf5170372b0b009 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/doc/GearTPC_mainpage.h @@ -0,0 +1,15 @@ +/** +@mainpage + +GearTPCKalDetector is a KalDet implementation for the LCTPC collaboration +which is flexible enough to handle multiple detector geometries +without having to adapt the code. It instantiates the full KalDet geometry only from information from the Gear file. +The design is flexible enough that any geometry which can be described with gear +can also be treated by the Kalman detector. Currently not all parts are +implemented, for instance straight pad rows / Kalman layers. In this +case an error message is printed and a gear::NotImplementedException is thrown. + +For backward compatibility the EXTPC interface has been reimplemented using +the GearTPC classes. Once all dependencies on EXTPC have been removed from +MarlinTPC these compatibility classes will be removed from KalDet. + */ diff --git a/Utilities/KalDet/src/lctpc/doc/Readme b/Utilities/KalDet/src/lctpc/doc/Readme new file mode 100644 index 0000000000000000000000000000000000000000..bfb7eb61b1155634b636efa6a360315d793083ff --- /dev/null +++ b/Utilities/KalDet/src/lctpc/doc/Readme @@ -0,0 +1,4 @@ +There are two different doxy-files for html and latex. For the latex version +the sourcecode brower, namespace and file lists are truned of in order not to +overload the document with information that is not very useful when +printed. In the html version you want these features. diff --git a/Utilities/KalDet/src/lctpc/gearTPC/EXTPCHit.cxx b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCHit.cxx new file mode 100644 index 0000000000000000000000000000000000000000..91aa0898cfc369fecb55f2eb75b6bbb77f77cd7c --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCHit.cxx @@ -0,0 +1,27 @@ +#include "EXTPCHit.h" + +EXTPCHit::EXTPCHit(Int_t m) : kaldet::GearTPCCylinderHit(m) , fSide(0) {} + +EXTPCHit::EXTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const TVector3 &xx, + Double_t b, + Int_t m) + : kaldet::GearTPCCylinderHit(ms, x, dx, xx, b, v, m), fSide(side) {} + +EXTPCHit::EXTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const void *hitp, + Double_t b, + Int_t m) + : kaldet::GearTPCCylinderHit(ms, x, dx, hitp, b, v, m), fSide(side) {} + +EXTPCHit::~EXTPCHit() +{} + diff --git a/Utilities/KalDet/src/lctpc/gearTPC/EXTPCHit.h b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCHit.h new file mode 100644 index 0000000000000000000000000000000000000000..8d604c36f5b3120156e030626f293e312aa3dac6 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCHit.h @@ -0,0 +1,54 @@ +#ifndef LCTPC_EXTPCHIT_H +#define LCTPC_EXTPCHIT_H + +#include "GearTPCCylinderHit.h" +#include <kaltest/TVMeasLayer.h> + +/** + * A backward compatibility class for GearTPCCylinderHit. + * Do not use this in new code, but use GearTPCCylinderHit directly. + * This class extends the GearTPCCylinderHit by a side, which is never used anywhere. + * + * \deprecated EXTPCHit + */ + +class EXTPCHit : public kaldet::GearTPCCylinderHit +{ + public: + /// The default constructor. + EXTPCHit(Int_t m = kMdim); + + /// Constructor initialising the original hit as 3D coordinates. + EXTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const TVector3 &xx, + Double_t b, + Int_t m = kMdim); + + /// Constructor initialising the original hit with a reference pointer. + EXTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const void *hitp, + Double_t b, + Int_t m = kMdim); + + /// The destructor. + virtual ~EXTPCHit(); + + /// Get the side value which has been set in the constructor. + inline Int_t GetSide () const { return fSide; } + + private: + Int_t fSide; /// (-1, +1) = (-z side, +z side) + + // ClassDef(EXTPCHit, 1) // EXTPC hit class + +}; + +#endif // LCTPC_EXTPCHIT_H diff --git a/Utilities/KalDet/src/lctpc/gearTPC/EXTPCKalDetector.cxx b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCKalDetector.cxx new file mode 100644 index 0000000000000000000000000000000000000000..913398a456ce561ef8a97cbe7ae3f46cd1ea5bdc --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCKalDetector.cxx @@ -0,0 +1,76 @@ +#include "EXTPCKalDetector.h" +#include <kaltest/TKalDetCradle.h> +#include <gear/GearMgr.h> +#include <gear/BField.h> +// #include <streamlog/streamlog.h> +#include <stdlib.h> +// global constants from Marlin, used for the global pointer to the GearMgr +// KILLENB: Worst style I have ever seen. Unfortunately needed to implement +// the static (stupid!!) GetInstance function. I will kick this out as soon +// as I have the comparison with the old code. +//#include <marlin/Global.h> + + +Double_t EXTPCKalDetector::fgVdrift = 76.e-3; // [mm/nsec] +EXTPCKalDetector * EXTPCKalDetector::fgInstance=0; + +//ClassImp(EXTPCKalDetector) + +EXTPCKalDetector::EXTPCKalDetector(const gear::GearMgr& gearMgr) + : kaldet::GearTPCKalDetector(gearMgr) +{ + gear::BField const & bField = gearMgr.getBField(); + // get the BField at 0,0,0. Check that there are no transverse components + // FIXME: Event though there are no transverse components at 0, 0, 0 does not mean + // there are no transverse components somewhere else. + gear::Vector3D bFieldVector = bField.at(gear::Vector3D(0., 0., 0.)); + if (bFieldVector[0]!=0 || bFieldVector[1]!=0) + { + // streamlog_out(ERROR) << "B-field has transverse components." + // << " EXTPCKalDetector only works with homogeneous B-field" + // << " in z direction" << std::endl; + throw gear::Exception("Magnetic field not in z direction."); + } + + fBField = bFieldVector[2]; +} + +EXTPCKalDetector::~EXTPCKalDetector() +{} + +EXTPCKalDetector * EXTPCKalDetector::GetInstance() +{ + //gear::GearMgr const * gearMgr = marlin::Global::GEAR; + + if (!fgInstance) { + //fgInstance = new EXTPCKalDetector(*gearMgr); + std::cout << "need to fix, no gearMgr...." << std::endl; + exit(1); + // Let's leak some memory. This cradle can never be deleted because we loose the pointer. + // But it cannot be deleted anyway because the Layers in the KalDetector have the cradle as + // parent, so deleting the cradle voids the detector. + // But you also cannot delete the KalDetector, because there are layers pointed to by the cradle. + // Stupid design. + TKalDetCradle * lp1tpc = new TKalDetCradle; + lp1tpc->Install(*fgInstance); + lp1tpc->Close(); + lp1tpc->Sort(); + + //std::cout << "# of layers: " << lp1tpc.GetEntries() << std::endl; + } + return fgInstance; + +} + + Double_t EXTPCKalDetector::GetBfield() + { + if (fgInstance) + return fgInstance->fBField; + else + { + // streamlog_out(ERROR) << " EXTPCKalDetector::GetBField() called without instantiating the object" + // << std::endl; + throw std::exception(); + return 0; + } + } diff --git a/Utilities/KalDet/src/lctpc/gearTPC/EXTPCKalDetector.h b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..96025f38d7ac92b6ac795935ca71b793a2b25799 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCKalDetector.h @@ -0,0 +1,45 @@ +#ifndef LCTPC_EXTPCKALDETECTOR_H +#define LCTPC_EXTPCKALDETECTOR_H + +#include "GearTPCKalDetector.h" + +/** + * A backward compatibility class for GearTPCKalDetector. + * It basically provides a static instance of the detector which can be + * accessed via the GetInstance() method. + * In addition it provides the static GetVDrift() and GetBField(), which are used + * in the old code. The use of this class is highly depreciated. + * + * \deprecated EXTPCKalDetector + */ + +class EXTPCKalDetector: public kaldet::GearTPCKalDetector +{ + private: + /// As this this a singleton class the constructor is private. + EXTPCKalDetector(const gear::GearMgr& gearMgr); + +public: + /// The destructor. + virtual ~EXTPCKalDetector(); + + /// Static access function to the singleton instance. + static EXTPCKalDetector * GetInstance(); + + /// Returns the hard coded drift velocity of 76.e-3 mm/ns. + static Double_t GetVdrift() { return fgVdrift; } + + /// Static function to access the magnetic field. + static Double_t GetBfield(); + + private: + static Double_t fgVdrift; //< The drift velocity. + static EXTPCKalDetector * fgInstance; //< The singleton pointer. + + Double_t fBField; //< The magnetic field + + // ClassDef(EXTPCKalDetector, 1) // User defined detector class + +}; + +#endif // LCTPC_EXTPCKALDETECTOR_H diff --git a/Utilities/KalDet/src/lctpc/gearTPC/EXTPCMeasLayer.cxx b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCMeasLayer.cxx new file mode 100644 index 0000000000000000000000000000000000000000..55f30ba5ae15f9387d1078b5b8c1e4f0e61f7a7b --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCMeasLayer.cxx @@ -0,0 +1,85 @@ +#include "EXTPCMeasLayer.h" +#include "EXTPCKalDetector.h" +#include "EXTPCHit.h" + +#include <TRandom.h> +// #include <streamlog/streamlog.h> + +//ClassImp(EXTPCMeasLayer) + +EXTPCMeasLayer::EXTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Double_t r0, + Double_t lhalf, + TVector3 xc, + Bool_t isPerfect, + Bool_t isActive, + Double_t sigmaX0, + Double_t sigmaX1, + Double_t sigmaZ0, + Double_t sigmaZ1) + : kaldet::GearTPCMeasLayer(min, mout, module, row, isPerfect, isActive, + sigmaX0, sigmaX1, sigmaZ0, sigmaZ1), + TCylinder(r0, lhalf, xc.X(), xc.Y(), xc.Z()) + +{ +} + +EXTPCMeasLayer::~EXTPCMeasLayer(){} + +Int_t EXTPCMeasLayer::GetModuleID() const +{ + return fModuleRows.begin()->first; +} + +Int_t EXTPCMeasLayer::GetLayerID() const +{ + return fModuleRows.begin()->second; +} + +TKalMatrix EXTPCMeasLayer::XvToMv(const TVector3 &xv, Int_t side) const +{ + return XvToMv(xv); +} + +void EXTPCMeasLayer::ProcessHit(const TVector3 &xx, + TObjArray &hits) const +{ + TKalMatrix h = XvToMv(xx); + Double_t rphi = h(0, 0); + Double_t d = h(1, 0); + + Double_t dx = GetSigmaX(d); + Double_t dz = GetSigmaZ(d); + rphi += gRandom->Gaus(0., dx); // smearing rphi + d += gRandom->Gaus(0., dz); // smearing drift distance + + Double_t meas [2]; + Double_t dmeas[2]; + meas [0] = rphi; + meas [1] = d; + dmeas[0] = dx; + dmeas[1] = dz; + + Double_t b; + Double_t vDrift; + try{ + EXTPCKalDetector const & detector = dynamic_cast<EXTPCKalDetector const &>(GetParent(false)); + b = detector.GetBfield(); + vDrift = detector.GetVdrift(); + } + catch( std::bad_cast & ) + { + // streamlog_out(ERROR) << "EXTPCMeasLayer::ProcessHit: Error: Parent is not an EXTPCKalDetector." + // << std::endl; + // streamlog_out(ERROR) << "This function is for backward compatibility only." + // <<" Please do not use it when directly instantiating a GearTPCKalDetector." + // << std::endl; + throw; + } + + hits.Add(new EXTPCHit(*this, meas, dmeas, 1 /*side, not functional anyway*/, + vDrift, xx, b )); +} diff --git a/Utilities/KalDet/src/lctpc/gearTPC/EXTPCMeasLayer.h b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..3557ae56f0f3b46757fc53446cb2707d918b327d --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/EXTPCMeasLayer.h @@ -0,0 +1,83 @@ +#ifndef LCTPC_EXTPCMEASLAYER_H +#define LCTPC_EXTPCMEASLAYER_H + +#include "GearTPCMeasLayer.h" +#include <kaltest/TCylinder.h> + +/** + * A backward compatibility class for GearTPCCylinderMeasLayer. + * It introduces one module and one row, which are associated to the layer. + * This is deprecated, the GearTPCCylinderMeasLayer provides an assiciation of several + * module-row pairs to the layer. + + * This class is an intermediate inheritance class so a GearTPCCylinderMeasLayer can be + * instantiated (as should be in the current code) and the old code can cast the + * TObject pointer, which is delivered by the detector cradle, to an EXTPCMeasLayer. + * + * \attention Do not use any of these function in new code. All new code should still run + * after this class has been removed from the ineritance chain. + * + * \deprecated EXTPCMeasLayer + */ +class EXTPCMeasLayer : public kaldet::GearTPCMeasLayer, public TCylinder +{ + +public: + /// Minimal constructor for this (partially) virtual class. + EXTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Double_t r0, + Double_t lhalf, + TVector3 xc, + Bool_t isPerfect, + Bool_t isActive, + Double_t sigmaX0 = 0., //< the constant part of sigmaX + Double_t sigmaX1 = 0., //< the z-dependent part of sigmaX + Double_t sigmaZ0 = 0., //< the constant part of sigmaZ + Double_t sigmaZ1 = 0.); //< the z-dependent part of sigmaZ + + /// The destructor. + virtual ~EXTPCMeasLayer(); + + /** + * Get the module associated with this layer (deprecated). + * \attention Do not programme against this when using the GearTPC interface. + * This is for backward compatibility only!!! + */ + Int_t GetModuleID() const; + + /** + * Get the layer ID (i.\ e.\ row in the module) associated with this Kalman layer (deprecated). + * + * \attention Do not programme against this when using the GearTPC interface. + * This is for backward compatibility only!!! + */ + Int_t GetLayerID () const; + + /** Deprecated XvToMv which in addition to the position takes a side. + * Side is ignored and XvToMv without the side is called. + * \attention Do not programme against this when using the GearTPC interface. + * This is for backward compatibility only!!! + */ + TKalMatrix XvToMv(const TVector3 &xv, Int_t side) const; + + /** The fully virtual declaration of XvToMv. It is called within the version which also takes + * the side argument, but is implemented in GearTPCCylinderMeasLayer. + */ + virtual TKalMatrix XvToMv(const TVector3 &xv) const = 0; + + /** Smear the incoming hit in the layes measurement surface and place the result into the TObjArray + * which is given as argument. + * From a design point of view this function should not be in the detector class but in a + * simulation extension. It is only put in for compatibility reasons. + * \attention Do not programme against this when using the GearTPC interface. + * This is for backward compatibility only!!! + */ + virtual void ProcessHit(const TVector3 &xx, TObjArray &hits) const; + + //ClassDef(EXTPCMeasLayer, 1) // User defined measurement layer class +}; + +#endif // LCTPC_EXTPCMEASLAYER_H diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderHit.cxx b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderHit.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d5441b0d8e5ab8f2da205a18692a850f3380773d --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderHit.cxx @@ -0,0 +1,111 @@ +#include "GearTPCCylinderHit.h" +#include "GearTPCCylinderMeasLayer.h" +#include <TMath.h> + +#include <iostream> +#include <iomanip> +// #include <streamlog/streamlog.h> + +using namespace std; + +namespace kaldet{ + +//_________________________________________________________________________ +// -------------- +// Ctors and Dtor +// -------------- +// +GearTPCCylinderHit::GearTPCCylinderHit(Int_t m) + : GearTPCHit(m) +{ +} + +GearTPCCylinderHit::GearTPCCylinderHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const TVector3 &xx, + Double_t b, + Double_t v, + Int_t m) + : GearTPCHit(ms, x, dx, xx, b, v, m) +{ +} + +GearTPCCylinderHit::GearTPCCylinderHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const void *hitp, + Double_t b, + Double_t v, + Int_t m) + : GearTPCHit(ms, x, dx, hitp, b, v, m) +{ +} + +GearTPCCylinderHit::~GearTPCCylinderHit() +{ +} + +//_________________________________________________________________________ +// -------------------------------- +// Implementation of public methods +// -------------------------------- +// +TKalMatrix GearTPCCylinderHit::XvToMv(const TVector3 &xv, Double_t t0) const +{ + // KILLENB What does this do? The ild version just returns measLayer->XvToMv() + + TKalMatrix h(GetDimension()); + Double_t r; + try{ + const GearTPCCylinderMeasLayer &ms + = dynamic_cast<const GearTPCCylinderMeasLayer &>(GetMeasLayer()); + h = ms.XvToMv(xv); + r = ms.GetR(); + } + catch(std::bad_cast &) + { + // streamlog_out(ERROR) << "GearTPCHit::XvToMv: Measurement layer is not a GearTPCCylinderMeasLayer\n" + // << " The current implementation only works for cylindrical layer, sorry." + // << std::endl; + throw; + } + + + Double_t phih = h(0, 0) / r; + Double_t phim = (*this)(0, 0) / r; + Double_t dphi = phih - phim; + + static const Double_t kPi = TMath::Pi(); + static const Double_t kTwoPi = 2 * kPi; + + while (dphi < -kPi) dphi += kTwoPi; + while (dphi > kPi) dphi -= kTwoPi; + + h(0, 0) = r * (phim + dphi); + h(1, 0) += fVDrift * t0; + + return h; +} + +void GearTPCCylinderHit::DebugPrint(Option_t *) const +{ + cerr << "------------------- Site Info -------------------------" << endl; + + for (Int_t i = 0; i < GetDimension(); i++) { + Double_t x = (*this)(i, 0); + Double_t dx = (*this)(i, 1); + cerr << " x[" << i << "] = " << setw(8) << setprecision(5) << x + << " " + << "dx[" << i << "] = " << setw(6) << setprecision(2) << dx + << setprecision(7) + << resetiosflags(ios::showpoint) + << endl; + } + cerr << " r = " << setw(8) + << dynamic_cast<const GearTPCCylinderMeasLayer &>(GetMeasLayer()).GetR() << endl; + cerr << "-------------------------------------------------------" << endl; +} + + +}//namespace kaldet diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderHit.h b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderHit.h new file mode 100644 index 0000000000000000000000000000000000000000..db9763a5b4a691e22bf61c46b78e6e5aceb7ddc0 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderHit.h @@ -0,0 +1,55 @@ +#ifndef GEARTPCCYLINDERHIT_H +#define GEARTPCCYLINDERHIT_H + +#include <kaltest/KalTrackDim.h> +#include "GearTPCHit.h" +#include <kaltest/TVMeasLayer.h> + +namespace kaldet{ + +/** The cylindrical implementation of the GearTPCHit. + */ +class GearTPCCylinderHit : public GearTPCHit { + +public: + /// KILLENB What does this constructor do? Best throw it out, it does not + /// properly initialise the class at all, does it? + GearTPCCylinderHit(Int_t m = kMdim); + + /** Constructor to initialise the GearTPCHit using space point coordinates (TVector3) as original hit. + */ + GearTPCCylinderHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const TVector3 &xx, + Double_t b, + Double_t v, + Int_t m = kMdim); + + /** Constructor using a pointer to the original hit as reference. + */ + GearTPCCylinderHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const void *hitp, + Double_t b, + Double_t v, + Int_t m = kMdim); + + /** The dectructor. + */ + virtual ~GearTPCCylinderHit(); + + /** Implementation of the space vector (xv) to measurement vector (mv) calculation + * for a cylindrical hit. + */ + virtual TKalMatrix XvToMv(const TVector3 &xv, Double_t t0) const; + + /** Print some debug output to std err. + */ + virtual void DebugPrint(Option_t *opt = "") const; +}; + +}//namespace kaldet + +#endif //GEARTPCCYLINDERHIT_H diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderMeasLayer.cxx b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderMeasLayer.cxx new file mode 100644 index 0000000000000000000000000000000000000000..050549e12ec5f0a8ac1cf8124b869fdef933f38c --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderMeasLayer.cxx @@ -0,0 +1,218 @@ +#include "GearTPCCylinderMeasLayer.h" +#include "GearTPCHit.h" +#include "GearTPCKalDetector.h" +#include "GearTPCCylinderHit.h" + +#include <TMath.h> + +#include <iostream> +// #include <streamlog/streamlog.h> + +#include <gear/GEAR.h> + +namespace kaldet +{ + + +GearTPCCylinderMeasLayer::GearTPCCylinderMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Double_t r0, + Double_t lhalf, + TVector3 xc, + Bool_t isPerfect, + Bool_t isActive, + Double_t sigmaX0, + Double_t sigmaX1, + Double_t sigmaZ0, + Double_t sigmaZ1, + Double_t phimin, + Double_t phimax) + : EXTPCMeasLayer(min, mout, module, row, r0, lhalf, xc ,isPerfect, + isActive, sigmaX0, sigmaX1, sigmaZ0, sigmaZ1), + /* this is the original code which should be reactivated once the EXTPCMeasLayer is phased out: + : GearTPCMeasLayer(min, mout, module, isPerfect, isActive, + sigmaX0, sigmaX1, sigmaZ0, sigmaZ1), + TCylinder(r0, lhalf, xc.X(), xc.Y(), xc.Z()), + */ + fPhiMin(phimin), + fPhiMax(phimax) +{ + //FIXME: As the handling of cylinder segments is not defined yet we force the layer to be + //a perfect cylinder + fIsPerfect = true; + + // for a full cylinder phi min and max do not make sense. Give a warning if they are used. + if (fIsPerfect) + { + if (phimin!=-TMath::Pi()) + { + // streamlog_out(WARNING) << "GearTPCCylinderMeasLayer: Ignoring input parameter phimin." + // << " The current implementation is a full cylinder." << std::endl; + phimin=-TMath::Pi(); + } + if (phimax!=TMath::Pi()) + { + // streamlog_out(WARNING) << "GearTPCCylinderMeasLayer: Ignoring input parameter phimax." + // << " The current implementation is a full cylinder." << std::endl; + phimax=TMath::Pi(); + } + } +} + +GearTPCCylinderMeasLayer::~GearTPCCylinderMeasLayer() +{ +} + +TKalMatrix GearTPCCylinderMeasLayer::XvToMv(const TVector3 &xv) const +{ + TVector3 xxv = xv - GetXc(); + + Double_t phi = TMath::ATan2(xxv.Y(), xxv.X());// - fPhiMin; + + static Double_t kPi = TMath::Pi(); + static Double_t kTwoPi = 2 * kPi; + while (phi < -kPi) phi += kTwoPi; + while (phi > kPi) phi -= kTwoPi; + + // Calculate hit coordinate information: + // mv(0, 0) = r * phi + // (1, 0) = drift distance + + TKalMatrix mv(kMdim, 1); + mv(0, 0) = GetR() * phi; + + mv(1, 0) = xxv.Z(); + + return mv; +} + +TKalMatrix GearTPCCylinderMeasLayer::XvToMv(const TVTrackHit &vhit, + const TVector3 &xv) const +{ + return XvToMv(xv); +} + +TVector3 GearTPCCylinderMeasLayer::HitToXv(const TVTrackHit &vhit) const +{ + // const EXTPCHit &hit = dynamic_cast<const EXTPCHit &>(vhit); + + + Double_t phi = vhit(0, 0) / GetR();// + fPhiMin; + + Double_t z = vhit(1, 0); + + Double_t x = GetR() * TMath::Cos(phi) + GetXc().X(); + Double_t y = GetR() * TMath::Sin(phi) + GetXc().Y(); + + return TVector3(x, y, z); +} + +void GearTPCCylinderMeasLayer::CalcDhDa(const TVTrackHit & vhit, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + double vDrift; + try{ + const GearTPCHit &hit = dynamic_cast<const GearTPCHit &>(vhit); + vDrift = hit.GetVdrift(); + } + catch(std::bad_cast &) + { + // streamlog_out(ERROR) << "GearTPCCylinderMeasLayer::CalcDhDa :" + // << "Cannot cast incoming TVTrackHit to GearTPCHit!"<< std::endl; + throw; + } + + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5, sdim - 1); + + TVector3 xxvc = xxv - GetXc(); + Double_t xv = xxvc.X(); + Double_t yv = xxvc.Y(); + Double_t xxyy = xv * xv + yv * yv; + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + for (Int_t i = 0; i < hdim; i++) { + H(0, i) = - (yv / xxyy) * dxphiada(0, i) + + (xv / xxyy) * dxphiada(1, i); + H(0, i) *= GetR(); + + H(1, i) = dxphiada(2, i); + } + + if (sdim == 6) { + H(0, sdim - 1) = 0.; + + // KILLENB I don't understand what this does, but I removed vDrift, so I set this to 0. + H(1, sdim - 1) = - vDrift; + } +} + +Double_t GearTPCCylinderMeasLayer::GetSortingPolicy() const +{ + // The sorting policy (copied from the header file): + // The layers are first sorted by radius + offset. This offset is only + // useful for segments of a cylinder, like the LP1. + // As offsets in this case can be positive or negative, but only make sense in one + // direction (you need a continuous number), we only allow offsets in X. + // This should not be too much of a problem, you should be able to rotate your coordinates + // so the offset is in X. If not you have to extend the sorting policy. (Please thake + // care not to reduce versatility when doing so. You might want to implement your own class?) + // + // For equal radii + offset the layers are sorted by moduleID. As we have to squeeze this + // information into only one number, we multiply the radius + offset by 1e9 and add the moduleID. + // A double has a precision of 53 bits, which is 15.9 digits. So the radius can be up to 1e6.9 mm + // without causing the last digit of the the ModuleID to be cut, and for up to 1000 modules the + // layers can be distinguished down to 1 nm without the two numbers mixing, or down to 1 micron + // with up to 1.000.000 modules. + + // The additional sorting by module is intended for cylinder segments. Here only one module/row + // per layer is allowed, so we just take the first entry in the set. In case of a perfect layer + // it does not matter because there should only be one layer at this radius, so the sort order + // should not be affected by adding an arbitrary module ID (as long as the module ID is < 1e6, as + // described above). + + // check that the offset is onyl in X + if ( (GetXc().Y()!=0) || (GetXc().Z()!=0) ) + { + throw gear::NotImplementedException("Offset is only allowed in X in the current implementation"); + } + + int moduleID = fModuleRows.begin()->first; + // give a warning in case of very large module IDs. The sorting policy might have to be adapted + if( moduleID > 1e6 ) + { + // streamlog_out(WARNING) << "GearTPCCylinderMeasLayer::GetSortingPolicy(): " + // << "Very large module ID " << moduleID << " found. " + // << "This might compromise the sorting policy." + // << std::endl; + } + + // FIXME: Do we have to check for a max r-offsetX? + return (GetR() + GetXc().X())*1e9 + moduleID; +} + +GearTPCHit * GearTPCCylinderMeasLayer::createHit(Double_t * meas, + Double_t * dmeas, + void * hitPointer, + Double_t bField, + Double_t vDrift, + Int_t m) const +{ + return new GearTPCCylinderHit(*this, meas, dmeas, hitPointer, + bField, vDrift, m); +} + + +}//namespace kaldet diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderMeasLayer.h b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..e20af5be813e99e3875837d844a58ccb2096d0fc --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCCylinderMeasLayer.h @@ -0,0 +1,131 @@ +#ifndef GEARTPCCYLINDERMEASLAYER_H +#define GEARTPCCYLINDERMEASLAYER_H +#include <TVector3.h> +#include <kaltest/TKalMatrix.h> +#include <kaltest/TCylinder.h> +#include <kaldet/EXTPCMeasLayer.h> +//#include <KalTrackDim.h> + +#include <TMath.h> + +#include <set> + +class TVTrackHit; + +namespace kaldet +{ + + /** + * A cylindrical measurement layer. + */ + class GearTPCCylinderMeasLayer + : public EXTPCMeasLayer + /* this is the original code which should be reactivated once the EXTPCMeasLayer is phased out: + : public GearTPCMeasLayer, public TCylinder + */ + { + + public: + /** The constructor. + * If the layer is perfect it is always a full circle. The constructor forces + * phiMin and phiMax to +-TMath::Pi(). Differing values will be ignored and a warning is + * printed. + * + * Note: The current implementation forces the layer to be perfect. Segmented layers are + * not supported yet. + * + * Note: for backward compatibility this is derrived from EXTPCMeasLayer. + * After the change to the GearTPC interface this should be changed to GearTPCMeasLayer and + * TCylinder, as EXTPCMeasLayer is inherrited now. + * The current version ensures compatibility for the transition phase. + */ + GearTPCCylinderMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Double_t r0, + Double_t lhalf, + TVector3 xc = TVector3(), + Bool_t isPerfect = true, + Bool_t isActive = true, + Double_t sigmaX0 = 0., + Double_t sigmaX1 = 0., + Double_t sigmaZ0 = 0., + Double_t sigmaZ1 = 0., + Double_t phiMin = -TMath::Pi(), + Double_t phiMax = TMath::Pi()); + + /** + * The desctructor. + */ + virtual ~GearTPCCylinderMeasLayer(); + + // Parent's pure virtuals that must be implemented + + /** Implements kaltest::TVMeasLayer's XvToMv. I have no idea why there are two arguments. + * It ignores ht and just calls XvToMv(xv). + */ + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const; + + /** Implements the coordinate transformation from the space vector xv to the + * measurement vector (Kalman matrix). + */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const; + + /** Implements the conversion from a Kalman hit (measurement vector) to + * a 3D space point. + */ + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + + /** + * Implements CalcDhDa, whatever that is. + */ + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + /** Implements the sorting policy. + * The layers are first sorted by radius + offset. This offset is only + * useful for segments of a cylinder, like the LP1. + * As offsets in this case can be positive or negative, but only make sense in one + * direction (you need a continuous number), we only allow offsets in x. + * This should not be too much of a problem, you should be able to rotate your coordinates + * so the offset is in x. If not you have to extend the sorting policy. (Please thake + * care not to reduce versatility when doing so. You might want to implement your own class?) + * + * For equal radii + offset the layers are sorted by moduleID. As we have to squeeze this + * information into only one number, we multiply the radius + offset by 1e9 and add the moduleID. + * A double has a precision of 53 bits, which is 15.9 digits. So the radius can be up to 1e6.9 mm + * without causing the last digit of the the ModuleID to be cut, and for up to 1000 modules the + * layers can be distinguished down to 1 nm without the two numbers mixing, or down to 1 micron + * with up to 1.000.000 modules. + * + * The additional sorting by module is intended for cylinder segments. Here only one module/row + * per layer is allowed, so we just take the first entry in the set. In case of a perfect layer + * it does not matter because there should only be one layer at this radius, so the sort order + * should not be affected by adding an arbitrary module ID (as long as the module ID is < 1e6, as + * described above). + */ + virtual Double_t GetSortingPolicy() const; + + /** + * Creates a GearTPCCylinderHit and hands over the ownership. + */ + virtual GearTPCHit * createHit(Double_t * meas, + Double_t * dmeas, + void * hitPointer, + Double_t bField, + Double_t vDrift, + Int_t m = kMdim) const; + + + +protected: + Double_t fPhiMin; //< Minimum phi. + Double_t fPhiMax; //< Maximum phi. + +}; + +}//namespace kaldet +#endif diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCHit.cxx b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCHit.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8215cb661408538e184ab9025a10a3fc8ca83a44 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCHit.cxx @@ -0,0 +1,81 @@ +#include "GearTPCHit.h" + +#include <iomanip> +// #include <streamlog/streamlog.h> + +namespace kaldet{ + +//_________________________________________________________________________ +// -------------- +// Ctors and Dtor +// -------------- +// +GearTPCHit::GearTPCHit(Int_t m) + : TVTrackHit(m), + fXXPtr(0), + fHitPtr(0), + fVDrift(0) +{ +} + +GearTPCHit::GearTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const TVector3 &xx, + Double_t b, + Double_t v, + Int_t m) + : TVTrackHit(ms, x, dx, b, m), + fXXPtr(&xx), + fHitPtr(0), + fVDrift(v) +{ +} + +GearTPCHit::GearTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const void *hitp, + Double_t b, + Double_t v, + Int_t m) + : TVTrackHit(ms, x, dx, b, m), + fXXPtr(0), + fHitPtr(hitp), + fVDrift(v) +{ +} + +GearTPCHit::~GearTPCHit() +{ +} + +//_________________________________________________________________________ +// ---------------- +// Compare two Hits +// ---------------- +// +Int_t GearTPCHit::Compare(const TObject *obj) const +{ + Double_t me = GetSortingPolicy(); + Double_t you = dynamic_cast<const GearTPCHit *>(obj)->GetSortingPolicy(); + if (you == 0) + { + // streamlog_out(ERROR) << "Cannot compare GearTPCHit to something which is not a" + // << " GearTPCHit" << std::endl; + throw std::bad_cast(); + } + return me < you ? -1 : (me > you ? +1 : 0); +} + +Double_t GearTPCHit::GetSortingPolicy() const +{ + return GetMeasLayer().HitToXv(*this).Mag(); +} + +Bool_t GearTPCHit::IsSortable() const +{ + return kTRUE; +} + +}//namespace kaldet diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCHit.h b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCHit.h new file mode 100644 index 0000000000000000000000000000000000000000..de947f6ec04fcb97bc33ef3c369177708d25672c --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCHit.h @@ -0,0 +1,94 @@ +#ifndef GEARTPCHIT_H +#define GEARTPCHIT_H + +#include <kaltest/KalTrackDim.h> +#include <kaltest/TVTrackHit.h> +#include <kaltest/TVMeasLayer.h> + +namespace kaldet{ + +/** Base class of a hit for GearTPCKalDetector. It extends the TVTrackHit with the functionality to + * store a space point or a pointer to the original hit for reference. In addition it stores + * the local drift velocity and allows sorting of the hits (according to the distance to the + * origin). + * + * It does not implement the purely virtual functions of the TVTrackHit, which happens in the + * specialisations for cylindrical and planar measurement layers. + */ +class GearTPCHit : public TVTrackHit { + +public: + /// KILLENB What does this constructor do? Best throw it out, it does not + /// properly initialise the class at all, does it? + GearTPCHit(Int_t m = kMdim); + + /** Constructor to initialise the GearTPCHit using space point coordinates (TVector3) as original hit. + */ + GearTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const TVector3 &xx, + Double_t b, + Double_t v, + Int_t m = kMdim); + + /** Constructor using a pointer to the original hit as reference. + */ + GearTPCHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + const void *hitp, + Double_t b, + Double_t v, + Int_t m = kMdim); + + /** The dectructor. + */ + virtual ~GearTPCHit(); + + /** + * The sorting policy of hits is implemented as the distance to the origin. + * + * Note: The sorting of hits does not necessarily correspond to the sort order of + * the corresponding Kalman layer! + */ + virtual Double_t GetSortingPolicy() const; + + /** + * Compare two hits according to their sorting policy. + * Returns + * \li -1 if this hits sorting policy is smaller + * \li 0 if both soting policies are equal + * \li 1 if this hits hits sortin policy is larger + * + * Killenb: n.b. Who comes up with this wierd stuff? Ever head of anything like a + * `less than operator` or `comparison operator`? + */ + virtual Int_t Compare(const TObject *obj) const; + + /** + * Returns true. + */ + virtual Bool_t IsSortable() const; + + /// Get the pointer to the reference hit. 0 if the TVector3 has been used for initialisation. + inline const void *GetHitPtr() const { return fHitPtr; } + + /// Get the referece position. (0, 0, 0) if the reference pointer has been used for initialisation. + inline TVector3 GetExactX() const { return *fXXPtr; } + + /// Get the local drift velocity set in the constructor. + inline Double_t GetVdrift() const { return fVDrift; } + +protected: + const TVector3 *fXXPtr; //< pointer to exact hit + const void *fHitPtr; //< pointer to raw Hit object + + Double_t fVDrift; //< the local drift veclocity at this point + + +}; + +}//namespace kaldet + +#endif diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCKalDetector.cxx b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCKalDetector.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a851e9b83173b665cf70af0c4413b59dced0c082 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCKalDetector.cxx @@ -0,0 +1,312 @@ +// STL +#include <vector> + +// GEAR +#include <gear/GEAR.h> +#include <gear/TPCParameters.h> +#include <gear/PadRowLayout2D.h> +#include <gear/BField.h> +#include <gearimpl/TPCModuleImpl.h> +#include <gearxml/GearXML.h> + +// #include <streamlog/streamlog.h> + +#include "GearTPCKalDetector.h" +#include "GearTPCCylinderMeasLayer.h" +//#include "GearTPCHit.h" +#include <kaltest/TKalDetCradle.h> +#include <TRandom.h> +#include <TMath.h> + +//#include "TTUBE.h" +//#include "TNode.h" +//#include "TVirtualPad.h" + +namespace kaldet +{ + +GearTPCKalDetector::GearTPCKalDetector(const gear::GearMgr& gearMgr) + : TVKalDetector(210) +{ + gear::TPCParameters const & tpcParameters = gearMgr.getTPCParameters(); + + // Try to read the material properties from the GEAR file. + // If it cannot be found use an Argon based mixture instead. + Double_t A, Z, density, radlen; + + try{ + // One try/catch block for all. + // It does not make sense to only replace part of the parameters, + // they all have to be there. + A = tpcParameters.getDoubleVal("TPCGas_A"); + Z = tpcParameters.getDoubleVal("TPCGas_Z"); + density = tpcParameters.getDoubleVal("TPCGas_density"); + radlen = tpcParameters.getDoubleVal("TPCGas_radlen"); + } + catch( gear::UnknownParameterException & ) + { + // streamlog_out(MESSAGE) << "GearTPCKalDetector: No TPCGas parameters found in the gear file." + // << " Using Ar/CH4 90/10." << std::endl; + + // Is this supposed to be Ar/CH4 90/10? + // I think it's wrong. A CH4 module does not consist of 0.2 carbon + // and 0.8 hydrogen atoms, but 1 C and 4 H, so it should be + // A = 39.948 * 0.9 + (12.011 + 1.00794 * 4) * 0.1; + A = 39.948 * 0.9 + (12.011 * 0.2 + 1.00794 * 0.8) * 0.1; + Z = 16.4; // now how does this calculate? + density = 0.749e-3; // in which units? + radlen = 1.196e4 * 2; // in which units? + } + + TMaterial &gas = *new TMaterial("TPCGas", "", A, Z, density, radlen, 0.); + + // FIXME: what about the cathode tickness. Sensitivity gap in the middle? + // And what about the LP? There it's not the half length... + Double_t lhalf + = tpcParameters.getMaxDriftLength(); // half length + +// gear::BField const & bField = gearMgr.getBField(); +// // get the BField at 0,0,0. Check that there are no transverse components +// // FIXME: Event though there are no transverse components at 0, 0, 0 does not mean +// // there are no transverse components somewhere else. +// gear::Vector3D bFieldVector = bField.at(gear::Vector3D(0., 0., 0.)); +// if (bFieldVector[0]!=0 || bFieldVector[1]!=0) +// { +// streamlog_out(ERROR) << "B-field has transverse components." +// << " GearTPCKalDetector only works with homogeneous B-field" +// << " in z direction" << std::endl; +// throw gear::Exception("Magnetic field not homogeneous"); +// } + + // set the protected member variable of EXVKalDetector + // fBfield = bFieldVector[2]; + + // FIXME: Just don't put dummy modules into the gear file? + // No, we might need the radiation length + // Damn it, the description in GEAR is not complete, grrrr. + // Bool_t active = GearTPCMeasLayer::kActive; + // Bool_t dummy = GearTPCMeasLayer::kDummy; + + // The index where in the TObjectArray the next element will be stored. Unfortunately we have to + // do the bookkeeping manually :-( + Int_t arrayIndex = 0; + + // A map to store if a layer, which is a full cylinder, already exists. If it has the same + // offset and the same radius, this is the case. Then to not add a Kalman layer but add the module + // to the layer. + std::map< std::pair<double, double> , Int_t > uniqueLayerMap;// <offset, r>, LayerIndex + + for (std::vector<gear::TPCModule *>::const_iterator moduleIter = tpcParameters.getModules().begin(); + moduleIter < tpcParameters.getModules().end(); ++moduleIter) + { + gear::TPCModule *module = *moduleIter; + + // The resolution parameters can vary from module to module. + // In case they are not there use the jgem values + Double_t sigmax0, sigmax1, sigmaz0, sigmaz1; + try{ + sigmax0 = module->getDoubleVal("sigmax0"); + sigmax1 = module->getDoubleVal("sigmax1"); + sigmaz0 = module->getDoubleVal("sigmaz0"); + sigmaz1 = module->getDoubleVal("sigmaz1"); + } + catch( gear::UnknownParameterException & ) + { + // streamlog_out(MESSAGE) << "No resolution parameters found for module " + // << module->getModuleID()<<"." + // << " Using jgem settings." << std::endl; + + // FIXME: n_eff of argon per distance, adapt to pad length. Or read from GEAR file? + Double_t neff = 22.7; + + // FIXME : I think the sqrt(10) is a leftover from the old cm units.... + sigmax0 = 38.3e-3; + sigmax1 = 101.5e-3 / TMath::Sqrt(10.) / TMath::Sqrt(neff); + sigmaz0 = 500.e-3 ; + sigmaz1 = 154.e-3 / TMath::Sqrt(10.) / TMath::Sqrt(neff); + } + + // FIXME: Implementation for RectangularPadRowLayout missing + switch (module->getLocalPadLayout().getCoordinateType()) + { + case gear::PadRowLayout2D::POLAR : + { + //Unfortunately cylinder segments are not implemented in KalDet yet. + //Perhaps in a future implementation... + // Get the phi min and phi max of the module, plus the right rotation + // in the global coordinate system. This is not the global angle because it is + // relative to the origin of the module, which has a shift in global coordinates. + //Double_t phimin = module->getLocalModuleExtent()[2] + module->getAngle(); + //Double_t phimax = module->getLocalModuleExtent()[3] + module->getAngle(); + + // the offset is either in r/phi or in x/y, depending on the global coordinate system + double xOffset, yOffset; + switch (module->getCoordinateType()) + { + case gear::PadRowLayout2D::POLAR : + xOffset=module->getOffset()[0]*cos(module->getOffset()[1]); + yOffset=module->getOffset()[0]*sin(module->getOffset()[1]); + break; + case gear::PadRowLayout2D::CARTESIAN : + xOffset=module->getOffset()[0]; + yOffset=module->getOffset()[1]; + break; + default: + throw gear::UnknownParameterException("Unknown global coordinate system in GearTPCKalDet"); + + } + + if (yOffset!=0) + { + // streamlog_out(ERROR) << "yOffset not 0. The current implementation of GearTPCKalDetector" + // << "only allows an offset in x direction." << std::endl; + throw gear::UnknownParameterException("Offset in y is not 0."); + } + + TVector3 cylinderCentre(xOffset, + yOffset, + 0.); // FIXME: cathode thickness + + // Loop the pad rows and place one cylinder segement each + for (int row = 0; row < module->getNRows(); ++row) + { + // To get the radius we have to ask for the centre of one one the pads, + // just take pad 0 in this row. + int padIndex = module->getPadIndex(row, 0); + + // The radius only makes sense in local module coordinates. + // So we have to ask the local pad layout. The module always answers in global coordinates. + Double_t r = module->getLocalPadLayout().getPadCenter(padIndex)[0]; + + std::map< std::pair<double, double> , Int_t >::iterator uniqueLayerIterator= + uniqueLayerMap.find( std::pair<double, double>(xOffset, r) ); + + if ( uniqueLayerIterator==uniqueLayerMap.end() ) + { + // streamlog_out(DEBUG2) << "adding new layer "<<arrayIndex<< " (xOffset="<<xOffset + // <<", r="<<r + // <<") with module "<< module->getModuleID() + // <<" and row "<<row << std::endl; + // add the measurement layer to this object, and remember where we put it + Add(new GearTPCCylinderMeasLayer(gas, gas, + module->getModuleID(), row, + r, lhalf, + cylinderCentre, + true, true, // perfect and active + sigmax0, sigmax1, sigmaz0, sigmaz1)); + // add the moduleRow to the map with the array indices + moduleRowToMeasurementLayerMap[ std::pair<int, int>(module->getModuleID(), row) ] + = arrayIndex; + + // add the layer to the uniqueLayerMap + uniqueLayerMap[std::pair<double, double>(xOffset, r)] = arrayIndex; + + // count up the array index + ++arrayIndex; + } + else // layer already exists + { + Int_t existingIndex = uniqueLayerIterator->second; + // streamlog_out(DEBUG2) << "adding module "<< module->getModuleID() + // <<", row "<<row <<" to existing layer " << existingIndex + // << " (xOffset="<<xOffset<<", row="<<row<<")" + // << std::endl; + + GearTPCCylinderMeasLayer * measLayer = + dynamic_cast<GearTPCCylinderMeasLayer *>( At(existingIndex)); + + // If the cast fails something went terribly wrong. This layer should be a + // GearTPCCylinderMeasLayers, otherwise we cannot add a cylindrical module + if (measLayer==0) + { + // streamlog_out(ERROR) << "Something went terribly wrong. Could not cast a member of " + // << " GerTPCKalDetector to GearTPCCylinderMeasLayer" << std::endl; + throw std::bad_cast(); + } + + measLayer->AddModuleRow( module->getModuleID(), row ); + + moduleRowToMeasurementLayerMap[ std::pair<int, int>(module->getModuleID(), row) ] + = existingIndex; + + } + + }// loop rows in module + } + break; + case gear::PadRowLayout2D::CARTESIAN : + throw gear::NotImplementedException("Cartesian local coordinates not yet supported by GearTPCKalDetector"); + default: + throw gear::UnknownParameterException("Unknown local coordinate system in GearTPCKalDet"); + }//switch coordinate type + + } + + SetOwner();// make the KalDetector (TObjectArry) owner of the measurement layers so they are + // deleted when the detector is deleted + +} + +GearTPCKalDetector::~GearTPCKalDetector() +{ +} + + +GearTPCMeasLayer const * GearTPCKalDetector::GetMeasLayer(int moduleID, int row) const +{ + std::map< std::pair<int, int >, Int_t >::const_iterator indexIter = + moduleRowToMeasurementLayerMap.find( std::pair<int, int>(moduleID, row) ); + + if (indexIter==moduleRowToMeasurementLayerMap.end()) + { + // streamlog_out(ERROR) << "GearTPCKalDetector::getMeasLayer: " + // << "layer with moduleID=" << moduleID + // << " and row=" << row << " not defined." << std::endl; + throw gear::Exception("Unknown row on moduleID"); + } + + // second is the key of the iterator (the arrow dereferencing the iterator to a key-value pair) + GearTPCMeasLayer const * measurementLayer = + dynamic_cast<GearTPCMeasLayer const * >( At(indexIter->second) ); + if (measurementLayer==0) + { + // streamlog_out(ERROR) << "GearTPCKalDetector::getMeasLayer: " + // << " cannot cast object this->At(" << indexIter->second + // << ") to GearTPCMeasLayer const * " << std::endl; + } + return measurementLayer; +} + +//_________________________________________________________________________ +// -------------- +// Utility Method +// -------------- +//_________________________________________________________________________ +// -------------------------------------- +// Draw: Drawing method for event display +// -------------------------------------- +// +//void GearTPCKalDetector::Draw(Int_t color, const Char_t *opt) +//{ +// if (! gPad) return; +// TNode *nodep = GetNodePtr(); +// nodep->cd(); +// +// if (! fNodePtr) { +// GearTPCMeasLayer *inp = static_cast<GearTPCMeasLayer *>(First()); +// GearTPCMeasLayer *outp = static_cast<GearTPCMeasLayer *>(Last()); +// Double_t rin = inp->GetR(); +// Double_t rout = outp->GetR(); +// Double_t hlen = outp->GetZmax(); +// const Char_t *name = "TPC"; +// const Char_t *nname = "TPCNode"; +// TTUBE *tubep = new TTUBE(name, name, "void", rin, rout, hlen); +// tubep->SetBit(kCanDelete); +// fNodePtr = new TNode(nname, nname, name); +// fNodePtr->SetLineColor(color); +// fNodePtr->SetLineWidth(1); // line width given in number of pixels +// } +// EXVKalDetector::Draw(color, opt); +//} + +}//namespace kaldet diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCKalDetector.h b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..800934a5dce925b27ac6460cec8ad011494a662c --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCKalDetector.h @@ -0,0 +1,77 @@ +#ifndef GEARTPCKALDETECTOR_H +#define GEARTPCKALDETECTOR_H + +#include "kaltest/TVKalDetector.h" + +#include "GearTPCMeasLayer.h" + +#include <map> + +namespace gear{ + class GearMgr ; +} + +namespace kaldet{ + + /** + * The LCTPC implementation for a TPC which is completely instantiated from GEAR. + * + */ +class GearTPCKalDetector : public TVKalDetector { + +public: + /** + * The constructor. All information to initialise the TPC is taken from GEAR. + * + * As a pragmatic approach to avoid dealing with conditions data and material databases, + * the information about the material budget and the resolution of the layers + * is taken from the GEAR file as user parameters. If the parameters are not found in the + * file the previously hard coded parameters are used as default, which ensures backward + * compatibility. + * + * The gas properties for the matrial budget can be given as user parameters + * for the TPCParameters: + * \param TPCGas_A The mean atomic mass (default 36.2740552) + * \param TPCGas_Z The mean number of protons (default 16.4) + * \param TPCGas_density The density (default 0.749e-3 in which units?) + * \param TPCGas_radlen The radiation length (default 2.392e4 in which units?) + * + * The default gas parameters (are supposed to) correspond to Ar/CH4 90/10. + * N.B.: KILLENB: I think there is a bug in the calculation, the mean A should be + * 37.6 instead of 36.3 (see source code). + * In addition the description as a single TMaterial is not good. + * Using TMixture would be better. + * + * The reslution is calculated as \f$\sigma_x = \sqrt{x_0^2 + x_1^2 \cdot z}\f$. + * This requires z to be proportional to the drift distance, i.\ e. z=0 is at the readout. + + * The resolution of the layers can be given as user parameters in each TPCModule + * section of the GEAR xml file. + * \param sigmax0 The constant part of the x resolution (default 38.3e-3 mm) + * \param sigmax1 The drift distance dependent part of the x resolution + * (default 6.74e-3 mm/sqrt(mm) ) + * \param sigmaz0 The constant part of the z resolution (default 0.5 mm) + * \param sigmaz1 The drift distance dependent part the z resolution + * (default 10.2e-3 mm/sqrt(mm) ) + */ + GearTPCKalDetector(const gear::GearMgr& gearMgr); + + /// The destructor. + virtual ~GearTPCKalDetector(); + + /** + * Get access to the measurement layers using moduleID and row. + * Do not directly access the measurement layers using At() + * because the order depends on the order in the gear file. + * Throws a gear::Exception if the row on the module is not defined. + */ + virtual GearTPCMeasLayer const * GetMeasLayer(int moduleID, int row) const; + +protected: + /// Map which contains the information which measurement layer is stored + /// at which position in the array. + std::map< std::pair<int, int >, Int_t > moduleRowToMeasurementLayerMap; +}; + +}// namespace kaldet +#endif //GEARTPCKALDETECTOR_H diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCMeasLayer.cxx b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCMeasLayer.cxx new file mode 100644 index 0000000000000000000000000000000000000000..44069288f86887f7fe43c2bd987654fe54ce2537 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCMeasLayer.cxx @@ -0,0 +1,72 @@ +#include "GearTPCMeasLayer.h" + +#include <TMath.h> + +#include <iostream> +// #include <streamlog/streamlog.h> + +#include <gear/GEAR.h> + +namespace kaldet +{ + + +GearTPCMeasLayer::GearTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Bool_t isPerfect, + Bool_t isActive, + Double_t sigmax0, + Double_t sigmax1, + Double_t sigmaz0, + Double_t sigmaz1) + : TVMeasLayer(min, mout, isActive), + fSigmaX0(sigmax0), + fSigmaX1(sigmax1), + fSigmaZ0(sigmaz0), + fSigmaZ1(sigmaz1), + fIsPerfect(isPerfect) +{ + fModuleRows.insert( std::pair<int, int>(module, row) ); +} + +GearTPCMeasLayer::~GearTPCMeasLayer() +{ +} + +Bool_t GearTPCMeasLayer::IsPerfect() const +{ + return fIsPerfect; +} + +std::set< std::pair <int, int> > const & GearTPCMeasLayer::GetModuleRows() const +{ + return fModuleRows; +} + + +void GearTPCMeasLayer::AddModuleRow(int module, int row) +{ + if (fIsPerfect) + { + fModuleRows.insert( std::pair<int, int>(module, row) ); + } + else + { + // streamlog_out(ERROR) << "You can only add additional modules to perfect layers." <<std::endl; + throw gear::Exception("GearTPCMeasLayer is not declared perfect."); + } +} + +Double_t GearTPCMeasLayer::GetSigmaX(Double_t zdrift) const +{ + return TMath::Sqrt(fSigmaX0 * fSigmaX0 + fSigmaX1 * fSigmaX1 * zdrift); +} + +Double_t GearTPCMeasLayer::GetSigmaZ(Double_t zdrift) const +{ + return TMath::Sqrt(fSigmaZ0 * fSigmaZ0 + fSigmaZ1 * fSigmaZ1 * zdrift); +} + +}//namespace kaldet diff --git a/Utilities/KalDet/src/lctpc/gearTPC/GearTPCMeasLayer.h b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..3c27effab1d15c742ca80af9d1d31954429e2aef --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/GearTPCMeasLayer.h @@ -0,0 +1,123 @@ +#ifndef GEARTPC_MEASLAYER_H +#define GEARTPC_MEASLAYER_H + +#include <kaltest/TVMeasLayer.h> +#include <set> + +namespace kaldet +{ + + class GearTPCHit; + + /** + * The GearTPCMeasLayer class introduces the z-dependent resolutions sigmaX and sigmaZ + * as well as Gear modules and rows which correspond to this layer. + * + * If the layer is defined as a perfect layer this means all modules are perfectly alligned + * and more than one module/row can be assigned to this layer. You can add them using AddModuleRow. + * The perfect layer should contain all the moduleRows on it, so it is guaranteed that the + * user can access all neighbouring modules this way. + * + * If the layer is not defined as perfect (default) there can only be one module on this layer. + * Calling AddModuleRow will throw an exception. This is the default behaviour because Gear does + * not guarantee that the modules are alligned. Displaced modules do not make up a perfect + * cylinder / plane and have to be treated as separate segments. Finding a neighbouring module/row + * is not trivial and has to be left to the user or a future Gear version. + */ + + class GearTPCMeasLayer + : public TVMeasLayer + { + + public: + /** The constructor. + * The materials and the type (active or passive) are passed on to the + * TVMeasLayer. sigmaX0 [mm] is the constant part of sigmaX, sigmaX1 [mm/sqrt(mm)] + * the z-dependent part, accordingly for sigmaZ. + * + * Module and row have to be specified. They will be added as the first + * module/row pair of this measurement layer. + * For a perfect layer modules can be added with AddModuleRow. + * + * Note: This class cannot be instantiated because the parent's geometry dependent + * purely virtual + * functions like XvToMv are not implemented. This will happen in the cylindrical or planar + * implementations. + * + * For inactive layers you will usually leave the sigmas at 0, they have no useful meaning in + * this case. + */ + GearTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Int_t module, + Int_t row, + Bool_t isPerfect, + Bool_t isActive, + Double_t sigmaX0 = 0., //< the constant part of sigmaX + Double_t sigmaX1 = 0., //< the z-dependent part of sigmaX + Double_t sigmaZ0 = 0. , //< the constant part of sigmaZ + Double_t sigmaZ1 = 0.); //< the z-dependent part of sigmaZ + + /// The destructor + virtual ~GearTPCMeasLayer(); + + /** + * A perfect measurement layer contains all the modules with rows (row segments) + * that make up the layer. + */ + virtual std::set< std::pair <int, int> > const & GetModuleRows() const; + + /** + * Add another row on another module which lies on the same cylinder. + */ + virtual void AddModuleRow(int module, int row); + + /** + * Get the measurement vector (mv) for this layer from a space point (xv) + */ + virtual TKalMatrix XvToMv (const TVector3 &xv) const = 0; + + /** + * Get the z-depenent resolution in the readout plane + * (usually x or r\f$\phi\f$). + */ + virtual Double_t GetSigmaX(Double_t z) const; + + /** + * Get the z-depenent resolution in z (drift direction). + */ + virtual Double_t GetSigmaZ(Double_t z) const; + + + /** + * Get the flag whether the layer is declared as perfect. + */ + virtual Bool_t IsPerfect() const; + + /** + * A virtual function to create the appropriate hit. Depending on the implementation + * (cylindrical or straight measurement layer) you get the appropriate implementation + * of GearTPCHit. + * It creates a new hit on the heap and hands over the ownership. + */ + virtual GearTPCHit * createHit(Double_t * meas, + Double_t * dmeas, + void * hitPointer, + Double_t bField, + Double_t vDrift, + Int_t m = kMdim) const = 0; + + protected: + Double_t fSigmaX0; // xy resolution + Double_t fSigmaX1; // xy resolution + Double_t fSigmaZ0; // z resolution + Double_t fSigmaZ1; // z resolution + + /// A set to hold all the module/row combinations associated to this layer + std::set< std::pair<int, int> > fModuleRows; + + Bool_t fIsPerfect; + }; + +}// namespace kaldet +#endif // GEARTPC_MEASLAYER_H diff --git a/Utilities/KalDet/src/lctpc/gearTPC/LinkDef.h b/Utilities/KalDet/src/lctpc/gearTPC/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..87a9fa8fe94d444b2575d334d8346d11ea013a83 --- /dev/null +++ b/Utilities/KalDet/src/lctpc/gearTPC/LinkDef.h @@ -0,0 +1,8 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + + +#endif diff --git a/Utilities/KalDet/src/othertpc/toytpc/EXTPCHit.cxx b/Utilities/KalDet/src/othertpc/toytpc/EXTPCHit.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ab697842e8ba76b7d21985b554697fac718b68a4 --- /dev/null +++ b/Utilities/KalDet/src/othertpc/toytpc/EXTPCHit.cxx @@ -0,0 +1,135 @@ +//************************************************************************* +//* ================ +//* EXTPCHit Class +//* ================ +//* +//* (Description) +//* User defined hit class +//* provides coordinate vector as defined by the MeasLayer +//* (Requires) +//* TVTrackHit +//* (Provides) +//* class EXTPCHit +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/tpc/EXTPCHit.cxx +//* 2009/11/23 K.Ikematsu Added GetSortingPolicy() method +//* 2009/11/23 K.Ikematsu Added data member *fHitPtr +//* as a pointer to raw Hit object +//* +//* $Id: EXTPCHit.cxx,v 1.1 2010-03-11 15:07:01 fujiik Exp $ +//************************************************************************* +// +#include "EXTPCHit.h" +#include "EXTPCMeasLayer.h" +#include "TMath.h" + +#include <iostream> +#include <iomanip> + +using namespace std; + +ClassImp(EXTPCHit) + +//_________________________________________________________________________ +// -------------- +// Ctors and Dtor +// -------------- +// +EXTPCHit::EXTPCHit(Int_t m) + : TVTrackHit(m), + fSide(0), + fVdrift(0) +{ +} + +EXTPCHit::EXTPCHit(const EXTPCMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const TVector3 &xx, + Double_t b, + Int_t m) + : TVTrackHit(ms, x, dx, b, m), + fSide(side), + fVdrift(v), + fXXPtr(&xx) +{ +} + +EXTPCHit::EXTPCHit(const EXTPCMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const void *hitp, + Double_t b, + Int_t m) + : TVTrackHit(ms, x, dx, b, m), + fSide(side), + fVdrift(v), + fHitPtr(hitp) +{ +} + +EXTPCHit::~EXTPCHit() +{ +} + +//_________________________________________________________________________ +// -------------------------------- +// Implementation of public methods +// -------------------------------- +// +TKalMatrix EXTPCHit::XvToMv(const TVector3 &xv, Double_t t0) const +{ + const EXTPCMeasLayer &ms + = dynamic_cast<const EXTPCMeasLayer &>(GetMeasLayer()); + TKalMatrix h = ms.XvToMv(xv, GetSide()); + h(0,0) = xv.X(); + h(1,0) += fVdrift * t0; + return h; +} + +void EXTPCHit::DebugPrint(Option_t *) const +{ + cerr << "------------------- Site Info -------------------------" << endl; + + for (Int_t i = 0; i < GetDimension(); i++) { + Double_t x = (*this)(i, 0); + Double_t dx = (*this)(i, 1); + cerr << " x[" << i << "] = " << setw(8) << setprecision(5) << x + << " " + << "dx[" << i << "] = " << setw(6) << setprecision(2) << dx + << setprecision(7) + << resetiosflags(ios::showpoint) + << endl; + } + cerr << " r = " << setw(8) + << static_cast<const EXTPCMeasLayer&>(GetMeasLayer()).GetXc().Y() << endl; + cerr << "-------------------------------------------------------" << endl; +} + +//_________________________________________________________________________ +// ---------------- +// Compare two Hits +// ---------------- +// +Int_t EXTPCHit::Compare(const TObject *obj) const +{ + Double_t me = GetSortingPolicy(); + Double_t you = dynamic_cast<const EXTPCHit *>(obj)->GetSortingPolicy(); + return me < you ? -1 : (me > you ? +1 : 0); +} + +Double_t EXTPCHit::GetSortingPolicy() const +{ + // Calculate "r" (Caution!! vaild only for GEAR coordinate system) + return GetMeasLayer().HitToXv(*this).Mag(); +} + +Bool_t EXTPCHit::IsSortable() const +{ + return kTRUE; +} diff --git a/Utilities/KalDet/src/othertpc/toytpc/EXTPCHit.h b/Utilities/KalDet/src/othertpc/toytpc/EXTPCHit.h new file mode 100644 index 0000000000000000000000000000000000000000..a151b88bd1cd060634c14378b1acd61eb98b4f8f --- /dev/null +++ b/Utilities/KalDet/src/othertpc/toytpc/EXTPCHit.h @@ -0,0 +1,73 @@ +#ifndef EXTPCHIT_H +#define EXTPCHIT_H +//************************************************************************* +//* ================ +//* EXTPCHit Class +//* ================ +//* +//* (Description) +//* User defined hit class +//* provides coordinate vector as defined by the MeasLayer +//* (Requires) +//* TVTrackHit +//* (Provides) +//* class EXTPCHit +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/tpc/EXTPCHit.h +//* 2009/11/23 K.Ikematsu Added GetSortingPolicy() method +//* 2009/11/23 K.Ikematsu Added data member *fHitPtr +//* as a pointer to raw Hit object +//* +//* $Id: EXTPCHit.h,v 1.1 2010-03-11 15:07:01 fujiik Exp $ +//************************************************************************* +// +#include "kaltest/KalTrackDim.h" +#include "kaltest/TVTrackHit.h" +#include "EXTPCMeasLayer.h" + +class EXTPCHit : public TVTrackHit { + +public: + EXTPCHit(Int_t m = kMdim); + + EXTPCHit(const EXTPCMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const TVector3 &xx, + Double_t b, + Int_t m = kMdim); + + EXTPCHit(const EXTPCMeasLayer &ms, + Double_t *x, + Double_t *dx, + Int_t side, + Double_t v, + const void *hitp, + Double_t b, + Int_t m = kMdim); + + virtual ~EXTPCHit(); + + virtual TKalMatrix XvToMv(const TVector3 &xv, Double_t t0) const; + virtual void DebugPrint(Option_t *opt = "") const; + virtual Double_t GetSortingPolicy() const; + virtual Int_t Compare(const TObject *obj) const; + virtual Bool_t IsSortable() const; + + inline Int_t GetSide () const { return fSide; } + inline Double_t GetVdrift() const { return fVdrift; } + inline const void *GetHitPtr() const { return fHitPtr; } + inline const TVector3 GetExactX() const { return *fXXPtr; } + +private: + Int_t fSide; // (-1, +1) = (-z side, +z side) + Double_t fVdrift; // drift veclocity + const TVector3 *fXXPtr; // pointer to exact hit + const void *fHitPtr; // pointer to raw Hit object + + ClassDef(EXTPCHit, 1) // EXTPC hit class +}; +#endif diff --git a/Utilities/KalDet/src/othertpc/toytpc/EXTPCKalDetector.cxx b/Utilities/KalDet/src/othertpc/toytpc/EXTPCKalDetector.cxx new file mode 100644 index 0000000000000000000000000000000000000000..279cd9cde882373a07d2b2e3479d57fdec16c8f3 --- /dev/null +++ b/Utilities/KalDet/src/othertpc/toytpc/EXTPCKalDetector.cxx @@ -0,0 +1,147 @@ +//************************************************************************* +//* ======================== +//* EXTPCKalDetector Class +//* ======================== +//* +//* (Description) +//* User defined detector class +//* (Requires) +//* EXVKalDetector +//* (Provides) +//* class EXTPCKalDetector +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/tpc/EXTPCKalDetector.cxx +//* +//* $Id: EXTPCKalDetector.cxx,v 1.1 2010-03-11 15:07:01 fujiik Exp $ +//************************************************************************* +// +// STL +#include <vector> + +// GEAR +#include "gear/GEAR.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gearimpl/TPCModuleImpl.h" +#include "gearxml/GearXML.h" + +// global constants from Marlin, used for the global pointer to the GearMgr +//#include <marlin/Global.h> + +#include "EXTPCKalDetector.h" +#include "EXTPCMeasLayer.h" +#include "EXTPCHit.h" +#include "kaltest/TKalDetCradle.h" + +// ROOT +#include "TRandom.h" +#include "TMath.h" +#include "TTUBE.h" +#include "TNode.h" +#include "TVirtualPad.h" + +EXTPCKalDetector * EXTPCKalDetector::fgInstance = 0; +Double_t EXTPCKalDetector::fgVdrift = 7.6e-3; + + +ClassImp(EXTPCKalDetector) + +// definition of gas parameters for mixture of Ar + CF4 + C4H10 +Double_t Ar = 0.95; // fraction of Argon in chamber gas +Double_t CF = 0.043; // fraction of CF4 in chamber gas +Double_t CH = 0.007; // fraction of C4H10 in chamber gas + +EXTPCKalDetector::EXTPCKalDetector(Int_t m) + : EXVKalDetector(m), + fNodePtr(0) +{ + Double_t A, Z, density, radlen; + + A = 39.948 * Ar + 17.601 * CF + 4.152 * CH; + Z = 18 * Ar + 8.4 * CF + 2.4 * CH; + density = (1.784 * Ar + 3.692 * CF + 2.65 * CH)/1000; + radlen = 1.196e4*2; // has to be checked, copied from 0.9 Ar, 0.1 C4H10 lines + TMaterial &gas = *new TMaterial("TPCGas", "", A, Z, density, radlen, 0.); +#if 1 + static const Int_t nlayers = 24; // number of layer + static const Double_t kmm2cm = 0.1; + static const Double_t lhalf = 600. * kmm2cm; //length + // diffusion coefficients transversal (x) and longitudinal (z) to magnetic field + static const Double_t neff = 22.7; +#if 0 + static const Double_t sigmax0 = 38.3e-4; + static const Double_t sigmax1 = 101.5e-4 /TMath::Sqrt(10.)/TMath::Sqrt(neff); + static const Double_t sigmaz0 = 500.e-4; + static const Double_t sigmaz1 = 154.e-4/TMath::Sqrt(10.)/TMath::Sqrt(neff); +#else + static const Double_t sigmax0 = 50e-4; + static const Double_t sigmax1 = 0.; + static const Double_t sigmaz0 = 500.e-4; + static const Double_t sigmaz1 = 0.; +#endif + fgVdrift = 50.e-3 * kmm2cm; +#else + + gear::TPCParameters const &theTPCParameters + = marlin::Global::GEAR->getTPCParameters(); + + Int_t nmodules = theTPCParameters.getNModules(); + + std::vector<const gear::TPCModule *> modules; + + for (Int_t i = 0; i < nmodules; i++) { + modules.push_back(&theTPCParameters.getModule(i)); + } + + static const Double_t kmm2cm = 0.1; + + static const Double_t lhalf + = theTPCParameters.getMaxDriftLength() * kmm2cm; // half length + static const Int_t nrows = modules[0]->getNRows(); // # of pad rows + ///// FIXME: temporary treatment ///////////////////////// + static const Int_t nlayers = nrows * 3; // # of layers + ////////////////////////////////////////////////////////// + static const Double_t neff = 22.7; + static const Double_t sigmax0 = 38.3e-4; + static const Double_t sigmax1 = 101.5e-4 / TMath::Sqrt(10.) / TMath::Sqrt(neff); + static const Double_t sigmaz0 = 500.e-4; + static const Double_t sigmaz1 = 154.e-4 / TMath::Sqrt(10.) / TMath::Sqrt(neff); +#endif + Bool_t active = EXTPCMeasLayer::kActive; + + // create measurement layers + Int_t module = 1; + for (Int_t layer = 0; layer < nlayers; layer++) { + Double_t XMin = -32. * kmm2cm; + Double_t XMax = 32. * kmm2cm; + Double_t y0 = (4.*layer-46.) * kmm2cm; + Add(new EXTPCMeasLayer(gas, gas, y0, XMin, XMax, lhalf, sigmax0, sigmax1, sigmaz0, sigmaz1, active, layer, module)); + } + SetOwner(); +} + +EXTPCKalDetector::~EXTPCKalDetector() +{ +} + +EXTPCKalDetector * EXTPCKalDetector::GetInstance() +{ + if (!fgInstance) { + fgInstance = new EXTPCKalDetector; + TKalDetCradle & toydet = * new TKalDetCradle; + toydet.Install(*fgInstance); + toydet.Close(); + toydet.Sort(); + } + return fgInstance; +} + +void EXTPCKalDetector::Draw(Int_t color, const Char_t *opt) +{ + if (! gPad) return; + TNode *nodep = GetNodePtr(); + nodep->cd(); + //EXVKalDetector::Draw(color, opt); + TAttDrawable::Draw(color, opt); +} diff --git a/Utilities/KalDet/src/othertpc/toytpc/EXTPCKalDetector.h b/Utilities/KalDet/src/othertpc/toytpc/EXTPCKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..63fa7576c72ce51ca619aea4eee4f44faea4f091 --- /dev/null +++ b/Utilities/KalDet/src/othertpc/toytpc/EXTPCKalDetector.h @@ -0,0 +1,45 @@ +#ifndef EXTPCDETECTOR_H +#define EXTPCDETECTOR_H +//************************************************************************* +//* ======================== +//* EXTPCKalDetector Class +//* ======================== +//* +//* (Description) +//* User defined detector class +//* (Requires) +//* EXVKalDetector +//* (Provides) +//* class EXTPCKalDetector +//* (Update Recored) +//* 2009/11/23 K.Ikematsu Derived from KalTest/examples/kaltest/ +//* hybrid/tpc/EXTPCKalDetector.h +//* +//* $Id: EXTPCKalDetector.h,v 1.1 2010-03-11 15:07:01 fujiik Exp $ +//************************************************************************* +// +#include "kaldet/EXVKalDetector.h" + +class TNode; + +class EXTPCKalDetector : public EXVKalDetector { +private: + EXTPCKalDetector(Int_t m = 100); + +public: + ~EXTPCKalDetector(); + static EXTPCKalDetector * GetInstance(); + + static Double_t GetVdrift() { return fgVdrift; } + + //using EXVKalDetector::Draw; + void Draw(Int_t color, const Char_t *opt = ""); + +private: + TNode * fNodePtr; // node pointer + static Double_t fgVdrift; // drift velocity + static EXTPCKalDetector * fgInstance; //! singleton pointer + + ClassDef(EXTPCKalDetector, 1) // User defined detector class +}; +#endif diff --git a/Utilities/KalDet/src/othertpc/toytpc/EXTPCMeasLayer.cxx b/Utilities/KalDet/src/othertpc/toytpc/EXTPCMeasLayer.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d7a4c9c5f2e1c21b92b5640a658e2134ea33032d --- /dev/null +++ b/Utilities/KalDet/src/othertpc/toytpc/EXTPCMeasLayer.cxx @@ -0,0 +1,202 @@ +//************************************************************************* +//* =================== +//* EXTPCMeasLayer Class +//* =================== +//* +//* (Description) +//* Sample measurement layer class used by EXTPCHit. +//* (Requires) +//* (Provides) +//* class EXTPCMeasLayer +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* +//************************************************************************* +// + +#include "EXTPCMeasLayer.h" +#include "EXTPCHit.h" +#include "EXTPCKalDetector.h" +#include "TRandom.h" +#include "TMath.h" + + +ClassImp(EXTPCMeasLayer) + +EXTPCMeasLayer::EXTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t y0, + Double_t lhalf, + Double_t sigmax0, + Double_t sigmax1, + Double_t sigmaz0, + Double_t sigmaz1, + Bool_t type) + : EXVMeasLayer(min, mout, type), + TPlane(TVector3(0.,y0,lhalf), TVector3(0.,1.,0.)), + fSigmaX0(sigmax0), + fSigmaX1(sigmax1), + fSigmaZ0(sigmaz0), + fSigmaZ1(sigmaz1), + fLayer(-1) +{ +} + +EXTPCMeasLayer::EXTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t y0, + Double_t XMin, + Double_t XMax, + Double_t lhalf, + Double_t sigmax0, + Double_t sigmax1, + Double_t sigmaz0, + Double_t sigmaz1, + Bool_t type, + Int_t layer, + Int_t module) + : EXVMeasLayer(min, mout, type), + TPlane(TVector3(0.,y0,lhalf), TVector3(0.,1.,0.)), + fXMin(XMin), + fXMax(XMax), + fSigmaX0(sigmax0), + fSigmaX1(sigmax1), + fSigmaZ0(sigmaz0), + fSigmaZ1(sigmaz1), + fModule(module), + fLayer(layer) +{ +} + +EXTPCMeasLayer::~EXTPCMeasLayer() +{ +} + +TKalMatrix EXTPCMeasLayer::XvToMv(const TVector3 &xv, + Int_t side) const +{ + TKalMatrix mv(kMdim,1); + mv(0,0) =xv.X(); + mv(1,0) =xv.Z(); + return mv; +} + +TKalMatrix EXTPCMeasLayer::XvToMv(const TVTrackHit &vht, + const TVector3 &xv) const +{ + return XvToMv(xv, dynamic_cast<const EXTPCHit &>(vht).GetSide()); +} + +TVector3 EXTPCMeasLayer::HitToXv(const TVTrackHit &vht) const +{ + const EXTPCHit &ht = dynamic_cast<const EXTPCHit &>(vht); + Double_t x = ht(0,0); + Double_t y = GetXc().Y(); + Double_t z = ht(1,0); + return TVector3(x,y,z); +} + +void EXTPCMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const +{ + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + for (Int_t i=0;i<hdim;i++){ + H(0,i) = dxphiada(0,i); + H(1,i) = dxphiada(2,i); + } +} + +/* + void EXTPCMeasLayer::CalcDhDa(const TVTrackHit &vht, + const TVector3 &xxv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const + { + const EXTPCHit &ht = dynamic_cast<const EXTPCHit &>(vht); + + // Calculate + // H = (@h/@a) = (@phi/@a, @z/@a)^t + // where + // h(a) = (phi, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + + + Int_t sdim = H.GetNcols(); + Int_t hdim = TMath::Max(5,sdim-1); + + TVector3 xxvc = xxv - GetXc(); + Double_t xv = xxvc.X(); + Double_t yv = xxvc.Y(); + Double_t xxyy = xv * xv + yv * yv; + + // Set H = (@h/@a) = (@d/@a, @z/@a)^t + + for (Int_t i=0; i<hdim; i++) { + H(0,i) = - (yv / xxyy) * dxphiada(0,i) + + (xv / xxyy) * dxphiada(1,i); + H(0,i) *= 0;//GetR(); +#if 0 + H(1,i) = - ht.GetSide() * dxphiada(2,i); +#else + H(1,i) = dxphiada(2,i); +#endif + } + if (sdim == 6) { + H(0,sdim-1) = 0.; +#if 0 + H(1,sdim-1) = ht.GetVdrift(); +#else + H(1,sdim-1) = - ht.GetVdrift(); +#endif + } +} +*/ + +Double_t EXTPCMeasLayer::GetSigmaX(Double_t zdrift) const +{ + return TMath::Sqrt(fSigmaX0 * fSigmaX0 + fSigmaX1 * fSigmaX1 * zdrift); +} + +Double_t EXTPCMeasLayer::GetSigmaZ(Double_t zdrift) const +{ + return TMath::Sqrt(fSigmaZ0 * fSigmaZ0 + fSigmaZ1 * fSigmaZ1 * zdrift); +} + +Double_t EXTPCMeasLayer::GetSortingPolicy() const +{ + return GetXc().Y(); +} + + +void EXTPCMeasLayer::ProcessHit(const TVector3 &xx, + TObjArray &hits) +{ + Int_t side = (xx.Z() < 0. ? -1 : 1); + TKalMatrix h = XvToMv(xx, side); + Double_t rphi = h(0, 0); + Double_t d = h(1, 0); + + Double_t dx = GetSigmaX(d); + Double_t dz = GetSigmaZ(d); + rphi += gRandom->Gaus(0., dx); // smearing rphi + d += gRandom->Gaus(0., dz); // smearing drift distance + + Double_t v = EXTPCKalDetector::GetVdrift(); +#if 0 + d += v * EXEventGen::GetT0(); // T0 shift +#endif + + Double_t meas [2]; + Double_t dmeas[2]; + meas [0] = rphi; + meas [1] = d; + dmeas[0] = dx; + dmeas[1] = dz; + + Double_t b = EXTPCKalDetector::GetBfield(); + hits.Add(new EXTPCHit(*this, meas, dmeas, side, v, xx, b)); +} diff --git a/Utilities/KalDet/src/othertpc/toytpc/EXTPCMeasLayer.h b/Utilities/KalDet/src/othertpc/toytpc/EXTPCMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..c9dc038828bc4709a15e3822463684cde2f2aa56 --- /dev/null +++ b/Utilities/KalDet/src/othertpc/toytpc/EXTPCMeasLayer.h @@ -0,0 +1,91 @@ +#ifndef EXTPCMEASLAYER_H +#define EXTPCMEASLAYER_H +//************************************************************************* +//* =================== +//* EXTPCMeasLayer Class +//* =================== +//* +//* (Description) +//* Sample measurement layer class used by EXTPCHit. +//* (Requires) +//* (Provides) +//* class EXTPCMeasLayer +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* +//************************************************************************* +// +#include "TVector3.h" +#include "kaltest/TKalMatrix.h" +#include "kaltest/TPlane.h" +#include "kaltest/KalTrackDim.h" +#include "kaldet/EXVMeasLayer.h" + +class TVTrackHit; + +class EXTPCMeasLayer : public EXVMeasLayer, public TPlane { +public: + // Ctors and Dtor + + EXTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t y0, + Double_t lhalf, + Double_t sigmax0, + Double_t sigmax1, + Double_t sigmaz0, + Double_t sigmaz1, + Bool_t type = EXVMeasLayer::kActive); + EXTPCMeasLayer(TMaterial &min, + TMaterial &mout, + Double_t y0, + Double_t xmin, + Double_t ymax, + Double_t lhalf, + Double_t sigmax0, + Double_t sigmax1, + Double_t sigmaz0, + Double_t sigmaz1, + Bool_t type = EXVMeasLayer::kDummy, + Int_t layer = -1, + Int_t module = 0); + virtual ~EXTPCMeasLayer(); + + // Getters and Setters + + inline Int_t GetModuleID() const { return fModule; } + inline Int_t GetLayerID () const { return fLayer; } + + // Parrent's pure virtuals that must be implemented + + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const; + virtual TKalMatrix XvToMv (const TVector3 &xv, + Int_t side) const; + virtual TVector3 HitToXv (const TVTrackHit &ht) const; + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const; + virtual void ProcessHit(const TVector3 &xx, + TObjArray &hits); + + virtual Double_t GetSortingPolicy () const; + + Double_t GetSigmaX(Double_t z) const; + Double_t GetSigmaZ(Double_t z) const; + +private: + Double_t fXMin; // minimum phi + Double_t fXMax; // maximum phi + Double_t fSigmaX0; // xy resolution + Double_t fSigmaX1; // xy resolution + Double_t fSigmaZ0; // z resolution + Double_t fSigmaZ1; // z resolution + Int_t fModule; // module number + Int_t fLayer; // layer number + + ClassDef(EXTPCMeasLayer,1) // Sample measurement layer class +}; + +#endif diff --git a/Utilities/KalDet/src/othertpc/toytpc/Imakefile b/Utilities/KalDet/src/othertpc/toytpc/Imakefile new file mode 100644 index 0000000000000000000000000000000000000000..559ab42540f563a1a806443e53f4f7b949b11f6e --- /dev/null +++ b/Utilities/KalDet/src/othertpc/toytpc/Imakefile @@ -0,0 +1,62 @@ +#include "../../conf/makejsf.tmpl" + +INSTALLDIR = ../.. +PACKAGENAME = KalDetToyTpc +SOREV = 2009.01 +SRCS = EXTPCKalDetector.$(SrcSuf) \ + EXTPCMeasLayer.$(SrcSuf) \ + EXTPCHit.$(SrcSuf) + +OBJS = $(subst .$(SrcSuf),.$(ObjSuf),$(SRCS)) \ + $(PACKAGENAME)Dict.$(ObjSuf) + +HDRS = $(subst .$(SrcSuf),.h,$(SRCS)) + +DICTNAME = $(PACKAGENAME)Dict + +LIBNAME = $(PACKAGENAME) + +SONAME = lib$(LIBNAME).$(DllSuf).$(SOREV) + +LIBINSTALLDIR = $(INSTALLDIR)/lib +INCINSTALLDIR = $(INSTALLDIR)/include +INCPATH = -I. -I$(KALTESTROOT)/include -I$(INCINSTALLDIR) +INCPATH += -I$(MARLIN)/include -I$(GEAR)/include +CXXFLAGS += $(INCPATH) -O -g +CXXFLAGS += -DUSE_GEAR +SHLIBLDFLAGS = $(DYLIBFLAGS) + +all:: $(SONAME) + +SharedLibraryTarget($(LIBNAME),$(SOREV),$(OBJS),.,.) + +#if defined(DarwinArchitecture) +$(SONAME): $(OBJS) + $(LD) $(SOFLAGS) -o $(SONAME) $(OBJS) $(LDFLAGS) + +install:: $(SONAME) + $(MKDIRHIER) $(DESTDIR)$(LIBINSTALLDIR) + $(INSTALL) $(INSTALLFLAGS) $(SONAME) $(LIBINSTALLDIR) + $(RM) $(LIBINSTALLDIR)/lib$(LIBNAME).$(DllSuf) + $(LN) $(SONAME) $(LIBINSTALLDIR)/lib$(LIBNAME).$(DllSuf) +#endif + +InstallSharedLibrary($(LIBNAME),$(SOREV),$(LIBINSTALLDIR)) + +InstallMultipleFlags($(HDRS),$(INCINSTALLDIR),-m 644 -C) + +clean:: + @rm -f $(OBJS) core *.$(DllSuf) $(DICTNAME).$(SrcSuf) $(DICTNAME).h + +depend:: $(SRCS) $(HDRS) + for i in $(SRCS); do \ + rmkdepend -a -- $(DEPENDFILES) -- $$i; done + +distclean:: clean + @rm -f $(OBJS) core *.$(DllSuf) $(DICTNAME).$(SrcSuf) $(DICTNAME).h *~ + @rm -f *.root Makefile + +$(DICTNAME).$(SrcSuf): $(HDRS) LinkDef.h + @echo "Generating dictionary ..." + rootcint -f $(DICTNAME).$(SrcSuf) \ + -c $(INCPATH) $(HDRS) LinkDef.h diff --git a/Utilities/KalDet/src/othertpc/toytpc/LinkDef.h b/Utilities/KalDet/src/othertpc/toytpc/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..c5932dc1edf594d424364e14af5a236cb1e2f4fe --- /dev/null +++ b/Utilities/KalDet/src/othertpc/toytpc/LinkDef.h @@ -0,0 +1,11 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class EXTPCKalDetector+; +#pragma link C++ class EXTPCHit+; +#pragma link C++ class EXTPCMeasLayer+; + +#endif diff --git a/Utilities/KalTest/CMakeLists.txt b/Utilities/KalTest/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..65fba19a54749a7dc885d91f576388805f0fcc65 --- /dev/null +++ b/Utilities/KalTest/CMakeLists.txt @@ -0,0 +1,51 @@ +############################################################################## +# Package: KalTest +# Desc: import from ILCSoft +############################################################################## + +gaudi_subdir(KalTest v0r0) + +find_package(ROOT REQUIRED COMPONENTS MathCore) + +gaudi_depends_on_subdirs() + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +SET( ROOT_DICT_CINT_DEFINITIONS "-DHANDLE_DICT_EXCEPTIONS=IGNORED_FOR_CINT" ) + +INCLUDE( MyFindROOT ) +INCLUDE( MacroRootDict ) + +SET( lib_input_dirs src/geomlib src/kallib src/kaltracklib src/utils ) + +FOREACH( lib_input_dir ${lib_input_dirs} ) + LIST( APPEND ROOT_DICT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/${lib_input_dir} ) +ENDFOREACH() + +#MESSAGE( STATUS "ROOT_DICT_INCLUDE_DIRS: ${ROOT_DICT_INCLUDE_DIRS}" ) + +FOREACH( lib_input_dir ${lib_input_dirs} ) + + AUX_SOURCE_DIRECTORY( ${lib_input_dir} lib_sources ) + + PREPARE_ROOT_DICT_HEADERS( ${lib_input_dir} ) + + INSTALL(DIRECTORY ${lib_input_dir}/ DESTINATION "include/kaltest" + FILES_MATCHING PATTERN "*.h" PATTERN "LinkDef.h" EXCLUDE + ) + + GEN_ROOT_DICT_SOURCES( ${lib_input_dir}Dict.cxx ) + + LIST( APPEND lib_sources ${ROOT_DICT_OUTPUT_SOURCES} ) + +ENDFOREACH() + +include_directories( ${ROOT_DICT_INCLUDE_DIRS} ) +include_directories( ${ROOT_INCLUDE_DIRS} ) + +set(KalTestLib_srcs ${lib_sources}) + +gaudi_add_library(KalTestLib ${KalTestLib_srcs} + PUBLIC_HEADERS kaltest + LINK_LIBRARIES GaudiKernel ROOT +) diff --git a/Utilities/KalTest/cmake/MacroCheckPackageLibs.cmake b/Utilities/KalTest/cmake/MacroCheckPackageLibs.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c4451b3e40839e00dcefe08680a34ef98a3dd2b6 --- /dev/null +++ b/Utilities/KalTest/cmake/MacroCheckPackageLibs.cmake @@ -0,0 +1,164 @@ +############################################################################## +# macro for checkin package libraries in ${PKG_ROOT}/lib +# +# +# macro usage: +# CHECK_PACKAGE_LIBS( PACKAGE_NAME stdlib1 stdlib2 ... stdlibn ) +# only standard libraries should be passed as arguments to the macro +# component libraries are set by cmake in PKG_FIND_COMPONENTS (when +# calling FIND_PACKAGE with COMPONENTS argument) or through the +# variable PKG_USE_COMPONENTS +# +# +# required variables: +# PKG_ROOT : path to PKG root directory +# +# +# returns following variables: +# PKG_LIBRARY_DIRS : list of paths to be used with LINK_DIRECTORIES +# PGK_LIBRARIES : list of STANDARD libraries (NOT including COMPONENTS) +# PKG_COMPONENT_LIBRARIES : list of COMPONENT libraries +# PKG_${COMPONENT}_FOUND : set to TRUE or FALSE for each library +# PKG_${COMPONENT}_LIBRARY : path to each individual library +# +# +# PKG_LIBRARIES and PKG_LIBRARY_DIRS will be empty if any of the standard +# libraries is missing +# +# @author Jan Engels, Desy +############################################################################## + + +SET( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE ) + +MACRO( CHECK_PACKAGE_LIBS _pkgname ) + + SET( _std_lib_missing FALSE ) + SET( _ext_lib_missing FALSE ) + + SET( _std_libnames ${ARGN} ) + SET( _ext_libnames ${${_pkgname}_FIND_COMPONENTS} ${${_pkgname}_USE_COMPONENTS} ) + + IF( _ext_libnames ) + SEPARATE_ARGUMENTS( _ext_libnames ) + LIST( REMOVE_DUPLICATES _ext_libnames ) + ENDIF() + + IF( NOT ${_pkgname}_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ${_pkgname}_LIBRARIES: ${_std_libnames}" ) + IF( _ext_libnames ) + MESSAGE( STATUS "Check for ${_pkgname}_COMPONENT_LIBRARIES: ${_ext_libnames}" ) + ENDIF() + ENDIF() + + SET( ${_pkgname}_LIBRARY_DIRS ) + MARK_AS_ADVANCED( ${_pkgname}_LIBRARY_DIRS ) + + SET( ${_pkgname}_LIBRARIES ) + MARK_AS_ADVANCED( ${_pkgname}_LIBRARIES ) + + SET( ${_pkgname}_COMPONENT_LIBRARIES ) + MARK_AS_ADVANCED( ${_pkgname}_COMPONENT_LIBRARIES ) + + SET( ${_pkgname}_COMPONENT_VARIABLES ) + MARK_AS_ADVANCED( ${_pkgname}_COMPONENT_VARIABLES ) + + FOREACH( _libname ${_std_libnames} ${_ext_libnames} ) + + # flag to check if it is a standard or a component library + LIST( FIND _std_libnames "${_libname}" _aux ) + IF( ${_aux} LESS 0 ) + SET( _is_std_lib FALSE ) + ELSE() + SET( _is_std_lib TRUE ) + ENDIF() + + # libname in upper case + STRING( TOUPPER ${_libname} _ulibname ) + + SET( ${_pkgname}_${_ulibname}_LIBRARY ${_pkgname}_${_ulibname}_LIBRARY-NOTFOUND ) + MARK_AS_ADVANCED( ${_pkgname}_${_ulibname}_LIBRARY ) + + # WARNING: using PATH_SUFFIXES may cause problems when using variable CMAKE_FIND_ROOT_PATH + # this problem does not occur if expanding PATHS + # look in FindMySQL.cmake for more info + #FIND_LIBRARY( ${_pkgname}_${_ulibname}_LIBRARY NAMES ${_libname} PATHS + # ${${_pkgname}_ROOT} ${${_pkgname}_DIR} ${${_pkgname}_LIB_SEARCH_PATH} + # PATH_SUFFIXES lib64 lib + # NO_DEFAULT_PATH + #) + + FIND_LIBRARY( ${_pkgname}_${_ulibname}_LIBRARY NAMES ${_libname} PATHS + ${${_pkgname}_ROOT}/lib64 ${${_pkgname}_ROOT}/lib + ${${_pkgname}_DIR}/lib64 ${${_pkgname}_DIR}/lib + ${${_pkgname}_LIB_SEARCH_PATH} ${${_pkgname}_LIB_SEARCH_PATH}/lib64 ${${_pkgname}_LIB_SEARCH_PATH}/lib + NO_DEFAULT_PATH + ) + + IF( NOT ${_pkgname}_DIR ) + FIND_LIBRARY( ${_pkgname}_${_ulibname}_LIBRARY NAMES ${_libname} ) + ENDIF() + + IF( ${_pkgname}_FIND_REQUIRED ) + LIST( APPEND ${_pkgname}_COMPONENT_VARIABLES ${_pkgname}_${_ulibname}_LIBRARY ) + ENDIF() + + IF( ${_pkgname}_${_ulibname}_LIBRARY ) # if library found + + SET( ${_pkgname}_${_ulibname}_FOUND TRUE ) + + # split libraries in PKG_LIBRARIES and PKG_COMPONENT_LIBRARIES + IF( _is_std_lib ) + LIST( APPEND ${_pkgname}_LIBRARIES ${${_pkgname}_${_ulibname}_LIBRARY} ) + ELSE() + LIST( APPEND ${_pkgname}_COMPONENT_LIBRARIES ${${_pkgname}_${_ulibname}_LIBRARY} ) + ENDIF() + + GET_FILENAME_COMPONENT( _aux ${${_pkgname}_${_ulibname}_LIBRARY} PATH ) + LIST( APPEND ${_pkgname}_LIBRARY_DIRS ${_aux} ) + + IF( NOT ${_pkgname}_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ${_pkgname}_${_ulibname}_LIBRARY: ${${_pkgname}_${_ulibname}_LIBRARY} -- ok" ) + ENDIF() + + ELSE() # library not found + + SET( ${_pkgname}_${_ulibname}_FOUND FALSE ) + + IF( _is_std_lib ) + SET( _std_lib_missing TRUE ) + ELSE() + SET( _ext_lib_missing TRUE ) + ENDIF() + + IF( NOT ${_pkgname}_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ${_pkgname}_${_ulibname}_LIBRARY: ${_libname} -- failed" ) + ENDIF() + + ENDIF() + + ENDFOREACH() + + # clear PKG_LIBRARIES if standard library is missing + IF( _std_lib_missing ) + SET( ${_pkgname}_LIBRARIES ) + ENDIF() + + # clear PKG_COMPONENT_LIBRARIES if a component library is missing and + # FIND_PACKAGE called with REQUIRED argument + IF( _ext_lib_missing AND ${_pkgname}_FIND_REQUIRED ) + SET( ${_pkgname}_COMPONENT_LIBRARIES ) + ENDIF() + + # remove duplicate paths in PKG_LIBRARY_DIRS + IF( ${_pkgname}_LIBRARY_DIRS ) + LIST( REMOVE_DUPLICATES ${_pkgname}_LIBRARY_DIRS ) + ENDIF() + + # debug + #MESSAGE( STATUS "${_pkgname}_LIBRARIES: ${${_pkgname}_LIBRARIES}" ) + #MESSAGE( STATUS "${_pkgname}_COMPONENT_LIBRARIES: ${${_pkgname}_COMPONENT_LIBRARIES}" ) + #MESSAGE( STATUS "${_pkgname}_LIBRARY_DIRS: ${${_pkgname}_LIBRARY_DIRS}" ) + +ENDMACRO( CHECK_PACKAGE_LIBS _pkgname ) + diff --git a/Utilities/KalTest/cmake/MacroCheckPackageVersion.cmake b/Utilities/KalTest/cmake/MacroCheckPackageVersion.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e3ec75d9faa2ee03919d01179636fb1ba843e41e --- /dev/null +++ b/Utilities/KalTest/cmake/MacroCheckPackageVersion.cmake @@ -0,0 +1,108 @@ +############################################################################## +# macro for checking a package version +# +# this macro should be called from your PKGVersion.cmake or from a +# FindPKG.cmake module with the following arguments: +# _pkgname : The package name +# _iversion : The installed version of the package +# +# +# the following conventions are used: +# +# if FIND_PACKAGE is called with EXACT argument than the version has to +# match EXACTLY, i.e.: +# 1.5 == 1.5 +# 1.5 == 1.5.0 +# 1.5 == 1.5.0.0 +# 1.5.2 == 1.5.2.0 +# 1.5.2.1 == 1.5.2.1 +# 1.5.2 != 1.5.2.1 +# 1.5 != 1.5.0.1 +# +# +# otherwise a MINIMUM_REQUIRED version is checked for, i.e. the same +# behavior as with the cmake variable CMAKE_MINIMUM_REQUIRED, e.g.: +# searching: 1.2 --> installed: 1.5.2.2 --> compatible +# searching: 1.5 --> installed: 1.5.2.2 --> compatible +# searching: 1.5.2.1 --> installed: 1.5.2.2 --> compatible +# searching: 1.5.2.3 --> installed: 1.5.2.2 --> unsuitable +# searching: 1.7 --> installed: 1.5.2.2 --> unsuitable +# +# +# following variables are returned (internally to cmake): +# PACKAGE_VERSION_EXACT : set to TRUE if exact version was found +# PACKAGE_VERSION_COMPATIBLE : set to TRUE if version is compatible +# PACKAGE_VERSION_UNSUITABLE : set to TRUE if version found is unsuitable +# +# +# @author Jan Engels, Desy IT +############################################################################## + +# these variables are evaluated internally by the cmake command FIND_PACKAGE to mark this +# package as suitable or not depending on the required version +SET( PACKAGE_VERSION_EXACT FALSE ) +SET( PACKAGE_VERSION_COMPATIBLE TRUE ) +SET( PACKAGE_VERSION_UNSUITABLE FALSE ) + + +# cmake internal variable PACKAGE_FIND_NAME is not defined on FindPKG.cmake +# modules, therefore it is passed as an argument to the macro +# _iversion is the installed version of the package +# _sversion is the version searched by the user with FIND_PACKAGE +#MACRO( CHECK_PACKAGE_VERSION _pkgname _iversion ) +MACRO( CHECK_PACKAGE_VERSION _pkgname ) # left with one argument only for backwards compatibility + + IF( NOT "${ARGV1}" STREQUAL "" ) + SET( _iversion ${ARGV1} ) + ELSE() + SET( _iversion ${${_pkgname}_VERSION_MAJOR}.${${_pkgname}_VERSION_MINOR}.${${_pkgname}_VERSION_PATCH}.${${_pkgname}_VERSION_TWEAK} ) + ENDIF() + + #SET( _sversion_major ${${_pkgname}_FIND_VERSION_MAJOR} ) + #SET( _sversion_minor ${${_pkgname}_FIND_VERSION_MINOR} ) + + SET( _sversion ${${_pkgname}_FIND_VERSION} ) + + IF( NOT ${_pkgname}_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ${_pkgname} (${_iversion})" ) + ENDIF() + + # only do work if FIND_PACKAGE called with a version argument + IF( _sversion ) + + #IF( NOT ${_pkgname}_FIND_QUIETLY ) + # MESSAGE( STATUS "Check for ${_pkgname}: looking for version ${_sversion}" ) + #ENDIF() + + IF( ${_iversion} VERSION_EQUAL ${_sversion} ) # if version matches EXACTLY + #IF( NOT ${_pkgname}_FIND_QUIETLY ) + # MESSAGE( STATUS "Check for ${_pkgname}: exact version found: ${_iversion}" ) + #ENDIF() + SET( PACKAGE_VERSION_EXACT TRUE ) + ELSE() # if version does not match EXACTLY, check if it is compatible/suitable + + # installed version must be greater or equal than version searched by the user, i.e. + # like with the CMAKE_MINIMUM_REQUIRED commando + # if user asks for version 1.2.5 then any version >= 1.2.5 is suitable/compatible + IF( NOT ${_sversion} VERSION_LESS ${_iversion} ) + SET( PACKAGE_VERSION_UNSUITABLE TRUE ) + ENDIF() + # ------------------------------------------------------------------------------------- + + IF( ${_pkgname}_FIND_VERSION_EXACT ) # if exact version was required search must fail!! + #IF( NOT ${_pkgname}_FIND_QUIETLY ) + # MESSAGE( "Check for ${_pkgname}: could not find exact version" ) + #ENDIF() + SET( PACKAGE_VERSION_UNSUITABLE TRUE ) + ENDIF() + + ENDIF() + + IF( PACKAGE_VERSION_UNSUITABLE ) + SET( PACKAGE_VERSION_COMPATIBLE FALSE ) + ENDIF() + + ENDIF( _sversion ) + +ENDMACRO( CHECK_PACKAGE_VERSION ) + diff --git a/Utilities/KalTest/cmake/MacroRootDict.cmake b/Utilities/KalTest/cmake/MacroRootDict.cmake new file mode 100644 index 0000000000000000000000000000000000000000..ed7747fd24cf553be16f1c55eed643fae39d205e --- /dev/null +++ b/Utilities/KalTest/cmake/MacroRootDict.cmake @@ -0,0 +1,145 @@ +IF(APPLE) + SET( LD_LIBRARY_PATH_VAR DYLD_LIBRARY_PATH ) +ELSE() + SET( LD_LIBRARY_PATH_VAR LD_LIBRARY_PATH ) +ENDIF() +SET( LD_LIBRARY_PATH_CONTENTS $ENV{${LD_LIBRARY_PATH_VAR}} ) +#MESSAGE( STATUS "LD_LIBRARY_PATH_CONTENTS: ${LD_LIBRARY_PATH_CONTENTS}" ) +#MESSAGE( STATUS "ROOT_CINT_EXECUTABLE: ${ROOT_CINT_EXECUTABLE}" ) + +SET( ROOT_CINT_WRAPPER ${LD_LIBRARY_PATH_VAR}=${ROOT_LIBRARY_DIR}:${LD_LIBRARY_PATH_CONTENTS} ${ROOT_CINT_EXECUTABLE} ) + +IF( NOT DEFINED ROOT_DICT_OUTPUT_DIR ) + SET( ROOT_DICT_OUTPUT_DIR "${PROJECT_BINARY_DIR}/rootdict" ) +ENDIF() + +# clean generated header files with 'make clean' +SET_DIRECTORY_PROPERTIES( PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${ROOT_DICT_OUTPUT_DIR}" ) + +IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ROOT_DICT_OUTPUT_DIR: ${PROJECT_BINARY_DIR}/rootdict" ) + MESSAGE( STATUS "Check for ROOT_DICT_CINT_DEFINITIONS: ${ROOT_DICT_CINT_DEFINITIONS}" ) +ENDIF() + + +# ============================================================================ +# helper macro to prepare input headers for GEN_ROOT_DICT_SOURCES +# sorts LinkDef.h to be the last header (required by rootcint) +# +# arguments: +# input_dir - directory to search for headers matching *.h +# +# returns: +# ROOT_DICT_INPUT_HEADERS - all header files found in input_dir with +# LinkDef.h as the last header (if found) +# +# ---------------------------------------------------------------------------- +MACRO( PREPARE_ROOT_DICT_HEADERS _input_dir ) + + FILE( GLOB ROOT_DICT_INPUT_HEADERS "${_input_dir}/*.h" ) + FILE( GLOB _linkdef_hdr "${_input_dir}/LinkDef.h" ) + + #LIST( FIND ROOT_DICT_INPUT_HEADERS ${_linkdef_hdr} _aux ) + #IF( ${_aux} EQUAL 0 OR ${_aux} GREATER 0 ) + # LIST( REMOVE_ITEM ROOT_DICT_INPUT_HEADERS "${_linkdef_hdr}" ) + # LIST( APPEND ROOT_DICT_INPUT_HEADERS "${_linkdef_hdr}" ) + #ENDIF() + + IF( _linkdef_hdr ) + LIST( REMOVE_ITEM ROOT_DICT_INPUT_HEADERS "${_linkdef_hdr}" ) + LIST( APPEND ROOT_DICT_INPUT_HEADERS "${_linkdef_hdr}") + ENDIF() + + #MESSAGE( STATUS "ROOT_DICT_INPUT_HEADERS: ${ROOT_DICT_INPUT_HEADERS}" ) + +ENDMACRO( PREPARE_ROOT_DICT_HEADERS ) + + + +# ============================================================================ +# helper macro to generate Linkdef.h files for rootcint +# +# arguments: +# namespace - prefix used for creating header <namespace>_Linkdef.h +# ARGN - list of sources to be used for generating Linkdef.h +# +# returns: +# ROOT_DICT_INPUT_HEADERS - all header files + <namespace>_LinkDef.h in the +# correct order to be used by macro GEN_ROOT_DICT_SOURCES +# +# ---------------------------------------------------------------------------- +MACRO( GEN_ROOT_DICT_LINKDEF_HEADER _namespace ) + + SET( _input_headers ${ARGN} ) + SET( _linkdef_header "${ROOT_DICT_OUTPUT_DIR}/${_namespace}_Linkdef.h" ) + + FOREACH( _header ${_input_headers} ) + SET( ${_namespace}_file_contents "${${_namespace}_file_contents}\\#pragma link C++ defined_in \\\"${_header}\\\"\\;\\\\n" ) + ENDFOREACH() + + ADD_CUSTOM_COMMAND( + OUTPUT ${_linkdef_header} + COMMAND mkdir -p ${ROOT_DICT_OUTPUT_DIR} + COMMAND printf "${${_namespace}_file_contents}" > ${_linkdef_header} + DEPENDS ${_input_headers} + COMMENT "generating: ${_linkdef_header}" + ) + + SET( ROOT_DICT_INPUT_HEADERS ${_input_headers} ${_linkdef_header} ) + +ENDMACRO() + + +# ============================================================================ +# macro for generating root dict sources with rootcint +# +# arguments: +# dict_src_filename - filename of the dictionary source (to be generated) +# +# requires following variables: +# ROOT_DICT_INPUT_HEADERS - list of headers needed to generate dict source +# * if LinkDef.h is in the list it must be at the end !! +# ROOT_DICT_INCLUDE_DIRS - list of include dirs to pass to rootcint -I.. +# ROOT_DICT_CINT_DEFINITIONS - extra definitions to pass to rootcint +# ROOT_DICT_OUTPUT_DIR - where dictionary source should be generated +# +# returns: +# ROOT_DICT_OUTPUT_SOURCES - list containing generated source and other +# previously generated sources + +# ---------------------------------------------------------------------------- +MACRO( GEN_ROOT_DICT_SOURCE _dict_src_filename ) + + # TODO check for ROOT_CINT_EXECUTABLE + + # need to prefix all include dirs with -I + set( _dict_includes ) + FOREACH( _inc ${ROOT_DICT_INCLUDE_DIRS} ) + SET( _dict_includes "${_dict_includes}\t-I${_inc}") #fg: the \t fixes a wired string expansion + #SET( _dict_includes ${_dict_includes} -I${_inc} ) + ENDFOREACH() + + STRING( REPLACE "/" "_" _dict_src_filename_nosc ${_dict_src_filename} ) + SET( _dict_src_file ${ROOT_DICT_OUTPUT_DIR}/${_dict_src_filename_nosc} ) + STRING( REGEX REPLACE "^(.*)\\.(.*)$" "\\1.h" _dict_hdr_file "${_dict_src_file}" ) + #message("${ROOT_DICT_INPUT_HEADERS}") + ADD_CUSTOM_COMMAND( + OUTPUT ${_dict_src_file} ${_dict_hdr_file} + COMMAND mkdir -p ${ROOT_DICT_OUTPUT_DIR} + COMMAND ${ROOT_CINT_WRAPPER} -f "${_dict_src_file}" -c ${ROOT_DICT_CINT_DEFINITIONS} ${_dict_includes} ${ROOT_DICT_INPUT_HEADERS} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DEPENDS ${ROOT_DICT_INPUT_HEADERS} + COMMENT "generating: ${_dict_src_file} ${_dict_hdr_file}" + ) + LIST( APPEND ROOT_DICT_OUTPUT_SOURCES ${_dict_src_file} ) + +ENDMACRO() + +# for backwards compatibility +MACRO( GEN_ROOT_DICT_SOURCES _dict_src_filename ) + #MESSAGE( "USING DEPRECATED GEN_ROOT_DICT_SOURCES. PLEASE USE GEN_ROOT_DICT_SOURCE instead." ) + SET( ROOT_DICT_OUTPUT_SOURCES ) + GEN_ROOT_DICT_SOURCE( ${_dict_src_filename} ) +ENDMACRO() +# ============================================================================ + diff --git a/Utilities/KalTest/cmake/MyFindROOT.cmake b/Utilities/KalTest/cmake/MyFindROOT.cmake new file mode 100644 index 0000000000000000000000000000000000000000..567ce159fc7b846f509fd6c968be7e292a0e98f9 --- /dev/null +++ b/Utilities/KalTest/cmake/MyFindROOT.cmake @@ -0,0 +1,316 @@ +############################################################################### +# cmake module for finding ROOT +# +# requires: +# MacroCheckPackageLibs.cmake for checking package libraries +# +# Following cmake variables are returned by this module: +# +# ROOT_FOUND : set to TRUE if ROOT found +# If FIND_PACKAGE is called with REQUIRED and COMPONENTS arguments +# ROOT_FOUND is only set to TRUE if ALL components are found. +# If REQUIRED is NOT set components may or may not be available +# +# ROOT_LIBRARIES : list of ROOT libraries (NOT including COMPONENTS) +# ROOT_INCLUDE_DIRS : list of paths to be used with INCLUDE_DIRECTORIES +# ROOT_LIBRARY_DIRS : list of paths to be used with LINK_DIRECTORIES +# ROOT_COMPONENT_LIBRARIES : list of ROOT component libraries +# ROOT_${COMPONENT}_FOUND : set to TRUE or FALSE for each library +# ROOT_${COMPONENT}_LIBRARY : path to individual libraries +# +# +# Please note that by convention components should be entered exactly as +# the library names, i.e. the component name equivalent to the library +# $ROOTSYS/lib/libMathMore.so should be called MathMore and NOT: +# mathmore or Mathmore or MATHMORE +# +# However to follow the usual cmake convention it is agreed that the +# ROOT_${COMPONENT}_FOUND and ROOT_${COMPONENT}_LIBRARY variables are ALL +# uppercase, i.e. the MathMore component returns: ROOT_MATHMORE_FOUND and +# ROOT_MATHMORE_LIBRARY NOT ROOT_MathMore_FOUND or ROOT_MathMore_LIBRARY +# +# +# The additional ROOT components should be defined as follows: +# FIND_PACKAGE( ROOT COMPONENTS MathMore Gdml Geom ...) +# +# If components are required use: +# FIND_PACKAGE( ROOT REQUIRED COMPONENTS MathMore Gdml Geom ...) +# +# If only root is required and components are NOT required use: +# FIND_PACKAGE( ROOT REQUIRED ) +# FIND_PACKAGE( ROOT COMPONENTS MathMore Gdml Geom ... QUIET ) +# then you need to check for ROOT_MATHMORE_FOUND, ROOT_GDML_FOUND, etc. +# +# The variable ROOT_USE_COMPONENTS can also be used before calling +# FIND_PACKAGE, i.e.: +# SET( ROOT_USE_COMPONENTS MathMore Gdml Geom ) +# FIND_PACKAGE( ROOT REQUIRED ) # all ROOT_USE_COMPONENTS must also be found +# FIND_PACKAGE( ROOT ) # check for ROOT_FOUND, ROOT_MATHMORE_FOUND, etc. +# +# @author Jan Engels, DESY +############################################################################### + +# ============================================== +# === ROOT_CONFIG_EXECUTABLE === +# ============================================== + +SET( ROOT_CONFIG_EXECUTABLE ROOT_CONFIG_EXECUTABLE-NOTFOUND ) +MARK_AS_ADVANCED( ROOT_CONFIG_EXECUTABLE ) +# FIND_PROGRAM: Once one of the calls succeeds the result variable will be set and stored in the cache so that no call will search again. +FIND_PROGRAM( ROOT_CONFIG_EXECUTABLE root-config PATHS ${ROOT_DIR}/bin NO_DEFAULT_PATH ) +FIND_PROGRAM( ROOT_CONFIG_EXECUTABLE root-config PATHS $ENV{ROOTSYS}/bin NO_DEFAULT_PATH) +FIND_PROGRAM( ROOT_CONFIG_EXECUTABLE root-config PATHS ENV PATH ) +FIND_PROGRAM( ROOT_CONFIG_EXECUTABLE root-config ) + +IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ROOT_CONFIG_EXECUTABLE: ${ROOT_CONFIG_EXECUTABLE}" ) +ENDIF() + +IF( ROOT_CONFIG_EXECUTABLE ) + + + # ============================================== + # === ROOT_VERSION === + # ============================================== + + INCLUDE( MacroCheckPackageVersion ) + + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --version + OUTPUT_VARIABLE _version + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( _exit_code EQUAL 0 ) + + # set required variables for MacroCheckPackageVersion + STRING(REGEX REPLACE "^([0-9]+).*" "\\1" ROOT_VERSION_MAJOR "${_version}") + STRING(REGEX REPLACE "^[0-9]+.([0-9]+).*" "\\1" ROOT_VERSION_MINOR "${_version}") + STRING(REGEX REPLACE "^[0-9]+.[0-9]+.([0-9]+).*" "\\1" ROOT_VERSION_PATCH "${_version}") + + SET( ROOT_VERSION "${ROOT_VERSION_MAJOR}.${ROOT_VERSION_MINOR}.${ROOT_VERSION_PATCH}" ) + ENDIF() + + CHECK_PACKAGE_VERSION( ROOT ${ROOT_VERSION} ) + + + + # ============================================== + # === ROOT_PREFIX === + # ============================================== + + # get root prefix from root-config output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --prefix + OUTPUT_VARIABLE ROOT_PREFIX + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( NOT _exit_code EQUAL 0 ) + # clear variable if root-config exits with error + # it might contain garbage + SET( ROOT_PREFIX ) + ENDIF() + + # PKG_ROOT variables are a cmake standard + # since this package is also called ROOT the variable name + # becomes ROOT_ROOT ... + SET( ROOT_ROOT ${ROOT_PREFIX} ) + + + + # ============================================== + # === ROOT_BIN_DIR === + # ============================================== + + # get bindir from root-config output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --bindir + OUTPUT_VARIABLE ROOT_BIN_DIR + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( NOT _exit_code EQUAL 0 ) + # clear variable if root-config exits with error + # it might contain garbage + SET( ROOT_BIN_DIR ) + ENDIF() + + + + # ============================================== + # === ROOT_EXECUTABLE === + # ============================================== + + + SET( ROOT_EXECUTABLE ROOT_EXECUTABLE-NOTFOUND ) + MARK_AS_ADVANCED( ROOT_EXECUTABLE ) + FIND_PROGRAM( ROOT_EXECUTABLE root PATHS ${ROOT_BIN_DIR} NO_DEFAULT_PATH ) + + IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ROOT_EXECUTABLE: ${ROOT_EXECUTABLE}" ) + ENDIF() + + + + + # ============================================== + # === ROOT_CINT_EXECUTABLE === + # ============================================== + + + # find rootcint + SET( ROOT_CINT_EXECUTABLE ROOT_CINT_EXECUTABLE-NOTFOUND ) + MARK_AS_ADVANCED( ROOT_CINT_EXECUTABLE ) + FIND_PROGRAM( ROOT_CINT_EXECUTABLE rootcint PATHS ${ROOT_BIN_DIR} NO_DEFAULT_PATH ) + + IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for ROOT_CINT_EXECUTABLE: ${ROOT_CINT_EXECUTABLE}" ) + ENDIF() + + + + # ============================================== + # === ROOT_INCLUDE_DIR === + # ============================================== + + # get include dir from root-config output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --incdir + OUTPUT_VARIABLE _inc_dir + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( NOT _exit_code EQUAL 0 ) + # clear variable if root-config exits with error + # it might contain garbage + SET( _inc_dir ) + ENDIF() + + + SET( ROOT_INCLUDE_DIRS ROOT_INCLUDE_DIRS-NOTFOUND ) + MARK_AS_ADVANCED( ROOT_INCLUDE_DIRS ) + + FIND_PATH( ROOT_INCLUDE_DIRS + NAMES TH1.h + PATHS ${ROOT_DIR}/include ${_inc_dir} + NO_DEFAULT_PATH + ) + + + + # ============================================== + # === ROOT_LIBRARIES === + # ============================================== + + # get library dir from root-config output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --libdir + OUTPUT_VARIABLE ROOT_LIBRARY_DIR + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( NOT _exit_code EQUAL 0 ) + # clear variable if root-config exits with error + # it might contain garbage + SET( ROOT_LIBRARY_DIR ) + ENDIF() + + + + # ========== standard root libraries ================= + + # standard root libraries (without components) + SET( _root_libnames ) + + # get standard root libraries from 'root-config --libs' output + EXECUTE_PROCESS( COMMAND "${ROOT_CONFIG_EXECUTABLE}" --noauxlibs --libs + OUTPUT_VARIABLE _aux + RESULT_VARIABLE _exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + IF( _exit_code EQUAL 0 ) + + # create a list out of the output + SEPARATE_ARGUMENTS( _aux ) + + # remove first item -L compiler flag + LIST( REMOVE_AT _aux 0 ) + + FOREACH( _lib ${_aux} ) + + # extract libnames from -l compiler flags + STRING( REGEX REPLACE "^-.(.*)$" "\\1" _libname "${_lib}") + + # fix for some root-config versions which export -lz even if using --noauxlibs + IF( NOT _libname STREQUAL "z" ) + + # append all library names into a list + LIST( APPEND _root_libnames ${_libname} ) + + ENDIF() + + ENDFOREACH() + + ENDIF() + + + + # ========== additional root components ================= + + #LIST( APPEND ROOT_FIND_COMPONENTS Minuit2 ) # DEPRECATED !!! + + + # ---------- libraries -------------------------------------------------------- + INCLUDE( MacroCheckPackageLibs ) + + SET( ROOT_LIB_SEARCH_PATH ${ROOT_LIBRARY_DIR} ) + + # only standard libraries should be passed as arguments to CHECK_PACKAGE_LIBS + # additional components are set by cmake in variable PKG_FIND_COMPONENTS + # first argument should be the package name + CHECK_PACKAGE_LIBS( ROOT ${_root_libnames} ) + + + + + # ====== DL LIBRARY ================================================== + # workaround for cmake bug in 64 bit: + # see: http://public.kitware.com/mantis/view.php?id=10813 + IF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) + FIND_LIBRARY( DL_LIB NAMES ${CMAKE_DL_LIBS} dl PATHS /usr/lib64 /lib64 NO_DEFAULT_PATH ) + ENDIF( CMAKE_SIZEOF_VOID_P EQUAL 8 ) + + FIND_LIBRARY( DL_LIB NAMES ${CMAKE_DL_LIBS} dl ) + MARK_AS_ADVANCED( DL_LIB ) + + IF( NOT ROOT_FIND_QUIETLY ) + MESSAGE( STATUS "Check for libdl.so: ${DL_LIB}" ) + ENDIF() + +ENDIF( ROOT_CONFIG_EXECUTABLE ) + +# Threads library +#FIND_PACKAGE( Threads REQUIRED) + + +# ---------- final checking --------------------------------------------------- +INCLUDE( FindPackageHandleStandardArgs ) +# set ROOT_FOUND to TRUE if all listed variables are TRUE and not empty +# ROOT_COMPONENT_VARIABLES will be set if FIND_PACKAGE is called with REQUIRED argument +FIND_PACKAGE_HANDLE_STANDARD_ARGS( ROOT DEFAULT_MSG ROOT_INCLUDE_DIRS ROOT_LIBRARIES ${ROOT_COMPONENT_VARIABLES} PACKAGE_VERSION_COMPATIBLE DL_LIB ) + +IF( ROOT_FOUND ) + LIST( APPEND ROOT_LIBRARIES ${DL_LIB} ) + # FIXME DEPRECATED + SET( ROOT_DEFINITIONS "-DUSEROOT -DUSE_ROOT -DMARLIN_USE_ROOT" ) + MARK_AS_ADVANCED( ROOT_DEFINITIONS ) + + # file including MACROS for generating root dictionary sources + GET_FILENAME_COMPONENT( _aux ${CMAKE_CURRENT_LIST_FILE} PATH ) + SET( ROOT_DICT_MACROS_FILE ${_aux}/MacroRootDict.cmake ) + +ENDIF( ROOT_FOUND ) + +# ---------- cmake bug -------------------------------------------------------- +# ROOT_FIND_REQUIRED is not reset between FIND_PACKAGE calls, i.e. the following +# code fails when geartgeo component not available: (fixed in cmake 2.8) +# FIND_PACKAGE( ROOT REQUIRED ) +# FIND_PACKAGE( ROOT COMPONENTS geartgeo QUIET ) +SET( ROOT_FIND_REQUIRED ) + diff --git a/Utilities/KalTest/kaltest/KalTrackDim.h b/Utilities/KalTest/kaltest/KalTrackDim.h new file mode 100644 index 0000000000000000000000000000000000000000..c71efbf0c5ecdacae3df27e50174a612983bebee --- /dev/null +++ b/Utilities/KalTest/kaltest/KalTrackDim.h @@ -0,0 +1,9 @@ +#ifndef KALDIM_H +#define KALDIM_H +#define kMdim 2 +#ifdef __NOT0__ +#define kSdim 5 +#else +#define kSdim 6 +#endif +#endif diff --git a/Utilities/KalTest/kaltest/TAttDrawable.h b/Utilities/KalTest/kaltest/TAttDrawable.h new file mode 100644 index 0000000000000000000000000000000000000000..3383a39af6a4d04d2e2f726e977dce746afa7a57 --- /dev/null +++ b/Utilities/KalTest/kaltest/TAttDrawable.h @@ -0,0 +1,37 @@ +#ifndef TATTDRAWABLE_H +#define TATTDRAWABLE_H +//************************************************************************* +//* =================== +//* TAttDrawable Class +//* =================== +//* +//* (Description) +//* TAttDrawable class adds drawable attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class TAttDrawable +//* (Update Recored) +//* 2004/11/04 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include <Rtypes.h> +//_____________________________________________________________________ +// ------------------------------ +// Base Class for Drawale Objects +// ------------------------------ +// +class TAttDrawable { +public: + TAttDrawable() {} + virtual ~TAttDrawable() {} + + virtual void Draw(const Char_t *opt=""); + virtual void Draw(Int_t /* color */, const Char_t *opt=""); +private: + + ClassDef(TAttDrawable, 1) // Base class for drawable objects +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TAttElement.h b/Utilities/KalTest/kaltest/TAttElement.h new file mode 100644 index 0000000000000000000000000000000000000000..3f9905e03e33fa454de66143f8707e7caad3e47e --- /dev/null +++ b/Utilities/KalTest/kaltest/TAttElement.h @@ -0,0 +1,55 @@ +#ifndef TATTELEMENT_H +#define TATTELEMENT_H +//************************************************************************* +//* =================== +//* TAttElement Class +//* =================== +//* +//* (Description) +//* TAttElement class adds constituent attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class TAttElement +//* (Update Recored) +//* 2003/10/10 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include <Rtypes.h> + +//_____________________________________________________________________ +// -------------------------------- +// Base Class for Element Objects +// -------------------------------- +// +class TAttElement { +public: + TAttElement() : fParentPtr(0) {} + virtual ~TAttElement() {} + + inline virtual const TAttElement & GetParent(Bool_t recur = kTRUE) const; + + inline virtual void SetParentPtr(TAttElement *obj) { fParentPtr = obj; } + +private: + TAttElement *fParentPtr; // pointer to parent + + ClassDef(TAttElement,1) // Base class for lockable objects +}; + +//_____________________________________________________________________ +// -------------------------------- +// Inline functions, if any +// -------------------------------- +const TAttElement & TAttElement::GetParent(Bool_t recursive) const +{ + if (fParentPtr) { + if (recursive) return fParentPtr->GetParent(recursive); + else return *fParentPtr; + } else { + return *this; + } +} + +#endif diff --git a/Utilities/KalTest/kaltest/TAttLockable.h b/Utilities/KalTest/kaltest/TAttLockable.h new file mode 100644 index 0000000000000000000000000000000000000000..8b6d068bf2a43d9a4aadd144d4ec961b9f539cb4 --- /dev/null +++ b/Utilities/KalTest/kaltest/TAttLockable.h @@ -0,0 +1,39 @@ +#ifndef TATTLOCKABLE_H +#define TATTLOCKABLE_H +//************************************************************************* +//* =================== +//* TAttLockable Class +//* =================== +//* +//* (Description) +//* TAttLockable class adds lockable attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class Lockable +//* (Update Recored) +//* 1999/06/05 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include <Rtypes.h> +//_____________________________________________________________________ +// ------------------------------ +// Base Class for Lockale Objects +// ------------------------------ +// +class TAttLockable { +public: + TAttLockable() : fStatus(kFALSE) {} + virtual ~TAttLockable() {} + + inline virtual Bool_t IsLocked() const { return fStatus; } + inline virtual void Lock() { fStatus = kTRUE; } + inline virtual void Unlock() { fStatus = kFALSE; } +private: + Bool_t fStatus; // lock byte + + ClassDef(TAttLockable,1) // Base class for lockable objects +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TCircle.h b/Utilities/KalTest/kaltest/TCircle.h new file mode 100644 index 0000000000000000000000000000000000000000..2bb548aa72649420ccfd7d22f1778816b76abb63 --- /dev/null +++ b/Utilities/KalTest/kaltest/TCircle.h @@ -0,0 +1,56 @@ +#ifndef TCIRCLE_H +#define TCIRCLE_H +//************************************************************************* +//* ==================== +//* TCircle Class +//* ==================== +//* +//* (Description) +//* A class to implement a circle object. +//* (Requires) +//* TVCurve +//* (Provides) +//* class TCircle +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include <iostream> +#include "TVector2.h" +#include "TVCurve.h" + +using namespace std; +//_____________________________________________________________________ +// ----------------------------------- +// Circle Class +// ----------------------------------- + +class TCircle : public TVCurve { +public: + TCircle(Double_t r = 1., Double_t xc = 0., Double_t yc = 0.); + virtual ~TCircle() {} + + virtual Int_t CalcXingPointWith(const TCircle &c, + TVector2 xx[], + Double_t eps = 1.e-8) const; + + inline virtual Double_t GetRadius() const { return fR; } + inline virtual const TVector2 & GetCenter() const { return fXc; } + + inline virtual void DebugPrint() const; + +private: + Double_t fR; // radius + TVector2 fXc; // center + + ClassDef(TCircle,1) // circle class +}; + +void TCircle::DebugPrint() const +{ + cerr << " radius = " << fR + << " center = (" << fXc.X() << "," << fXc.Y() << ")" << endl; +} + +#endif diff --git a/Utilities/KalTest/kaltest/TCutCone.h b/Utilities/KalTest/kaltest/TCutCone.h new file mode 100644 index 0000000000000000000000000000000000000000..b66cfef1f8e73f51c5fea356c75ea3fa053da57c --- /dev/null +++ b/Utilities/KalTest/kaltest/TCutCone.h @@ -0,0 +1,122 @@ +#ifndef TCUTCONE_H +#define TCUTCONE_H +//************************************************************************* +//* ==================== +//* TCutCone Class +//* ==================== +//* +//* (Description) +//* A class to implement a conical surface object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TCutCone +//* (Update Recored) +//* 2012/01/19 K.Fujii Original version derived from THYpe. +//* This class is implemented as an extreme +//* (fR0=0) case of THype, thereby containing +//* both -ve and +ve sides. If you want to +//* restrict them to one side, override +//* IsOnSurface(), etc. +//************************************************************************* +// +#include "TVSurface.h" +#include "TVector3.h" +#include "TMatrixD.h" + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Hype Class +// ----------------------------------- + +class TCutCone : public TVSurface { +public: + TCutCone(Double_t z1 = 0.5, + Double_t hlen = 1.0, + Double_t tana = 0.1, + Double_t xc = 0., + Double_t yc = 0, + Double_t zc = 0.) + : fZ1(z1), + fHalfLen(hlen), + fXc(xc,yc,zc), + fTanA(tana) + { + } + + virtual ~TCutCone() {} + + virtual Double_t CalcS (const TVector3 &xx) const; + virtual TMatrixD CalcDSDx(const TVector3 &xx) const; + + inline virtual Bool_t IsOnSurface(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetSortingPolicy() const; + + inline virtual Double_t GetZ1 () const { return fZ1; } + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual Double_t GetTanA () const { return fTanA; } + inline virtual Double_t GetLength () const; + inline virtual Double_t GetZmin () const; + inline virtual Double_t GetZmax () const; + +private: + Double_t fZ1; // z position of the front face + Double_t fHalfLen; // half length (cone length from the apex) + TVector3 fXc; // center + Double_t fTanA; // tan(half cone angle) +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) + static const Double_t kTol = 1.e-5; // tolerance +#else + static const Double_t kTol; // tolerance +#endif + + ClassDef(TCutCone,1) // hype class +}; +//======================================================= +// inline functions +//======================================================= + +Double_t TCutCone::GetLength () const +{ + return 2*fHalfLen; +} + +Double_t TCutCone::GetZmin() const +{ + return TMath::Min(fXc.Z() - fHalfLen, fXc.Z() + fHalfLen); +} + +Double_t TCutCone::GetZmax() const +{ + return TMath::Max(fXc.Z() - fHalfLen, fXc.Z() + fHalfLen); +} + +Bool_t TCutCone::IsOnSurface(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + Double_t r = xxc.Perp(); + Double_t z = xxc.Z(); + Double_t s = r*r - fTanA*fTanA*z*z; + + return (TMath::Abs(s) < kTol && xx.Z() >= GetZmin() && xx.Z() <= GetZmax()); +} + +Bool_t TCutCone::IsOutside(const TVector3 &xx) const +{ + Double_t r = (xx-fXc).Perp(); + Double_t z = xx.Z(); + Double_t R2 =fTanA*fTanA*z*z; + + return (r*r > R2 || z < GetZmin() || z > GetZmax()); +} + +Double_t TCutCone::GetSortingPolicy() const +{ + return GetZ1()*GetTanA(); +} +#endif + diff --git a/Utilities/KalTest/kaltest/TCylinder.h b/Utilities/KalTest/kaltest/TCylinder.h new file mode 100644 index 0000000000000000000000000000000000000000..793da6310ca0395efaf3341233d767eb94776d7f --- /dev/null +++ b/Utilities/KalTest/kaltest/TCylinder.h @@ -0,0 +1,104 @@ +#ifndef TCYLINDER_H +#define TCYLINDER_H +//************************************************************************* +//* ==================== +//* TCylinder Class +//* ==================== +//* +//* (Description) +//* A class to implement a cylinder object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TCylinder +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* 2005/02/23 K.Fujii Added GetSortingPolicy(). +//* +//************************************************************************* +// +#include "TVSurface.h" +#include "TVector3.h" +#include "TMatrixD.h" + +#include <cmath> + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Cylinder Class +// ----------------------------------- + +class TCylinder : public TVSurface { +public: + TCylinder(Double_t r = 1., Double_t hlen = 1., + Double_t xc = 0., Double_t yc = 0, Double_t zc = 0.) + : fR(r), fHalfLen(hlen), fXc(xc,yc,zc) {} + + virtual ~TCylinder() {} + + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + virtual Double_t CalcS (const TVector3 &xx) const; + virtual TMatrixD CalcDSDx(const TVector3 &xx) const; + + inline virtual Bool_t IsOnSurface(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetSortingPolicy() const; + + inline virtual Double_t GetR () const { return fR; } + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual Double_t GetLength () const; + inline virtual Double_t GetZmin () const; + inline virtual Double_t GetZmax () const; + +private: + Double_t fR; // radius + Double_t fHalfLen; // half length + TVector3 fXc; // center + + ClassDef(TCylinder,1) // cylinder class +}; +//======================================================= +// inline functions +//======================================================= + +Double_t TCylinder::GetLength () const +{ + return 2*fHalfLen; +} + +Double_t TCylinder::GetZmin() const +{ + return fXc.Z() - fHalfLen; +} + +Double_t TCylinder::GetZmax() const +{ + return fXc.Z() + fHalfLen; +} + +Bool_t TCylinder::IsOnSurface(const TVector3 &xx) const +{ + return (xx.Z() >= GetZmin() && xx.Z() <= GetZmax()) && std::fabs( (xx-fXc).Perp() - fR ) < 1.e-6; +} + +Bool_t TCylinder::IsOutside(const TVector3 &xx) const +{ + Double_t r = (xx-fXc).Perp(); + Double_t z = xx.Z(); + return (r > fR || z < GetZmin() || z > GetZmax()); +} + +Double_t TCylinder::GetSortingPolicy() const +{ + return GetR(); +} +#endif + diff --git a/Utilities/KalTest/kaltest/THelicalTrack.h b/Utilities/KalTest/kaltest/THelicalTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..26f9a2de53c05b66c3471d79262ff478358f4593 --- /dev/null +++ b/Utilities/KalTest/kaltest/THelicalTrack.h @@ -0,0 +1,86 @@ +#ifndef THELICALTRACK_H +#define THELICALTRACK_H +//************************************************************************* +//* ==================== +//* THelicalTrack Class +//* ==================== +//* +//* (Description) +//* A class to implement a helical track object. +//* +//* A helix is parametrized in the standard way: +//* +//* x = x0 + drho * cos(phi0) + rho * (cos(phi0) - cos(phi0 + phi)) +//* y = y0 + drho * sin(phi0) + rho * (sin(phi0) - cos(sin0 + phi)) +//* z = z0 + dz - rho * tan(lambda) * phi +//* +//* with +//* +//* rho = alpha/kappa +//* +//* (Requires) +//* TVTrack, TCylinder, TCircle, TVector3, TMatrixD +//* (Provides) +//* class THelicalTrack +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// + +#include "TVTrack.h" + +//_____________________________________________________________________ +// ----------------------------------- +// Helical Track Class +// ----------------------------------- + +class THelicalTrack : public TVTrack { +public: + + // Ctors and Dtor + + THelicalTrack(Double_t dr = 0., + Double_t phi0 = 0., + Double_t kappa = 1.e-5, + Double_t dz = 0., + Double_t tanl = 0., + Double_t x0 = 0., + Double_t y0 = 0., + Double_t z0 = 0., + Double_t b = 30.); + + THelicalTrack(const TMatrixD &a, const TVector3 &x0, Double_t b = 30.); + THelicalTrack(const TVector3 &x1, const TVector3 &x2, const TVector3 &x3, + Double_t b = 30., Bool_t dir = kIterForward); + + virtual ~THelicalTrack() {} + + // Utility methods + + virtual void MoveTo(const TVector3 &x0to, + Double_t &fid, + TMatrixD *F = 0, + TMatrixD *C = 0); + + TVector3 CalcXAt (Double_t phi) const; + TMatrixD CalcDxDa (Double_t phi) const; + TMatrixD CalcDxDphi(Double_t phi) const; + void CalcDapDa (Double_t fid, + Double_t dr, + Double_t drp, + TMatrixD &F) const; + +private: + void CalcStartHelix(const TVector3 &x1, + const TVector3 &x2, + const TVector3 &x3, + Bool_t dir = kIterForward); + +private: + + ClassDef(THelicalTrack,1) // circle class +}; + +#endif + diff --git a/Utilities/KalTest/kaltest/THype.h b/Utilities/KalTest/kaltest/THype.h new file mode 100644 index 0000000000000000000000000000000000000000..04e4765d06b864ab8b09baee20240e0124aedb08 --- /dev/null +++ b/Utilities/KalTest/kaltest/THype.h @@ -0,0 +1,110 @@ +#ifndef THYPE_H +#define THYPE_H +//************************************************************************* +//* ==================== +//* THype Class +//* ==================== +//* +//* (Description) +//* A class to implement a hyperboloidal surface object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class THype +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* 2005/02/23 K.Fujii Added GetSortingPolicy(). +//* +//************************************************************************* +// +#include "TVSurface.h" +#include "TVector3.h" +#include "TMatrixD.h" + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Hype Class +// ----------------------------------- + +class THype : public TVSurface { +public: + THype(Double_t r = 1., Double_t hlen = 1., Double_t tana = 0., + Double_t xc = 0., Double_t yc = 0, Double_t zc = 0.) + : fR0(r), fHalfLen(hlen), fXc(xc,yc,zc), fTanA(tana) {} + + virtual ~THype() {} + + virtual Double_t CalcS (const TVector3 &xx) const; + virtual TMatrixD CalcDSDx(const TVector3 &xx) const; + + inline virtual Bool_t IsOnSurface(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetSortingPolicy() const; + + inline virtual Double_t GetR0 () const { return fR0; } + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual Double_t GetTanA () const { return fTanA; } + inline virtual Double_t GetLength () const; + inline virtual Double_t GetZmin () const; + inline virtual Double_t GetZmax () const; + +private: + Double_t fR0; // radius at z = 0. + Double_t fHalfLen; // half length + TVector3 fXc; // center + Double_t fTanA; // tan(stereo angle) +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) + static const Double_t kTol = 1.e-5; // tolerance +#else + static const Double_t kTol; // tolerance +#endif + + ClassDef(THype,1) // hype class +}; +//======================================================= +// inline functions +//======================================================= + +Double_t THype::GetLength () const +{ + return 2*fHalfLen; +} + +Double_t THype::GetZmin() const +{ + return fXc.Z() - fHalfLen; +} + +Double_t THype::GetZmax() const +{ + return fXc.Z() + fHalfLen; +} + +Bool_t THype::IsOnSurface(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + Double_t r = xxc.Perp(); + Double_t z = xxc.Z(); + Double_t s = r*r - fTanA*fTanA*z*z - fR0*fR0; + + return (TMath::Abs(s) < kTol && xx.Z() >= GetZmin() && xx.Z() <= GetZmax()); +} + +Bool_t THype::IsOutside(const TVector3 &xx) const +{ + Double_t r = (xx-fXc).Perp(); + Double_t z = xx.Z(); + Double_t R2 = fR0*fR0 + fTanA*fTanA*z*z; + + return (r*r > R2 || z < GetZmin() || z > GetZmax()); +} + +Double_t THype::GetSortingPolicy() const +{ + return GetR0(); +} +#endif + diff --git a/Utilities/KalTest/kaltest/TKalDetCradle.h b/Utilities/KalTest/kaltest/TKalDetCradle.h new file mode 100644 index 0000000000000000000000000000000000000000..f666378e82b7ed68bad514fd3218e4efd3556ea2 --- /dev/null +++ b/Utilities/KalTest/kaltest/TKalDetCradle.h @@ -0,0 +1,84 @@ +#ifndef TKALDETCRADLE_H +#define TKALDETCRADLE_H +//************************************************************************* +//* ===================== +//* TKalDetCradle Class +//* ===================== +//* +//* (Description) +//* A sigleton to hold information of detector system +//* used in Kalman filter classes. +//* (Requires) +//* TObjArray +//* TVKalDetector +//* (Provides) +//* class TKalDetCradle +//* (Update Recored) +//* 2005/02/23 A.Yamaguchi Original Version. +//* 2005/08/14 K.Fujii Removed CalcTable(), GetMeasLayerTable(), +//* GetPhiTable(), and GetDir() and added +//* Transport() to do their functions. +//* 2010/04/06 K.Fujii Modified Transport() to allow a 1-dim hit, +//* for which pivot is at the xpected hit. +//* +//************************************************************************* + +#include "TObjArray.h" // from ROOT +#include "TAttElement.h" // from Utils +#include "TKalMatrix.h" // from KalTrackLib + +class TKalTrackSite; +class TVKalDetector; +class TVMeasLayer; + +//_____________________________________________________________________ +// ------------------------------ +// Detector system class +// ------------------------------ + +class TKalDetCradle : public TObjArray, public TAttElement { +public: + TKalDetCradle(Int_t n = 1); + virtual ~TKalDetCradle(); + + // Utility methods + virtual void Install(TVKalDetector &det); + + inline virtual void SwitchOnMS () { fIsMSON = kTRUE; } + inline virtual void SwitchOffMS () { fIsMSON = kFALSE; } + inline virtual void SwitchOnDEDX () { fIsDEDXON = kTRUE; } + inline virtual void SwitchOffDEDX() { fIsDEDXON = kFALSE; } + inline virtual void Close () { fIsClosed = kTRUE; Update(); } + inline virtual void Reopen () { fIsClosed = kFALSE; } + inline virtual Bool_t IsMSOn () const { return fIsMSON; } + inline virtual Bool_t IsDEDXOn () const { return fIsDEDXON; } + inline virtual Bool_t IsClosed () const { return fIsClosed; } + + void Transport(const TKalTrackSite &from, // site from + TKalTrackSite &to, // site to + TKalMatrix &sv, // state vector + TKalMatrix &F, // propagator matrix + TKalMatrix &Q); // process noise matrix + + int Transport(const TKalTrackSite &from, // site from + const TVMeasLayer &to, // layer to reach + TVector3 &x0, // intersection point + TKalMatrix &sv, // state vector + TKalMatrix &F, // propagator matrix + TKalMatrix &Q); // process noise matrix + + + +private: + void Update(); + +private: + Bool_t fIsMSON; //! switch for multiple scattering + Bool_t fIsDEDXON; //! switch for energy loss + Bool_t fDone; //! flag to tell if sorting done + Bool_t fIsClosed; //! flag to tell if cradle closed + + ClassDef(TKalDetCradle,1) // Base class for detector system +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TKalFilterCond.h b/Utilities/KalTest/kaltest/TKalFilterCond.h new file mode 100644 index 0000000000000000000000000000000000000000..54970788ac7d340c1ae14559465ad53d1a0ce907 --- /dev/null +++ b/Utilities/KalTest/kaltest/TKalFilterCond.h @@ -0,0 +1,35 @@ +#ifndef TKALFILTERCOND_H +#define TKALFILTERCOND_H +//************************************************************************* +//* ===================== +//* TKalFilterCond Class +//* ===================== +//* +//* (Description) +//* A class to specify filter conditions used in Kalman filter. +//* (Requires) +//* (Provides) +//* class TKalFilterCond +//* (Update Recored) +//* 2010/04/06 K.Fujii Original Version. +//* +//************************************************************************* +#include "Rtypes.h" +//_____________________________________________________________________ +// ------------------------------ +// Filter condition class +// ------------------------------ + +class TKalTrackSite; + +class TKalFilterCond { + public: + + // need virtual destructor is we have virtual functions + virtual ~TKalFilterCond() {}; + + virtual Bool_t IsAccepted(const TKalTrackSite &site); + + ClassDef(TKalFilterCond,1) // Base class for detector system + }; +#endif diff --git a/Utilities/KalTest/kaltest/TKalMatrix.h b/Utilities/KalTest/kaltest/TKalMatrix.h new file mode 100644 index 0000000000000000000000000000000000000000..947b92c02f0b96eb6f990a1e3da3acc1888bcc05 --- /dev/null +++ b/Utilities/KalTest/kaltest/TKalMatrix.h @@ -0,0 +1,58 @@ +#ifndef TKALMATRIX_H +#define TKALMATRIX_H +//************************************************************************* +//* =================== +//* TKalMatrix Class +//* =================== +//* +//* (Description) +//* TKalMatrix is a wrapper of TMatrixD. +//* (Requires) +//* TMatrixD +//* (Provides) +//* class TKalMatrix +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* +//************************************************************************* + +#include "TMatrixD.h" +#include "TVector3.h" +//_____________________________________________________________________ +// ------------------------------ +// Base Class for matrix used by Kalman filter +// ------------------------------ +// +class TKalMatrix : public TMatrixD { +public: + TKalMatrix(Int_t rowdim = 1, Int_t coldim = 1); + + TKalMatrix(const TKalMatrix &orig); + TKalMatrix(const TMatrixD &orig); + + TKalMatrix(TMatrixD::EMatrixCreatorsOp1 op, + const TKalMatrix &prototype); + TKalMatrix(TMatrixD::EMatrixCreatorsOp1 op, + const TMatrixD &prototype); + + TKalMatrix(const TKalMatrix &a, + TMatrixD::EMatrixCreatorsOp2 op, + const TKalMatrix &b) ; + TKalMatrix(const TMatrixD &a, + TMatrixD::EMatrixCreatorsOp2 op, + const TMatrixD &b) ; + + TKalMatrix(const TVector3 &v); + + virtual ~TKalMatrix() {} + + virtual void DebugPrint(Option_t *opt = "", Int_t nc = 5) const; + + static TKalMatrix ToKalMat (const TVector3 &vec); + static TVector3 ToThreeVec(const TMatrixD &mat); + +private: + + ClassDef(TKalMatrix,1) // Base class for Kalman matrix +}; +#endif diff --git a/Utilities/KalTest/kaltest/TKalTrack.h b/Utilities/KalTest/kaltest/TKalTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..13540c2928d7392307ba46445c0c57fd7838de66 --- /dev/null +++ b/Utilities/KalTest/kaltest/TKalTrack.h @@ -0,0 +1,54 @@ +#ifndef TKALTRACK_H +#define TKALTRACK_H +//************************************************************************* +//* ================= +//* TKalTrack Class +//* ================= +//* +//* (Description) +//* Track class for Kalman filter +//* (Requires) +//* TVKalSystem +//* (Provides) +//* class TKalTrack +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 A.Yamaguchi Added a new data member fMass and its +//* getter and setter. +//* 2005/08/15 K.Fujii Removed fDir and its getter and setter. +//* 2005/08/25 K.Fujii Added Drawable attribute. +//* 2005/08/26 K.Fujii Removed Drawable attribute. +//* +//************************************************************************* + +#include "TVKalSystem.h" // from KalLib +#include "TKalTrackState.h" // from KalTrackLib + +//_________________________________________________________________________ +// ------------------------------ +// TKalTrack: Kalman Track class +// ------------------------------ + +class TKalTrack : public TVKalSystem { +public: + TKalTrack(Int_t n = 1); + ~TKalTrack() {} + + inline virtual void SetMass(Double_t m) { fMass = m; } + inline virtual Double_t GetMass() const { return fMass; } + + Double_t FitToHelix(TKalTrackState &a, TKalMatrix &C, Int_t &ndf); + +private: + Double_t fMass; // mass [GeV] + +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) + static const Double_t kMpi = 0.13957018; //! pion mass [GeV] +#else + static const Double_t kMpi; //! pion mass [GeV] +#endif + + ClassDef(TKalTrack,1) // Base class for Kalman Filter +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TKalTrackSite.h b/Utilities/KalTest/kaltest/TKalTrackSite.h new file mode 100644 index 0000000000000000000000000000000000000000..3764e87f58efa5d5c5a3666ca63a003f7a0be391 --- /dev/null +++ b/Utilities/KalTest/kaltest/TKalTrackSite.h @@ -0,0 +1,76 @@ +#ifndef TKALTRACKSITE_H +#define TKALTRACKSITE_H +//************************************************************************* +//* ===================== +//* TKalTrackSite Class +//* ===================== +//* +//* (Description) +//* Track measurement site class used by Kalman filter. +//* (Requires) +//* TKalTrackState +//* (Provides) +//* class TKalTrackSite +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2004/09/17 K.Fujii Added ownership flag. +//* 2010/04/06 K.Fujii Added a setter for the pivot and a +//* condition object +//* +//************************************************************************* + +#include "TVector3.h" // from ROOT +#include "TVKalSite.h" // from KalLib +#include "TVTrackHit.h" // from KalTrackLib + +class TVKalState; +class TKalTrackState; +class TKalFilterCond; + +//_________________________________________________________________________ +// --------------------------------- +// Class for Kalman measurement site +// --------------------------------- +// +class TKalTrackSite : public TVKalSite { +public: + TKalTrackSite(Int_t m = kMdim, Int_t p = kSdim); + TKalTrackSite( const TVTrackHit &ht, + Int_t p = kSdim); + ~TKalTrackSite(); + + Int_t CalcExpectedMeasVec (const TVKalState &a, TKalMatrix &h); + Int_t CalcMeasVecDerivative(const TVKalState &a, TKalMatrix &H); + Bool_t IsAccepted(); + + void DebugPrint() const; + + inline const TVTrackHit & GetHit () const { return *fHitPtr; } + inline const TVector3 & GetPivot () const { return fX0; } + inline Double_t GetBfield () const { return fHitPtr->GetBfield(); } + inline Bool_t IsInB () const { return GetBfield() != 0.; } + inline Bool_t IsHitOwner() const { return fIsHitOwner; } + + inline void SetPivot (const TVector3 &x0) { fX0 = x0; } + inline void SetHitOwner (Bool_t b=kTRUE) { fIsHitOwner = b; } + inline void SetFilterCond(TKalFilterCond *cp) { fCondPtr = cp; } + +private: + TVKalState & CreateState(const TKalMatrix &sv, Int_t type = 0); + TVKalState & CreateState(const TKalMatrix &sv, + const TKalMatrix &C, + Int_t type = 0); + Int_t CalcXexp (const TVKalState &a, + TVector3 &xx, + Double_t &phi) const; + +private: + const TVTrackHit *fHitPtr; // pointer to corresponding hit + TVector3 fX0; // pivot + Bool_t fIsHitOwner; // true if site owns hit + TKalFilterCond *fCondPtr; // pointer to filter condition object + + ClassDef(TKalTrackSite,1) // sample measurement site class +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TKalTrackState.h b/Utilities/KalTest/kaltest/TKalTrackState.h new file mode 100644 index 0000000000000000000000000000000000000000..6931adcf0aa8c13fa6029584ca9d154623c152ba --- /dev/null +++ b/Utilities/KalTest/kaltest/TKalTrackState.h @@ -0,0 +1,76 @@ +#ifndef TKALTRACKSTATE_H +#define TKALTRACKSTATE_H +//************************************************************************* +//* ====================== +//* TKalTrackState Class +//* ====================== +//* +//* (Description) +//* Track state vector class used in Kalman Filter. +//* (Requires) +//* TVKalState +//* (Provides) +//* class TKalTrackState +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 A.Yamaguchi Added CalcDapDa method. +//* 2005/02/XX A.Yamaguchi Moved CalcDapDa method to THelicalTrack. +//* 2005/08/13 K.Fujii Removed CalcProcessNoise method. +//* 2010/04/06 K.Fujii Modified MoveTo to allow a 1-dim hit, +//* for which pivot is at the xpected hit. +//* +//************************************************************************* + +#include "TVKalState.h" // from KalLib +#include "THelicalTrack.h" // from GeomLib +#include "TStraightTrack.h" // from GeomLib +#include "KalTrackDim.h" // from KalTrackLib + +class TKalTrackSite; + +//_________________________________________________________________________ +// ----------------------------------- +// Base Class for Kalman state vector +// ----------------------------------- +// + +class TKalTrackState : public TVKalState { + +public: + + // Ctors and Dtor + + TKalTrackState(Int_t p = kSdim); + TKalTrackState(const TKalMatrix &sv, Int_t type = 0, Int_t p = kSdim); + TKalTrackState(const TKalMatrix &sv, const TKalMatrix &c, + Int_t type = 0, Int_t p = kSdim); + TKalTrackState(const TKalMatrix &sv, const TVKalSite &site, + Int_t type = 0, Int_t p = kSdim); + TKalTrackState(const TKalMatrix &sv, const TKalMatrix &c, + const TVKalSite &site, Int_t type = 0, Int_t p = kSdim); + virtual ~TKalTrackState() {} + + // Implementation of paraent class pure virtuals + + TKalTrackState * MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix *QPtr = 0) const; + TKalTrackState & MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix &Q) const; + void DebugPrint() const; + + // Derived class methods + + THelicalTrack GetHelix() const; + TStraightTrack GetLine () const; + TVTrack &CreateTrack() const; + +private: + + TVector3 fX0; // pivot + + ClassDef(TKalTrackState,1) // sample state vector class +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TPlane.h b/Utilities/KalTest/kaltest/TPlane.h new file mode 100644 index 0000000000000000000000000000000000000000..a75d6737b3efa6406340b401beb9c126cce9db71 --- /dev/null +++ b/Utilities/KalTest/kaltest/TPlane.h @@ -0,0 +1,80 @@ +#ifndef TPLANE_H +#define TPLANE_H +//************************************************************************* +//* ==================== +//* TPlane Class +//* ==================== +//* +//* (Description) +//* A class to implement a flat plane object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TPlane +//* (Update Recored) +//* 2004/10/30 A.Yamaguchi Original version. +//* 2005/02/23 K.Fujii Added GetSortingPolicy(). +//* +//************************************************************************* +// +#include "TVSurface.h" +#include "TVector3.h" +#include "TMatrixD.h" + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Plane Class +// ----------------------------------- + +class TPlane : public TVSurface { +public: + TPlane(); + TPlane(const TVector3 &xc); + TPlane(const TVector3 &xc, const TVector3 &n); + + virtual ~TPlane() {} + + virtual Double_t CalcS (const TVector3 &xx) const; + virtual TMatrixD CalcDSDx(const TVector3 &xx) const; + + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual const TVector3 & GetNormal () const { return fNormal; } + inline virtual Bool_t IsOnSurface(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetSortingPolicy() const; + + +private: + TVector3 fXc; // center + TVector3 fNormal; // normal + + ClassDef(TPlane,1) // plane class +}; +//======================================================= +// inline functions +//======================================================= + + +Bool_t TPlane::IsOnSurface(const TVector3 &xx) const +{ +#if 0 + return (xx - fXc) * fNormal == 0. ? kTRUE : kFALSE; +#else + return kTRUE; +#endif +} + +Bool_t TPlane::IsOutside(const TVector3 &xx) const +{ + return (xx - fXc) * fNormal > 0. ? kTRUE : kFALSE; +} + +Double_t TPlane::GetSortingPolicy() const +{ + return TMath::Abs(fXc*fNormal.Unit()); +} +#endif + diff --git a/Utilities/KalTest/kaltest/TStraightTrack.h b/Utilities/KalTest/kaltest/TStraightTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..d48c91e144dd923bd37a8fe20190237b46e924a0 --- /dev/null +++ b/Utilities/KalTest/kaltest/TStraightTrack.h @@ -0,0 +1,75 @@ +#ifndef TSTRAIGHTTRACK_H +#define TSTRAIGHTTRACK_H +//************************************************************************* +//* ====================== +//* TStraightTrack Class +//* ====================== +//* +//* (Description) +//* A class to implement a straight track object. +//* +//* The stragiht track is implemented as the kappa->infinity limit +//* of a helical track: +//* +//* x = x0 + drho * cos(phi0) - t * sin(phi0) +//* y = y0 + drho * sin(phi0) + t * cos(phi0) +//* z = z0 + dz + t * tan(lambda) +//* +//* (Requires) +//* TVTrack, TCylinder, TCircle, TVector3, TMatrixD +//* (Provides) +//* class TStraightTrack +//* (Update Recored) +//* 2003/10/24 K.Fujii Original version. +//* +//************************************************************************* +// + +#include "TVTrack.h" + +//_____________________________________________________________________ +// ----------------------------------- +// Straight Track Class +// ----------------------------------- + +class TStraightTrack : public TVTrack { +public: + + // Ctors and Dtor + + TStraightTrack(Double_t dr = 0., + Double_t phi0 = 0., + Double_t kappa = 1.e-5, + Double_t dz = 0., + Double_t tanl = 0., + Double_t x0 = 0., + Double_t y0 = 0., + Double_t z0 = 0., + Double_t b = 0.); + + TStraightTrack(const TMatrixD &a, const TVector3 & x0, Double_t b = 0.); + + virtual ~TStraightTrack() {} + + // Utility methods + + virtual void MoveTo(const TVector3 &x0to, + Double_t &t, + TMatrixD *F = 0, + TMatrixD *C = 0); + + TVector3 CalcXAt (Double_t phi) const; + TMatrixD CalcDxDa (Double_t phi) const; + TMatrixD CalcDxDphi(Double_t phi) const; + void CalcDapDa (Double_t fid, + Double_t dr, + Double_t drp, + TMatrixD &F) const; + +private: + + ClassDef(TStraightTrack,1) // circle class +}; + +#endif + diff --git a/Utilities/KalTest/kaltest/TTube.h b/Utilities/KalTest/kaltest/TTube.h new file mode 100644 index 0000000000000000000000000000000000000000..f10a135e2e29453d52c051b1bea98dda009835e7 --- /dev/null +++ b/Utilities/KalTest/kaltest/TTube.h @@ -0,0 +1,92 @@ +#ifndef TTUBE_H +#define TTUBE_H +//************************************************************************* +//* ==================== +//* TTube Class +//* ==================== +//* +//* (Description) +//* A class to implement a tube object. +//* (Requires) +//* TVSolid +//* (Provides) +//* class TTube +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TVSolid.h" +#include "TVector3.h" + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Cylinder Class +// ----------------------------------- + +class TTube : public TVSolid { +public: + TTube(Double_t rin = 0., Double_t rout = 1., Double_t hlen = 1., + Double_t xc = 0., Double_t yc = 0, Double_t zc = 0.) + : fRin(rin), fRout(rout), fHalfLen(hlen), fXc(xc,yc,zc) {} + + virtual ~TTube() {} + + virtual Int_t CalcXingPointWith(const TVTrack &hel, + Double_t &phi, + TVector3 &xx, + Int_t mode, + Double_t eps = 1.e-8) const; + + inline virtual Bool_t IsOnBarrel(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetRin () const { return fRin; } + inline virtual Double_t GetRout () const { return fRout; } + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual Double_t GetLength () const; + inline virtual Double_t GetZmin () const; + inline virtual Double_t GetZmax () const; + +private: + Double_t fRin; // inner radius + Double_t fRout; // outer radius + Double_t fHalfLen; // half length + TVector3 fXc; // center + + ClassDef(TTube,1) // TTube class +}; +//======================================================= +// inline functions +//======================================================= + +Double_t TTube::GetLength () const +{ + return 2*fHalfLen; +} + +Double_t TTube::GetZmin() const +{ + return fXc.Z() - fHalfLen; +} + +Double_t TTube::GetZmax() const +{ + return fXc.Z() + fHalfLen; +} + +Bool_t TTube::IsOnBarrel(const TVector3 &xx) const +{ + return (xx.Z() >= GetZmin() && xx.Z() <= GetZmax()); +} + +Bool_t TTube::IsOutside(const TVector3 &xx) const +{ + Double_t r = (xx-fXc).Perp(); + Double_t z = xx.Z(); + return (r < fRin || r > fRout || z < GetZmin() || z > GetZmax()); +} +#endif + diff --git a/Utilities/KalTest/kaltest/TVCurve.h b/Utilities/KalTest/kaltest/TVCurve.h new file mode 100644 index 0000000000000000000000000000000000000000..040912825ded5dfdeb1f52254aa75508c9343595 --- /dev/null +++ b/Utilities/KalTest/kaltest/TVCurve.h @@ -0,0 +1,32 @@ +#ifndef TVCURVE_H +#define TVCURVE_H +//************************************************************************* +//* ==================== +//* TVCurve Class +//* ==================== +//* +//* (Description) +//* This is the base class for various curves. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVCurve +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TObject.h" +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any curve +// ----------------------------------- + +class TVCurve : public TObject { +public: +private: + + ClassDef(TVCurve,1) // Base class for any curve +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TVKalDetector.h b/Utilities/KalTest/kaltest/TVKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..0edc3946f65bd5088081955a42cb7a06be17c948 --- /dev/null +++ b/Utilities/KalTest/kaltest/TVKalDetector.h @@ -0,0 +1,39 @@ +#ifndef TVKALDETECTOR_H +#define TVKALDETECTOR_H +//************************************************************************* +//* ===================== +//* TVKalDetector Class +//* ===================== +//* +//* (Description) +//* Base class to hold information of detector system +//* used in Kalman filter classes. +//* (Requires) +//* TObjArray +//* (Provides) +//* class TVKalDetector +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2005/02/23 A.Yamaguchi Moved most methods to TKalDetCradle. +//* +//************************************************************************* + +#include "TObjArray.h" // from ROOT +#include "TAttElement.h" // from Utils + +//_________________________________________________________________________ +// ------------------------------ +// Detector system class +// ------------------------------ +// + +class TVKalDetector : public TObjArray, public TAttElement { +public: + // Ctors and Dtor + TVKalDetector(Int_t n = 1) : TObjArray(n) {} + virtual ~TVKalDetector() {} + + ClassDef(TVKalDetector,1) // Base class for detector system +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TVKalSite.h b/Utilities/KalTest/kaltest/TVKalSite.h new file mode 100644 index 0000000000000000000000000000000000000000..d00345af335c708b91b79bacb42aafd3cf97fd2a --- /dev/null +++ b/Utilities/KalTest/kaltest/TVKalSite.h @@ -0,0 +1,124 @@ +#ifndef TVKALSITE_H +#define TVKALSITE_H +//************************************************************************* +//* =================== +//* TVKalSite Class +//* =================== +//* +//* (Description) +//* This is the base class for measurement vector used by Kalman filter. +//* (Requires) +//* TKalMatrix +//* (Provides) +//* class TVKalSite +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2005/02/23 A.Yamaguchi Added getter and setter for a new static +//* data member, fgKalSysPtr. +//* 2005/08/25 A.Yamaguchi Removed getter and setter for a new static +//* data member, fgKalSysPtr. +//* 2009/06/18 K.Fujii Implement inverse Kalman filter +//* +//************************************************************************* +// +#include "TObjArray.h" + +#include "TAttLockable.h" +#include "TKalMatrix.h" +#include "TVKalState.h" + +class TVKalSystem; + +//_____________________________________________________________________ +// ------------------------------ +// Base Class for Kalman measurement vector +// ------------------------------ +// +class TVKalSite : public TObjArray, public TAttLockable { +friend class TVKalSystem; + +public: + enum EStType { kPredicted = 0, + kFiltered, + kSmoothed, + kInvFiltered }; +public: + // Ctors and Dtor + + TVKalSite(Int_t m = 2, Int_t p = 6); + virtual ~TVKalSite(); + + // Utility Methods + + virtual Int_t CalcExpectedMeasVec (const TVKalState &a, + TKalMatrix &m) = 0; + virtual Int_t CalcMeasVecDerivative(const TVKalState &a, + TKalMatrix &H) = 0; + virtual Bool_t IsAccepted() = 0; + + virtual void DebugPrint() const = 0; + + virtual Bool_t Filter(); + + virtual void Smooth(TVKalSite &pre); + + virtual void InvFilter(); + + inline void Add(TObject *obj); + + // Getters + + inline virtual Int_t GetDimension() const { return fM.GetNrows(); } + inline virtual TVKalState & GetCurState () { return *fCurStatePtr; } + inline virtual TVKalState & GetCurState () const { return *fCurStatePtr; } + inline virtual TVKalState & GetState (EStType t); + inline virtual TKalMatrix & GetMeasVec () { return fM; } + inline virtual TKalMatrix & GetMeasNoiseMat () { return fV; } + inline virtual TKalMatrix & GetResVec () { return fResVec; } + inline virtual TKalMatrix & GetCovMat () { return fR; } + inline virtual Double_t GetDeltaChi2() const { return fDeltaChi2; } + virtual TKalMatrix GetResVec (EStType t); + +private: + // Private utility methods + + virtual TVKalState & CreateState(const TKalMatrix &sv, Int_t type = 0) = 0; + virtual TVKalState & CreateState(const TKalMatrix &sv, const TKalMatrix &c, + Int_t type = 0) = 0; + +private: + + // private data member ------------------------------------------- + + TVKalState *fCurStatePtr; // pointer to current best state + TKalMatrix fM; // measurement vector: M(m,1) + TKalMatrix fV; // noise matrix: M(m,m) + TKalMatrix fH; // H = (@h/@a): M(m,p) + TKalMatrix fHt; // H^t = (@h/@a)^t: M(p,m) + TKalMatrix fResVec; // m - h(a): M(m,1) + TKalMatrix fR; // covariance matrix: M(m,m) + Double_t fDeltaChi2; // chi2 increment + + ClassDef(TVKalSite,1) // Base class for measurement vector objects +}; + +//======================================================= +// inline functions +//======================================================= + +void TVKalSite::Add(TObject *obj) +{ + TObjArray::Add(obj); + fCurStatePtr = static_cast<TVKalState *>(obj); + fCurStatePtr->SetSitePtr(this); +} + +TVKalState & TVKalSite::GetState(TVKalSite::EStType t) +{ + TVKalState *ap = 0; + if (t >= 0 && t < GetEntries()) { + ap = static_cast<TVKalState *>(UncheckedAt(t)); + } + return *ap; +} +#endif diff --git a/Utilities/KalTest/kaltest/TVKalState.h b/Utilities/KalTest/kaltest/TVKalState.h new file mode 100644 index 0000000000000000000000000000000000000000..38efabd27814efd840f65834261512184024ed5a --- /dev/null +++ b/Utilities/KalTest/kaltest/TVKalState.h @@ -0,0 +1,90 @@ +#ifndef TVKALSTATE_H +#define TVKALSTATE_H +//************************************************************************* +//* ==================== +//* TVKalState Class +//* ==================== +//* +//* (Description) +//* This is the base class for a state vector used in Kalman Filter. +//* (Requires) +//* TKalMatrix +//* (Provides) +//* class TVKalState +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TKalMatrix.h" +class TVKalSite; +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for Kalman state vector +// ----------------------------------- +// +class TVKalState : public TKalMatrix { +public: + + // Ctors and Dtor + + TVKalState(Int_t type = 0, Int_t p = 6); + TVKalState(const TKalMatrix &sv, Int_t type = 0, Int_t p = 6); + TVKalState(const TKalMatrix &sv, const TKalMatrix &c, + Int_t type = 0, Int_t p = 6); + TVKalState(const TKalMatrix &sv, const TVKalSite &site, + Int_t type = 0, Int_t p = 6); + TVKalState(const TKalMatrix &sv, const TKalMatrix &c, + const TVKalSite &site, Int_t type = 0, Int_t p = 6); + virtual ~TVKalState() {} + + // Pure virtuals to be implemented in derived classes + // + // MoveTo should calculate + // a: predicted state vector : a^k-1_k = f_k-1(a_k-1) + // F: propagator derivative : F_k-1 = (@f_k-1/@a_k-1) + // Q: process noise from k-1 to k : Q_k-1) + // and return a^k-1_k. + // + + virtual TVKalState * MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix *QPtr = 0) const = 0; + virtual TVKalState & MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix &Q) const = 0; + + virtual void DebugPrint() const = 0; + + virtual void Propagate(TVKalSite &to); // calculates f, F, and Q + + + // Getters + + inline virtual Int_t GetDimension () const { return GetNrows(); } + inline virtual const TVKalSite & GetSite () const { return *fSitePtr; } + inline virtual const TKalMatrix & GetCovMat () const { return fC; } + inline virtual const TKalMatrix & GetProcNoiseMat() const { return fQ; } + inline virtual const TKalMatrix & GetPropMat (const Char_t *t = "") const { return (t[0] == 'T' ? fFt : fF); } + + // Setters + + inline virtual void SetStateVec (const TKalMatrix &c) { TMatrixD::operator=(c); } + inline virtual void SetCovMat (const TKalMatrix &c) { fC = c; } + inline virtual void SetProcNoiseMat(const TKalMatrix &q) { fQ = q; } + inline virtual void SetSitePtr (TVKalSite *s) { fSitePtr = s; } + +private: + + // private data members ------------------------------------------- + + Int_t fType; // (0,1,2,3) = (uninited,predicted,filtered,smoothed) + TVKalSite *fSitePtr; // pointer to corresponding KalSite + TKalMatrix fF; // propagator matrix to next site (F = @f/@a) + TKalMatrix fFt; // transposed propagator matrix (F^T = (@f/@a)^T) + TKalMatrix fQ; // process noise from this to the next sites + TKalMatrix fC; // covariance matrix + + ClassDef(TVKalState,1) // Base class for state vector objects +}; +#endif diff --git a/Utilities/KalTest/kaltest/TVKalSystem.h b/Utilities/KalTest/kaltest/TVKalSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..fff6d5a8631cb0211e9b8af29e6b6dbe34af8987 --- /dev/null +++ b/Utilities/KalTest/kaltest/TVKalSystem.h @@ -0,0 +1,82 @@ +#ifndef TVKALSYSTEM_H +#define TVKALSYSTEM_H +//************************************************************************* +//* =================== +//* TVKalSystem Class +//* =================== +//* +//* (Description) +//* Base class for Kalman filtering class +//* (Requires) +//* TObjArray +//* (Provides) +//* class TVKalSystem +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2005/08/25 A.Yamaguchi Added fgCurInstancePtr and its getter & setter. +//* 2009/06/18 K.Fujii Implement inverse Kalman filter +//* +//************************************************************************* + +#include "TObjArray.h" +#include "TVKalSite.h" + +//_____________________________________________________________________ +// ------------------------------ +// Kalman Filtering class +// ------------------------------ +// +class TKalMatrix; + +class TVKalSystem : public TObjArray { +friend class TVKalSite; +public: + + // Ctors and Dtor + + TVKalSystem(Int_t n = 1); + virtual ~TVKalSystem(); + + // Utility methods + + virtual Bool_t AddAndFilter(TVKalSite &next); + virtual void SmoothBackTo(Int_t k); + virtual void SmoothAll(); + virtual void InvFilter(Int_t k); + + inline void Add(TObject *obj); + + // Getters + + inline virtual TVKalSite & GetCurSite() { return *fCurSitePtr; } + inline virtual TVKalState & GetState(TVKalSite::EStType t) + { return fCurSitePtr->GetState(t); } + inline virtual Double_t GetChi2() { return fChi2; } + virtual Int_t GetNDF (Bool_t self = kTRUE); + + static TVKalSystem *GetCurInstancePtr() { return fgCurInstancePtr; } + + // Setters + +private: + static void SetCurInstancePtr(TVKalSystem *ksp) { fgCurInstancePtr = ksp; } + +private: + TVKalSite *fCurSitePtr; // pointer to current site + Double_t fChi2; // current total chi2 + + static TVKalSystem *fgCurInstancePtr; //! currently active instance + + ClassDef(TVKalSystem,1) // Base class for Kalman Filter +}; + +//======================================================= +// inline functions +//======================================================= + +void TVKalSystem::Add(TObject *obj) +{ + TObjArray::Add(obj); + fCurSitePtr = static_cast<TVKalSite *>(obj); +} +#endif diff --git a/Utilities/KalTest/kaltest/TVMeasLayer.h b/Utilities/KalTest/kaltest/TVMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..5cdc314352f89963a5a8dc560c0623dac861c177 --- /dev/null +++ b/Utilities/KalTest/kaltest/TVMeasLayer.h @@ -0,0 +1,86 @@ +#ifndef TVMEASLAYER_H +#define TVMEASLAYER_H +//************************************************************************* +//* ==================== +//* TVMeasLayer Class +//* ==================== +//* +//* (Description) +//* Measurement layer interface class. +//* (Requires) +//* (Provides) +//* class TVMeasLayer +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 A.Yamaguchi Added new data members, fFwdX0Inv, +//* fBwdX0Inv and fIndex, and their +//* corresponding getters and setters. +//* Added a new method, GetX0Inv(). +//* 2005/0X/XX A.Yamaguchi Replaced fFwdX0Inv, fBwdX0Inv, and +//* their getters and setters by +//* fMaterialOutPtr, fMaterialInPtr, and +//* their getters and setters. +//* 2005/08/15 K.Fujii Added fIsActive and IsActive(). +//* 2011/12/03 S.Aplin Added new member: name +//* default value set to "TVMeasLayer" +//* and corresponding member function +//* TString GetName() +//* +//************************************************************************* + +#include "TVector3.h" // from ROOT +#include "TMaterial.h" // from ROOT +#include "TAttElement.h" // from Utils +#include "TKalMatrix.h" // from KalLib +#include "KalTrackDim.h" // from KalTrackLib + +class TVTrack; +class TVTrackHit; + +class TVMeasLayer : public TAttElement { +public: + // Ctors and Dtor + + TVMeasLayer(TMaterial &matIn, + TMaterial &matOut, + Bool_t isactive = kTRUE, + const Char_t *name = "TVMeasLayer"); + virtual ~TVMeasLayer() {} + + // Utiliy Methods + + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const = 0; + virtual TVector3 HitToXv (const TVTrackHit &ht) const = 0; + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const = 0; + + inline virtual TMaterial &GetMaterial(Bool_t isoutgoing) const + { return isoutgoing ? *fMaterialOutPtr : *fMaterialInPtr; } + + inline Int_t GetIndex() const { return fIndex; } + inline void SetIndex(Int_t i) { fIndex = i; } + inline Bool_t IsActive() const { return fIsActive; } + + virtual Double_t GetEnergyLoss ( Bool_t isoutgoing, + const TVTrack &hel, + Double_t df) const; + virtual void CalcQms ( Bool_t isoutgoing, + const TVTrack &hel, + Double_t df, + TKalMatrix &Qms) const; + + inline TString GetName() const { return fname; } + +private: + TMaterial *fMaterialInPtr; // pointer of inner Material + TMaterial *fMaterialOutPtr; // pointer of outer Material + Int_t fIndex; // index in TKalDetCradle + Bool_t fIsActive; // flag to tell layer is active or not + const Char_t *fname; + ClassDef(TVMeasLayer,1) // Measurement layer interface class +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TVSolid.h b/Utilities/KalTest/kaltest/TVSolid.h new file mode 100644 index 0000000000000000000000000000000000000000..83b4f57e20505c8bda69f27297ec0e604f2957b3 --- /dev/null +++ b/Utilities/KalTest/kaltest/TVSolid.h @@ -0,0 +1,32 @@ +#ifndef TVSOLID_H +#define TVSOLID_H +//************************************************************************* +//* ==================== +//* TVSolid Class +//* ==================== +//* +//* (Description) +//* This is the base class for various solids. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVSolid +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TObject.h" +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any solid +// ----------------------------------- + +class TVSolid : public TObject { +public: +private: + + ClassDef(TVSolid,1) // Base class for any solid +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TVSurface.h b/Utilities/KalTest/kaltest/TVSurface.h new file mode 100644 index 0000000000000000000000000000000000000000..be0a085a4ab3a00d09b2f5dbfe533f670d937e4a --- /dev/null +++ b/Utilities/KalTest/kaltest/TVSurface.h @@ -0,0 +1,68 @@ +#ifndef TVSURFACE_H +#define TVSURFACE_H +//************************************************************************* +//* ==================== +//* TVSurface Class +//* ==================== +//* +//* (Description) +//* This is the base class for various solids. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVSurface +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* 2005/02/23 K.Fujii Added new methods, Compare() and +//* GetSortingPolicy(). +//* +//* 2011/06/17 D.Kamai Added new method, GetOutwardNormal() +//* +//************************************************************************* +// +#include "TObject.h" +#include "TMatrixD.h" +#include "TVector3.h" + +class TVTrack; +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any surface +// ----------------------------------- + +class TVSurface : public TObject { +public: + + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps = 1.e-8) const; + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + virtual Double_t CalcS (const TVector3 &xx) const = 0; + virtual TMatrixD CalcDSDx (const TVector3 &xx) const = 0; + virtual Bool_t IsOnSurface (const TVector3 &xx) const = 0; + virtual Bool_t IsOutside (const TVector3 &xx) const = 0; + inline virtual TVector3 GetOutwardNormal (const TVector3 &xx) const; + + virtual Double_t GetSortingPolicy () const = 0; + + virtual Int_t Compare (const TObject *obj) const; + virtual Bool_t IsSortable() const { return kTRUE; } + +private: + + ClassDef(TVSurface,1) // Base class for any surface +}; + +TVector3 TVSurface::GetOutwardNormal(const TVector3 &xx) const +{ + TMatrixD dsdx = CalcDSDx(xx); + return TVector3(dsdx(0,0),dsdx(0,1),dsdx(0,2)).Unit(); +} + +#endif diff --git a/Utilities/KalTest/kaltest/TVTrack.h b/Utilities/KalTest/kaltest/TVTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..9e8f0f4548363a1b9aa6573a094863186e221413 --- /dev/null +++ b/Utilities/KalTest/kaltest/TVTrack.h @@ -0,0 +1,150 @@ +#ifndef TVTRACK_H +#define TVTRACK_H +//************************************************************************* +//* =============== +//* TVTrack Class +//* =============== +//* +//* (Description) +//* This is the base class for various tracks. +//* (Requires) +//* TVCurve; +//* (Provides) +//* class TVTrack +//* (Update Recored) +//* 2003/10/24 K.Fujii Original version. +//* 2005/08/14 K.Fujii Added IsInB(). +//* +//************************************************************************* +// + +#include "TVector3.h" +#include "TMatrixD.h" + +#if 1 +#include "TMath.h" +#include "TCollection.h" +#endif + +#include "TVCurve.h" + +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any track +// ----------------------------------- + +class TVTrack : public TVCurve { +public: + // Ctors and Dtor + + TVTrack(Double_t dr = 0., + Double_t phi0 = 0., + Double_t kappa = 1.e-5, + Double_t dz = 0., + Double_t tanl = 0., + Double_t x0 = 0., + Double_t y0 = 0., + Double_t z0 = 0., + Double_t b = 30.); + + TVTrack(const TMatrixD &a, const TVector3 & x0, Double_t b = 30.); + + virtual ~TVTrack() {} + + // Utility methods + + virtual void MoveTo(const TVector3 &x0to, + Double_t &fid, + TMatrixD *F = 0, + TMatrixD *C = 0) = 0; + + virtual void MoveTo(const TVector3 &x0to, + Double_t &fid, + TMatrixD &C) + { + Int_t sdim = C.GetNrows(); + TMatrixD F(sdim, sdim); + MoveTo(x0to,fid,&F,&C); + } + + inline virtual void ScatterBy(Double_t dphi, Double_t dtnl) + { + fPhi0 += dphi; + fKappa += (fKappa*fTanL/(1+fTanL*fTanL)) * dtnl; + fTanL += dtnl; + } + + inline virtual void PutInto(TMatrixD &sv) const + { + sv(0,0) = fDrho; + sv(1,0) = fPhi0; + sv(2,0) = fKappa; + sv(3,0) = fDz; + sv(4,0) = fTanL; + } + + virtual TVector3 CalcXAt (Double_t phi) const = 0; + virtual TMatrixD CalcDxDa (Double_t phi) const = 0; + virtual TMatrixD CalcDxDphi(Double_t phi) const = 0; + virtual void CalcDapDa (Double_t fid, + Double_t dr, + Double_t drp, + TMatrixD &F) const = 0; + + // Getters + + inline virtual Double_t GetDrho () const { return fDrho; } + inline virtual Double_t GetPhi0 () const { return fPhi0; } + inline virtual Double_t GetKappa () const { return fKappa; } + inline virtual Double_t GetDz () const { return fDz; } + inline virtual Double_t GetTanLambda() const { return fTanL; } + inline virtual const TVector3 & GetPivot () const { return fX0; } + inline virtual Double_t GetRho () const { return fAlpha/fKappa; } + inline virtual Double_t GetPtoR () const { return fAlpha; } + + // Setters + + inline virtual void SetTo(const TMatrixD &sv, const TVector3 &x0) + { + fDrho = sv(0,0); + fPhi0 = sv(1,0); + fKappa = sv(2,0); + fDz = sv(3,0); + fTanL = sv(4,0); + fX0 = x0; + } + + inline virtual void SetMagField(Double_t b) + { + // // units: mm, sec, Tesla + if (b != 0.) fAlpha = kGiga/kLightVelocity*1000./b; + // units: cm, sec, kGaus + //if (b != 0.) fAlpha = kGiga/kLightVelocity*100./(b/10); + else fAlpha = kInfinity; + } + + inline virtual Bool_t IsInB() const { return fAlpha < kInfinity ? kTRUE : kFALSE; } + +protected: + Double_t fDrho; // drho + Double_t fPhi0; // phi0 + Double_t fKappa; // kappa + Double_t fDz; // dz + Double_t fTanL; // tanl + TVector3 fX0; // pivot + Double_t fAlpha; // alpha + +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) + static const Double_t kLightVelocity = 2.99792458e8; //! light velocity [m/sec] + static const Double_t kGiga = 1.0e9; //! Giga = 10^{9} + static const Double_t kInfinity = 1.e+20; //! infinity +#else + static const Double_t kLightVelocity; //! light velocity [m/sec] + static const Double_t kGiga; //! Giga = 10^{9} + static const Double_t kInfinity; //! infinity +#endif + + ClassDef(TVTrack,1) // Base class for any track +}; + +#endif diff --git a/Utilities/KalTest/kaltest/TVTrackHit.h b/Utilities/KalTest/kaltest/TVTrackHit.h new file mode 100644 index 0000000000000000000000000000000000000000..9559bb624fd9e23f31b7a39c5e9ea3afbd61bf64 --- /dev/null +++ b/Utilities/KalTest/kaltest/TVTrackHit.h @@ -0,0 +1,55 @@ +#ifndef TVTRACKHIT_H +#define TVTRACKHIT_H + +//************************************************************************* +//* ==================== +//* TVTrackHit Class +//* ==================== +//* +//* (Description) +//* Abstract base class to store single hit information. +//* (Requires) +//* (Provides) +//* class TVTrackHit +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/08/11 K.Fujii Removed fXX and its getter and setter. +//* +//************************************************************************* + +#include "TVector3.h" // from ROOT +#include "TKalMatrix.h" // from KalLib +#include "KalTrackDim.h" // from KalTrackLib +#include "TVMeasLayer.h" // from KalTrackLib + +class TVTrackHit : public TKalMatrix { +public: + TVTrackHit(Int_t m = kMdim); + + TVTrackHit(const TVMeasLayer &ms, Double_t *x, Double_t *dx, + Double_t b = 30., Int_t m = kMdim); + TVTrackHit(const TVTrackHit &hit); + + virtual ~TVTrackHit(); + + inline virtual Double_t GetX (Int_t i) const { return (*this)(i,0); } + inline virtual Double_t GetDX(Int_t i) const { return (*this)(i,1); } + inline virtual Int_t GetDimension() const { return fDim; } + inline virtual Double_t GetBfield() const { return fBfield; } + + inline virtual const TVMeasLayer & GetMeasLayer() const + { return *fMeasLayerPtr; } + + virtual TKalMatrix XvToMv (const TVector3 &xv, Double_t t0) const = 0; + + // virtual void DebugPrint(Option_t *opt = "") const = 0; + +private: + Int_t fDim; // dimension of coordinate space + Double_t fBfield; // B field + TVMeasLayer *fMeasLayerPtr; // pointer to measurement layer + + ClassDef(TVTrackHit,1) // Sample hit class +}; + +#endif diff --git a/Utilities/KalTest/src/CMakeLists.txt.remove b/Utilities/KalTest/src/CMakeLists.txt.remove new file mode 100644 index 0000000000000000000000000000000000000000..e56e882093ee6f8d8a681f9080d3b43fd118a527 --- /dev/null +++ b/Utilities/KalTest/src/CMakeLists.txt.remove @@ -0,0 +1,42 @@ +# build KalTest library + +SET( lib_input_dirs geomlib kallib kaltracklib utils ) + +FOREACH( lib_input_dir ${lib_input_dirs} ) + LIST( APPEND ROOT_DICT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/${lib_input_dir} ) +ENDFOREACH() + +#MESSAGE( STATUS "ROOT_DICT_INCLUDE_DIRS: ${ROOT_DICT_INCLUDE_DIRS}" ) + +FOREACH( lib_input_dir ${lib_input_dirs} ) + + AUX_SOURCE_DIRECTORY( ${lib_input_dir} lib_sources ) + + PREPARE_ROOT_DICT_HEADERS( ${lib_input_dir} ) + + INSTALL_DIRECTORY( ${lib_input_dir}/ DESTINATION "include/kaltest" + FILES_MATCHING PATTERN "*.h" PATTERN "LinkDef.h" EXCLUDE + ) + + GEN_ROOT_DICT_SOURCES( ${lib_input_dir}Dict.cxx ) + + LIST( APPEND lib_sources ${ROOT_DICT_OUTPUT_SOURCES} ) + +ENDFOREACH() + +INCLUDE_DIRECTORIES( ${ROOT_DICT_INCLUDE_DIRS} ) +INCLUDE_DIRECTORIES( ${ROOT_INCLUDE_DIRS} ) + +#MESSAGE( STATUS "KalTest lib sources: ${lib_sources}" ) + +ADD_SHARED_LIBRARY( KalTest ${lib_sources} ) +INSTALL_SHARED_LIBRARY( KalTest DESTINATION lib ) +TARGET_LINK_LIBRARIES( KalTest ${ROOT_LIBRARIES} ) + +IF( APPLE ) #---- need special linker flags for ROOT dictionary on MacOS + SET_TARGET_PROPERTIES( KalTest PROPERTIES + LINK_FLAGS "-single_module -undefined dynamic_lookup -bind_at_load" + ) +ENDIF( APPLE ) + + diff --git a/Utilities/KalTest/src/geomlib/Imakefile b/Utilities/KalTest/src/geomlib/Imakefile new file mode 100644 index 0000000000000000000000000000000000000000..8f0b2c6ee5f3b5fc655e6a2f47a2ab57499f1a48 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/Imakefile @@ -0,0 +1,62 @@ +#include "../../conf/makejsf.tmpl" + +LDFLAGS = /* $(GLIBS) */ + +INSTALLDIR = ../.. +SOREV = 2005.01 +PACKAGENAME = S4Geom + +SRCS = THelicalTrack.$(SrcSuf) \ + TCircle.$(SrcSuf) \ + TVCutCone.$(SrcSuf) \ + TVCurve.$(SrcSuf) \ + TCylinder.$(SrcSuf) \ + TPlane.$(SrcSuf) \ + THype.$(SrcSuf) \ + TStraightTrack.$(SrcSuf) \ + TTube.$(SrcSuf) \ + TVSolid.$(SrcSuf) \ + TVSurface.$(SrcSuf) \ + TVTrack.$(SrcSuf) + +OBJS = $(subst .$(SrcSuf),.$(ObjSuf),$(SRCS)) \ + $(PACKAGENAME)Dict.$(ObjSuf) + +HDRS = $(subst .$(SrcSuf),.h,$(SRCS)) + +DICTNAME = $(PACKAGENAME)Dict + +LIBNAME = $(PACKAGENAME) + +SONAME = lib$(LIBNAME).$(DllSuf).$(SOREV) + +LIBINSTALLDIR = $(INSTALLDIR)/lib +INCINSTALLDIR = $(INSTALLDIR)/include +INCPATH = -I. -I$(INCINSTALLDIR) +CXXFLAGS += $(INCPATH) -O0 -g +SHLIBLDFLAGS = $(DYLIBFLAGS) + +all:: $(SONAME) + +SharedLibraryTarget($(LIBNAME),$(SOREV),$(OBJS),.,.) + +InstallSharedLibrary($(LIBNAME),$(SOREV),$(LIBINSTALLDIR)) + +InstallMultipleFlags($(HDRS),$(INCINSTALLDIR),-m 644) + +clean:: + @rm -f $(OBJS) core *.$(DllSuf) $(DICTNAME).$(SrcSuf) $(DICTNAME).h + +depend:: $(SRCS) $(HDRS) + for i in $(SRCS); do \ + rmkdepend -a -- $(CXXFLAGS) $(INCPATH) $(DEPENDFILES) -- $$i; done + +distclean:: clean + @rm -f $(OBJS) core *.$(DllSuf) *.$(DylibSuf) + @rm -f $(DICTNAME).$(SrcSuf) $(DICTNAME).h *~ + @rm -f $(SONAME) *.root Makefile + +$(DICTNAME).$(SrcSuf): $(HDRS) LinkDef.h + @echo "Generating dictionary ..." + rootcint -f $(DICTNAME).$(SrcSuf) \ + -c -I$(INCINSTALLDIR) $(HDRS) LinkDef.h diff --git a/Utilities/KalTest/src/geomlib/LinkDef.h b/Utilities/KalTest/src/geomlib/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..76322c6ce358eed5a308e3b60a3eb22e6ece95b0 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/LinkDef.h @@ -0,0 +1,20 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class TCircle+; +#pragma link C++ class TCutCone+; +#pragma link C++ class TCylinder+; +#pragma link C++ class TPlane+; +#pragma link C++ class THype+; +#pragma link C++ class TTube+; +#pragma link C++ class THelicalTrack+; +#pragma link C++ class TStraightTrack+; +#pragma link C++ class TVCurve+; +#pragma link C++ class TVSolid+; +#pragma link C++ class TVSurface+; +#pragma link C++ class TVTrack+; + +#endif diff --git a/Utilities/KalTest/src/geomlib/TCircle.cxx b/Utilities/KalTest/src/geomlib/TCircle.cxx new file mode 100644 index 0000000000000000000000000000000000000000..eca9a6d803adc90ec96e8d2b766b62cb57cc4454 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TCircle.cxx @@ -0,0 +1,67 @@ +//************************************************************************* +//* ==================== +//* TCircle Class +//* ==================== +//* +//* (Description) +//* A class to implement a circle object. +//* (Requires) +//* TVCurve +//* (Provides) +//* class TCircle +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TCircle.h" +#if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0) +#include "TMath.h" +#endif +//_____________________________________________________________________ +// ----------------------------------- +// Circle Class +// ----------------------------------- + +ClassImp(TCircle) + +TCircle::TCircle(Double_t r, Double_t xc, Double_t yc) + : fR(r), fXc(xc,yc) +{ +} + +Int_t TCircle::CalcXingPointWith(const TCircle &c, + TVector2 xx[], + Double_t eps) const +{ + TVector2 x12 = c.fXc - fXc; + Double_t a = x12.Mod2(); + Double_t sqa = TMath::Sqrt(a); + Double_t radd = fR + c.fR; + Double_t rsub = fR - c.fR; + Double_t arsub = TMath::Abs(rsub); + if (sqa > radd+eps || sqa <= eps || sqa < arsub-eps) { + // no intersection + return 0; + } else if (sqa > radd-eps) { + // single intersection + xx[0] = fXc + (fR/sqa)*x12; + return 1; + } else { + // two intersection + Double_t d = radd*rsub + a; + a = 1./sqa; + d *= 0.5*a; + Double_t dp = (fR+d)*(fR-d); + if (dp <= 0.) dp = 0.; + else dp = TMath::Sqrt(dp)*a; + d *= a; + TVector2 d1 = fXc + d*x12; + TVector2 d2(dp*x12.Y(), -dp*x12.X()); + xx[0] = d1 + d2; + xx[1] = d1 - d2; + + return 2; + } +} + diff --git a/Utilities/KalTest/src/geomlib/TCircle.h b/Utilities/KalTest/src/geomlib/TCircle.h new file mode 100644 index 0000000000000000000000000000000000000000..2bb548aa72649420ccfd7d22f1778816b76abb63 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TCircle.h @@ -0,0 +1,56 @@ +#ifndef TCIRCLE_H +#define TCIRCLE_H +//************************************************************************* +//* ==================== +//* TCircle Class +//* ==================== +//* +//* (Description) +//* A class to implement a circle object. +//* (Requires) +//* TVCurve +//* (Provides) +//* class TCircle +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include <iostream> +#include "TVector2.h" +#include "TVCurve.h" + +using namespace std; +//_____________________________________________________________________ +// ----------------------------------- +// Circle Class +// ----------------------------------- + +class TCircle : public TVCurve { +public: + TCircle(Double_t r = 1., Double_t xc = 0., Double_t yc = 0.); + virtual ~TCircle() {} + + virtual Int_t CalcXingPointWith(const TCircle &c, + TVector2 xx[], + Double_t eps = 1.e-8) const; + + inline virtual Double_t GetRadius() const { return fR; } + inline virtual const TVector2 & GetCenter() const { return fXc; } + + inline virtual void DebugPrint() const; + +private: + Double_t fR; // radius + TVector2 fXc; // center + + ClassDef(TCircle,1) // circle class +}; + +void TCircle::DebugPrint() const +{ + cerr << " radius = " << fR + << " center = (" << fXc.X() << "," << fXc.Y() << ")" << endl; +} + +#endif diff --git a/Utilities/KalTest/src/geomlib/TCutCone.cxx b/Utilities/KalTest/src/geomlib/TCutCone.cxx new file mode 100644 index 0000000000000000000000000000000000000000..642b42c401c00616fecee8b354cc4995a98d2b52 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TCutCone.cxx @@ -0,0 +1,66 @@ +//************************************************************************* +//* ==================== +//* TCutCone Class +//* ==================== +//* +//* (Description) +//* A class to implement a hyperboloidal surface object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TCutCone +//* (Update Recored) +//* 2012/01/19 K.Fujii Original version derived from THYpe. +//* This class is implemented as an extreme +//* (fR0=0) case of THype, thereby containing +//* both -ve and +ve sides. If you want to +//* restrict them to one side, override +//* IsOnSurface(), etc. +//************************************************************************* +// +#include <iostream> +#include "TCircle.h" +#include "TCutCone.h" +#include "TVTrack.h" + +using namespace std; + +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) +#else +const Double_t TCutCone::kTol = 1.e-5; // tolerance +#endif + +//_____________________________________________________________________ +// ----------------------------------- +// TCutCone Class +// ----------------------------------- + +ClassImp(TCutCone) + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate S +// ----------------------------------- +// +Double_t TCutCone::CalcS(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + Double_t r = xxc.Perp(); + Double_t s = (r - xxc.Z()*fTanA) * (r + xxc.Z()* fTanA); + return s; +} + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate (@S/@x) +// ----------------------------------- +// +TMatrixD TCutCone::CalcDSDx(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + TMatrixD dsdx(1,3); + dsdx(0,0) = 2.* xxc.X(); + dsdx(0,1) = 2.* xxc.Y(); + dsdx(0,2) = -2.* xxc.Z() * fTanA * fTanA; + return dsdx; +} diff --git a/Utilities/KalTest/src/geomlib/TCutCone.h b/Utilities/KalTest/src/geomlib/TCutCone.h new file mode 100644 index 0000000000000000000000000000000000000000..b66cfef1f8e73f51c5fea356c75ea3fa053da57c --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TCutCone.h @@ -0,0 +1,122 @@ +#ifndef TCUTCONE_H +#define TCUTCONE_H +//************************************************************************* +//* ==================== +//* TCutCone Class +//* ==================== +//* +//* (Description) +//* A class to implement a conical surface object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TCutCone +//* (Update Recored) +//* 2012/01/19 K.Fujii Original version derived from THYpe. +//* This class is implemented as an extreme +//* (fR0=0) case of THype, thereby containing +//* both -ve and +ve sides. If you want to +//* restrict them to one side, override +//* IsOnSurface(), etc. +//************************************************************************* +// +#include "TVSurface.h" +#include "TVector3.h" +#include "TMatrixD.h" + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Hype Class +// ----------------------------------- + +class TCutCone : public TVSurface { +public: + TCutCone(Double_t z1 = 0.5, + Double_t hlen = 1.0, + Double_t tana = 0.1, + Double_t xc = 0., + Double_t yc = 0, + Double_t zc = 0.) + : fZ1(z1), + fHalfLen(hlen), + fXc(xc,yc,zc), + fTanA(tana) + { + } + + virtual ~TCutCone() {} + + virtual Double_t CalcS (const TVector3 &xx) const; + virtual TMatrixD CalcDSDx(const TVector3 &xx) const; + + inline virtual Bool_t IsOnSurface(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetSortingPolicy() const; + + inline virtual Double_t GetZ1 () const { return fZ1; } + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual Double_t GetTanA () const { return fTanA; } + inline virtual Double_t GetLength () const; + inline virtual Double_t GetZmin () const; + inline virtual Double_t GetZmax () const; + +private: + Double_t fZ1; // z position of the front face + Double_t fHalfLen; // half length (cone length from the apex) + TVector3 fXc; // center + Double_t fTanA; // tan(half cone angle) +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) + static const Double_t kTol = 1.e-5; // tolerance +#else + static const Double_t kTol; // tolerance +#endif + + ClassDef(TCutCone,1) // hype class +}; +//======================================================= +// inline functions +//======================================================= + +Double_t TCutCone::GetLength () const +{ + return 2*fHalfLen; +} + +Double_t TCutCone::GetZmin() const +{ + return TMath::Min(fXc.Z() - fHalfLen, fXc.Z() + fHalfLen); +} + +Double_t TCutCone::GetZmax() const +{ + return TMath::Max(fXc.Z() - fHalfLen, fXc.Z() + fHalfLen); +} + +Bool_t TCutCone::IsOnSurface(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + Double_t r = xxc.Perp(); + Double_t z = xxc.Z(); + Double_t s = r*r - fTanA*fTanA*z*z; + + return (TMath::Abs(s) < kTol && xx.Z() >= GetZmin() && xx.Z() <= GetZmax()); +} + +Bool_t TCutCone::IsOutside(const TVector3 &xx) const +{ + Double_t r = (xx-fXc).Perp(); + Double_t z = xx.Z(); + Double_t R2 =fTanA*fTanA*z*z; + + return (r*r > R2 || z < GetZmin() || z > GetZmax()); +} + +Double_t TCutCone::GetSortingPolicy() const +{ + return GetZ1()*GetTanA(); +} +#endif + diff --git a/Utilities/KalTest/src/geomlib/TCylinder.cxx b/Utilities/KalTest/src/geomlib/TCylinder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a2c8a2f8b2bb59190aff6ec0f000f93dadb36dcb --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TCylinder.cxx @@ -0,0 +1,148 @@ +//************************************************************************* +//* ==================== +//* TCylinder Class +//* ==================== +//* +//* (Description) +//* A class to implement a cylinder object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TCylinder +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. Currently fXc is +//* supposed to be at the origin +//* 2009/05/30 K.Fujii Now allow nonzero fXc. +//* +//************************************************************************* +// +#include <iostream> +#include "TCircle.h" +#include "TCylinder.h" +#include "TVTrack.h" + +using namespace std; + +//_____________________________________________________________________ +// ----------------------------------- +// Cylinder Class +// ----------------------------------- + +ClassImp(TCylinder) + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate S +// ----------------------------------- +// +Double_t TCylinder::CalcS(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + Double_t s = xxc.X() * xxc.X() + xxc.Y() * xxc.Y() - fR * fR; + return s; +} + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate (@S/@x) +// ----------------------------------- +// +TMatrixD TCylinder::CalcDSDx(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + TMatrixD dsdx(1,3); + dsdx(0,0) = 2.*xxc.X(); + dsdx(0,1) = 2.*xxc.Y(); + dsdx(0,2) = 0.; + return dsdx; +} + + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate crossing point with track +// ----------------------------------- +// +Int_t TCylinder::CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps) const +{ + // This assumes nonzero B field. + // + // Copy helix parameters to local variables. + // + + Double_t dr = hel.GetDrho(); + Double_t fi0 = hel.GetPhi0(); + Double_t cpa = hel.GetKappa(); + Double_t dz = hel.GetDz(); + Double_t tnl = hel.GetTanLambda(); + TVector3 X0 = hel.GetPivot(); + + // + // Check if charge is nonzero. + // + + Int_t chg = (Int_t)TMath::Sign(1.1,cpa); + if (!chg) { + cerr << ">>>> Error >>>> TCylinder::CalcXingPointWith" << endl + << " Kappa = 0 is invalid for a helix " << endl; + return -1; + } + + // + // Project everything to XY plane and calculate crossing points. + // + + Double_t rho = hel.GetRho(); + Double_t rdr = rho + dr; + Double_t zdz = X0.Z() + dz; + Double_t csf0 = TMath::Cos(fi0); + Double_t snf0 = TMath::Sin(fi0); + Double_t xc = X0.X() + rdr*csf0; + Double_t yc = X0.Y() + rdr*snf0; + Double_t zc = zdz; + + Double_t r = TMath::Abs(rho); + TCircle c(r,xc,yc); + + Double_t rv = GetR(); + Double_t xcv = GetXc().X(); + Double_t ycv = GetXc().Y(); + TCircle cv(rv,xcv,ycv); + + TVector2 xxp[2]; + Int_t nx = c.CalcXingPointWith(cv, xxp); + if (nx != 2) return 0; + + // + // Crossing detected. + // + + static const Double_t kPi = TMath::Pi(); + static const Double_t kHalfPi = 0.5*TMath::Pi(); + static const Double_t kTwoPi = 2.0*TMath::Pi(); + + phi = 9999.; + for (Int_t ix=0; ix<nx; ix++) { + Double_t x = xxp[ix].X() - xc; + Double_t y = xxp[ix].Y() - yc; + Double_t dfi = TMath::ATan2(y,x) - fi0 - kHalfPi*(1+chg); + if (!mode) { + while (dfi < -kPi) dfi += kTwoPi; + while (dfi >= kPi) dfi -= kTwoPi; + } else { + Int_t sign = (mode > 0 ? +1 : -1); // (+1,-1) = (fwd,bwd) + while (dfi < 0.) dfi += kTwoPi; + while (dfi >= kTwoPi) dfi -= kTwoPi; + if (sign*chg > 0) dfi -= kTwoPi; + } + if (TMath::Abs(dfi) < TMath::Abs(phi)) { + phi = dfi; + xx.SetXYZ(xxp[ix].X(), xxp[ix].Y(), zc - rho*tnl*phi); + } + } + return (IsOnSurface(xx) ? 1 : 0); +} diff --git a/Utilities/KalTest/src/geomlib/TCylinder.h b/Utilities/KalTest/src/geomlib/TCylinder.h new file mode 100644 index 0000000000000000000000000000000000000000..793da6310ca0395efaf3341233d767eb94776d7f --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TCylinder.h @@ -0,0 +1,104 @@ +#ifndef TCYLINDER_H +#define TCYLINDER_H +//************************************************************************* +//* ==================== +//* TCylinder Class +//* ==================== +//* +//* (Description) +//* A class to implement a cylinder object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TCylinder +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* 2005/02/23 K.Fujii Added GetSortingPolicy(). +//* +//************************************************************************* +// +#include "TVSurface.h" +#include "TVector3.h" +#include "TMatrixD.h" + +#include <cmath> + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Cylinder Class +// ----------------------------------- + +class TCylinder : public TVSurface { +public: + TCylinder(Double_t r = 1., Double_t hlen = 1., + Double_t xc = 0., Double_t yc = 0, Double_t zc = 0.) + : fR(r), fHalfLen(hlen), fXc(xc,yc,zc) {} + + virtual ~TCylinder() {} + + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + virtual Double_t CalcS (const TVector3 &xx) const; + virtual TMatrixD CalcDSDx(const TVector3 &xx) const; + + inline virtual Bool_t IsOnSurface(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetSortingPolicy() const; + + inline virtual Double_t GetR () const { return fR; } + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual Double_t GetLength () const; + inline virtual Double_t GetZmin () const; + inline virtual Double_t GetZmax () const; + +private: + Double_t fR; // radius + Double_t fHalfLen; // half length + TVector3 fXc; // center + + ClassDef(TCylinder,1) // cylinder class +}; +//======================================================= +// inline functions +//======================================================= + +Double_t TCylinder::GetLength () const +{ + return 2*fHalfLen; +} + +Double_t TCylinder::GetZmin() const +{ + return fXc.Z() - fHalfLen; +} + +Double_t TCylinder::GetZmax() const +{ + return fXc.Z() + fHalfLen; +} + +Bool_t TCylinder::IsOnSurface(const TVector3 &xx) const +{ + return (xx.Z() >= GetZmin() && xx.Z() <= GetZmax()) && std::fabs( (xx-fXc).Perp() - fR ) < 1.e-6; +} + +Bool_t TCylinder::IsOutside(const TVector3 &xx) const +{ + Double_t r = (xx-fXc).Perp(); + Double_t z = xx.Z(); + return (r > fR || z < GetZmin() || z > GetZmax()); +} + +Double_t TCylinder::GetSortingPolicy() const +{ + return GetR(); +} +#endif + diff --git a/Utilities/KalTest/src/geomlib/THelicalTrack.cxx b/Utilities/KalTest/src/geomlib/THelicalTrack.cxx new file mode 100644 index 0000000000000000000000000000000000000000..71b2300ea48ef2426446c751c1bcefa8ec009115 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/THelicalTrack.cxx @@ -0,0 +1,424 @@ +//************************************************************************* +//* ==================== +//* THelicalTrack Class +//* ==================== +//* +//* (Description) +//* A class to implement a helical track object. +//* (Requires) +//* TVTrack, TCylinder, TCircle, TVector3, TMatrixD +//* (Provides) +//* class THelicalTrack +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// + +#include <iostream> +#include "THelicalTrack.h" + +using namespace std; + +//_____________________________________________________________________ +// ----------------------------------- +// Helical Track Class +// ----------------------------------- +// +//_____________________________________________________________________ +// -------------- +// Ctors and Dtor +// -------------- +// + +THelicalTrack::THelicalTrack(Double_t dr, + Double_t phi0, + Double_t kappa, + Double_t dz, + Double_t tanl, + Double_t x0, + Double_t y0, + Double_t z0, + Double_t b) + : TVTrack(dr,phi0,kappa,dz,tanl, x0,y0,z0, b) +{ +} + +THelicalTrack::THelicalTrack(const TMatrixD &a, const TVector3 &x0, Double_t b) + : TVTrack(a, x0, b) +{ +} + +THelicalTrack::THelicalTrack(const TVector3 &x1, + const TVector3 &x2, + const TVector3 &x3, + Double_t b, + Bool_t dir) +{ + SetMagField(b); + CalcStartHelix(x1,x2,x3,dir); +} + +//_____________________________________________________________________ +// ---------------- +// Utility methods +// ---------------- + +void THelicalTrack::MoveTo(const TVector3 &xv0to, // new pivoit + Double_t &fid, // deflection angle + TMatrixD *FPtr, // propagator matrix + TMatrixD *CPtr) // covariance matrix +{ + // --------------------------------------------------- + // (0) Preparation + // --------------------------------------------------- + // Define some numerical constants. + // + + static const Double_t kPi = TMath::Pi(); + static const Double_t kTwoPi = 2.0*kPi; + + // Copy helix parmeters to local variables + + Double_t dr = fDrho; + Double_t fi0 = fPhi0; + while (fi0 < 0.) fi0 += kTwoPi; + while (fi0 > kTwoPi) fi0 -= kTwoPi; + Double_t cpa = fKappa; + Double_t dz = fDz; + Double_t tnl = fTanL; + + Double_t x0 = fX0.X(); + Double_t y0 = fX0.Y(); + Double_t z0 = fX0.Z(); + Double_t xv = xv0to.X(); + Double_t yv = xv0to.Y(); + Double_t zv = xv0to.Z(); + + // --------------------------------------------------- + // (1) Calculate a' = f_k-1(a_k-1) + // --------------------------------------------------- + // a' = (dr', fi0', cpa', dz', tnl') + // a = (dr , fi0 , cpa , dz , tnl ) + // + + Double_t r = fAlpha/cpa; + Double_t rdr = r + dr; + Double_t csf0 = TMath::Cos(fi0); + Double_t snf0 = TMath::Sqrt(TMath::Max(0.0, (1.0-csf0)*(1.0+csf0))); + if (fi0 > kPi) snf0 = -snf0; + + Double_t xc = x0 + rdr*csf0; + Double_t yc = y0 + rdr*snf0; + Double_t fi0p = 0.; + + if (cpa > 0.) fi0p = TMath::ATan2((yc-yv),(xc-xv)); + if (cpa < 0.) fi0p = TMath::ATan2((yv-yc),(xv-xc)); + while (fi0p < 0.) fi0p += kTwoPi; + while (fi0p > kTwoPi) fi0p -= kTwoPi; + + Double_t csf = TMath::Cos(fi0p); + Double_t snf = TMath::Sqrt(TMath::Max(0.0, (1.0-csf)*(1.0+csf))); + if (fi0p > kPi) snf = -snf; + + Double_t anrm = 1.0/TMath::Sqrt(csf*csf+snf*snf); + csf *= anrm; + snf *= anrm; + Double_t csfd = csf*csf0 + snf*snf0; + Double_t snfd = snf*csf0 - csf*snf0; + + fid = fi0p - fi0; + while (fid < 0) fid += kTwoPi; + while (fid > kTwoPi) fid -= kTwoPi; + if (fid > kPi) fid -= kTwoPi; + + Double_t drp = (xc-xv)*csf + (yc-yv)*snf - r; + Double_t dzp = z0 - zv + dz - r*tnl*fid; + + +#if 0 //======== this code should not be necessary with a bug fix in TKalDetCradle ===================== + + // make sure that the helix really moves to the closest point to the reference point + // use protective_counter to ensure we don't enter an infinate loop + + if (tnl > 1.0e-10) { // protect against unreasonably small values of tnl, as in the case special case of a circle this will lead to division by zero below + + double phi_to_ref = dzp/(-r*tnl); + int protective_counter = 0; + + while ((phi_to_ref < -kPi) && protective_counter < 1000 ) { + phi_to_ref += kTwoPi; + ++protective_counter; + } + + protective_counter = 0; + + while ((phi_to_ref > kPi) && protective_counter < 1000 ) { + phi_to_ref -= kTwoPi; + ++protective_counter; + } + + double phi_correction = dzp/(-r*tnl) - phi_to_ref; + + dzp += phi_correction*r*tnl; + + } + +#endif // ============================================================================================= + + + TMatrixD av(5,1); + av(0,0) = drp; + av(1,0) = fi0p; + av(2,0) = cpa; + av(3,0) = dzp; + av(4,0) = tnl; + + THelicalTrack helto(av,xv0to); + helto.fAlpha = fAlpha; + + if (!FPtr && !CPtr) { + *this = helto; + return; + } + + TMatrixD Fdummy(5,5); + TMatrixD &F = FPtr ? *FPtr : Fdummy; + + // --------------------------------------------------- + // (2) Calculate @a'/@a = @a'/a = F_k-1 + // --------------------------------------------------- + // a' = (dr', fi0', cpa', dz', tnl') + // a = (dr , fi0 , cpa , dz , tnl ) + // + + Double_t rdrpr = 1.0/(r+drp); + Double_t rcpar = r/cpa; + + // @drho'/@a + F(0,0) = csfd; + F(0,1) = rdr*snfd; + F(0,2) = rcpar*(1.0-csfd); + F(0,3) = 0; + F(0,4) = 0; + + // @phi0'/@a + F(1,0) = -rdrpr*snfd; + F(1,1) = rdr*rdrpr*csfd; + F(1,2) = rcpar*rdrpr*snfd; + F(1,3) = 0; + F(1,4) = 0; + + // @kappa'/@a + F(2,0) = 0; + F(2,1) = 0; + F(2,2) = 1; + F(2,3) = 0; + F(2,4) = 0; + + // @dz'/@a + F(3,0) = r*rdrpr*tnl*snfd; + F(3,1) = r*tnl*(1.0-rdr*rdrpr*csfd); + F(3,2) = rcpar*tnl*(fid-r*rdrpr*snfd); + F(3,3) = 1; + F(3,4) = -r*fid; + + // @tanl'/@a + F(4,0) = 0; + F(4,1) = 0; + F(4,2) = 0; + F(4,3) = 0; + F(4,4) = 1; + + if (!CPtr) { + *this = helto; + return; + } + + // --------------------------------------------------- + // (3) Calculate C' = C^k-1_k + // --------------------------------------------------- + + TMatrixD &C = *CPtr; + TMatrixD Ft = TMatrixD(TMatrixD::kTransposed, F); + TMatrixD Cp = F * C * Ft; + C = Cp; + + *this = helto; +} + +TVector3 THelicalTrack::CalcXAt(Double_t phi) const +{ + Double_t csf0 = TMath::Cos(fPhi0); + Double_t snf0 = TMath::Sin(fPhi0); + Double_t snfd = TMath::Sin(fPhi0 + phi); + Double_t csfd = TMath::Cos(fPhi0 + phi); + Double_t rho = fAlpha/fKappa; + + Double_t x = fX0.X() + fDrho * csf0 + rho * (csf0 - csfd); + Double_t y = fX0.Y() + fDrho * snf0 + rho * (snf0 - snfd); + Double_t z = fX0.Z() + fDz - rho * fTanL * phi; + +#if 0 + std::cerr << "THelicalTrack::CalcXAt" << std::endl; + std::cerr << " phi0 = " << fPhi0 << std::endl; + std::cerr << " phi = " << phi << std::endl; + std::cerr << " Drho = " << fDrho << std::endl; + std::cerr << " rho = " << rho << std::endl; + std::cerr << " x0 = " << fX0.X() << std::endl; + std::cerr << " y0 = " << fX0.Y() << std::endl; + std::cerr << " z0 = " << fX0.Z() << std::endl; + std::cerr << " x = " << x << std::endl; + std::cerr << " y = " << y << std::endl; + std::cerr << " z = " << z << std::endl; +#endif + + return TVector3(x,y,z); +} + +TMatrixD THelicalTrack::CalcDxDa(Double_t phi) const +{ + Double_t fi0 = fPhi0; + Double_t r = fAlpha/fKappa; + Double_t rcpar = r/fKappa; + + Double_t snf0 = TMath::Sin(fi0); + Double_t csf0 = TMath::Cos(fi0); + Double_t snfd = TMath::Sin(fi0 + phi); + Double_t csfd = TMath::Cos(fi0 + phi); + + TMatrixD dxda(3,5); + // @x/@a + dxda(0,0) = csf0; + dxda(0,1) = -fDrho * snf0 - r * (snf0 - snfd); + dxda(0,2) = -rcpar * (csf0 - csfd); + dxda(0,3) = 0; + dxda(0,4) = 0; + + // @y/@a + dxda(1,0) = snf0; + dxda(1,1) = fDrho * csf0 + r *(csf0 - csfd); + dxda(1,2) = -rcpar * (snf0 - snfd); + dxda(1,3) = 0; + dxda(1,4) = 0; + + // @z/@a + dxda(2,0) = 0; + dxda(2,1) = 0; + dxda(2,2) = rcpar * phi * fTanL; + dxda(2,3) = 1; + dxda(2,4) = - r * phi; + + return dxda; +} + +TMatrixD THelicalTrack::CalcDxDphi(Double_t phi) const +{ + Double_t r = fAlpha/fKappa; + + Double_t snfd = TMath::Sin(fPhi0 + phi); + Double_t csfd = TMath::Cos(fPhi0 + phi); + + TMatrixD dxdphi(3,1); + dxdphi(0,0) = r * snfd; + dxdphi(1,0) = -r * csfd; + dxdphi(2,0) = -r * fTanL; + + return dxdphi; +} + +void THelicalTrack::CalcStartHelix(const TVector3 &x1, + const TVector3 &x2, + const TVector3 &x3, + Bool_t dir) +{ + static const TVector3 ez(0., 0., 1.); + TVector3 x12 = x2 - x1; + TVector3 x13 = x3 - x1; + TVector3 x23 = x3 - x2; + x12.SetZ(0.); + x13.SetZ(0.); + x23.SetZ(0.); + Double_t x12mag = x12.Mag(); + x12 = x12.Unit(); + Double_t x13mag = x13.Mag(); + x13 = x13.Unit(); + Double_t x23mag = x23.Mag(); + x23 = x23.Unit(); + + Double_t sinHalfPhi23 = x12.Cross(x13).Z(); + Double_t cosHalfPhi23 = 0.5 * (x13mag/x12mag + (1. - x23mag/x12mag)*(x12mag + x23mag)/x13mag); + Double_t halfPhi23 = TMath::ATan2(sinHalfPhi23, cosHalfPhi23); + + Double_t r = -0.5 * x23mag / sinHalfPhi23; + + TVector3 xc = 0.5 * (x2 + x3) + r * cosHalfPhi23 * x23.Cross(ez); + + if (dir == kIterBackward) r = -r; + TMatrixD sv(5,1); + sv(0,0) = 0; + sv(1,0) = TMath::ATan2(r * (xc.Y() - x1.Y()), r * (xc.X() - x1.X())); + sv(2,0) = GetPtoR() / r; + sv(3,0) = 0; + sv(4,0) = (x2.Z() - x3.Z()) / (r * 2 * halfPhi23); + + SetTo(sv, x1); +} + +void THelicalTrack::CalcDapDa(Double_t fid, + Double_t dr, + Double_t drp, + TMatrixD &F) const +{ + // --------------------------------------------------- + // (2) Calculate @a'/@a = @a'/a = F_k-1 + // --------------------------------------------------- + // a' = (dr', fi0', cpa', dz', tnl') + // a = (dr , fi0 , cpa , dz , tnl ) + // + + // @drho'/@a + Double_t cpa = fKappa; + Double_t tnl = fTanL; + Double_t csfd = TMath::Cos(fid); + Double_t snfd = TMath::Sin(fid); + Double_t r = fAlpha / cpa; + Double_t rdr = r + dr; + Double_t rcpar = r / cpa; + Double_t rdrpr = 1. / (r + drp); + + F(0,0) = csfd; + F(0,1) = rdr*snfd; + F(0,2) = rcpar*(1.-csfd); + F(0,3) = 0.; + F(0,4) = 0.; + + // @phi0'/@a + F(1,0) = -rdrpr*snfd; + F(1,1) = rdr*rdrpr*csfd; + F(1,2) = rcpar*rdrpr*snfd; + F(1,3) = 0.; + F(1,4) = 0.; + + // @kappa'/@a + F(2,0) = 0.; + F(2,1) = 0.; + F(2,2) = 1.; + F(2,3) = 0.; + F(2,4) = 0.; + + // @dz'/@a + F(3,0) = r*rdrpr*tnl*snfd; + F(3,1) = r*tnl*(1.-rdr*rdrpr*csfd); + F(3,2) = rcpar*tnl*(fid-r*rdrpr*snfd); + F(3,3) = 1.; + F(3,4) = -r*fid; + + // @tanl'/@a + F(4,0) = 0.; + F(4,1) = 0.; + F(4,2) = 0.; + F(4,3) = 0.; + F(4,4) = 1.; +} + diff --git a/Utilities/KalTest/src/geomlib/THelicalTrack.h b/Utilities/KalTest/src/geomlib/THelicalTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..26f9a2de53c05b66c3471d79262ff478358f4593 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/THelicalTrack.h @@ -0,0 +1,86 @@ +#ifndef THELICALTRACK_H +#define THELICALTRACK_H +//************************************************************************* +//* ==================== +//* THelicalTrack Class +//* ==================== +//* +//* (Description) +//* A class to implement a helical track object. +//* +//* A helix is parametrized in the standard way: +//* +//* x = x0 + drho * cos(phi0) + rho * (cos(phi0) - cos(phi0 + phi)) +//* y = y0 + drho * sin(phi0) + rho * (sin(phi0) - cos(sin0 + phi)) +//* z = z0 + dz - rho * tan(lambda) * phi +//* +//* with +//* +//* rho = alpha/kappa +//* +//* (Requires) +//* TVTrack, TCylinder, TCircle, TVector3, TMatrixD +//* (Provides) +//* class THelicalTrack +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// + +#include "TVTrack.h" + +//_____________________________________________________________________ +// ----------------------------------- +// Helical Track Class +// ----------------------------------- + +class THelicalTrack : public TVTrack { +public: + + // Ctors and Dtor + + THelicalTrack(Double_t dr = 0., + Double_t phi0 = 0., + Double_t kappa = 1.e-5, + Double_t dz = 0., + Double_t tanl = 0., + Double_t x0 = 0., + Double_t y0 = 0., + Double_t z0 = 0., + Double_t b = 30.); + + THelicalTrack(const TMatrixD &a, const TVector3 &x0, Double_t b = 30.); + THelicalTrack(const TVector3 &x1, const TVector3 &x2, const TVector3 &x3, + Double_t b = 30., Bool_t dir = kIterForward); + + virtual ~THelicalTrack() {} + + // Utility methods + + virtual void MoveTo(const TVector3 &x0to, + Double_t &fid, + TMatrixD *F = 0, + TMatrixD *C = 0); + + TVector3 CalcXAt (Double_t phi) const; + TMatrixD CalcDxDa (Double_t phi) const; + TMatrixD CalcDxDphi(Double_t phi) const; + void CalcDapDa (Double_t fid, + Double_t dr, + Double_t drp, + TMatrixD &F) const; + +private: + void CalcStartHelix(const TVector3 &x1, + const TVector3 &x2, + const TVector3 &x3, + Bool_t dir = kIterForward); + +private: + + ClassDef(THelicalTrack,1) // circle class +}; + +#endif + diff --git a/Utilities/KalTest/src/geomlib/THype.cxx b/Utilities/KalTest/src/geomlib/THype.cxx new file mode 100644 index 0000000000000000000000000000000000000000..49fe26c8279228fd9e83e9c5d4b800ba265cd377 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/THype.cxx @@ -0,0 +1,62 @@ +//************************************************************************* +//* ==================== +//* THype Class +//* ==================== +//* +//* (Description) +//* A class to implement a hyperboloidal surface object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class THype +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. Currently fXc is +//* supposed to be at the origin. +//************************************************************************* +// +#include <iostream> +#include "TCircle.h" +#include "THype.h" +#include "TVTrack.h" + +using namespace std; + +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) +#else +const Double_t THype::kTol = 1.e-5; // tolerance +#endif + +//_____________________________________________________________________ +// ----------------------------------- +// THype Class +// ----------------------------------- + +ClassImp(THype) + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate S +// ----------------------------------- +// +Double_t THype::CalcS(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + Double_t s = xxc.X() * xxc.X() + xxc.Y() * xxc.Y() + - fR0 * fR0 - xxc.Z() * xxc.Z() * fTanA * fTanA; + return s; +} + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate (@S/@x) +// ----------------------------------- +// +TMatrixD THype::CalcDSDx(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + TMatrixD dsdx(1,3); + dsdx(0,0) = 2.* xxc.X(); + dsdx(0,1) = 2.* xxc.Y(); + dsdx(0,2) = -2.* xxc.Z() * fTanA * fTanA; + return dsdx; +} diff --git a/Utilities/KalTest/src/geomlib/THype.h b/Utilities/KalTest/src/geomlib/THype.h new file mode 100644 index 0000000000000000000000000000000000000000..04e4765d06b864ab8b09baee20240e0124aedb08 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/THype.h @@ -0,0 +1,110 @@ +#ifndef THYPE_H +#define THYPE_H +//************************************************************************* +//* ==================== +//* THype Class +//* ==================== +//* +//* (Description) +//* A class to implement a hyperboloidal surface object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class THype +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* 2005/02/23 K.Fujii Added GetSortingPolicy(). +//* +//************************************************************************* +// +#include "TVSurface.h" +#include "TVector3.h" +#include "TMatrixD.h" + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Hype Class +// ----------------------------------- + +class THype : public TVSurface { +public: + THype(Double_t r = 1., Double_t hlen = 1., Double_t tana = 0., + Double_t xc = 0., Double_t yc = 0, Double_t zc = 0.) + : fR0(r), fHalfLen(hlen), fXc(xc,yc,zc), fTanA(tana) {} + + virtual ~THype() {} + + virtual Double_t CalcS (const TVector3 &xx) const; + virtual TMatrixD CalcDSDx(const TVector3 &xx) const; + + inline virtual Bool_t IsOnSurface(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetSortingPolicy() const; + + inline virtual Double_t GetR0 () const { return fR0; } + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual Double_t GetTanA () const { return fTanA; } + inline virtual Double_t GetLength () const; + inline virtual Double_t GetZmin () const; + inline virtual Double_t GetZmax () const; + +private: + Double_t fR0; // radius at z = 0. + Double_t fHalfLen; // half length + TVector3 fXc; // center + Double_t fTanA; // tan(stereo angle) +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) + static const Double_t kTol = 1.e-5; // tolerance +#else + static const Double_t kTol; // tolerance +#endif + + ClassDef(THype,1) // hype class +}; +//======================================================= +// inline functions +//======================================================= + +Double_t THype::GetLength () const +{ + return 2*fHalfLen; +} + +Double_t THype::GetZmin() const +{ + return fXc.Z() - fHalfLen; +} + +Double_t THype::GetZmax() const +{ + return fXc.Z() + fHalfLen; +} + +Bool_t THype::IsOnSurface(const TVector3 &xx) const +{ + TVector3 xxc = xx - fXc; + Double_t r = xxc.Perp(); + Double_t z = xxc.Z(); + Double_t s = r*r - fTanA*fTanA*z*z - fR0*fR0; + + return (TMath::Abs(s) < kTol && xx.Z() >= GetZmin() && xx.Z() <= GetZmax()); +} + +Bool_t THype::IsOutside(const TVector3 &xx) const +{ + Double_t r = (xx-fXc).Perp(); + Double_t z = xx.Z(); + Double_t R2 = fR0*fR0 + fTanA*fTanA*z*z; + + return (r*r > R2 || z < GetZmin() || z > GetZmax()); +} + +Double_t THype::GetSortingPolicy() const +{ + return GetR0(); +} +#endif + diff --git a/Utilities/KalTest/src/geomlib/TPlane.cxx b/Utilities/KalTest/src/geomlib/TPlane.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ca9a6fc3fe4b63f6769a2c865c17be8b40650bdb --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TPlane.cxx @@ -0,0 +1,67 @@ +//************************************************************************* +//* ==================== +//* TPlane Class +//* ==================== +//* +//* (Description) +//* A class to implement a plane object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TPlane +//* (Update Recored) +//* 2004/10/30 A.Yamaguchi Original version. Currently fXc is +//* supposed to be at the origin +//* +//************************************************************************* +// +#include "TPlane.h" + + +//_____________________________________________________________________ +// ----------------------------------- +// Plane Class +// ----------------------------------- + +ClassImp(TPlane) + +TPlane::TPlane() + : fXc(), fNormal() +{ +} + +TPlane::TPlane(const TVector3 &xc) + : fXc(xc), fNormal(xc.Unit()) +{ +} + +TPlane::TPlane(const TVector3 &xc, const TVector3 &n) + : fXc(xc), fNormal(n.Unit()) +{ +} + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate S +// ----------------------------------- +// +Double_t TPlane::CalcS(const TVector3 &xx) const +{ + return (xx - fXc) * fNormal; +} + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate (@S/@x) +// ----------------------------------- +// +TMatrixD TPlane::CalcDSDx(const TVector3 &xx) const +{ + TMatrixD dsdx(1,3); + dsdx(0,0) = fNormal.X(); + dsdx(0,1) = fNormal.Y(); + dsdx(0,2) = fNormal.Z(); + return dsdx; +} + + diff --git a/Utilities/KalTest/src/geomlib/TPlane.h b/Utilities/KalTest/src/geomlib/TPlane.h new file mode 100644 index 0000000000000000000000000000000000000000..a75d6737b3efa6406340b401beb9c126cce9db71 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TPlane.h @@ -0,0 +1,80 @@ +#ifndef TPLANE_H +#define TPLANE_H +//************************************************************************* +//* ==================== +//* TPlane Class +//* ==================== +//* +//* (Description) +//* A class to implement a flat plane object. +//* (Requires) +//* TVSurface +//* (Provides) +//* class TPlane +//* (Update Recored) +//* 2004/10/30 A.Yamaguchi Original version. +//* 2005/02/23 K.Fujii Added GetSortingPolicy(). +//* +//************************************************************************* +// +#include "TVSurface.h" +#include "TVector3.h" +#include "TMatrixD.h" + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Plane Class +// ----------------------------------- + +class TPlane : public TVSurface { +public: + TPlane(); + TPlane(const TVector3 &xc); + TPlane(const TVector3 &xc, const TVector3 &n); + + virtual ~TPlane() {} + + virtual Double_t CalcS (const TVector3 &xx) const; + virtual TMatrixD CalcDSDx(const TVector3 &xx) const; + + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual const TVector3 & GetNormal () const { return fNormal; } + inline virtual Bool_t IsOnSurface(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetSortingPolicy() const; + + +private: + TVector3 fXc; // center + TVector3 fNormal; // normal + + ClassDef(TPlane,1) // plane class +}; +//======================================================= +// inline functions +//======================================================= + + +Bool_t TPlane::IsOnSurface(const TVector3 &xx) const +{ +#if 0 + return (xx - fXc) * fNormal == 0. ? kTRUE : kFALSE; +#else + return kTRUE; +#endif +} + +Bool_t TPlane::IsOutside(const TVector3 &xx) const +{ + return (xx - fXc) * fNormal > 0. ? kTRUE : kFALSE; +} + +Double_t TPlane::GetSortingPolicy() const +{ + return TMath::Abs(fXc*fNormal.Unit()); +} +#endif + diff --git a/Utilities/KalTest/src/geomlib/TStraightTrack.cxx b/Utilities/KalTest/src/geomlib/TStraightTrack.cxx new file mode 100644 index 0000000000000000000000000000000000000000..413e13925e6e07ceaf709afff6a16953f75e5a52 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TStraightTrack.cxx @@ -0,0 +1,282 @@ +//************************************************************************* +//* ====================== +//* TStraightTrack Class +//* ====================== +//* +//* (Description) +//* A class to implement a straight track object. +//* (Requires) +//* TVTrack, TCylinder, TCircle, TVector3, TMatrixD +//* (Provides) +//* class TStraightTrack +//* (Update Recored) +//* 2003/10/24 K.Fujii Original version. +//* +//************************************************************************* +// + +#include <iostream> +#include "TStraightTrack.h" + +using namespace std; + +//_____________________________________________________________________ +// ----------------------------------- +// Straight Track Class +// ----------------------------------- +// +//_____________________________________________________________________ +// -------------- +// Ctors and Dtor +// -------------- +// + +TStraightTrack::TStraightTrack(Double_t dr, + Double_t phi0, + Double_t kappa, + Double_t dz, + Double_t tanl, + Double_t x0, + Double_t y0, + Double_t z0, + Double_t b) + : TVTrack(dr,phi0,kappa,dz,tanl, x0,y0,z0, b) +{ +} + +TStraightTrack::TStraightTrack(const TMatrixD &a, + const TVector3 &x0, + Double_t b) + : TVTrack(a, x0, b) +{ +} + +//_____________________________________________________________________ +// ---------------- +// Utility methods +// ---------------- + +void TStraightTrack::MoveTo(const TVector3 &xv0to, + Double_t &t, + TMatrixD *FPtr, + TMatrixD *CPtr) +{ + // --------------------------------------------------- + // (0) Preparation + // --------------------------------------------------- + // Define some numerical constants. + // + + static const Double_t kPi = TMath::Pi(); + static const Double_t kTwoPi = 2.0*kPi; + + // Copy helix parmeters to local variables + + Double_t dr = fDrho; + Double_t fi0 = fPhi0; + while (fi0 < 0.) fi0 += kTwoPi; + while (fi0 > kTwoPi) fi0 -= kTwoPi; + Double_t cpa = fKappa; + Double_t dz = fDz; + Double_t tnl = fTanL; + + Double_t x0 = fX0.X(); + Double_t y0 = fX0.Y(); + Double_t z0 = fX0.Z(); + Double_t xv = xv0to.X(); + Double_t yv = xv0to.Y(); + Double_t zv = xv0to.Z(); + + // --------------------------------------------------- + // (1) Calculate a' = f_k-1(a_k-1) + // --------------------------------------------------- + // a' = (dr', fi0', cpa', dz', tnl') + // a = (dr , fi0 , cpa , dz , tnl ) + // + + Double_t csf0 = TMath::Cos(fi0); + Double_t snf0 = TMath::Sqrt( TMath::Max(0.0, (1.0-csf0)*(1.0+csf0)) ); + if (fi0 > kPi) snf0 = -snf0; + + t = -(xv - x0) * snf0 + (yv - y0) * csf0; + + Double_t drp = dr - (xv - x0) * csf0 - (yv - y0) * snf0; + Double_t dzp = dz - (zv - z0) + t * tnl; + + TMatrixD av(5,1); + av(0,0) = drp; + av(1,0) = fi0; + av(2,0) = cpa; + av(3,0) = dzp; + av(4,0) = tnl; + + TStraightTrack helto(av,xv0to); + helto.fAlpha = fAlpha; + + if (!FPtr && !CPtr) { + *this = helto; + return; + } + + TMatrixD Fdummy(5,5); + TMatrixD &F = FPtr ? *FPtr : Fdummy; + + // --------------------------------------------------- + // (2) Calculate @a'/@a = @a'/a = F_k-1 + // --------------------------------------------------- + // a' = (dr', fi0', cpa', dz', tnl') + // a = (dr , fi0 , cpa , dz , tnl ) + // + + // @drho'/@a + F(0,0) = 1; + F(0,1) = -t; + F(0,2) = 0; + F(0,3) = 0; + F(0,4) = 0; + + // @phi0'/@a + F(1,0) = 0; + F(1,1) = 1; + F(1,2) = 0; + F(1,3) = 0; + F(1,4) = 0; + + // @kappa'/@a + + F(2,0) = 0; + F(2,1) = 0; + F(2,2) = 1; + F(2,3) = 0; + F(2,4) = 0; + + // @dz'/@a + F(3,0) = 0; + F(3,1) = (drp - dr)* tnl; + F(3,2) = 0; + F(3,3) = 1; + F(3,4) = t; + + // @tanl'/@a + F(4,0) = 0; + F(4,1) = 0; + F(4,2) = 0; + F(4,3) = 0; + F(4,4) = 1; + + if (!CPtr) { + *this = helto; + return; + } + + // --------------------------------------------------- + // (3) Calculate C' = C^k-1_k + // --------------------------------------------------- + + TMatrixD &C = *CPtr; + TMatrixD Ft = TMatrixD(TMatrixD::kTransposed, F); + TMatrixD Cp = F * C * Ft; + C = Cp; + + *this = helto; +} + +TVector3 TStraightTrack::CalcXAt(Double_t t) const +{ + Double_t csf0 = TMath::Cos(fPhi0); + Double_t snf0 = TMath::Sin(fPhi0); + + Double_t x = fX0.X() + fDrho * csf0 - t * snf0; + Double_t y = fX0.Y() + fDrho * snf0 + t * csf0; + Double_t z = fX0.Z() + fDz + t * fTanL; + + return TVector3(x,y,z); +} + +TMatrixD TStraightTrack::CalcDxDa(Double_t t) const +{ + Double_t fi0 = fPhi0; + + Double_t snf0 = TMath::Sin(fi0); + Double_t csf0 = TMath::Cos(fi0); + + TMatrixD dxda(3,5); + // @x/@a + dxda(0,0) = csf0; + dxda(0,1) = - fDrho * snf0 - t * csf0; + dxda(0,2) = 0; + dxda(0,3) = 0; + dxda(0,4) = 0; + + // @y/@a + dxda(1,0) = snf0; + dxda(1,1) = fDrho * csf0 - t * snf0; + dxda(1,2) = 0; + dxda(1,3) = 0; + dxda(1,4) = 0; + + // @z/@a + dxda(2,0) = 0; + dxda(2,1) = 0; + dxda(2,2) = 0; + dxda(2,3) = 1; + dxda(2,4) = t; + + return dxda; +} + +TMatrixD TStraightTrack::CalcDxDphi(Double_t t) const +{ + Double_t snf0 = TMath::Sin(fPhi0); + Double_t csf0 = TMath::Cos(fPhi0); + + TMatrixD dxdphi(3,1); + dxdphi(0,0) = -snf0; + dxdphi(1,0) = csf0; + dxdphi(2,0) = fTanL; + + return dxdphi; +} + +void TStraightTrack::CalcDapDa(Double_t fid, + Double_t dr, + Double_t drp, + TMatrixD &F) const +{ + // @drho'/@a + F(0,0) = 1; + F(0,1) = -fid; + F(0,2) = 0; + F(0,3) = 0; + F(0,4) = 0; + + // @phi0'/@a + F(1,0) = 0; + F(1,1) = 1; + F(1,2) = 0; + F(1,3) = 0; + F(1,4) = 0; + + // @kappa'/@a + + F(2,0) = 0; + F(2,1) = 0; + F(2,2) = 1; + F(2,3) = 0; + F(2,4) = 0; + + // @dz'/@a + F(3,0) = 0; + F(3,1) = (drp - dr)* fTanL; + F(3,2) = 0; + F(3,3) = 1; + F(3,4) = fid; + + // @tanl'/@a + F(4,0) = 0; + F(4,1) = 0; + F(4,2) = 0; + F(4,3) = 0; + F(4,4) = 1; +} + diff --git a/Utilities/KalTest/src/geomlib/TStraightTrack.h b/Utilities/KalTest/src/geomlib/TStraightTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..d48c91e144dd923bd37a8fe20190237b46e924a0 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TStraightTrack.h @@ -0,0 +1,75 @@ +#ifndef TSTRAIGHTTRACK_H +#define TSTRAIGHTTRACK_H +//************************************************************************* +//* ====================== +//* TStraightTrack Class +//* ====================== +//* +//* (Description) +//* A class to implement a straight track object. +//* +//* The stragiht track is implemented as the kappa->infinity limit +//* of a helical track: +//* +//* x = x0 + drho * cos(phi0) - t * sin(phi0) +//* y = y0 + drho * sin(phi0) + t * cos(phi0) +//* z = z0 + dz + t * tan(lambda) +//* +//* (Requires) +//* TVTrack, TCylinder, TCircle, TVector3, TMatrixD +//* (Provides) +//* class TStraightTrack +//* (Update Recored) +//* 2003/10/24 K.Fujii Original version. +//* +//************************************************************************* +// + +#include "TVTrack.h" + +//_____________________________________________________________________ +// ----------------------------------- +// Straight Track Class +// ----------------------------------- + +class TStraightTrack : public TVTrack { +public: + + // Ctors and Dtor + + TStraightTrack(Double_t dr = 0., + Double_t phi0 = 0., + Double_t kappa = 1.e-5, + Double_t dz = 0., + Double_t tanl = 0., + Double_t x0 = 0., + Double_t y0 = 0., + Double_t z0 = 0., + Double_t b = 0.); + + TStraightTrack(const TMatrixD &a, const TVector3 & x0, Double_t b = 0.); + + virtual ~TStraightTrack() {} + + // Utility methods + + virtual void MoveTo(const TVector3 &x0to, + Double_t &t, + TMatrixD *F = 0, + TMatrixD *C = 0); + + TVector3 CalcXAt (Double_t phi) const; + TMatrixD CalcDxDa (Double_t phi) const; + TMatrixD CalcDxDphi(Double_t phi) const; + void CalcDapDa (Double_t fid, + Double_t dr, + Double_t drp, + TMatrixD &F) const; + +private: + + ClassDef(TStraightTrack,1) // circle class +}; + +#endif + diff --git a/Utilities/KalTest/src/geomlib/TTube.cxx b/Utilities/KalTest/src/geomlib/TTube.cxx new file mode 100644 index 0000000000000000000000000000000000000000..307ebb1e1bde0910e2abba5c5244fafb0585b09e --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TTube.cxx @@ -0,0 +1,141 @@ +//************************************************************************* +//* ==================== +//* TTube Class +//* ==================== +//* +//* (Description) +//* A class to implement a tube object. +//* (Requires) +//* TVSolid +//* (Provides) +//* class TTube +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include <iostream> +#include "TCircle.h" +#include "TTube.h" +#include "TVTrack.h" + +using namespace std; + +//_____________________________________________________________________ +// ----------------------------------- +// Tube Class +// ----------------------------------- + +ClassImp(TTube) + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate crossing point with helix +// ----------------------------------- +// +Int_t TTube::CalcXingPointWith(const TVTrack &hel, + Double_t &phi, + TVector3 &xx, + Int_t mode, + Double_t eps) const +{ + // This assumes nonzero B field. + // + // Copy helix parameters to local variables. + // + + Double_t dr = hel.GetDrho(); + Double_t fi0 = hel.GetPhi0(); + Double_t cpa = hel.GetKappa(); + Double_t dz = hel.GetDz(); + Double_t tnl = hel.GetTanLambda(); + TVector3 X0 = hel.GetPivot(); + + // + // Check if charge is nonzero. + // + + Int_t chg = (Int_t)TMath::Sign(1.1,cpa); + if (!chg) { + cerr << ">>>> Error >>>> TTube::CalcXingPointWith" << endl + << " Kappa = 0 is invalid for a helix " << endl; + return -1; + } + + // + // Project everything to XY plane and calculate crossing points. + // + + Double_t rho = hel.GetRho(); + Double_t rdr = rho + dr; + Double_t zdz = X0.Z() + dz; + Double_t csf0 = TMath::Cos(fi0); + Double_t snf0 = TMath::Sin(fi0); + Double_t xc = X0.X() + rdr*csf0; + Double_t yc = X0.Y() + rdr*snf0; + Double_t zc = zdz; + + Double_t r = TMath::Abs(rho); + TCircle c(r,xc,yc); + + Double_t rv = GetRout(); + Double_t xcv = GetXc().X(); + Double_t ycv = GetXc().Y(); + TCircle cv(rv,xcv,ycv); + + TVector2 xxp[2]; + Int_t nx = c.CalcXingPointWith(cv, xxp); + + // + // Switch on the number of crossing points. + // + + static const Double_t kPi = TMath::Pi(); + static const Double_t kHalfPi = 0.5*TMath::Pi(); + static const Double_t kTwoPi = 2.0*TMath::Pi(); + + Int_t iret = 0; + switch (nx) { + case 2: // track hitting barrel part + phi = 9999.; + for (Int_t ix=0; ix<nx; ix++) { + Double_t x = xxp[ix].X() - xc; + Double_t y = xxp[ix].Y() - yc; + Double_t dfi = TMath::ATan2(y,x) - fi0 - kHalfPi*(1+chg); + if (!mode) { + while (dfi < -kPi) dfi += kTwoPi; + while (dfi >= kPi) dfi -= kTwoPi; + } else { + Int_t sign = (mode > 0 ? +1 : -1); // (+1,-1) = (fwd,bwd) + while (dfi < 0.) dfi += kTwoPi; + while (dfi >= kTwoPi) dfi -= kTwoPi; + if (sign*chg > 0) dfi -= kTwoPi; + } + if (TMath::Abs(dfi) < TMath::Abs(phi)) { + phi = dfi; + xx.SetXYZ(xxp[ix].X(), xxp[ix].Y(), zc - rho*tnl*dfi); + } + } + if (IsOnBarrel(xx)) return 1; + default: // track hitting end cap part + if (TMath::Abs(tnl) < 0.1) { + return 0; + } else if (tnl < 0.) { + xx.SetZ(GetZmin()); + iret = 2; + } else { + xx.SetZ(GetZmax()); + iret = 3; + } + phi = (zdz-xx.Z())/rho/tnl; + if (TMath::Abs(phi) > kTwoPi) { + return 0; + } else { + xx.SetX(xc - rho*TMath::Cos(phi+fi0)); + xx.SetY(yc - rho*TMath::Sin(phi+fi0)); + if (IsOutside(xx)) return 0; + } + break; + } + return iret; +} diff --git a/Utilities/KalTest/src/geomlib/TTube.h b/Utilities/KalTest/src/geomlib/TTube.h new file mode 100644 index 0000000000000000000000000000000000000000..f10a135e2e29453d52c051b1bea98dda009835e7 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TTube.h @@ -0,0 +1,92 @@ +#ifndef TTUBE_H +#define TTUBE_H +//************************************************************************* +//* ==================== +//* TTube Class +//* ==================== +//* +//* (Description) +//* A class to implement a tube object. +//* (Requires) +//* TVSolid +//* (Provides) +//* class TTube +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TVSolid.h" +#include "TVector3.h" + +class TVTrack; + +//_____________________________________________________________________ +// ----------------------------------- +// Cylinder Class +// ----------------------------------- + +class TTube : public TVSolid { +public: + TTube(Double_t rin = 0., Double_t rout = 1., Double_t hlen = 1., + Double_t xc = 0., Double_t yc = 0, Double_t zc = 0.) + : fRin(rin), fRout(rout), fHalfLen(hlen), fXc(xc,yc,zc) {} + + virtual ~TTube() {} + + virtual Int_t CalcXingPointWith(const TVTrack &hel, + Double_t &phi, + TVector3 &xx, + Int_t mode, + Double_t eps = 1.e-8) const; + + inline virtual Bool_t IsOnBarrel(const TVector3 &xx) const; + inline virtual Bool_t IsOutside (const TVector3 &xx) const; + + inline virtual Double_t GetRin () const { return fRin; } + inline virtual Double_t GetRout () const { return fRout; } + inline virtual const TVector3 & GetXc () const { return fXc; } + inline virtual Double_t GetLength () const; + inline virtual Double_t GetZmin () const; + inline virtual Double_t GetZmax () const; + +private: + Double_t fRin; // inner radius + Double_t fRout; // outer radius + Double_t fHalfLen; // half length + TVector3 fXc; // center + + ClassDef(TTube,1) // TTube class +}; +//======================================================= +// inline functions +//======================================================= + +Double_t TTube::GetLength () const +{ + return 2*fHalfLen; +} + +Double_t TTube::GetZmin() const +{ + return fXc.Z() - fHalfLen; +} + +Double_t TTube::GetZmax() const +{ + return fXc.Z() + fHalfLen; +} + +Bool_t TTube::IsOnBarrel(const TVector3 &xx) const +{ + return (xx.Z() >= GetZmin() && xx.Z() <= GetZmax()); +} + +Bool_t TTube::IsOutside(const TVector3 &xx) const +{ + Double_t r = (xx-fXc).Perp(); + Double_t z = xx.Z(); + return (r < fRin || r > fRout || z < GetZmin() || z > GetZmax()); +} +#endif + diff --git a/Utilities/KalTest/src/geomlib/TVCurve.cxx b/Utilities/KalTest/src/geomlib/TVCurve.cxx new file mode 100644 index 0000000000000000000000000000000000000000..38b3fcc7c74981898e1b1026f81ce0a902b7c0f0 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TVCurve.cxx @@ -0,0 +1,22 @@ +//************************************************************************* +//* ==================== +//* TVCurve Class +//* ==================== +//* +//* (Description) +//* This is the base class for various curves. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVCurve +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TVCurve.h" +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any curve +// ----------------------------------- +ClassImp(TVCurve) diff --git a/Utilities/KalTest/src/geomlib/TVCurve.h b/Utilities/KalTest/src/geomlib/TVCurve.h new file mode 100644 index 0000000000000000000000000000000000000000..040912825ded5dfdeb1f52254aa75508c9343595 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TVCurve.h @@ -0,0 +1,32 @@ +#ifndef TVCURVE_H +#define TVCURVE_H +//************************************************************************* +//* ==================== +//* TVCurve Class +//* ==================== +//* +//* (Description) +//* This is the base class for various curves. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVCurve +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TObject.h" +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any curve +// ----------------------------------- + +class TVCurve : public TObject { +public: +private: + + ClassDef(TVCurve,1) // Base class for any curve +}; + +#endif diff --git a/Utilities/KalTest/src/geomlib/TVSolid.cxx b/Utilities/KalTest/src/geomlib/TVSolid.cxx new file mode 100644 index 0000000000000000000000000000000000000000..afc58e5ca93e4ae8b5cd4f957ad559dd90ab74b5 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TVSolid.cxx @@ -0,0 +1,23 @@ +//************************************************************************* +//* ==================== +//* TVSolid Class +//* ==================== +//* +//* (Description) +//* This is the base class for various solids. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVSolid +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TVSolid.h" +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any solid +// ----------------------------------- + +ClassImp(TVSolid) diff --git a/Utilities/KalTest/src/geomlib/TVSolid.h b/Utilities/KalTest/src/geomlib/TVSolid.h new file mode 100644 index 0000000000000000000000000000000000000000..83b4f57e20505c8bda69f27297ec0e604f2957b3 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TVSolid.h @@ -0,0 +1,32 @@ +#ifndef TVSOLID_H +#define TVSOLID_H +//************************************************************************* +//* ==================== +//* TVSolid Class +//* ==================== +//* +//* (Description) +//* This is the base class for various solids. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVSolid +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TObject.h" +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any solid +// ----------------------------------- + +class TVSolid : public TObject { +public: +private: + + ClassDef(TVSolid,1) // Base class for any solid +}; + +#endif diff --git a/Utilities/KalTest/src/geomlib/TVSurface.cxx b/Utilities/KalTest/src/geomlib/TVSurface.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3294ab991b2cf9def7125ec4a1d307025a9e808d --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TVSurface.cxx @@ -0,0 +1,127 @@ +//************************************************************************* +//* ==================== +//* TVSurface Class +//* ==================== +//* +//* (Description) +//* This is the base class for various surfaces. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVSurface +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* 2005/02/23 K.Fujii Added new methods, Compare() and +//* GetSortingPolicy(). +//* +//************************************************************************* +// +#include <iostream> +#include "TVSurface.h" +#include "TVTrack.h" + +using namespace std; + +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any surface +// ----------------------------------- + +ClassImp(TVSurface) + +//_____________________________________________________________________ +// ----------------------------------- +// Calculate crossing point with track +// ----------------------------------- +// +Int_t TVSurface::CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps) const +{ + return CalcXingPointWith(hel,xx,phi,0,eps); +} + +Int_t TVSurface::CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps) const +{ + + static const Int_t maxcount = 100; + static const Double_t initlambda = 1.e-10; + static const Double_t lambdaincr = 10.; + static const Double_t lambdadecr = 0.1; + + xx = hel.CalcXAt(phi); + + Double_t lastphi = phi; + Double_t lasts = 99999; + Double_t lambda = initlambda; + + TVector3 lastxx = xx; + Int_t count = 0; + + Double_t s; + + while (1) { + if (count > maxcount) { + s = lasts; + phi = lastphi; + xx = lastxx; +#if 0 + cerr << "TVSurface::CalcXingPointWith:" + << " --- Loop count limit reached ---------- " << endl + << " phi : " << phi << endl + << " x : " << xx.X() << " " + << xx.Y() << " " + << xx.Z() << endl + << " s : " << s << endl + << " lambda : " << lambda << endl; +#endif + return 0; + } + count++; + s = CalcS(xx); + if (TMath::Abs(s) < eps) break; + if (TMath::Abs(s) < TMath::Abs(lasts)) { + lasts = s; + lastphi = phi; + lastxx = xx; + lambda *= lambdadecr; + } else { + s = lasts; + phi = lastphi; + xx = lastxx; + lambda *= lambdaincr; + } + TMatrixD dsdx = CalcDSDx(xx); + TMatrixD dxdphi = hel.CalcDxDphi(phi); + TMatrixD dsdphi = dsdx * dxdphi; + Double_t denom = (1 + lambda) * dsdphi(0,0); + phi -= s / denom; + xx = hel.CalcXAt(phi); + } + + if( mode!=0 ){ // (+1,-1) = (fwd,bwd) + const Int_t chg = (Int_t)TMath::Sign(1.1, hel.GetKappa()); + if( chg*phi*mode > 0){ + return 0; + } + } + + return (IsOnSurface(xx) ? 1 : 0); +} + +//_____________________________________________________________________ +// ----------------------------------- +// Compare to Surfaces +// ----------------------------------- +// +Int_t TVSurface::Compare(const TObject *obj) const +{ + Double_t me = GetSortingPolicy(); + Double_t you = dynamic_cast<const TVSurface *>(obj)->GetSortingPolicy(); + return me < you ? -1 : (me > you ? +1 : 0); +} diff --git a/Utilities/KalTest/src/geomlib/TVSurface.h b/Utilities/KalTest/src/geomlib/TVSurface.h new file mode 100644 index 0000000000000000000000000000000000000000..be0a085a4ab3a00d09b2f5dbfe533f670d937e4a --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TVSurface.h @@ -0,0 +1,68 @@ +#ifndef TVSURFACE_H +#define TVSURFACE_H +//************************************************************************* +//* ==================== +//* TVSurface Class +//* ==================== +//* +//* (Description) +//* This is the base class for various solids. +//* (Requires) +//* TObject; +//* (Provides) +//* class TVSurface +//* (Update Recored) +//* 2003/10/03 K.Fujii Original version. +//* 2005/02/23 K.Fujii Added new methods, Compare() and +//* GetSortingPolicy(). +//* +//* 2011/06/17 D.Kamai Added new method, GetOutwardNormal() +//* +//************************************************************************* +// +#include "TObject.h" +#include "TMatrixD.h" +#include "TVector3.h" + +class TVTrack; +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any surface +// ----------------------------------- + +class TVSurface : public TObject { +public: + + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Double_t eps = 1.e-8) const; + virtual Int_t CalcXingPointWith(const TVTrack &hel, + TVector3 &xx, + Double_t &phi, + Int_t mode, + Double_t eps = 1.e-8) const; + + virtual Double_t CalcS (const TVector3 &xx) const = 0; + virtual TMatrixD CalcDSDx (const TVector3 &xx) const = 0; + virtual Bool_t IsOnSurface (const TVector3 &xx) const = 0; + virtual Bool_t IsOutside (const TVector3 &xx) const = 0; + inline virtual TVector3 GetOutwardNormal (const TVector3 &xx) const; + + virtual Double_t GetSortingPolicy () const = 0; + + virtual Int_t Compare (const TObject *obj) const; + virtual Bool_t IsSortable() const { return kTRUE; } + +private: + + ClassDef(TVSurface,1) // Base class for any surface +}; + +TVector3 TVSurface::GetOutwardNormal(const TVector3 &xx) const +{ + TMatrixD dsdx = CalcDSDx(xx); + return TVector3(dsdx(0,0),dsdx(0,1),dsdx(0,2)).Unit(); +} + +#endif diff --git a/Utilities/KalTest/src/geomlib/TVTrack.cxx b/Utilities/KalTest/src/geomlib/TVTrack.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4eb727e25418ed68d7f3d501d90c3f32372e096c --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TVTrack.cxx @@ -0,0 +1,61 @@ +//************************************************************************* +//* =============== +//* TVTrack Class +//* =============== +//* +//* (Description) +//* A class to implement a track object. +//* (Requires) +//* TVCurve +//* (Provides) +//* class TVTrack +//* (Update Recored) +//* 2003/10/24 K.Fujii Original version. +//* +//************************************************************************* +// + +#include <iostream> +#include "TVTrack.h" + +using namespace std; +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) +#else +const Double_t TVTrack::kLightVelocity = 2.99792458e8; +const Double_t TVTrack::kGiga = 1.e9; +const Double_t TVTrack::kInfinity = 1.e20; +#endif + +//_____________________________________________________________________ +// ----------------------------------- +// Track Class +// ----------------------------------- +// +//_____________________________________________________________________ +// -------------- +// Ctors and Dtor +// -------------- +// + +TVTrack::TVTrack(Double_t dr, + Double_t phi0, + Double_t kappa, + Double_t dz, + Double_t tanl, + Double_t x0, + Double_t y0, + Double_t z0, + Double_t b) + : fDrho(dr), fPhi0(phi0), fKappa(kappa), fDz(dz), fTanL(tanl), + fX0(x0,y0,z0) +{ + SetMagField(b); +} + +TVTrack::TVTrack(const TMatrixD &a, const TVector3 & x0, Double_t b) + : fDrho(a(0,0)), fPhi0(a(1,0)), fKappa(a(2,0)), + fDz(a(3,0)), fTanL(a(4,0)), + fX0(x0) +{ + SetMagField(b); +} diff --git a/Utilities/KalTest/src/geomlib/TVTrack.h b/Utilities/KalTest/src/geomlib/TVTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..9e8f0f4548363a1b9aa6573a094863186e221413 --- /dev/null +++ b/Utilities/KalTest/src/geomlib/TVTrack.h @@ -0,0 +1,150 @@ +#ifndef TVTRACK_H +#define TVTRACK_H +//************************************************************************* +//* =============== +//* TVTrack Class +//* =============== +//* +//* (Description) +//* This is the base class for various tracks. +//* (Requires) +//* TVCurve; +//* (Provides) +//* class TVTrack +//* (Update Recored) +//* 2003/10/24 K.Fujii Original version. +//* 2005/08/14 K.Fujii Added IsInB(). +//* +//************************************************************************* +// + +#include "TVector3.h" +#include "TMatrixD.h" + +#if 1 +#include "TMath.h" +#include "TCollection.h" +#endif + +#include "TVCurve.h" + +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for any track +// ----------------------------------- + +class TVTrack : public TVCurve { +public: + // Ctors and Dtor + + TVTrack(Double_t dr = 0., + Double_t phi0 = 0., + Double_t kappa = 1.e-5, + Double_t dz = 0., + Double_t tanl = 0., + Double_t x0 = 0., + Double_t y0 = 0., + Double_t z0 = 0., + Double_t b = 30.); + + TVTrack(const TMatrixD &a, const TVector3 & x0, Double_t b = 30.); + + virtual ~TVTrack() {} + + // Utility methods + + virtual void MoveTo(const TVector3 &x0to, + Double_t &fid, + TMatrixD *F = 0, + TMatrixD *C = 0) = 0; + + virtual void MoveTo(const TVector3 &x0to, + Double_t &fid, + TMatrixD &C) + { + Int_t sdim = C.GetNrows(); + TMatrixD F(sdim, sdim); + MoveTo(x0to,fid,&F,&C); + } + + inline virtual void ScatterBy(Double_t dphi, Double_t dtnl) + { + fPhi0 += dphi; + fKappa += (fKappa*fTanL/(1+fTanL*fTanL)) * dtnl; + fTanL += dtnl; + } + + inline virtual void PutInto(TMatrixD &sv) const + { + sv(0,0) = fDrho; + sv(1,0) = fPhi0; + sv(2,0) = fKappa; + sv(3,0) = fDz; + sv(4,0) = fTanL; + } + + virtual TVector3 CalcXAt (Double_t phi) const = 0; + virtual TMatrixD CalcDxDa (Double_t phi) const = 0; + virtual TMatrixD CalcDxDphi(Double_t phi) const = 0; + virtual void CalcDapDa (Double_t fid, + Double_t dr, + Double_t drp, + TMatrixD &F) const = 0; + + // Getters + + inline virtual Double_t GetDrho () const { return fDrho; } + inline virtual Double_t GetPhi0 () const { return fPhi0; } + inline virtual Double_t GetKappa () const { return fKappa; } + inline virtual Double_t GetDz () const { return fDz; } + inline virtual Double_t GetTanLambda() const { return fTanL; } + inline virtual const TVector3 & GetPivot () const { return fX0; } + inline virtual Double_t GetRho () const { return fAlpha/fKappa; } + inline virtual Double_t GetPtoR () const { return fAlpha; } + + // Setters + + inline virtual void SetTo(const TMatrixD &sv, const TVector3 &x0) + { + fDrho = sv(0,0); + fPhi0 = sv(1,0); + fKappa = sv(2,0); + fDz = sv(3,0); + fTanL = sv(4,0); + fX0 = x0; + } + + inline virtual void SetMagField(Double_t b) + { + // // units: mm, sec, Tesla + if (b != 0.) fAlpha = kGiga/kLightVelocity*1000./b; + // units: cm, sec, kGaus + //if (b != 0.) fAlpha = kGiga/kLightVelocity*100./(b/10); + else fAlpha = kInfinity; + } + + inline virtual Bool_t IsInB() const { return fAlpha < kInfinity ? kTRUE : kFALSE; } + +protected: + Double_t fDrho; // drho + Double_t fPhi0; // phi0 + Double_t fKappa; // kappa + Double_t fDz; // dz + Double_t fTanL; // tanl + TVector3 fX0; // pivot + Double_t fAlpha; // alpha + +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) + static const Double_t kLightVelocity = 2.99792458e8; //! light velocity [m/sec] + static const Double_t kGiga = 1.0e9; //! Giga = 10^{9} + static const Double_t kInfinity = 1.e+20; //! infinity +#else + static const Double_t kLightVelocity; //! light velocity [m/sec] + static const Double_t kGiga; //! Giga = 10^{9} + static const Double_t kInfinity; //! infinity +#endif + + ClassDef(TVTrack,1) // Base class for any track +}; + +#endif diff --git a/Utilities/KalTest/src/kallib/Imakefile b/Utilities/KalTest/src/kallib/Imakefile new file mode 100644 index 0000000000000000000000000000000000000000..f6a24db463e62180649eaff310475360cdc06887 --- /dev/null +++ b/Utilities/KalTest/src/kallib/Imakefile @@ -0,0 +1,54 @@ +#include "../../conf/makejsf.tmpl" + +LDFLAGS = /* $(GLIBS) */ + +INSTALLDIR = ../.. +SOREV = 2005.01 +PACKAGENAME = S4Kalman + +SRCS = TKalMatrix.$(SrcSuf) \ + TVKalSite.$(SrcSuf) \ + TVKalState.$(SrcSuf) \ + TVKalSystem.$(SrcSuf) + +OBJS = $(subst .$(SrcSuf),.$(ObjSuf),$(SRCS)) \ + $(PACKAGENAME)Dict.$(ObjSuf) + +HDRS = $(subst .$(SrcSuf),.h,$(SRCS)) + +DICTNAME = $(PACKAGENAME)Dict + +LIBNAME = $(PACKAGENAME) + +SONAME = lib$(LIBNAME).$(DllSuf).$(SOREV) + +LIBINSTALLDIR = $(INSTALLDIR)/lib +INCINSTALLDIR = $(INSTALLDIR)/include +INCPATH = -I. -I$(INCINSTALLDIR) +CXXFLAGS += $(INCPATH) -O0 -g +SHLIBLDFLAGS = $(DYLIBFLAGS) + +all:: $(SONAME) + +SharedLibraryTarget($(LIBNAME),$(SOREV),$(OBJS),.,.) + +InstallSharedLibrary($(LIBNAME),$(SOREV),$(LIBINSTALLDIR)) + +InstallMultipleFlags($(HDRS),$(INCINSTALLDIR),-m 644) + +clean:: + @rm -f $(OBJS) core *.$(DllSuf) $(DICTNAME).$(SrcSuf) $(DICTNAME).h + +depend:: $(SRCS) $(HDRS) + for i in $(SRCS); do \ + rmkdepend -a -- $(CXXFLAGS) $(INCPATH) $(DEPENDFILES) -- $$i; done + +distclean:: clean + @rm -f $(OBJS) core *.$(DllSuf) *.$(DylibSuf) + @rm -f $(DICTNAME).$(SrcSuf) $(DICTNAME).h *~ + @rm -f $(SONAME) *.root Makefile + +$(DICTNAME).$(SrcSuf): $(HDRS) LinkDef.h + @echo "Generating dictionary ..." + rootcint -f $(DICTNAME).$(SrcSuf) \ + -c -I$(INCINSTALLDIR) $(HDRS) LinkDef.h diff --git a/Utilities/KalTest/src/kallib/LinkDef.h b/Utilities/KalTest/src/kallib/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..38cd360482aae2e6736d756bafe73f2d98b6478a --- /dev/null +++ b/Utilities/KalTest/src/kallib/LinkDef.h @@ -0,0 +1,12 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class TKalMatrix+; +#pragma link C++ class TVKalSite+; +#pragma link C++ class TVKalState+; +#pragma link C++ class TVKalSystem+; + +#endif diff --git a/Utilities/KalTest/src/kallib/TKalMatrix.cxx b/Utilities/KalTest/src/kallib/TKalMatrix.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f5789334c25f2eba6697983ec8b93a3c4a44fb6b --- /dev/null +++ b/Utilities/KalTest/src/kallib/TKalMatrix.cxx @@ -0,0 +1,148 @@ +//************************************************************************* +//* ==================== +//* TKalMatrix Class +//* ==================== +//* +//* (Description) +//* This is the base class for matrix used by Kalman filter. +//* (Requires) +//* TMatrixD +//* (Provides) +//* class TKalMatrix +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* +//************************************************************************* +// +#include <iostream> +#include <iomanip> +#include "TString.h" +#include "TKalMatrix.h" + +//_____________________________________________________________________ +// ------------------------------ +// A Wrapper for TMatrixD +// ------------------------------ +// +ClassImp(TKalMatrix) + +//------------------------------------------------------- +// Ctors and Dtor +//------------------------------------------------------- + +TKalMatrix::TKalMatrix(Int_t rowdim, Int_t coldim) + :TMatrixD(rowdim, coldim) +{ +} + +TKalMatrix::TKalMatrix(const TKalMatrix &orig) + :TMatrixD(orig) +{ +} + +TKalMatrix::TKalMatrix(const TMatrixD &orig) + :TMatrixD(orig) +{ +} + +TKalMatrix::TKalMatrix(TMatrixD::EMatrixCreatorsOp1 op, + const TKalMatrix &prototype) + :TMatrixD(op, prototype) +{ +} + +TKalMatrix::TKalMatrix(TMatrixD::EMatrixCreatorsOp1 op, + const TMatrixD &prototype) + :TMatrixD(op, prototype) +{ +} + +TKalMatrix::TKalMatrix(const TKalMatrix &a, + TMatrixD::EMatrixCreatorsOp2 op, + const TKalMatrix &b) + :TMatrixD(a, op, b) +{ +} + +TKalMatrix::TKalMatrix(const TMatrixD &a, + TMatrixD::EMatrixCreatorsOp2 op, + const TMatrixD &b) + :TMatrixD(a, op, b) +{ +} + +TKalMatrix::TKalMatrix(const TVector3 &v) + :TMatrixD(TKalMatrix::ToKalMat(v)) +{ +} + +//------------------------------------------------------- +// Print +//------------------------------------------------------- + +void TKalMatrix::DebugPrint(Option_t *opt, Int_t ncolsps) const +{ + using namespace std; + + Int_t ncols = GetNcols(); + Int_t nrows = GetNrows(); + Int_t nsheets = (ncols-1)/ncolsps + 1; + Int_t lastcw = ncols - ncolsps*(nsheets-1); + Int_t ns = 0; + + TString title(opt); + TString off(title.Length()); + for (Int_t c=0; c<title.Length(); c++) off += " "; + + for (Int_t sc = 1; sc <= ncols; sc += ncolsps) { + ns++; + if (ns == 1) cerr << title << "+-"; + if (ns == nsheets) { + for (Int_t ib = 1; ib <= 11*lastcw; ib++) cerr << " "; + cerr << "-+" << endl; + } else { + cerr << endl; + } + for (Int_t i = 1; i <= nrows; i++) { + if (ns == 1) cerr << off << "| "; + for (Int_t j = sc; j < sc+ncolsps && j <= ncols; j++) { + cerr // << setiosflags(ios::scientific) + << setw(11) << setprecision(4) + << (*this)(i-1,j-1); + if (j == ncols) cerr << " |"; + } + cerr << endl; + } + if (ns == 1) cerr << off << "+-"; + if (ns == nsheets) { + for (Int_t ib = 1; ib <= 11*lastcw; ib++) cerr << " "; + cerr << "-+" << endl; + } else { + cerr << endl; + } + } +} + +//------------------------------------------------------- +// VectorToMatrix +//------------------------------------------------------- + +TKalMatrix TKalMatrix::ToKalMat(const TVector3 &a) +{ + TKalMatrix md(3,1); + md(0,0) = a.x(); + md(1,0) = a.y(); + md(2,0) = a.z(); + return md; +} + +//------------------------------------------------------- +// MatrixToVector +//------------------------------------------------------- + +TVector3 TKalMatrix::ToThreeVec(const TMatrixD &a) +{ + TVector3 v; + v.SetXYZ(a(0,0), a(1,0),a(2,0)); + return v; +} diff --git a/Utilities/KalTest/src/kallib/TKalMatrix.h b/Utilities/KalTest/src/kallib/TKalMatrix.h new file mode 100644 index 0000000000000000000000000000000000000000..947b92c02f0b96eb6f990a1e3da3acc1888bcc05 --- /dev/null +++ b/Utilities/KalTest/src/kallib/TKalMatrix.h @@ -0,0 +1,58 @@ +#ifndef TKALMATRIX_H +#define TKALMATRIX_H +//************************************************************************* +//* =================== +//* TKalMatrix Class +//* =================== +//* +//* (Description) +//* TKalMatrix is a wrapper of TMatrixD. +//* (Requires) +//* TMatrixD +//* (Provides) +//* class TKalMatrix +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* +//************************************************************************* + +#include "TMatrixD.h" +#include "TVector3.h" +//_____________________________________________________________________ +// ------------------------------ +// Base Class for matrix used by Kalman filter +// ------------------------------ +// +class TKalMatrix : public TMatrixD { +public: + TKalMatrix(Int_t rowdim = 1, Int_t coldim = 1); + + TKalMatrix(const TKalMatrix &orig); + TKalMatrix(const TMatrixD &orig); + + TKalMatrix(TMatrixD::EMatrixCreatorsOp1 op, + const TKalMatrix &prototype); + TKalMatrix(TMatrixD::EMatrixCreatorsOp1 op, + const TMatrixD &prototype); + + TKalMatrix(const TKalMatrix &a, + TMatrixD::EMatrixCreatorsOp2 op, + const TKalMatrix &b) ; + TKalMatrix(const TMatrixD &a, + TMatrixD::EMatrixCreatorsOp2 op, + const TMatrixD &b) ; + + TKalMatrix(const TVector3 &v); + + virtual ~TKalMatrix() {} + + virtual void DebugPrint(Option_t *opt = "", Int_t nc = 5) const; + + static TKalMatrix ToKalMat (const TVector3 &vec); + static TVector3 ToThreeVec(const TMatrixD &mat); + +private: + + ClassDef(TKalMatrix,1) // Base class for Kalman matrix +}; +#endif diff --git a/Utilities/KalTest/src/kallib/TVKalSite.cxx b/Utilities/KalTest/src/kallib/TVKalSite.cxx new file mode 100644 index 0000000000000000000000000000000000000000..be6dcbe770e15503994c58b570531040ca4d9d52 --- /dev/null +++ b/Utilities/KalTest/src/kallib/TVKalSite.cxx @@ -0,0 +1,187 @@ +//************************************************************************* +//* ==================== +//* TVKalSite Class +//* ==================== +//* +//* (Description) +//* This is the base class for measurement vector used by Kalman filter. +//* (Requires) +//* TKalMatrix +//* TVKalState +//* (Provides) +//* class TVKalSite +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2009/06/18 K.Fujii Implement inverse Kalman filter +//* +//************************************************************************* +// + +#include <iostream> +#include <cstdlib> +#include "TVKalSite.h" +#include "TVKalState.h" + +//_____________________________________________________________________ +// ------------------------------ +// Base Class for measurement vector used by Kalman filter +// ------------------------------ +// +ClassImp(TVKalSite) + +TVKalSite::TVKalSite(Int_t m, Int_t p) + :TObjArray(2), + TAttLockable(), + fCurStatePtr(0), + fM(m,1), + fV(m,m), + fH(m,p), + fHt(p,m), + fResVec(m,1), + fR(m,m), + fDeltaChi2(0.) +{ + // Create fStateVector at constractor of concreate class: + // SetStateVector(new TXXXKalmanStateVector(.....)) +} + +TVKalSite::~TVKalSite() +{ +} + +//--------------------------------------------------------------- +// Filter +//--------------------------------------------------------------- + +Bool_t TVKalSite::Filter() +{ + // prea and preC should be preset by TVKalState::Propagate() + TVKalState &prea = GetState(TVKalSite::kPredicted); + TKalMatrix h = fM; + if (!CalcExpectedMeasVec(prea,h)) return kFALSE; + TKalMatrix pull = fM - h; + TKalMatrix preC = GetState(TVKalSite::kPredicted).GetCovMat(); + + // Calculate fH and fHt + + if (!CalcMeasVecDerivative(prea,fH)) return kFALSE; + fHt = TKalMatrix(TKalMatrix::kTransposed, fH); + + // Calculate covariance matrix of residual + + TKalMatrix preR = fV + fH * preC * fHt; + TKalMatrix preRinv = TKalMatrix(TKalMatrix::kInverted, preR); + + // Calculate kalman gain matrix + + TKalMatrix preCinv = TKalMatrix(TKalMatrix::kInverted, preC); + TKalMatrix G = TKalMatrix(TKalMatrix::kInverted, fV); + + // Calculate filtered state vector + + TKalMatrix curCinv = preCinv + fHt * G * fH; + TKalMatrix curC = TKalMatrix(TKalMatrix::kInverted, curCinv); + TKalMatrix K = curC * fHt * G; + + TKalMatrix Kpull = K * pull; + TKalMatrix Kpullt = TKalMatrix(TKalMatrix::kTransposed,Kpull); + TKalMatrix av = prea + Kpull; + TVKalState &a = CreateState(av,curC,TVKalSite::kFiltered); + TVKalState *aPtr = &a; + + Add(aPtr); + SetOwner(); + + // Calculate chi2 increment + + fR = fV - fH * curC *fHt; + if (!CalcExpectedMeasVec(a,h)) return kFALSE; + fResVec = fM - h; + TKalMatrix curResVect = TKalMatrix(TKalMatrix::kTransposed, fResVec); + fDeltaChi2 = (curResVect * G * fResVec + Kpullt * preCinv * Kpull)(0,0); + + if (IsAccepted()) return kTRUE; + else return kFALSE; +} + +//--------------------------------------------------------------- +// Smooth +//--------------------------------------------------------------- + +void TVKalSite::Smooth(TVKalSite &pre) +{ + if (&GetState(TVKalSite::kSmoothed)) return; + + TVKalState &cura = GetState(TVKalSite::kFiltered); + TVKalState &prea = pre.GetState(TVKalSite::kPredicted); + TVKalState &sprea = pre.GetState(TVKalSite::kSmoothed); + + TKalMatrix curC = cura.GetCovMat(); + TKalMatrix curFt = cura.GetPropMat("T"); + TKalMatrix preC = prea.GetCovMat(); + TKalMatrix spreC = sprea.GetCovMat(); + TKalMatrix preCinv = TKalMatrix(TKalMatrix::kInverted, preC); + TKalMatrix curA = curC * curFt * preCinv; + TKalMatrix curAt = TKalMatrix(TKalMatrix::kTransposed, curA); + TKalMatrix scurC = curC + curA * (spreC - preC) * curAt; + + TKalMatrix sv = cura + curA * (sprea - prea); + Add(&CreateState(sv,scurC,TVKalSite::kSmoothed)); + SetOwner(); + + // Update residual vector + + fR = fV - fH * scurC *fHt; + fResVec -= fH * (sv - cura); + TKalMatrix curResVect = TKalMatrix(TKalMatrix::kTransposed, fResVec); + TKalMatrix curRinv = TKalMatrix(TKalMatrix::kInverted, fR); + fDeltaChi2 = (curResVect * curRinv * fResVec)(0,0); +} + +//--------------------------------------------------------------- +// InvFilter +//--------------------------------------------------------------- + +void TVKalSite::InvFilter() +{ + if (&GetState(TVKalSite::kInvFiltered)) return; + + TVKalState &sa = GetState(TVKalSite::kSmoothed); + TKalMatrix pull = fResVec; + + TKalMatrix sC = sa.GetCovMat(); + TKalMatrix sR = fH * sC * fHt - fV; + TKalMatrix sRinv = TKalMatrix(TKalMatrix::kInverted, sR); + TKalMatrix Kstar = sC * fHt * sRinv; + TKalMatrix svstar = sa + Kstar * pull; + TKalMatrix sCinv = TKalMatrix(TKalMatrix::kInverted, sC); + TKalMatrix G = TKalMatrix(TKalMatrix::kInverted, fV); + TKalMatrix Cstar = TKalMatrix(TKalMatrix::kInverted, sCinv + fHt * G * fH); + Add(&CreateState(svstar,Cstar,TVKalSite::kInvFiltered)); + SetOwner(); +} + +//--------------------------------------------------------------- +// Getters +//--------------------------------------------------------------- + +TKalMatrix TVKalSite::GetResVec (TVKalSite::EStType t) +{ + using namespace std; + TVKalState &a = GetState(t); + TVKalState &sa = (&GetState(TVKalSite::kSmoothed) != 0 + ? GetState(TVKalSite::kSmoothed) + : GetState(TVKalSite::kFiltered)); + if (!&a || !&sa) { + cerr << ":::::: ERROR in TVKalSite::GetResVec(EStType) " << endl + << " Invalid states requested" << endl + << " &a = " << &a << " &sa = " << &sa << endl + << " Abort!" << endl; + ::abort(); + } + if (&a == &sa) { + return fResVec; + } else { + return (fResVec - fH * (a - sa)); + } +} diff --git a/Utilities/KalTest/src/kallib/TVKalSite.h b/Utilities/KalTest/src/kallib/TVKalSite.h new file mode 100644 index 0000000000000000000000000000000000000000..d00345af335c708b91b79bacb42aafd3cf97fd2a --- /dev/null +++ b/Utilities/KalTest/src/kallib/TVKalSite.h @@ -0,0 +1,124 @@ +#ifndef TVKALSITE_H +#define TVKALSITE_H +//************************************************************************* +//* =================== +//* TVKalSite Class +//* =================== +//* +//* (Description) +//* This is the base class for measurement vector used by Kalman filter. +//* (Requires) +//* TKalMatrix +//* (Provides) +//* class TVKalSite +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2005/02/23 A.Yamaguchi Added getter and setter for a new static +//* data member, fgKalSysPtr. +//* 2005/08/25 A.Yamaguchi Removed getter and setter for a new static +//* data member, fgKalSysPtr. +//* 2009/06/18 K.Fujii Implement inverse Kalman filter +//* +//************************************************************************* +// +#include "TObjArray.h" + +#include "TAttLockable.h" +#include "TKalMatrix.h" +#include "TVKalState.h" + +class TVKalSystem; + +//_____________________________________________________________________ +// ------------------------------ +// Base Class for Kalman measurement vector +// ------------------------------ +// +class TVKalSite : public TObjArray, public TAttLockable { +friend class TVKalSystem; + +public: + enum EStType { kPredicted = 0, + kFiltered, + kSmoothed, + kInvFiltered }; +public: + // Ctors and Dtor + + TVKalSite(Int_t m = 2, Int_t p = 6); + virtual ~TVKalSite(); + + // Utility Methods + + virtual Int_t CalcExpectedMeasVec (const TVKalState &a, + TKalMatrix &m) = 0; + virtual Int_t CalcMeasVecDerivative(const TVKalState &a, + TKalMatrix &H) = 0; + virtual Bool_t IsAccepted() = 0; + + virtual void DebugPrint() const = 0; + + virtual Bool_t Filter(); + + virtual void Smooth(TVKalSite &pre); + + virtual void InvFilter(); + + inline void Add(TObject *obj); + + // Getters + + inline virtual Int_t GetDimension() const { return fM.GetNrows(); } + inline virtual TVKalState & GetCurState () { return *fCurStatePtr; } + inline virtual TVKalState & GetCurState () const { return *fCurStatePtr; } + inline virtual TVKalState & GetState (EStType t); + inline virtual TKalMatrix & GetMeasVec () { return fM; } + inline virtual TKalMatrix & GetMeasNoiseMat () { return fV; } + inline virtual TKalMatrix & GetResVec () { return fResVec; } + inline virtual TKalMatrix & GetCovMat () { return fR; } + inline virtual Double_t GetDeltaChi2() const { return fDeltaChi2; } + virtual TKalMatrix GetResVec (EStType t); + +private: + // Private utility methods + + virtual TVKalState & CreateState(const TKalMatrix &sv, Int_t type = 0) = 0; + virtual TVKalState & CreateState(const TKalMatrix &sv, const TKalMatrix &c, + Int_t type = 0) = 0; + +private: + + // private data member ------------------------------------------- + + TVKalState *fCurStatePtr; // pointer to current best state + TKalMatrix fM; // measurement vector: M(m,1) + TKalMatrix fV; // noise matrix: M(m,m) + TKalMatrix fH; // H = (@h/@a): M(m,p) + TKalMatrix fHt; // H^t = (@h/@a)^t: M(p,m) + TKalMatrix fResVec; // m - h(a): M(m,1) + TKalMatrix fR; // covariance matrix: M(m,m) + Double_t fDeltaChi2; // chi2 increment + + ClassDef(TVKalSite,1) // Base class for measurement vector objects +}; + +//======================================================= +// inline functions +//======================================================= + +void TVKalSite::Add(TObject *obj) +{ + TObjArray::Add(obj); + fCurStatePtr = static_cast<TVKalState *>(obj); + fCurStatePtr->SetSitePtr(this); +} + +TVKalState & TVKalSite::GetState(TVKalSite::EStType t) +{ + TVKalState *ap = 0; + if (t >= 0 && t < GetEntries()) { + ap = static_cast<TVKalState *>(UncheckedAt(t)); + } + return *ap; +} +#endif diff --git a/Utilities/KalTest/src/kallib/TVKalState.cxx b/Utilities/KalTest/src/kallib/TVKalState.cxx new file mode 100644 index 0000000000000000000000000000000000000000..bd509381744491e0529dcf185189b7eeba92df71 --- /dev/null +++ b/Utilities/KalTest/src/kallib/TVKalState.cxx @@ -0,0 +1,120 @@ +//************************************************************************* +//* ==================== +//* TVKalState Class +//* ==================== +//* +//* (Description) +//* This is the base class for state vector used by Kalman filter. +//* (Requires) +//* TKalMatrix +//* (Provides) +//* class TVKalState +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version +//* +//************************************************************************* +// +#include "TVKalState.h" +#include "TVKalSite.h" +//_____________________________________________________________________ +// ------------------------------ +// Base Class for measurement vector used by Kalman filter +// ------------------------------ +// +ClassImp(TVKalState) + +TVKalState::TVKalState(Int_t type, Int_t p) + : TKalMatrix(p,1), + fType(type), + fSitePtr(0), + fF(p,p), + fFt(p,p), + fQ(p,p), + fC(p,p) +{ + fF.UnitMatrix(); + fFt.UnitMatrix(); +} + +TVKalState::TVKalState(const TKalMatrix &sv, + Int_t type, Int_t p) + : TKalMatrix(sv), + fType(type), + fSitePtr(0), + fF(p,p), + fFt(p,p), + fQ(p,p), + fC(p,p) +{ + fF.UnitMatrix(); + fFt.UnitMatrix(); +} + +TVKalState::TVKalState(const TKalMatrix &sv, const TKalMatrix &c, + Int_t type, Int_t p) + : TKalMatrix(sv), + fType(type), + fSitePtr(0), + fF(p,p), + fFt(p,p), + fQ(p,p), + fC(c) +{ + fF.UnitMatrix(); + fFt.UnitMatrix(); +} + +TVKalState::TVKalState(const TKalMatrix &sv, const TVKalSite &site, + Int_t type, Int_t p) + : TKalMatrix(sv), + fType(type), + fSitePtr((TVKalSite *)&site), + fF(p,p), + fFt(p,p), + fQ(p,p), + fC(p,p) +{ + fF.UnitMatrix(); + fFt.UnitMatrix(); +} + +TVKalState::TVKalState(const TKalMatrix &sv, const TKalMatrix &c, + const TVKalSite &site, Int_t type, Int_t p) + : TKalMatrix(sv), + fType(type), + fSitePtr((TVKalSite *)&site), + fF(p,p), + fFt(p,p), + fQ(p,p), + fC(c) +{ + fF.UnitMatrix(); + fFt.UnitMatrix(); +} + +//------------------------------------------------------------------- +// Propagate +//------------------------------------------------------------------ + +void TVKalState::Propagate(TVKalSite &to) +{ + // Calculate + // prea: predicted state vector : a^k-1_k = f_k-1(a_k-1) + // fF: propagator derivative : F_k-1 = (@f_k-1/@a_k-1) + // fQ: process noise from k-1 to k : Q_k-1) + + TVKalState &prea = MoveTo(to,fF,fQ); + TVKalState *preaPtr = &prea; + + fFt = TKalMatrix(TKalMatrix::kTransposed, fF); + + // Calculate covariance matrix + + TKalMatrix preC = fF * fC * fFt + fQ; + + // Set predicted state vector and covariance matrix to next site + + prea.SetCovMat(preC); + to.Add(preaPtr); + to.SetOwner(); +} diff --git a/Utilities/KalTest/src/kallib/TVKalState.h b/Utilities/KalTest/src/kallib/TVKalState.h new file mode 100644 index 0000000000000000000000000000000000000000..38efabd27814efd840f65834261512184024ed5a --- /dev/null +++ b/Utilities/KalTest/src/kallib/TVKalState.h @@ -0,0 +1,90 @@ +#ifndef TVKALSTATE_H +#define TVKALSTATE_H +//************************************************************************* +//* ==================== +//* TVKalState Class +//* ==================== +//* +//* (Description) +//* This is the base class for a state vector used in Kalman Filter. +//* (Requires) +//* TKalMatrix +//* (Provides) +//* class TVKalState +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* +//************************************************************************* +// +#include "TKalMatrix.h" +class TVKalSite; +//_____________________________________________________________________ +// ----------------------------------- +// Base Class for Kalman state vector +// ----------------------------------- +// +class TVKalState : public TKalMatrix { +public: + + // Ctors and Dtor + + TVKalState(Int_t type = 0, Int_t p = 6); + TVKalState(const TKalMatrix &sv, Int_t type = 0, Int_t p = 6); + TVKalState(const TKalMatrix &sv, const TKalMatrix &c, + Int_t type = 0, Int_t p = 6); + TVKalState(const TKalMatrix &sv, const TVKalSite &site, + Int_t type = 0, Int_t p = 6); + TVKalState(const TKalMatrix &sv, const TKalMatrix &c, + const TVKalSite &site, Int_t type = 0, Int_t p = 6); + virtual ~TVKalState() {} + + // Pure virtuals to be implemented in derived classes + // + // MoveTo should calculate + // a: predicted state vector : a^k-1_k = f_k-1(a_k-1) + // F: propagator derivative : F_k-1 = (@f_k-1/@a_k-1) + // Q: process noise from k-1 to k : Q_k-1) + // and return a^k-1_k. + // + + virtual TVKalState * MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix *QPtr = 0) const = 0; + virtual TVKalState & MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix &Q) const = 0; + + virtual void DebugPrint() const = 0; + + virtual void Propagate(TVKalSite &to); // calculates f, F, and Q + + + // Getters + + inline virtual Int_t GetDimension () const { return GetNrows(); } + inline virtual const TVKalSite & GetSite () const { return *fSitePtr; } + inline virtual const TKalMatrix & GetCovMat () const { return fC; } + inline virtual const TKalMatrix & GetProcNoiseMat() const { return fQ; } + inline virtual const TKalMatrix & GetPropMat (const Char_t *t = "") const { return (t[0] == 'T' ? fFt : fF); } + + // Setters + + inline virtual void SetStateVec (const TKalMatrix &c) { TMatrixD::operator=(c); } + inline virtual void SetCovMat (const TKalMatrix &c) { fC = c; } + inline virtual void SetProcNoiseMat(const TKalMatrix &q) { fQ = q; } + inline virtual void SetSitePtr (TVKalSite *s) { fSitePtr = s; } + +private: + + // private data members ------------------------------------------- + + Int_t fType; // (0,1,2,3) = (uninited,predicted,filtered,smoothed) + TVKalSite *fSitePtr; // pointer to corresponding KalSite + TKalMatrix fF; // propagator matrix to next site (F = @f/@a) + TKalMatrix fFt; // transposed propagator matrix (F^T = (@f/@a)^T) + TKalMatrix fQ; // process noise from this to the next sites + TKalMatrix fC; // covariance matrix + + ClassDef(TVKalState,1) // Base class for state vector objects +}; +#endif diff --git a/Utilities/KalTest/src/kallib/TVKalSystem.cxx b/Utilities/KalTest/src/kallib/TVKalSystem.cxx new file mode 100644 index 0000000000000000000000000000000000000000..5c4bee34568af89f0be4b9c1d16083b9778aa389 --- /dev/null +++ b/Utilities/KalTest/src/kallib/TVKalSystem.cxx @@ -0,0 +1,153 @@ +//************************************************************************* +//* ==================== +//* TVKalSystem Class +//* ==================== +//* +//* (Description) +//* This is the base class of Kalman filter. +//* (Requires) +//* TObject +//* (Provides) +//* class TVKalSystem +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2009/06/18 K.Fujii Implement inverse Kalman filter +//* +//************************************************************************* + +#include <iostream> +#include <cstdlib> +#include "TVKalSystem.h" +#include "TVKalState.h" + +//_____________________________________________________________________ +// ------------------------------ +// Base Class for measurement vector used by Kalman filter +// ------------------------------ +// +ClassImp(TVKalSystem) + +TVKalSystem *TVKalSystem::fgCurInstancePtr = 0; + +TVKalSystem::TVKalSystem(Int_t n) + :TObjArray(n), + fCurSitePtr(0), + fChi2(0.) +{ + if (!fgCurInstancePtr) fgCurInstancePtr = this; +} + +TVKalSystem::~TVKalSystem() +{ + if (this == fgCurInstancePtr) fgCurInstancePtr = 0; +} + +//------------------------------------------------------- +// AddAndFilter +//------------------------------------------------------- + +Bool_t TVKalSystem::AddAndFilter(TVKalSite &next) +{ + SetCurInstancePtr(this); + + // + // Propagate current state to the next site + // + + GetState(TVKalSite::kFiltered).Propagate(next); + + // + // Calculate new pull and gain matrix + // + + if (next.Filter()) { + // + // Add this to the system if accepted. + // + + Add(&next); + fChi2 += next.GetDeltaChi2(); + return kTRUE; + } else { + return kFALSE; + } +} + +//------------------------------------------------------- +// GetNDF +//------------------------------------------------------- + +Int_t TVKalSystem::GetNDF(Bool_t self) +{ + Int_t ndf = 0; + Int_t nsites = GetEntries(); + for (Int_t isite=1; isite<nsites; isite++) { + TVKalSite &site = *static_cast<TVKalSite *>(At(isite)); + if (!site.IsLocked()) ndf += site.GetDimension(); + } + if (self) ndf -= GetCurSite().GetCurState().GetDimension(); + return ndf; +} + +//------------------------------------------------------- +// SmoothBackTo +//------------------------------------------------------- + +void TVKalSystem::SmoothBackTo(Int_t k) +{ + TIter previous(this,kIterBackward); + TIter cur (this,kIterBackward); + + TVKalSite *prePtr; + TVKalSite *curPtr = static_cast<TVKalSite *>(cur()); + TVKalState &cura = curPtr->GetState(TVKalSite::kFiltered); + TVKalState &scura = curPtr->GetState(TVKalSite::kSmoothed); + if (!&scura) { + curPtr->Add(&curPtr->CreateState(cura, cura.GetCovMat(), + TVKalSite::kSmoothed)); + } + + while ((curPtr = static_cast<TVKalSite *>(cur())) && + (prePtr = static_cast<TVKalSite *>(previous()))) { + curPtr->Smooth(*prePtr); + fCurSitePtr = curPtr; + if (IndexOf(curPtr) == k) break; + } +} + +//------------------------------------------------------- +// SmoothAll +//------------------------------------------------------- + +void TVKalSystem::SmoothAll() +{ + SmoothBackTo(0); +} + +//------------------------------------------------------- +// InvFilter +//------------------------------------------------------- + +void TVKalSystem::InvFilter(Int_t k) +{ + using namespace std; + // + // Check if site k exists + // + TVKalSite *curPtr = static_cast<TVKalSite *>(At(k)); + if (!curPtr) { + cerr << "::::: ERROR in TVKalSystem::InvFilter(k=" << k << ")" << endl + << " Site " << k << " nonexistent! Abort!" + << endl; + ::abort(); + } + // + // Check if site k already smoothed + // + if (!&curPtr->GetState(TVKalSite::kSmoothed)) SmoothBackTo(k); + // + // Inverse filter site k + // + fCurSitePtr = curPtr; + curPtr->InvFilter(); +} diff --git a/Utilities/KalTest/src/kallib/TVKalSystem.h b/Utilities/KalTest/src/kallib/TVKalSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..fff6d5a8631cb0211e9b8af29e6b6dbe34af8987 --- /dev/null +++ b/Utilities/KalTest/src/kallib/TVKalSystem.h @@ -0,0 +1,82 @@ +#ifndef TVKALSYSTEM_H +#define TVKALSYSTEM_H +//************************************************************************* +//* =================== +//* TVKalSystem Class +//* =================== +//* +//* (Description) +//* Base class for Kalman filtering class +//* (Requires) +//* TObjArray +//* (Provides) +//* class TVKalSystem +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2005/08/25 A.Yamaguchi Added fgCurInstancePtr and its getter & setter. +//* 2009/06/18 K.Fujii Implement inverse Kalman filter +//* +//************************************************************************* + +#include "TObjArray.h" +#include "TVKalSite.h" + +//_____________________________________________________________________ +// ------------------------------ +// Kalman Filtering class +// ------------------------------ +// +class TKalMatrix; + +class TVKalSystem : public TObjArray { +friend class TVKalSite; +public: + + // Ctors and Dtor + + TVKalSystem(Int_t n = 1); + virtual ~TVKalSystem(); + + // Utility methods + + virtual Bool_t AddAndFilter(TVKalSite &next); + virtual void SmoothBackTo(Int_t k); + virtual void SmoothAll(); + virtual void InvFilter(Int_t k); + + inline void Add(TObject *obj); + + // Getters + + inline virtual TVKalSite & GetCurSite() { return *fCurSitePtr; } + inline virtual TVKalState & GetState(TVKalSite::EStType t) + { return fCurSitePtr->GetState(t); } + inline virtual Double_t GetChi2() { return fChi2; } + virtual Int_t GetNDF (Bool_t self = kTRUE); + + static TVKalSystem *GetCurInstancePtr() { return fgCurInstancePtr; } + + // Setters + +private: + static void SetCurInstancePtr(TVKalSystem *ksp) { fgCurInstancePtr = ksp; } + +private: + TVKalSite *fCurSitePtr; // pointer to current site + Double_t fChi2; // current total chi2 + + static TVKalSystem *fgCurInstancePtr; //! currently active instance + + ClassDef(TVKalSystem,1) // Base class for Kalman Filter +}; + +//======================================================= +// inline functions +//======================================================= + +void TVKalSystem::Add(TObject *obj) +{ + TObjArray::Add(obj); + fCurSitePtr = static_cast<TVKalSite *>(obj); +} +#endif diff --git a/Utilities/KalTest/src/kaltracklib/Imakefile b/Utilities/KalTest/src/kaltracklib/Imakefile new file mode 100644 index 0000000000000000000000000000000000000000..6e2dd20af7efd67d7faf0afb6405974c49c8f9f1 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/Imakefile @@ -0,0 +1,59 @@ +#include "../../conf/makejsf.tmpl" + +LDFLAGS = /* $(GLIBS) */ + +INSTALLDIR = ../.. +SOREV = 2005.01 +PACKAGENAME = S4KalTrack + +SRCS = TVTrackHit.$(SrcSuf) \ + TVMeasLayer.$(SrcSuf) \ + TKalTrackSite.$(SrcSuf) \ + TKalTrackState.$(SrcSuf) \ + TKalTrack.$(SrcSuf) \ + TKalDetCradle.$(SrcSuf) \ + TVKalDetector.$(SrcSuf) \ + TKalFilterCond.$(SrcSuf) + + +OBJS = $(subst .$(SrcSuf),.$(ObjSuf),$(SRCS)) \ + $(PACKAGENAME)Dict.$(ObjSuf) + +HDRS = $(subst .$(SrcSuf),.h,$(SRCS)) KalTrackDim.h + +DICTNAME = $(PACKAGENAME)Dict + +LIBNAME = $(PACKAGENAME) + +SONAME = lib$(LIBNAME).$(DllSuf).$(SOREV) + +LIBINSTALLDIR = $(INSTALLDIR)/lib +INCINSTALLDIR = $(INSTALLDIR)/include +INCPATH = -I. -I$(INCINSTALLDIR) +CXXFLAGS += $(INCPATH) -O0 -g +SHLIBLDFLAGS = $(DYLIBFLAGS) + +all:: $(SONAME) + +SharedLibraryTarget($(LIBNAME),$(SOREV),$(OBJS),.,.) + +InstallSharedLibrary($(LIBNAME),$(SOREV),$(LIBINSTALLDIR)) + +InstallMultipleFlags($(HDRS),$(INCINSTALLDIR),-m 644) + +clean:: + @rm -f $(OBJS) core *.$(DllSuf) $(DICTNAME).$(SrcSuf) $(DICTNAME).h + +depend:: $(SRCS) $(HDRS) + for i in $(SRCS); do \ + rmkdepend -a -- $(CXXFLAGS) $(INCPATH) $(DEPENDFILES) -- $$i; done + +distclean:: clean + @rm -f $(OBJS) core *.$(DllSuf) *.$(DylibSuf) + @rm -f $(DICTNAME).$(SrcSuf) $(DICTNAME).h *~ + @rm -f $(SONAME) *.root Makefile + +$(DICTNAME).$(SrcSuf): $(HDRS) LinkDef.h + @echo "Generating dictionary ..." + rootcint -f $(DICTNAME).$(SrcSuf) \ + -c -I$(INCINSTALLDIR) $(HDRS) LinkDef.h diff --git a/Utilities/KalTest/src/kaltracklib/KalTrackDim.h b/Utilities/KalTest/src/kaltracklib/KalTrackDim.h new file mode 100644 index 0000000000000000000000000000000000000000..c71efbf0c5ecdacae3df27e50174a612983bebee --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/KalTrackDim.h @@ -0,0 +1,9 @@ +#ifndef KALDIM_H +#define KALDIM_H +#define kMdim 2 +#ifdef __NOT0__ +#define kSdim 5 +#else +#define kSdim 6 +#endif +#endif diff --git a/Utilities/KalTest/src/kaltracklib/LinkDef.h b/Utilities/KalTest/src/kaltracklib/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..4eaa502a09f9e7ce028388220c0cf935ce1184cb --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/LinkDef.h @@ -0,0 +1,16 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class TVTrackHit+; +#pragma link C++ class TVMeasLayer+; +#pragma link C++ class TKalTrackSite+; +#pragma link C++ class TKalTrackState+; +#pragma link C++ class TKalTrack+; +#pragma link C++ class TKalDetCradle+; +#pragma link C++ class TVKalDetector+; +#pragma link C++ class TKalFilterCond+; + +#endif diff --git a/Utilities/KalTest/src/kaltracklib/TKalDetCradle.cxx b/Utilities/KalTest/src/kaltracklib/TKalDetCradle.cxx new file mode 100644 index 0000000000000000000000000000000000000000..5f8c643d242d5289b0f8170e2153819cc6ede1ab --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalDetCradle.cxx @@ -0,0 +1,287 @@ +//************************************************************************* +//* ===================== +//* TKalDetCradle Class +//* ===================== +//* +//* (Description) +//* A singleton class to hold information of detector system +//* used in Kalman filter classes. +//* (Requires) +//* TObjArray +//* TVKalDetector +//* (Provides) +//* class TKalDetCradle +//* (Update Recored) +//* 2005/02/23 A.Yamaguchi Original version. +//* 2005/08/14 K.Fujii Removed CalcTable(), GetMeasLayerTable(), +//* GetPhiTable(), and GetDir() and added +//* Transport() to do their functions. +//* 2010/04/06 K.Fujii Modified Transport() to allow a 1-dim hit, +//* for which pivot is at the expected hit. +//* +//************************************************************************* + +#include "TKalDetCradle.h" // from KalTrackLib +#include "TVMeasLayer.h" // from KalTrackLib +#include "TVKalDetector.h" // from KalTrackLib +#include "TKalTrackSite.h" // from KalTrackLib +#include "TKalTrackState.h" // from KalTrackLib +#include "TVSurface.h" // from GeomLib +#include <memory> // from STL +#include <iostream> // from STL + +ClassImp(TKalDetCradle) + +//_________________________________________________________________________ +// ---------------------------------- +// Ctors and Dtor +// ---------------------------------- + +TKalDetCradle::TKalDetCradle(Int_t n) +: TObjArray(n), fIsMSON(kTRUE), fIsDEDXON(kTRUE), +fDone(kFALSE), fIsClosed(kFALSE) +{ +} + +TKalDetCradle::~TKalDetCradle() +{ +} + +//_________________________________________________________________________ +// ---------------------------------- +// Utility Methods +// ---------------------------------- +//_________________________________________________________________________ +// ----------------- +// Install +// ----------------- +// installs a sub-detector into this cradle. +// +void TKalDetCradle::Install(TVKalDetector &det) +{ + if (IsClosed()) { + std::cerr << ">>>> Error!! >>>> TKalDetCradle::Install" << std::endl + << " Cradle already closed. Abort!!" << std::endl; + abort(); + } + TIter next(&det); + TObject *mlp = 0; // measment layer pointer + while ((mlp = next())) { + Add(mlp); + dynamic_cast<TAttElement *>(mlp)->SetParentPtr(&det); + det.SetParentPtr(this); + } + fDone = kFALSE; +} + +void TKalDetCradle::Transport(const TKalTrackSite &from, // site from + TKalTrackSite &to, // site to + TKalMatrix &sv, // state vector + TKalMatrix &F, // propagator matrix + TKalMatrix &Q) // process noise matrix +{ + + const TVMeasLayer& ml_to = to.GetHit().GetMeasLayer() ; + TVector3 x0; + this->Transport(from, ml_to, x0, sv, F, Q ) ; + + THelicalTrack hel(sv, x0, to.GetHit().GetBfield()) ; + + // --------------------------------------------------------------------- + // Move pivot from last expected hit to actural hit at site to + // --------------------------------------------------------------------- + + if (to.GetDimension() > 1) { + + double fid = 0.; + Int_t sdim = sv.GetNrows(); // number of track parameters + TKalMatrix DF(sdim, sdim); // propagator matrix segment + + hel.MoveTo(to.GetPivot(), fid, &DF); // move pivot to actual hit (to) + F = DF * F; // update F accordingly + hel.PutInto(sv); // save updated hel to sv + + } else { + to.SetPivot(x0); // if it is a 1-dim hit + } + +} + +// +// +// +//_________________________________________________________________________ +// ----------------- +// Transport +// ----------------- +// transports state (sv) from site (from) to layer (ml_to), taking into +// account multiple scattering and energy loss and updates state (sv), +// fills pivot in x0, propagator matrix (F), and process noise matrix (Q). +// + +int TKalDetCradle::Transport(const TKalTrackSite &from, // site from + const TVMeasLayer &ml_to, // layer to reach + TVector3 &x0, // pivot for sv + TKalMatrix &sv, // state vector + TKalMatrix &F, // propagator matrix + TKalMatrix &Q) // process noise matrix +{ + // --------------------------------------------------------------------- + // Sort measurement layers in this cradle if not + // --------------------------------------------------------------------- + if (!fDone) Update(); + + // --------------------------------------------------------------------- + // Locate sites from and to in this cradle + // --------------------------------------------------------------------- + Int_t fridx = from.GetHit().GetMeasLayer().GetIndex(); // index of site from + Int_t toidx = ml_to.GetIndex(); // index of layer to + Int_t di = fridx > toidx ? -1 : 1; // layer increment + + std::auto_ptr<TVTrack> help(&static_cast<TKalTrackState &> + (from.GetCurState()).CreateTrack()); // tmp track + + TVTrack &hel = *help; + + //===================== + // FIXME + //===================== + TVector3 xfrom = from.GetPivot(); // get the referenece point + TVector3 xto; // reference point at destination to be returned by CalcXingPointWith + Double_t fito = 0; // deflection angle to destination to be returned by CalcXingPointWith + + const TVSurface *sfp = dynamic_cast<const TVSurface *>(&ml_to);// surface at destination + + sfp->CalcXingPointWith(hel, xto, fito, 0); // the default tolerance is used + // as mode is 0 here the closest point crossing point is taken + // this means that if we are at the top of a looping track + // and the point to which we want to move is on the other side of + // the loop but has a lower radius the transport will move down + // through all layers and segfault on reaching index -1 + + // if( does_cross < 1 ) return does_cross ; + + TMatrixD dxdphi = hel.CalcDxDphi(fito); // tangent vector at destination surface + TVector3 dxdphiv(dxdphi(0,0),dxdphi(1,0),dxdphi(2,0)); // convert matirix diagonal to vector +// Double_t cpa = hel.GetKappa(); // get pt + + Bool_t isout = -fito*dxdphiv.Dot(sfp->GetOutwardNormal(xto)) < 0 ? kTRUE : kFALSE; // out-going or in-coming at the destination surface + //===================== + // ENDFIXME + //===================== + + TVector3 xx; // expected hit position vector + Double_t fid = 0.; // deflection angle from the last hit + + Int_t sdim = sv.GetNrows(); // number of track parameters + F.UnitMatrix(); // set the propagator matrix to the unit matrix + Q.Zero(); // zero the noise matrix + + TKalMatrix DF(sdim, sdim); // propagator matrix segment + + // --------------------------------------------------------------------- + // Loop over layers and transport sv, F, and Q step by step + // --------------------------------------------------------------------- + Int_t ifr = fridx; // set index to the index of the intitial starting layer + + // here we make first make sure that the helix is at the crossing point of the current surface. + // this is necessary to ensure that the material is only accounted for between fridx and toidx + // otherwise it is possible to have inconsistencies with material treatment. + // loop until we reach the index toidx, which is the surface we need to reach + for (Int_t ito=fridx; (di>0 && ito<=toidx)||(di<0 && ito>=toidx); ito += di) { + + Double_t fid_temp = fid; // deflection angle from the last layer crossing + + int mode = ito!=fridx ? di : 0; // need to move to the from site as the helix may not be on the crossing point yet, meaning that the eloss and ms will be incorrectely attributed ... + + if (dynamic_cast<TVSurface *>(At(ito))->CalcXingPointWith(hel, xx, fid, mode)) { // if we have a crossing point at this surface, note di specifies if we are moving forwards or backwards + + //===================== + // FIXME + //===================== + static const Double_t kMergin = 1.0; + // if the distance from the current crossing point to the starting point - kMergin(1mm) is greater than the distance from the destination to the starting point + // this is needed to skip crossing points which come from the far side of the IP, for a cylinder this would not be a problem + // but for the bounded planes it is perfectly posible due to the sorting in R + // reset the deflection angle and skip this layer + // this would at stop layers being added which are too far away but I am not sure how this will work with the problem described above. + if( (xx-xfrom).Mag() - kMergin > (xto-xfrom).Mag() ){ + fid = fid_temp; + continue ; + } + //===================== + // ENDFIXME + //===================== + const TVMeasLayer &ml = *dynamic_cast<TVMeasLayer *>(At(ifr)); // get the last layer + + TKalMatrix Qms(sdim, sdim); + if (IsMSOn()&& ito!=fridx ){ + + ml.CalcQms(isout, hel, fid, Qms); // Qms for this step, using the fact that the material was found to be outgoing or incomming above, and the distance from the last layer + } + + hel.MoveTo(xx, fid, &DF); // move the helix to the present crossing point, DF will simply have its values overwritten so it could be explicitly set to unity here + if (sdim == 6) DF(5, 5) = 1.; // t0 stays the same + F = DF * F; // update F + TKalMatrix DFt = TKalMatrix(TMatrixD::kTransposed, DF); + + Q = DF * (Q + Qms) * DFt; // transport Q to the present crossing point + + if (IsDEDXOn() && ito!=fridx) { + hel.PutInto(sv); // copy hel to sv + // whether the helix is moving forwards or backwards is calculated using the sign of the charge and the sign of the deflection angle + // Bool_t isfwd = ((cpa > 0 && df < 0) || (cpa <= 0 && df > 0)) ? kForward : kBackward; // taken from TVMeasurmentLayer::GetEnergyLoss not df = fid + sv(2,0) += ml.GetEnergyLoss(isout, hel, fid); // correct for dE/dx, returns delta kappa i.e. the change in pt + hel.SetTo(sv, hel.GetPivot()); // save sv back to hel + } + ifr = ito; // for the next iteration set the "previous" layer to the current layer moved to + + + } else { // if there is no crossing point reset fid to its original value: + + fid = fid_temp ; + } + + } // end of loop over surfaces + + // // --------------------------------------------------------------------- + // // Move pivot to crossing point with layer to move to + // // --------------------------------------------------------------------- + // dynamic_cast<const TVSurface *>(&ml_to)->CalcXingPointWith(hel, xx, fid); + // hel.MoveTo(xx, fid, &DF); // move pivot to expected hit, DF will simply have its values overwritten so it could be explicitly set to unity here + // F = DF * F; // update F accordingly + + x0 = hel.GetPivot() ; + hel.PutInto(sv); // save updated hel to sv + + return 0; + +} + + + +//_________________________________________________________________________ +// ----------------- +// Update +// ----------------- +// sorts meaurement layers according to layer's sorting policy +// and puts index to layers from inside to outside. +// +void TKalDetCradle::Update() +{ + fDone = kTRUE; + + UnSort(); // unsort + Sort(); // sort layers according to sorting policy + + TIter next(this); + TVMeasLayer *mlp = 0; + Int_t i = 0; + + while ((mlp = dynamic_cast<TVMeasLayer *>(next()))) { + mlp->SetIndex(i++); + } + +} + + diff --git a/Utilities/KalTest/src/kaltracklib/TKalDetCradle.h b/Utilities/KalTest/src/kaltracklib/TKalDetCradle.h new file mode 100644 index 0000000000000000000000000000000000000000..f666378e82b7ed68bad514fd3218e4efd3556ea2 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalDetCradle.h @@ -0,0 +1,84 @@ +#ifndef TKALDETCRADLE_H +#define TKALDETCRADLE_H +//************************************************************************* +//* ===================== +//* TKalDetCradle Class +//* ===================== +//* +//* (Description) +//* A sigleton to hold information of detector system +//* used in Kalman filter classes. +//* (Requires) +//* TObjArray +//* TVKalDetector +//* (Provides) +//* class TKalDetCradle +//* (Update Recored) +//* 2005/02/23 A.Yamaguchi Original Version. +//* 2005/08/14 K.Fujii Removed CalcTable(), GetMeasLayerTable(), +//* GetPhiTable(), and GetDir() and added +//* Transport() to do their functions. +//* 2010/04/06 K.Fujii Modified Transport() to allow a 1-dim hit, +//* for which pivot is at the xpected hit. +//* +//************************************************************************* + +#include "TObjArray.h" // from ROOT +#include "TAttElement.h" // from Utils +#include "TKalMatrix.h" // from KalTrackLib + +class TKalTrackSite; +class TVKalDetector; +class TVMeasLayer; + +//_____________________________________________________________________ +// ------------------------------ +// Detector system class +// ------------------------------ + +class TKalDetCradle : public TObjArray, public TAttElement { +public: + TKalDetCradle(Int_t n = 1); + virtual ~TKalDetCradle(); + + // Utility methods + virtual void Install(TVKalDetector &det); + + inline virtual void SwitchOnMS () { fIsMSON = kTRUE; } + inline virtual void SwitchOffMS () { fIsMSON = kFALSE; } + inline virtual void SwitchOnDEDX () { fIsDEDXON = kTRUE; } + inline virtual void SwitchOffDEDX() { fIsDEDXON = kFALSE; } + inline virtual void Close () { fIsClosed = kTRUE; Update(); } + inline virtual void Reopen () { fIsClosed = kFALSE; } + inline virtual Bool_t IsMSOn () const { return fIsMSON; } + inline virtual Bool_t IsDEDXOn () const { return fIsDEDXON; } + inline virtual Bool_t IsClosed () const { return fIsClosed; } + + void Transport(const TKalTrackSite &from, // site from + TKalTrackSite &to, // site to + TKalMatrix &sv, // state vector + TKalMatrix &F, // propagator matrix + TKalMatrix &Q); // process noise matrix + + int Transport(const TKalTrackSite &from, // site from + const TVMeasLayer &to, // layer to reach + TVector3 &x0, // intersection point + TKalMatrix &sv, // state vector + TKalMatrix &F, // propagator matrix + TKalMatrix &Q); // process noise matrix + + + +private: + void Update(); + +private: + Bool_t fIsMSON; //! switch for multiple scattering + Bool_t fIsDEDXON; //! switch for energy loss + Bool_t fDone; //! flag to tell if sorting done + Bool_t fIsClosed; //! flag to tell if cradle closed + + ClassDef(TKalDetCradle,1) // Base class for detector system +}; + +#endif diff --git a/Utilities/KalTest/src/kaltracklib/TKalFilterCond.cxx b/Utilities/KalTest/src/kaltracklib/TKalFilterCond.cxx new file mode 100644 index 0000000000000000000000000000000000000000..64579bfbc8402591a8a6de615988eac083e77fdc --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalFilterCond.cxx @@ -0,0 +1,42 @@ +//************************************************************************* +//* ===================== +//* TKalFilterCond Class +//* ===================== +//* +//* (Description) +//* A class to specify filter conditions used in Kalman filter. +//* (Requires) +//* (Provides) +//* class TKalFilterCond +//* (Update Recored) +//* 2010/04/06 K.Fujii Original Version. +//* +//************************************************************************* + +#include "TKalFilterCond.h" +#include "TKalTrackSite.h" +#include <iostream> + +//_____________________________________________________________________ +// ------------------------------ +// Filter condition class +// ------------------------------ + +ClassImp(TKalFilterCond) + +Bool_t TKalFilterCond::IsAccepted(const TKalTrackSite &site) +{ +#if 0 + // return kTRUE if this site is acceptable + using namespace std; + Double_t delchi2 = site.GetDeltaChi2(); + if (delchi2 > 25.) { + cerr << ">>>> TKalFilterCond::IsAccepted >>>>>>>>>>>>> " << endl + << " Too big chi2 increment!!! " << endl; + site.DebugPrint(); + return kFALSE; + } +#else + return kTRUE; +#endif +} diff --git a/Utilities/KalTest/src/kaltracklib/TKalFilterCond.h b/Utilities/KalTest/src/kaltracklib/TKalFilterCond.h new file mode 100644 index 0000000000000000000000000000000000000000..54970788ac7d340c1ae14559465ad53d1a0ce907 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalFilterCond.h @@ -0,0 +1,35 @@ +#ifndef TKALFILTERCOND_H +#define TKALFILTERCOND_H +//************************************************************************* +//* ===================== +//* TKalFilterCond Class +//* ===================== +//* +//* (Description) +//* A class to specify filter conditions used in Kalman filter. +//* (Requires) +//* (Provides) +//* class TKalFilterCond +//* (Update Recored) +//* 2010/04/06 K.Fujii Original Version. +//* +//************************************************************************* +#include "Rtypes.h" +//_____________________________________________________________________ +// ------------------------------ +// Filter condition class +// ------------------------------ + +class TKalTrackSite; + +class TKalFilterCond { + public: + + // need virtual destructor is we have virtual functions + virtual ~TKalFilterCond() {}; + + virtual Bool_t IsAccepted(const TKalTrackSite &site); + + ClassDef(TKalFilterCond,1) // Base class for detector system + }; +#endif diff --git a/Utilities/KalTest/src/kaltracklib/TKalTrack.cxx b/Utilities/KalTest/src/kaltracklib/TKalTrack.cxx new file mode 100644 index 0000000000000000000000000000000000000000..23ae6a2033bd4e619eba606e0ccb2064ec1b608b --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalTrack.cxx @@ -0,0 +1,181 @@ +//************************************************************************* +//* ================= +//* TKalTrack Class +//* ================= +//* +//* (Description) +//* Track class for Kalman filter +//* (Requires) +//* TVKalSystem +//* (Provides) +//* class TKalTrack +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 A.Yamaguchi Added a new data member, fMass. +//* 2005/08/25 K.Fujii Added drawable attribute. +//* 2005/08/26 K.Fujii Removed drawable attribute. +//* +//************************************************************************* + +#include "TKalTrackState.h" // from KalTrackLib +#include "TKalTrackSite.h" // from KalTrackLib +#include "TKalTrack.h" // from KalTrackLib +#include <iostream> // from STL + +using namespace std; +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) +#else +const Double_t TKalTrack::kMpi = 0.13957018; // pion mass [GeV] +#endif + + +//_________________________________________________________________________ +// ------------------------------ +// TKalTrack: Kalman rack class +// ------------------------------ + +ClassImp(TKalTrack) + +//_________________________________________________________________________ +// ---------------------------------- +// Ctor +// ---------------------------------- +TKalTrack::TKalTrack(Int_t n) + :TVKalSystem(n), fMass(kMpi) +{ +} + +//_________________________________________________________________________ +// ---------------------------------- +// Utility Method +// ---------------------------------- +//_________________________________________________________________________ +// ----------------- +// FitToHelix +// ----------------- +// chi^2-fits hits belonging to this track to a single helix. +// +Double_t TKalTrack::FitToHelix(TKalTrackState &a, TKalMatrix &C, Int_t &ndf) +{ + // Define static constants... + + static const Double_t kChi2Dum = 1.e20; + static const Double_t kChi2Tol = 1.e-8; + static const Double_t kLambda = 1.; + static const Double_t kLincr = 10.; + static const Double_t kLdecr = 0.1; + static const Int_t kLoopMax = 100; + + // Initialize return values... + + TKalTrackState abest(a); + Double_t chi2best = kChi2Dum; + Double_t lambda = kLambda; + Int_t nloops = 0; + + ndf = 0; + Int_t nsites = 0; + Double_t chi2 = 0.; + + // Prepare som matrices + + TIter next(this); + TKalTrackSite &site0 = *(TKalTrackSite *)next(); + + Int_t mdim = site0.GetDimension(); + Int_t sdim = site0.GetCurState().GetDimension(); + + TKalMatrix dchi2dabest(1 , sdim); + TKalMatrix dchi2da (1 , sdim); + TKalMatrix d2chi2dada (sdim, sdim); + TKalMatrix d2chi2best (sdim, sdim); + TKalMatrix curh (mdim, 1 ); + TKalMatrix curH (mdim, sdim); + TKalMatrix curHt (sdim, mdim); + TKalMatrix curVinv (mdim, mdim); + TKalMatrix curResVec (mdim, 1 ); + + // Minimization loop starts here + + while (1) { + if (nloops > kLoopMax) { + cerr << "TKalTrack::FitToHelix >>>>>>>>>>>>>>" + << " Loop count limit reached. nloops = " << nloops << endl; + a = abest; + chi2 = chi2best; + break; + } + nloops++; + + d2chi2dada.Zero(); + dchi2da.Zero(); + chi2 = 0; + + // Loop over hits and accumulate chi2 + + next.Reset(); + TKalTrackSite *sitePtr = 0; + nsites = 0; + while ((sitePtr = (TKalTrackSite *)next())) { + TKalTrackSite &site = *sitePtr; + + if (site.IsLocked()) continue; + if (!site.CalcExpectedMeasVec (a, curh)) continue; + if (!site.CalcMeasVecDerivative(a, curH)) continue; + nsites++; // site accepted + + //dchi2/da + curVinv = TKalMatrix(TKalMatrix::kInverted,site.GetMeasNoiseMat()); + curResVec = site.GetMeasVec() - curh; + + TKalMatrix curResVecT(TKalMatrix::kTransposed, curResVec); + dchi2da += (curResVecT * curVinv * curH); + + // accumulate chi2 + Double_t delchi2 = (curResVecT * curVinv * curResVec)(0,0); + chi2 += delchi2; + + // inverse covariance matrix + TKalMatrix curHt(TKalMatrix::kTransposed, curH); + d2chi2dada += (curHt * curVinv * curH); + } + + // + // if (chi2best - chi2) < kChi2Tol, break while loop. + // + + if (TMath::Abs(chi2best - chi2) < kChi2Tol) { + d2chi2best = d2chi2dada; + break; + } + + if (chi2 < chi2best) { + // chi2 decreased. Save this step as the current best + chi2best = chi2; + abest = (TKalTrackState &)a; + dchi2dabest = dchi2da; + d2chi2best = d2chi2dada; + lambda *= kLdecr; + } else { + // chi2 increased. Restore the current best + dchi2da = dchi2dabest; + d2chi2dada = d2chi2best; + lambda *= kLincr; + } + + // Modify the 2nd derivative and try again + + for (Int_t i=0; i<sdim; i++) { + d2chi2dada(i, i) *= (1 + lambda); + } + + TKalMatrix d2chi2dadainv(TKalMatrix::kInverted, d2chi2dada); + TKalMatrix dchi2daT (TKalMatrix::kTransposed, dchi2da); + a += (d2chi2dadainv * dchi2daT); + } + + ndf = nsites * mdim - sdim; + C = TKalMatrix(TKalMatrix::kInverted, d2chi2best); + + return chi2; +} diff --git a/Utilities/KalTest/src/kaltracklib/TKalTrack.h b/Utilities/KalTest/src/kaltracklib/TKalTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..13540c2928d7392307ba46445c0c57fd7838de66 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalTrack.h @@ -0,0 +1,54 @@ +#ifndef TKALTRACK_H +#define TKALTRACK_H +//************************************************************************* +//* ================= +//* TKalTrack Class +//* ================= +//* +//* (Description) +//* Track class for Kalman filter +//* (Requires) +//* TVKalSystem +//* (Provides) +//* class TKalTrack +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 A.Yamaguchi Added a new data member fMass and its +//* getter and setter. +//* 2005/08/15 K.Fujii Removed fDir and its getter and setter. +//* 2005/08/25 K.Fujii Added Drawable attribute. +//* 2005/08/26 K.Fujii Removed Drawable attribute. +//* +//************************************************************************* + +#include "TVKalSystem.h" // from KalLib +#include "TKalTrackState.h" // from KalTrackLib + +//_________________________________________________________________________ +// ------------------------------ +// TKalTrack: Kalman Track class +// ------------------------------ + +class TKalTrack : public TVKalSystem { +public: + TKalTrack(Int_t n = 1); + ~TKalTrack() {} + + inline virtual void SetMass(Double_t m) { fMass = m; } + inline virtual Double_t GetMass() const { return fMass; } + + Double_t FitToHelix(TKalTrackState &a, TKalMatrix &C, Int_t &ndf); + +private: + Double_t fMass; // mass [GeV] + +#if __GNUC__ < 4 && !defined(__STRICT_ANSI__) + static const Double_t kMpi = 0.13957018; //! pion mass [GeV] +#else + static const Double_t kMpi; //! pion mass [GeV] +#endif + + ClassDef(TKalTrack,1) // Base class for Kalman Filter +}; + +#endif diff --git a/Utilities/KalTest/src/kaltracklib/TKalTrackSite.cxx b/Utilities/KalTest/src/kaltracklib/TKalTrackSite.cxx new file mode 100644 index 0000000000000000000000000000000000000000..528fede6e88df4c7f951095e5c178e512a64fdac --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalTrackSite.cxx @@ -0,0 +1,161 @@ +//************************************************************************* +//* ===================== +//* TKalTrackSite Class +//* ===================== +//* +//* (Description) +//* Track measurement site class used by Kalman filter. +//* (Requires) +//* TKalTrackState +//* (Provides) +//* class TKalTrackSite +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2010/04/06 K.Fujii Modified a c-tor to allow a 1-dim hit, +//* for which pivot is at the xpected hit. +//* Modified IsAccepted() to allow user- +//* defined filter conditions. +//* +//************************************************************************* + +#include "TKalTrackSite.h" // from KalTrackLib +#include "TKalTrackState.h" // from KalTrackLib +#include "TVTrackHit.h" // from KalTrackLib +#include "TKalFilterCond.h" // from KalTrackLib +#include "TVSurface.h" // from GeomLib + +#include <iostream> // from STL +#include <memory> // from STL + +using namespace std; + +//_________________________________________________________________________ +// ---------------------------------- +// Class for measurement site +// ---------------------------------- +// +ClassImp(TKalTrackSite) + +//_________________________________________________________________________ +// ---------------------------------- +// Ctors and Dtor +// ---------------------------------- +TKalTrackSite::TKalTrackSite(Int_t m, Int_t p) + : TVKalSite(m,p), fHitPtr(0), fX0(), fIsHitOwner(kFALSE), + fCondPtr(0) +{ +} + +TKalTrackSite::TKalTrackSite(const TVTrackHit &ht, + Int_t p) + : TVKalSite(ht.GetDimension(),p), + fHitPtr(static_cast<const TVTrackHit *>(&ht)), + fX0(), + fIsHitOwner(kFALSE), + fCondPtr(0) +{ + for (Int_t i=0; i<ht.GetDimension(); i++) { + GetMeasVec ()(i,0) = ht.GetX(i); + GetMeasNoiseMat()(i,i) = TMath::Power(ht.GetDX(i),2); + } + // Leave the pivot at the origin for a 1-dim hit + if (ht.GetDimension() > 1) fX0 = ht.GetMeasLayer().HitToXv(ht); +} + +TKalTrackSite::~TKalTrackSite() +{ + if (IsHitOwner() && fHitPtr) delete fHitPtr; +} + +//_________________________________________________________________________ +// ---------------------------------- +// Implementation of public methods +// ---------------------------------- + +TVKalState & TKalTrackSite::CreateState(const TKalMatrix &sv, Int_t type) +{ + SetOwner(); + return *(new TKalTrackState(sv,*this,type)); +} + +TVKalState & TKalTrackSite::CreateState(const TKalMatrix &sv, + const TKalMatrix &c, + Int_t type) +{ + SetOwner(); + return *(new TKalTrackState(sv,c,*this,type)); +} + +Int_t TKalTrackSite::CalcXexp(const TVKalState &a, + TVector3 &xx, + Double_t &phi) const +{ + std::auto_ptr<TVTrack> hel(&static_cast<const TKalTrackState &>(a).CreateTrack()); + + const TVSurface &ms = dynamic_cast<const TVSurface &>(GetHit().GetMeasLayer()); + return ms.CalcXingPointWith(*hel,xx,phi); +} + + + +Int_t TKalTrackSite::CalcExpectedMeasVec(const TVKalState &a, TKalMatrix &h) +{ + Double_t phi = 0.; + TVector3 xxv; + if (!CalcXexp(a,xxv,phi)) return 0; // no hit + + if (a.GetNrows() == 6) h = GetHit().XvToMv(xxv,a(5,0)); + else h = GetHit().XvToMv(xxv,0.); + + return 1; +} + +Int_t TKalTrackSite::CalcMeasVecDerivative(const TVKalState &a, + TKalMatrix &H) +{ + // Calculate + // H = (@h/@a) = (@d/@a, @z/@a)^t + // where + // h(a) = (d, z)^t: expected meas vector + // a = (drho, phi0, kappa, dz, tanl, t0) + // + + TVector3 xxv; + Double_t phi = 0.; + + if (!CalcXexp(a,xxv,phi)) return 0; // hit on S(x) = 0 + + const TVSurface &ms = dynamic_cast<const TVSurface &>(GetHit().GetMeasLayer()); + TKalMatrix dsdx(ms.CalcDSDx(xxv)); // (@S(x)/@x) + + std::auto_ptr<TVTrack> hel(&static_cast<const TKalTrackState &>(a).CreateTrack()); + + TKalMatrix dxda = hel->CalcDxDa(phi); // (@x(phi,a)/@a) + TKalMatrix dxdphi = hel->CalcDxDphi(phi); // (@x(phi,a)/@phi) + + TKalMatrix dphida = dsdx * dxda; + TKalMatrix dsdphi = dsdx * dxdphi; + Double_t denom = -dsdphi(0,0); + dphida *= 1/denom; + + TKalMatrix dxphiada = dxdphi * dphida + dxda; // (@x(phi(a),a)/@a) + + GetHit().GetMeasLayer().CalcDhDa(GetHit(), xxv, dxphiada, H); // H = (@h/@a) + + return 1; +} + +Bool_t TKalTrackSite::IsAccepted() +{ + if (fCondPtr) return fCondPtr->IsAccepted(*this); + else return kTRUE; +} + +void TKalTrackSite::DebugPrint() const +{ + cerr << " dchi2 = " << GetDeltaChi2() << endl; + cerr << " res_d = " << (*(TKalTrackSite *)this).GetResVec()(0,0) << endl; + cerr << " res_z = " << (*(TKalTrackSite *)this).GetResVec()(1,0) << endl; + fHitPtr->DebugPrint(); +} + diff --git a/Utilities/KalTest/src/kaltracklib/TKalTrackSite.h b/Utilities/KalTest/src/kaltracklib/TKalTrackSite.h new file mode 100644 index 0000000000000000000000000000000000000000..3764e87f58efa5d5c5a3666ca63a003f7a0be391 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalTrackSite.h @@ -0,0 +1,76 @@ +#ifndef TKALTRACKSITE_H +#define TKALTRACKSITE_H +//************************************************************************* +//* ===================== +//* TKalTrackSite Class +//* ===================== +//* +//* (Description) +//* Track measurement site class used by Kalman filter. +//* (Requires) +//* TKalTrackState +//* (Provides) +//* class TKalTrackSite +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2004/09/17 K.Fujii Added ownership flag. +//* 2010/04/06 K.Fujii Added a setter for the pivot and a +//* condition object +//* +//************************************************************************* + +#include "TVector3.h" // from ROOT +#include "TVKalSite.h" // from KalLib +#include "TVTrackHit.h" // from KalTrackLib + +class TVKalState; +class TKalTrackState; +class TKalFilterCond; + +//_________________________________________________________________________ +// --------------------------------- +// Class for Kalman measurement site +// --------------------------------- +// +class TKalTrackSite : public TVKalSite { +public: + TKalTrackSite(Int_t m = kMdim, Int_t p = kSdim); + TKalTrackSite( const TVTrackHit &ht, + Int_t p = kSdim); + ~TKalTrackSite(); + + Int_t CalcExpectedMeasVec (const TVKalState &a, TKalMatrix &h); + Int_t CalcMeasVecDerivative(const TVKalState &a, TKalMatrix &H); + Bool_t IsAccepted(); + + void DebugPrint() const; + + inline const TVTrackHit & GetHit () const { return *fHitPtr; } + inline const TVector3 & GetPivot () const { return fX0; } + inline Double_t GetBfield () const { return fHitPtr->GetBfield(); } + inline Bool_t IsInB () const { return GetBfield() != 0.; } + inline Bool_t IsHitOwner() const { return fIsHitOwner; } + + inline void SetPivot (const TVector3 &x0) { fX0 = x0; } + inline void SetHitOwner (Bool_t b=kTRUE) { fIsHitOwner = b; } + inline void SetFilterCond(TKalFilterCond *cp) { fCondPtr = cp; } + +private: + TVKalState & CreateState(const TKalMatrix &sv, Int_t type = 0); + TVKalState & CreateState(const TKalMatrix &sv, + const TKalMatrix &C, + Int_t type = 0); + Int_t CalcXexp (const TVKalState &a, + TVector3 &xx, + Double_t &phi) const; + +private: + const TVTrackHit *fHitPtr; // pointer to corresponding hit + TVector3 fX0; // pivot + Bool_t fIsHitOwner; // true if site owns hit + TKalFilterCond *fCondPtr; // pointer to filter condition object + + ClassDef(TKalTrackSite,1) // sample measurement site class +}; + +#endif diff --git a/Utilities/KalTest/src/kaltracklib/TKalTrackState.cxx b/Utilities/KalTest/src/kaltracklib/TKalTrackState.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9c0b7a440c2a00a36f8fe537bc83a7445f9c45f0 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalTrackState.cxx @@ -0,0 +1,161 @@ +//************************************************************************* +//* ====================== +//* TKalTrackState Class +//* ====================== +//* +//* (Description) +//* Track state vector class used in Kalman Filter. +//* (Requires) +//* TVKalState +//* (Provides) +//* class TKalTrackState +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 Y.Yamaguchi Improved CalcProcessNoise(). +//* 2005/08/14 K.Fujii Removed CalcProcessNoise() and +//* let TKalDetCradle::Transport() do its +//* function. +//* 2010/04/06 K.Fujii Modified MoveTo to allow a 1-dim hit, +//* for which pivot is at the xpected hit. +//* +//************************************************************************* + +#include "TKalDetCradle.h" // from KalTrackLib +#include "TVKalDetector.h" // from KalTrackLib +#include "TKalTrackState.h" // from KalTrackLib +#include "TKalTrackSite.h" // from KalTrackLib +#include "TKalTrack.h" // from KalTrackLib + +#include <iostream> // from STL +#include <memory> // from STL + +using namespace std; + +//_________________________________________________________________________ +// ----------------------------------- +// Kalman track state vector +// ----------------------------------- +//_________________________________________________________________________ +// ----------------- +// Ctors and Dtor +// ----------------- +// +TKalTrackState::TKalTrackState(Int_t p) + : TVKalState(p), fX0() +{ +} + +TKalTrackState::TKalTrackState(const TKalMatrix &sv, Int_t type, Int_t p) + : TVKalState(sv,type,p), fX0() +{ +} + +TKalTrackState::TKalTrackState(const TKalMatrix &sv, const TKalMatrix &c, + Int_t type, Int_t p) + : TVKalState(sv,c,type,p), fX0() +{ +} + +TKalTrackState::TKalTrackState(const TKalMatrix &sv, const TVKalSite &site, + Int_t type, Int_t p) + : TVKalState(sv,site,type,p), + fX0(((TKalTrackSite *)&site)->GetPivot()) +{ +} + +TKalTrackState::TKalTrackState(const TKalMatrix &sv, const TKalMatrix &c, + const TVKalSite &site, Int_t type, Int_t p) + : TVKalState(sv,c,site,type,p), + fX0(((TKalTrackSite *)&site)->GetPivot()) +{ +} + +//_________________________________________________________________________ +// ---------------------------------------------- +// Implementation of base-class pure virtuals +// ---------------------------------------------- +// +TKalTrackState * TKalTrackState::MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix *QPtr) const +{ + if (QPtr) { + const TKalTrackSite &from = static_cast<const TKalTrackSite &>(GetSite()); + TKalTrackSite &siteto = static_cast<TKalTrackSite &>(to); + TKalDetCradle &det = const_cast<TKalDetCradle &> + (static_cast<const TKalDetCradle &> + (from.GetHit().GetMeasLayer().GetParent())); + Int_t sdim = GetDimension(); + TKalMatrix sv(sdim,1); + det.Transport(from, siteto, sv, F, *QPtr); // siteto's pivot might be modified + if (sdim == 6) { + sv(5,0) = (*this)(5,0); + F (5,5) = 1.; + } + return new TKalTrackState(sv, siteto, TVKalSite::kPredicted, sdim); + } else { + return 0; + } +} + +TKalTrackState & TKalTrackState::MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix &Q) const +{ + return *MoveTo(to, F, &Q); +} + +void TKalTrackState::DebugPrint() const +{ + cerr << " +- -+ " << "+-" << endl + << " | drho | " << "| " << (*this)(0,0) << endl + << " | phi0 | " << "| " << (*this)(1,0) << endl + << " a = | kappa | = " << "| " << (*this)(2,0) << endl + << " | dz | " << "| " << (*this)(3,0) << endl + << " | tanl | " << "| " << (*this)(4,0) << endl; + if (GetDimension() == 6) { + cerr + << " | t0 | " << "| " << (*this)(5,0) << endl; + } + cerr << " +- -+ " << "+-" << endl; + cerr << " +-" << endl + << " X0 = | " << fX0.X() << endl + << " | " << fX0.Y() << endl + << " | " << fX0.Z() << endl + << " +-" << endl; + GetCovMat().DebugPrint(" covMat = ", 6); +} + +//_________________________________________________________________________ +// -------------------------------- +// Derived class methods +// -------------------------------- +// +THelicalTrack TKalTrackState::GetHelix() const +{ + TKalMatrix a(5,1); + for (Int_t i=0; i<5; i++) a(i,0) = (*this)(i,0); + return THelicalTrack(a,fX0,((TKalTrackSite *)&GetSite())->GetBfield()); +} + +TStraightTrack TKalTrackState::GetLine() const +{ + TKalMatrix a(5,1); + for (Int_t i=0; i<5; i++) a(i,0) = (*this)(i,0); + return TStraightTrack(a,fX0,((TKalTrackSite *)&GetSite())->GetBfield()); +} + +TVTrack &TKalTrackState::CreateTrack() const +{ + TVTrack *tkp = 0; + + TKalMatrix a(5,1); + for (Int_t i=0; i<5; i++) a(i,0) = (*this)(i,0); + Double_t bfield = static_cast<const TKalTrackSite &>(GetSite()).GetBfield(); + + if (bfield == 0.) tkp = new TStraightTrack(a,fX0); + else tkp = new THelicalTrack(a,fX0, bfield); + + return *tkp; +} + diff --git a/Utilities/KalTest/src/kaltracklib/TKalTrackState.h b/Utilities/KalTest/src/kaltracklib/TKalTrackState.h new file mode 100644 index 0000000000000000000000000000000000000000..6931adcf0aa8c13fa6029584ca9d154623c152ba --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TKalTrackState.h @@ -0,0 +1,76 @@ +#ifndef TKALTRACKSTATE_H +#define TKALTRACKSTATE_H +//************************************************************************* +//* ====================== +//* TKalTrackState Class +//* ====================== +//* +//* (Description) +//* Track state vector class used in Kalman Filter. +//* (Requires) +//* TVKalState +//* (Provides) +//* class TKalTrackState +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 A.Yamaguchi Added CalcDapDa method. +//* 2005/02/XX A.Yamaguchi Moved CalcDapDa method to THelicalTrack. +//* 2005/08/13 K.Fujii Removed CalcProcessNoise method. +//* 2010/04/06 K.Fujii Modified MoveTo to allow a 1-dim hit, +//* for which pivot is at the xpected hit. +//* +//************************************************************************* + +#include "TVKalState.h" // from KalLib +#include "THelicalTrack.h" // from GeomLib +#include "TStraightTrack.h" // from GeomLib +#include "KalTrackDim.h" // from KalTrackLib + +class TKalTrackSite; + +//_________________________________________________________________________ +// ----------------------------------- +// Base Class for Kalman state vector +// ----------------------------------- +// + +class TKalTrackState : public TVKalState { + +public: + + // Ctors and Dtor + + TKalTrackState(Int_t p = kSdim); + TKalTrackState(const TKalMatrix &sv, Int_t type = 0, Int_t p = kSdim); + TKalTrackState(const TKalMatrix &sv, const TKalMatrix &c, + Int_t type = 0, Int_t p = kSdim); + TKalTrackState(const TKalMatrix &sv, const TVKalSite &site, + Int_t type = 0, Int_t p = kSdim); + TKalTrackState(const TKalMatrix &sv, const TKalMatrix &c, + const TVKalSite &site, Int_t type = 0, Int_t p = kSdim); + virtual ~TKalTrackState() {} + + // Implementation of paraent class pure virtuals + + TKalTrackState * MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix *QPtr = 0) const; + TKalTrackState & MoveTo(TVKalSite &to, + TKalMatrix &F, + TKalMatrix &Q) const; + void DebugPrint() const; + + // Derived class methods + + THelicalTrack GetHelix() const; + TStraightTrack GetLine () const; + TVTrack &CreateTrack() const; + +private: + + TVector3 fX0; // pivot + + ClassDef(TKalTrackState,1) // sample state vector class +}; + +#endif diff --git a/Utilities/KalTest/src/kaltracklib/TVKalDetector.cxx b/Utilities/KalTest/src/kaltracklib/TVKalDetector.cxx new file mode 100644 index 0000000000000000000000000000000000000000..438b72fe663cfb84d498f3fa9469f358dd6091d5 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TVKalDetector.cxx @@ -0,0 +1,22 @@ +//************************************************************************* +//* ===================== +//* TVKalDetector Class +//* ===================== +//* +//* (Description) +//* Base class to hold information of detector system +//* used in Kalman filter classes. +//* (Requires) +//* TObjArray +//* (Provides) +//* class TVKalDetector +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2005/08/14 K.Fujii Moved GetEnergyLoss() and CalcQms() to +//* TVMeasLayer. +//* +//************************************************************************* + +#include "TVKalDetector.h" + +ClassImp(TVKalDetector) diff --git a/Utilities/KalTest/src/kaltracklib/TVKalDetector.h b/Utilities/KalTest/src/kaltracklib/TVKalDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..0edc3946f65bd5088081955a42cb7a06be17c948 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TVKalDetector.h @@ -0,0 +1,39 @@ +#ifndef TVKALDETECTOR_H +#define TVKALDETECTOR_H +//************************************************************************* +//* ===================== +//* TVKalDetector Class +//* ===================== +//* +//* (Description) +//* Base class to hold information of detector system +//* used in Kalman filter classes. +//* (Requires) +//* TObjArray +//* (Provides) +//* class TVKalDetector +//* (Update Recored) +//* 2003/09/30 K.Fujii Original version. +//* 2005/02/23 A.Yamaguchi Moved most methods to TKalDetCradle. +//* +//************************************************************************* + +#include "TObjArray.h" // from ROOT +#include "TAttElement.h" // from Utils + +//_________________________________________________________________________ +// ------------------------------ +// Detector system class +// ------------------------------ +// + +class TVKalDetector : public TObjArray, public TAttElement { +public: + // Ctors and Dtor + TVKalDetector(Int_t n = 1) : TObjArray(n) {} + virtual ~TVKalDetector() {} + + ClassDef(TVKalDetector,1) // Base class for detector system +}; + +#endif diff --git a/Utilities/KalTest/src/kaltracklib/TVMeasLayer.cxx b/Utilities/KalTest/src/kaltracklib/TVMeasLayer.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b11457defeacd5aad9269a2493a2d44e633644f4 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TVMeasLayer.cxx @@ -0,0 +1,179 @@ +//************************************************************************* +//* ==================== +//* TVMeasLayer Class +//* ==================== +//* +//* (Description) +//* Measurement layer interface class. +//* (Requires) +//* (Provides) +//* class TVMeasLayer +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 A.Yamaguchi Added new data members, fFwdX0Inv, +//* fBwdX0Inv and fIndex, and their +//* corresponding getters and setters. +//* Added a new method, GetX0Inv(). +//* 2005/0X/XX A.Yamaguchi Replaced fFwdX0Inv, fBwdX0Inv, and +//* their getters and setters by +//* fMaterialOutPtr, fMaterialInPtr, and +//* their getters and setters. +//* 2005/08/15 K.Fujii Added fIsActive and IsActive(). +//* Moved GetEnergyLoss() and CalcQms() +//* from TVKalDetector. +//* 2011/12/03 S.Aplin Added new member: name +//* default value set to "TVMeasLayer" +//* and corresponding member function +//* TString GetName() +//* +//************************************************************************* + +#include "TVMeasLayer.h" // from KalTrackLib +#include "TKalTrack.h" // from KalTrackLib +#include "TVTrack.h" // from KalTrackLib + +ClassImp(TVMeasLayer) + +//_________________________________________________________________________ +// ---------------------------------- +// Ctor +// ---------------------------------- +TVMeasLayer::TVMeasLayer(TMaterial &matIn, + TMaterial &matOut, + Bool_t isactive, + const Char_t *name) + : fMaterialInPtr(&matIn), + fMaterialOutPtr(&matOut), + fIndex(0), + fIsActive(isactive), + fname(name) +{ +} + +//_________________________________________________________________________ +// ---------------------------------- +// Utility Methods +// ---------------------------------- +//_________________________________________________________________________ +// ----------------- +// GetEnergyLoss +// ----------------- +// returns energy loss. +// +Double_t TVMeasLayer::GetEnergyLoss( Bool_t isoutgoing, + const TVTrack &hel, + Double_t df) const +{ + Double_t cpa = hel.GetKappa(); + Double_t tnl = hel.GetTanLambda(); + Double_t tnl2 = tnl * tnl; + Double_t tnl21 = 1. + tnl2; + Double_t cslinv = TMath::Sqrt(tnl21); + Double_t mom2 = tnl21 / (cpa * cpa); + + // ----------------------------------------- + // Bethe-Bloch eq. (Physical Review D P195.) + // ----------------------------------------- + static const Double_t kK = 0.307075e-3; // [GeV*cm^2] + static const Double_t kMe = 0.510998902e-3; // electron mass [GeV] + static const Double_t kMpi = 0.13957018; // pion mass [GeV] + + TKalTrack *ktp = static_cast<TKalTrack *>(TVKalSystem::GetCurInstancePtr()); + Double_t mass = ktp ? ktp->GetMass() : kMpi; + + const TMaterial &mat = GetMaterial(isoutgoing); + Double_t dnsty = mat.GetDensity(); // density + Double_t A = mat.GetA(); // atomic mass + Double_t Z = mat.GetZ(); // atomic number + //Double_t I = Z * 1.e-8; // mean excitation energy [GeV] + //Double_t I = (2.4 +Z) * 1.e-8; // mean excitation energy [GeV] + Double_t I = (9.76 * Z + 58.8 * TMath::Power(Z, -0.19)) * 1.e-9; + Double_t hwp = 28.816 * TMath::Sqrt(dnsty * Z/A) * 1.e-9; + Double_t bg2 = mom2 / (mass * mass); + Double_t gm2 = 1. + bg2; + Double_t meM = kMe / mass; + Double_t x = log10(TMath::Sqrt(bg2)); + Double_t C0 = - (2. * log(I/hwp) + 1.); + Double_t a = -C0/27.; + Double_t del; + if (x >= 3.) del = 4.606 * x + C0; + else if (0.<=x && x<3.) del = 4.606 * x + C0 + a * TMath::Power(3.-x, 3.); + else del = 0.; + Double_t tmax = 2.*kMe*bg2 / (1. + meM*(2.*TMath::Sqrt(gm2) + meM)); + Double_t dedx = kK * Z/A * gm2/bg2 * (0.5*log(2.*kMe*bg2*tmax / (I*I)) + - bg2/gm2 - del); + + Double_t path = hel.IsInB() + ? TMath::Abs(hel.GetRho()*df)*cslinv + : TMath::Abs(df)*cslinv; + + //fg: switched from using cm to mm in KalTest - material (density) and energy still in GeV and cm + path /= 10. ; + + Double_t edep = dedx * dnsty * path; + + + Double_t cpaa = TMath::Sqrt(tnl21 / (mom2 + edep + * (edep + 2. * TMath::Sqrt(mom2 + mass * mass)))); + Double_t dcpa = TMath::Abs(cpa) - cpaa; + + static const Bool_t kForward = kTRUE; + static const Bool_t kBackward = kFALSE; + Bool_t isfwd = ((cpa > 0 && df < 0) || (cpa <= 0 && df > 0)) ? kForward : kBackward; + return isfwd ? (cpa > 0 ? dcpa : -dcpa) : (cpa > 0 ? -dcpa : dcpa); +} + +//_________________________________________________________________________ +// ----------------- +// CalQms +// ----------------- +// calculates process noise matrix for multiple scattering with +// thin layer approximation. +// +void TVMeasLayer::CalcQms( Bool_t isoutgoing, + const TVTrack &hel, + Double_t df, + TKalMatrix &Qms) const +{ + Double_t cpa = hel.GetKappa(); + Double_t tnl = hel.GetTanLambda(); + Double_t tnl2 = tnl * tnl; + Double_t tnl21 = 1. + tnl2; + Double_t cpatnl = cpa * tnl; + Double_t cslinv = TMath::Sqrt(tnl21); + Double_t mom = TMath::Abs(1. / cpa) * cslinv; + + static const Double_t kMpi = 0.13957018; // pion mass [GeV] + TKalTrack *ktp = static_cast<TKalTrack *>(TVKalSystem::GetCurInstancePtr()); + Double_t mass = ktp ? ktp->GetMass() : kMpi; + Double_t beta = mom / TMath::Sqrt(mom * mom + mass * mass); + + const TMaterial &mat = GetMaterial(isoutgoing); + Double_t x0inv = 1. / mat.GetRadLength(); // radiation length inverse + + // *Calculate sigma_ms0 ============================================= + static const Double_t kMS1 = 0.0136; + static const Double_t kMS12 = kMS1 * kMS1; + static const Double_t kMS2 = 0.038; + + Double_t path = hel.IsInB() + ? TMath::Abs(hel.GetRho()*df)*cslinv + : TMath::Abs(df)*cslinv; + + //fg: switched from using cm to mm in KalTest - material (density) and energy still in GeV and cm + path /= 10. ; + + Double_t xl = path * x0inv; + // ------------------------------------------------------------------ + // Very Crude Treatment!! + Double_t tmp = 1. + kMS2 * TMath::Log(TMath::Max(1.e-4, xl)); + tmp /= (mom * beta); + Double_t sgms2 = kMS12 * xl * tmp * tmp; + // ------------------------------------------------------------------ + + Qms(1,1) = sgms2 * tnl21; + Qms(2,2) = sgms2 * cpatnl * cpatnl; + Qms(2,4) = sgms2 * cpatnl * tnl21; + Qms(4,2) = sgms2 * cpatnl * tnl21; + Qms(4,4) = sgms2 * tnl21 * tnl21; +} diff --git a/Utilities/KalTest/src/kaltracklib/TVMeasLayer.h b/Utilities/KalTest/src/kaltracklib/TVMeasLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..5cdc314352f89963a5a8dc560c0623dac861c177 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TVMeasLayer.h @@ -0,0 +1,86 @@ +#ifndef TVMEASLAYER_H +#define TVMEASLAYER_H +//************************************************************************* +//* ==================== +//* TVMeasLayer Class +//* ==================== +//* +//* (Description) +//* Measurement layer interface class. +//* (Requires) +//* (Provides) +//* class TVMeasLayer +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/02/23 A.Yamaguchi Added new data members, fFwdX0Inv, +//* fBwdX0Inv and fIndex, and their +//* corresponding getters and setters. +//* Added a new method, GetX0Inv(). +//* 2005/0X/XX A.Yamaguchi Replaced fFwdX0Inv, fBwdX0Inv, and +//* their getters and setters by +//* fMaterialOutPtr, fMaterialInPtr, and +//* their getters and setters. +//* 2005/08/15 K.Fujii Added fIsActive and IsActive(). +//* 2011/12/03 S.Aplin Added new member: name +//* default value set to "TVMeasLayer" +//* and corresponding member function +//* TString GetName() +//* +//************************************************************************* + +#include "TVector3.h" // from ROOT +#include "TMaterial.h" // from ROOT +#include "TAttElement.h" // from Utils +#include "TKalMatrix.h" // from KalLib +#include "KalTrackDim.h" // from KalTrackLib + +class TVTrack; +class TVTrackHit; + +class TVMeasLayer : public TAttElement { +public: + // Ctors and Dtor + + TVMeasLayer(TMaterial &matIn, + TMaterial &matOut, + Bool_t isactive = kTRUE, + const Char_t *name = "TVMeasLayer"); + virtual ~TVMeasLayer() {} + + // Utiliy Methods + + virtual TKalMatrix XvToMv (const TVTrackHit &ht, + const TVector3 &xv) const = 0; + virtual TVector3 HitToXv (const TVTrackHit &ht) const = 0; + virtual void CalcDhDa (const TVTrackHit &ht, + const TVector3 &xv, + const TKalMatrix &dxphiada, + TKalMatrix &H) const = 0; + + inline virtual TMaterial &GetMaterial(Bool_t isoutgoing) const + { return isoutgoing ? *fMaterialOutPtr : *fMaterialInPtr; } + + inline Int_t GetIndex() const { return fIndex; } + inline void SetIndex(Int_t i) { fIndex = i; } + inline Bool_t IsActive() const { return fIsActive; } + + virtual Double_t GetEnergyLoss ( Bool_t isoutgoing, + const TVTrack &hel, + Double_t df) const; + virtual void CalcQms ( Bool_t isoutgoing, + const TVTrack &hel, + Double_t df, + TKalMatrix &Qms) const; + + inline TString GetName() const { return fname; } + +private: + TMaterial *fMaterialInPtr; // pointer of inner Material + TMaterial *fMaterialOutPtr; // pointer of outer Material + Int_t fIndex; // index in TKalDetCradle + Bool_t fIsActive; // flag to tell layer is active or not + const Char_t *fname; + ClassDef(TVMeasLayer,1) // Measurement layer interface class +}; + +#endif diff --git a/Utilities/KalTest/src/kaltracklib/TVTrackHit.cxx b/Utilities/KalTest/src/kaltracklib/TVTrackHit.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ad9284ac48e2974f09ef1fafb08a6a409ecd3176 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TVTrackHit.cxx @@ -0,0 +1,54 @@ +//************************************************************************* +//* ==================== +//* TVTrackHit Class +//* ==================== +//* +//* (Description) +//* Abstract base class to store single hit information. +//* (Requires) +//* (Provides) +//* class TVTrackHit +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* +//************************************************************************* + +#include "TVTrackHit.h" // from KalTrackLib + +ClassImp(TVTrackHit) + +//_________________________________________________________________________ +// ---------------------------------- +// Ctors and Dtor +// ---------------------------------- + +TVTrackHit::TVTrackHit(Int_t m) + : TKalMatrix(m,2), fDim(m), fBfield(30.), fMeasLayerPtr(0) +{ +} + +TVTrackHit::TVTrackHit(const TVMeasLayer &ms, + Double_t *x, + Double_t *dx, + Double_t b, + Int_t m) + : TKalMatrix(m,2), fDim(m), fBfield(b), + fMeasLayerPtr((TVMeasLayer *)&ms) +{ + for (Int_t i=0; i<m; i++) { + (*this)(i,0) = x [i]; + (*this)(i,1) = dx[i]; + } +} + +TVTrackHit::TVTrackHit(const TVTrackHit &hit) + : TKalMatrix(hit), + fDim(hit.fDim), + fBfield(hit.fBfield), + fMeasLayerPtr(hit.fMeasLayerPtr) +{ +} + +TVTrackHit::~TVTrackHit() +{ +} diff --git a/Utilities/KalTest/src/kaltracklib/TVTrackHit.h b/Utilities/KalTest/src/kaltracklib/TVTrackHit.h new file mode 100644 index 0000000000000000000000000000000000000000..9559bb624fd9e23f31b7a39c5e9ea3afbd61bf64 --- /dev/null +++ b/Utilities/KalTest/src/kaltracklib/TVTrackHit.h @@ -0,0 +1,55 @@ +#ifndef TVTRACKHIT_H +#define TVTRACKHIT_H + +//************************************************************************* +//* ==================== +//* TVTrackHit Class +//* ==================== +//* +//* (Description) +//* Abstract base class to store single hit information. +//* (Requires) +//* (Provides) +//* class TVTrackHit +//* (Update Recored) +//* 2003/09/30 Y.Nakashima Original version. +//* 2005/08/11 K.Fujii Removed fXX and its getter and setter. +//* +//************************************************************************* + +#include "TVector3.h" // from ROOT +#include "TKalMatrix.h" // from KalLib +#include "KalTrackDim.h" // from KalTrackLib +#include "TVMeasLayer.h" // from KalTrackLib + +class TVTrackHit : public TKalMatrix { +public: + TVTrackHit(Int_t m = kMdim); + + TVTrackHit(const TVMeasLayer &ms, Double_t *x, Double_t *dx, + Double_t b = 30., Int_t m = kMdim); + TVTrackHit(const TVTrackHit &hit); + + virtual ~TVTrackHit(); + + inline virtual Double_t GetX (Int_t i) const { return (*this)(i,0); } + inline virtual Double_t GetDX(Int_t i) const { return (*this)(i,1); } + inline virtual Int_t GetDimension() const { return fDim; } + inline virtual Double_t GetBfield() const { return fBfield; } + + inline virtual const TVMeasLayer & GetMeasLayer() const + { return *fMeasLayerPtr; } + + virtual TKalMatrix XvToMv (const TVector3 &xv, Double_t t0) const = 0; + + // virtual void DebugPrint(Option_t *opt = "") const = 0; + +private: + Int_t fDim; // dimension of coordinate space + Double_t fBfield; // B field + TVMeasLayer *fMeasLayerPtr; // pointer to measurement layer + + ClassDef(TVTrackHit,1) // Sample hit class +}; + +#endif diff --git a/Utilities/KalTest/src/utils/Imakefile b/Utilities/KalTest/src/utils/Imakefile new file mode 100644 index 0000000000000000000000000000000000000000..674cb1dd4d6c5c3cce984d24d56a9919d828b29a --- /dev/null +++ b/Utilities/KalTest/src/utils/Imakefile @@ -0,0 +1,53 @@ +#include "../../conf/makejsf.tmpl" + +INSTALLDIR = ../.. +PACKAGENAME = S4Utils +SOREV = 2005.01 + +SRCS = TAttDrawable.$(SrcSuf) \ + TAttElement.$(SrcSuf) \ + TAttLockable.$(SrcSuf) + +OBJS = $(subst .$(SrcSuf),.$(ObjSuf),$(SRCS)) \ + $(PACKAGENAME)Dict.$(ObjSuf) + +HDRS = $(subst .$(SrcSuf),.h,$(SRCS)) + +DICTNAME = $(PACKAGENAME)Dict + +LIBNAME = $(PACKAGENAME) + +SONAME = lib$(LIBNAME).$(DllSuf).$(SOREV) + +LIBINSTALLDIR = $(INSTALLDIR)/lib +INCINSTALLDIR = $(INSTALLDIR)/include +INCPATH = -I. -I$(INCINSTALLDIR) +CXXFLAGS += $(INCPATH) +SHLIBLDFLAGS = $(DYLIBFLAGS) + + +all:: $(SONAME) + +SharedLibraryTarget($(LIBNAME),$(SOREV),$(OBJS),.,.) + +InstallSharedLibrary($(LIBNAME),$(SOREV),$(LIBINSTALLDIR)) + +InstallMultipleFlags($(HDRS),$(INCINSTALLDIR),-m 644) + +clean:: + @rm -f $(OBJS) core *.$(DllSuf) $(DICTNAME).$(SrcSuf) $(DICTNAME).h $(SONAME) *.$(DylibSuf) + +depend:: $(SRCS) $(HDRS) + for i in $(SRCS); do \ + rmkdepend -a -- $(DEPENDFILES) -- $$i; done + + +distclean:: clean + @rm -f $(OBJS) core *.$(DllSuf) $(DICTNAME).$(SrcSuf) $(DICTNAME).h *~ + @rm -f $(SONAME) *.root Makefile + @(cd $(INSTALLDIR); rm -f *.root *.tdr *.out *~ core) + +$(DICTNAME).$(SrcSuf): $(HDRS) LinkDef.h + @echo "Generating dictionary ..." + rootcint -f $(DICTNAME).$(SrcSuf) \ + -c $(HDRS) LinkDef.h diff --git a/Utilities/KalTest/src/utils/LinkDef.h b/Utilities/KalTest/src/utils/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..599b5eb0aea9029429ced6340aa56259a01fa6e5 --- /dev/null +++ b/Utilities/KalTest/src/utils/LinkDef.h @@ -0,0 +1,11 @@ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class TAttDrawable+; +#pragma link C++ class TAttElement+; +#pragma link C++ class TAttLockable+; + +#endif diff --git a/Utilities/KalTest/src/utils/TAttDrawable.cxx b/Utilities/KalTest/src/utils/TAttDrawable.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0b2b06dadb229e89fdce195e67aa469771cba93a --- /dev/null +++ b/Utilities/KalTest/src/utils/TAttDrawable.cxx @@ -0,0 +1,38 @@ +//************************************************************************* +//* ==================== +//* TAttDrawable Class +//* ==================== +//* +//* (Description) +//* TAttDrawable class adds drawable attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class TAttDrawable +//* (Update Recored) +//* 2004/11/04 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include "TAttDrawable.h" +//_________________________________________________________________________ +// ------------------------------- +// Base Class for Drawable Objects +// ------------------------------- +// +ClassImp(TAttDrawable) + +//========================================================================= +//* Draw ------------------------------------------------------------------ + +void TAttDrawable::Draw(const Char_t *opt) +{ + static Int_t color = 0; + color++; + color %= 10; + Draw(color, opt); +} + +void TAttDrawable::Draw(Int_t /* color */, const Char_t * /* opt */) +{ +} diff --git a/Utilities/KalTest/src/utils/TAttDrawable.h b/Utilities/KalTest/src/utils/TAttDrawable.h new file mode 100644 index 0000000000000000000000000000000000000000..3383a39af6a4d04d2e2f726e977dce746afa7a57 --- /dev/null +++ b/Utilities/KalTest/src/utils/TAttDrawable.h @@ -0,0 +1,37 @@ +#ifndef TATTDRAWABLE_H +#define TATTDRAWABLE_H +//************************************************************************* +//* =================== +//* TAttDrawable Class +//* =================== +//* +//* (Description) +//* TAttDrawable class adds drawable attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class TAttDrawable +//* (Update Recored) +//* 2004/11/04 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include <Rtypes.h> +//_____________________________________________________________________ +// ------------------------------ +// Base Class for Drawale Objects +// ------------------------------ +// +class TAttDrawable { +public: + TAttDrawable() {} + virtual ~TAttDrawable() {} + + virtual void Draw(const Char_t *opt=""); + virtual void Draw(Int_t /* color */, const Char_t *opt=""); +private: + + ClassDef(TAttDrawable, 1) // Base class for drawable objects +}; + +#endif diff --git a/Utilities/KalTest/src/utils/TAttElement.cxx b/Utilities/KalTest/src/utils/TAttElement.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b086fc8630e8729d0e1b21993e070050ba3a30f6 --- /dev/null +++ b/Utilities/KalTest/src/utils/TAttElement.cxx @@ -0,0 +1,24 @@ +//************************************************************************* +//* =================== +//* TAttElement Class +//* =================== +//* +//* (Description) +//* TAttElement class adds constituent attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class TAttElement +//* (Update Recored) +//* 2003/10/10 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include "TAttElement.h" +//_____________________________________________________________________ +// -------------------------------- +// Base Class for Element Objects +// -------------------------------- +// + +ClassImp(TAttElement) diff --git a/Utilities/KalTest/src/utils/TAttElement.h b/Utilities/KalTest/src/utils/TAttElement.h new file mode 100644 index 0000000000000000000000000000000000000000..3f9905e03e33fa454de66143f8707e7caad3e47e --- /dev/null +++ b/Utilities/KalTest/src/utils/TAttElement.h @@ -0,0 +1,55 @@ +#ifndef TATTELEMENT_H +#define TATTELEMENT_H +//************************************************************************* +//* =================== +//* TAttElement Class +//* =================== +//* +//* (Description) +//* TAttElement class adds constituent attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class TAttElement +//* (Update Recored) +//* 2003/10/10 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include <Rtypes.h> + +//_____________________________________________________________________ +// -------------------------------- +// Base Class for Element Objects +// -------------------------------- +// +class TAttElement { +public: + TAttElement() : fParentPtr(0) {} + virtual ~TAttElement() {} + + inline virtual const TAttElement & GetParent(Bool_t recur = kTRUE) const; + + inline virtual void SetParentPtr(TAttElement *obj) { fParentPtr = obj; } + +private: + TAttElement *fParentPtr; // pointer to parent + + ClassDef(TAttElement,1) // Base class for lockable objects +}; + +//_____________________________________________________________________ +// -------------------------------- +// Inline functions, if any +// -------------------------------- +const TAttElement & TAttElement::GetParent(Bool_t recursive) const +{ + if (fParentPtr) { + if (recursive) return fParentPtr->GetParent(recursive); + else return *fParentPtr; + } else { + return *this; + } +} + +#endif diff --git a/Utilities/KalTest/src/utils/TAttLockable.cxx b/Utilities/KalTest/src/utils/TAttLockable.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d2d81325be8a62fe5a262ce4fadb05430f9c4041 --- /dev/null +++ b/Utilities/KalTest/src/utils/TAttLockable.cxx @@ -0,0 +1,23 @@ +//************************************************************************* +//* ==================== +//* TAttLockable Class +//* ==================== +//* +//* (Description) +//* TAttLockable class adds lockable attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class Lockable +//* (Update Recored) +//* 1999/06/05 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include "TAttLockable.h" +//_____________________________________________________________________ +// ------------------------------ +// Base Class for Lockale Objects +// ------------------------------ +// +ClassImp(TAttLockable) diff --git a/Utilities/KalTest/src/utils/TAttLockable.h b/Utilities/KalTest/src/utils/TAttLockable.h new file mode 100644 index 0000000000000000000000000000000000000000..8b6d068bf2a43d9a4aadd144d4ec961b9f539cb4 --- /dev/null +++ b/Utilities/KalTest/src/utils/TAttLockable.h @@ -0,0 +1,39 @@ +#ifndef TATTLOCKABLE_H +#define TATTLOCKABLE_H +//************************************************************************* +//* =================== +//* TAttLockable Class +//* =================== +//* +//* (Description) +//* TAttLockable class adds lockable attribute to an object. +//* (Requires) +//* none +//* (Provides) +//* class Lockable +//* (Update Recored) +//* 1999/06/05 K.Fujii Original very primitive version. +//* +//************************************************************************* +// +#include <Rtypes.h> +//_____________________________________________________________________ +// ------------------------------ +// Base Class for Lockale Objects +// ------------------------------ +// +class TAttLockable { +public: + TAttLockable() : fStatus(kFALSE) {} + virtual ~TAttLockable() {} + + inline virtual Bool_t IsLocked() const { return fStatus; } + inline virtual void Lock() { fStatus = kTRUE; } + inline virtual void Unlock() { fStatus = kFALSE; } +private: + Bool_t fStatus; // lock byte + + ClassDef(TAttLockable,1) // Base class for lockable objects +}; + +#endif diff --git a/Utilities/KiTrack/CMakeLists.txt b/Utilities/KiTrack/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ba301e6f28ee08c56499eba92278cc5edc6343f1 --- /dev/null +++ b/Utilities/KiTrack/CMakeLists.txt @@ -0,0 +1,21 @@ +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 +) diff --git a/Utilities/KiTrack/Criteria/Criteria.h b/Utilities/KiTrack/Criteria/Criteria.h new file mode 100644 index 0000000000000000000000000000000000000000..b0ec231b34d02feaf5a1bece67600dba34f8077c --- /dev/null +++ b/Utilities/KiTrack/Criteria/Criteria.h @@ -0,0 +1,110 @@ +#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 + diff --git a/Utilities/KiTrack/Criteria/ICriterion.h b/Utilities/KiTrack/Criteria/ICriterion.h new file mode 100644 index 0000000000000000000000000000000000000000..1ff8f950735e1f30f5f3297866b94575240e3fad --- /dev/null +++ b/Utilities/KiTrack/Criteria/ICriterion.h @@ -0,0 +1,68 @@ +#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 + + + + diff --git a/Utilities/KiTrack/ILDImpl/FTDHit01.h b/Utilities/KiTrack/ILDImpl/FTDHit01.h new file mode 100644 index 0000000000000000000000000000000000000000..6750231efe04a04032f1e90a987f689ff7ed1771 --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/FTDHit01.h @@ -0,0 +1,21 @@ +#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 + diff --git a/Utilities/KiTrack/ILDImpl/FTDHitSimple.h b/Utilities/KiTrack/ILDImpl/FTDHitSimple.h new file mode 100644 index 0000000000000000000000000000000000000000..36219730464c2130d7d3e85f4d3bc7aac530bc7d --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/FTDHitSimple.h @@ -0,0 +1,45 @@ +#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 + diff --git a/Utilities/KiTrack/ILDImpl/FTDNeighborPetalSecCon.h b/Utilities/KiTrack/ILDImpl/FTDNeighborPetalSecCon.h new file mode 100644 index 0000000000000000000000000000000000000000..07bfced54efc43ee8e73b969ff093011cbe6ea85 --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/FTDNeighborPetalSecCon.h @@ -0,0 +1,46 @@ +#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 + diff --git a/Utilities/KiTrack/ILDImpl/FTDSectorConnector.h b/Utilities/KiTrack/ILDImpl/FTDSectorConnector.h new file mode 100644 index 0000000000000000000000000000000000000000..8aaf4bfdf546f87b9d8c94a176fcd0a924d8f2ea --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/FTDSectorConnector.h @@ -0,0 +1,55 @@ +#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 + diff --git a/Utilities/KiTrack/ILDImpl/FTDTrack.h b/Utilities/KiTrack/ILDImpl/FTDTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..3db4c908806aad9761408f6818b64cdf8a729905 --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/FTDTrack.h @@ -0,0 +1,71 @@ +#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 + + diff --git a/Utilities/KiTrack/ILDImpl/IFTDHit.h b/Utilities/KiTrack/ILDImpl/IFTDHit.h new file mode 100644 index 0000000000000000000000000000000000000000..33b817bf5bc5f0aaa73edb6188574977dbb757fe --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/IFTDHit.h @@ -0,0 +1,49 @@ +#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 + diff --git a/Utilities/KiTrack/ILDImpl/SectorSystemFTD.h b/Utilities/KiTrack/ILDImpl/SectorSystemFTD.h new file mode 100644 index 0000000000000000000000000000000000000000..9f83b89587763b76e3f352f06a2aca8eb5a4536e --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/SectorSystemFTD.h @@ -0,0 +1,93 @@ +#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 + + diff --git a/Utilities/KiTrack/ILDImpl/SectorSystemVXD.h b/Utilities/KiTrack/ILDImpl/SectorSystemVXD.h new file mode 100644 index 0000000000000000000000000000000000000000..6852f63a3de3f23326c721260f1707e040ea12a5 --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/SectorSystemVXD.h @@ -0,0 +1,89 @@ +#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 + + diff --git a/Utilities/KiTrack/ILDImpl/VXDHitSimple.h b/Utilities/KiTrack/ILDImpl/VXDHitSimple.h new file mode 100644 index 0000000000000000000000000000000000000000..fc464eef939caba44d798d3478ba0c72d25b1a3a --- /dev/null +++ b/Utilities/KiTrack/ILDImpl/VXDHitSimple.h @@ -0,0 +1,44 @@ +#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 + diff --git a/Utilities/KiTrack/KiTrack/Automaton.h b/Utilities/KiTrack/KiTrack/Automaton.h new file mode 100644 index 0000000000000000000000000000000000000000..249aa354cd556a0df6d20a1d1e1b547ab3661fd8 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/Automaton.h @@ -0,0 +1,215 @@ +#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 + + diff --git a/Utilities/KiTrack/KiTrack/HopfieldNeuralNet.h b/Utilities/KiTrack/KiTrack/HopfieldNeuralNet.h new file mode 100644 index 0000000000000000000000000000000000000000..f1b22e46a52505e0d37ac1f6d6eee649e0ad69f1 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/HopfieldNeuralNet.h @@ -0,0 +1,129 @@ +#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 + diff --git a/Utilities/KiTrack/KiTrack/IHit.h b/Utilities/KiTrack/KiTrack/IHit.h new file mode 100644 index 0000000000000000000000000000000000000000..736c6d216ddff74ec18c6dd6f0398a395643a619 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/IHit.h @@ -0,0 +1,89 @@ +#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 + + + + diff --git a/Utilities/KiTrack/KiTrack/ISectorConnector.h b/Utilities/KiTrack/KiTrack/ISectorConnector.h new file mode 100644 index 0000000000000000000000000000000000000000..558ea8883d663dcf5b28c4bb8047187768225799 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/ISectorConnector.h @@ -0,0 +1,40 @@ +#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 + + + diff --git a/Utilities/KiTrack/KiTrack/ISectorSystem.h b/Utilities/KiTrack/KiTrack/ISectorSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..a9b3d99259ae9f1bfb847b07f3a20359c39aea77 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/ISectorSystem.h @@ -0,0 +1,56 @@ +#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 + diff --git a/Utilities/KiTrack/KiTrack/ITrack.h b/Utilities/KiTrack/KiTrack/ITrack.h new file mode 100644 index 0000000000000000000000000000000000000000..50d7e895273413f3e4e827858d2334b90a7457fc --- /dev/null +++ b/Utilities/KiTrack/KiTrack/ITrack.h @@ -0,0 +1,47 @@ +#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 + + diff --git a/Utilities/KiTrack/KiTrack/KiTrackExceptions.h b/Utilities/KiTrack/KiTrack/KiTrackExceptions.h new file mode 100644 index 0000000000000000000000000000000000000000..6e2a4a39aa6df090fe2fcf6c13add0a7a481ef9a --- /dev/null +++ b/Utilities/KiTrack/KiTrack/KiTrackExceptions.h @@ -0,0 +1,105 @@ +#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 + + diff --git a/Utilities/KiTrack/KiTrack/Segment.h b/Utilities/KiTrack/KiTrack/Segment.h new file mode 100644 index 0000000000000000000000000000000000000000..6a31c2f37136410d28bc9e0775223778be6af352 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/Segment.h @@ -0,0 +1,99 @@ +#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 + diff --git a/Utilities/KiTrack/KiTrack/SegmentBuilder.h b/Utilities/KiTrack/KiTrack/SegmentBuilder.h new file mode 100644 index 0000000000000000000000000000000000000000..a33a4f779a737368579df5d5e84ad85f7b2e873e --- /dev/null +++ b/Utilities/KiTrack/KiTrack/SegmentBuilder.h @@ -0,0 +1,94 @@ +#ifndef SegmentBuilder_h +#define SegmentBuilder_h + +#include "Criteria/ICriterion.h" +#include "KiTrack/ISectorConnector.h" +#include "KiTrack/Automaton.h" + +namespace KiTrack{ + + + /** This classe builds the Cellular Automaton from the hits + * + * It can be used to take all the autHits stored in a map< int , vector < IHits > > and makes + * 1-hit-segments out of them ( see the class Segment for more info on them ). + * + * The created 1-segments then are connected. + * + * For the rules of connecting criteria and hitConnectors can be added to the object: + * + * - a hitConnector takes the sector of the segment ( for example a cellID0 or a layer number or an own code ) and returns + * all the sectors we might connect to. So there we get the information like: "this segment can be connected + * to layer 3 and 4, module 7,8,9 in forward direction". + * + * - the criteria take two segments and return whether they are compatible or not. + * A criterion could check for anything, that is stored in the segments. + * For example: if the line formed from two 1-hit segments passes close by the IP might + * be a criterion for very stiff tracks. + * + * So the hitConnectors tell us were to look and the criteria whether to connect. If two 1-hit segments are found, + * that are compatible, they will be connected. Connected means: The inner 1-segment will save the outer one as a parent + * and the outer one will save the inner one as a child. + * + * All this (except adding hitConnectors and Criteria) is done in the method get1SegAutomaton. + * + * This method finally then returns an automaton (segments sorted by their layers), ready to be used. + * + */ + class SegmentBuilder{ + + + public: + + /** + * @param ftdRep the FTDRepresentation to take the autHits from + */ + SegmentBuilder( std::map< int , std::vector< IHit* > > map_sector_hits ); + + /** Adds a criterion. + */ + void addCriterion ( ICriterion* criterion ){ _criteria.push_back( criterion );}; + + /** Adds criteria + */ + void addCriteria ( std::vector< ICriterion* > criteria){ _criteria.insert( _criteria.end(), criteria.begin() , criteria.end() ); } + + /** Adds a hitConnector + */ + void addSectorConnector ( ISectorConnector* connector ){ _sectorConnectors.push_back( connector ); }; + + /** + * @return An automaton containing all the hits from the FTDRepresentation sorted now by layers. + * (attention: those are not necessarily the same layers as the FTD layers). + * Also they are connected. + */ + Automaton get1SegAutomaton(); + + + private: + + + std::vector <ICriterion* > _criteria{}; + std::vector <ISectorConnector* > _sectorConnectors{}; + + std::map< int , std::vector< IHit* > > _map_sector_hits{}; + + + + + + }; + + + + + +} + + +#endif + + + + + diff --git a/Utilities/KiTrack/KiTrack/Subset.h b/Utilities/KiTrack/KiTrack/Subset.h new file mode 100644 index 0000000000000000000000000000000000000000..6b3e9fd5bb216e7f2dfcc086bbc75a2537eb76d8 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/Subset.h @@ -0,0 +1,58 @@ +#ifndef Subset_h +#define Subset_h + + +#include "KiTrack/ITrack.h" + + +namespace KiTrack { + + /** A base class for subsets. + * + * The idea behind the subset classes is, that one has a collection of elements, but not all elements are compatible + * with each other. One wants to find a subset of these elements, where all are compatible. Also the subset should have + * a high quality. + * Details about this can be found in the derived classes. For technical reasons (templates and virtual methods) + * this class only covers the basics. + */ + template <class T> + class Subset{ + + public: + + /** Adds an element + */ + void add( T newElement ){ _elements.push_back( newElement ); }; + + /** Adds a vector of elements + */ + void add( std::vector<T> newElements ){ _elements.insert( _elements.end() , newElements.begin() , newElements.end() ); }; + + + /** @return the subset of the best tracks, i.e. all the tracks that were accepted + */ + std::vector< T > getAccepted(){ return _acceptedElements;} ; + + /** @return the tracks that got rejected (and are therefore not in the best subset) + */ + std::vector< T > getRejected(){ return _rejectedElements;} ; + + + + protected: + + std::vector< T > _elements{}; + std::vector< T > _acceptedElements{}; + std::vector< T > _rejectedElements{}; + + + }; + + + + +} + + +#endif + diff --git a/Utilities/KiTrack/KiTrack/SubsetHopfieldNN.h b/Utilities/KiTrack/KiTrack/SubsetHopfieldNN.h new file mode 100644 index 0000000000000000000000000000000000000000..5d92a2f079f6ef05cfcafac9af86ef5943b4e163 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/SubsetHopfieldNN.h @@ -0,0 +1,399 @@ +#ifndef SubsetHopfieldNN_h +#define SubsetHopfieldNN_h + +#include <CLHEP/Random/RandFlat.h> + +#include "KiTrack/Subset.h" +#include "KiTrack/HopfieldNeuralNet.h" + + + +namespace KiTrack { + + /** A class to get the best subset with help of a Hopfield Neural Network + * + */ + template< class T > + class SubsetHopfieldNN : public Subset<T>{ + + public: + + /** Calculates the best set using a Hopfield Neural Network + * (see <a href="../SubsetHopfieldNN.pdf">this</a> for more info) . + * + * After this the results can be accessed with + * the getAccepted() and getRejected() methods (provided by the baseclass Subset). + * + * + * This is a templated class to allow the reuse with objects from different. + * The goal is this: if you have a set of things that are somehow compatible or incompatible + * with each other and you want a subset that only contains compatible ones and has a high quality, to find + * this subset. + * + * For example: you plan a concert where a lot of different artists shall perform together. You have 20 that + * you are interested in asking. BUT: not all of them get along together very well. So artist 1 might be incompatible + * with artist 2 and 7 for some arbitrary reasons. And artist 2 is incompatible with artist 1,3 and 13 and so on. + * In order not to completely mess up the concert you can only invite artists who are entirely compatible with each other. + * AND: not all artists are equal: some are really famous and some are pretty mediocre. + * So you want to find a set of artists with the highest possible quality which is completely compatible. + * + * This is done by this class. The algorithm used for it is a Hopfield Neural Network (HNN). + * + * In order to work it needs to know two things: how to calculate the quality of an element and how to determine + * if two elements are compatible. These are of course things the user has to provide. + * For both a functor object is needed. + * + * Here is how it could look like in the artist example: + * +\verbatim + +class AristQI{ + + public: + + // returns the quality of an artist (a value between 0 and 1, 0 being bad and 1 being fantastic) + inline double operator()( Artist artist ){ + + return artist.numberOfFans()/nPeopleOnEarth; // a number between 0 and 1 + + } + +}; + +class ArtistCompatibility{ + +public: + + // returns whether two artists are compatible + inline bool operator()( Artist artistA, Artist artistB ){ + + if( artistA.hates( artistB ) ) return false; + else return true; + + } + +}; + + +//Somewhere within the program: + +ArtistCompatibility comp; +ArtistQI qi; + +SubsetHopfieldNN< Artist > subset; +subset.add( vecOfArtists ); +subset.calculateBestSet( comp, qi ); + +std::vector< Artist > artistsToInvite = subset.getAccepted(); +std::vector< Artist > artistsToStayAtHome = subset.getRejected(); + + +\endverbatim + * + * + * @param areCompatible a functor of type bool( T, T ) that should tell whether two elements are compatible + * or not. + * + * @param getQI a functor of type double( T ) that returns the quality of an element and should range between 0 and 1. + */ + template< class GetQI, class AreCompatible > + void calculateBestSet( AreCompatible areCompatible, GetQI getQI ); + + + SubsetHopfieldNN(){ + + _TStart = 2.1; + _TInf = 0.1; + _omega = 0.75; + _limitForStable = 0.01; + _initStateMin = 0.; + _initStateMax = 0.1; + _activationThreshold = 0.5; + + } + + void setTStart( double tStart ){ _TStart = tStart; } + void setTInf( double tInf ){ _TInf = tInf; } + void setOmega( double omega ){ _omega = omega; } + void setLimitForStable( double limitForStable ){ _limitForStable = limitForStable; } + void setInitStateMin( double initStateMin ){ _initStateMin = initStateMin; } + void setInitStateMax( double initStateMax ){ _initStateMax = initStateMax; } + void setActivationThreshold( double activationThreshold ){ _activationThreshold = activationThreshold; } + + double getTStart(){ return _TStart; } + double getTInf(){ return _TInf; } + double getOmega(){ return _omega; } + double getLimitForStable(){ return _limitForStable; } + double getInitStateMin(){ return _initStateMin; } + double getInitStateMax(){ return _initStateMax; } + double getActivationThreshold(){ return _activationThreshold; } + + protected: + + + double _TStart{}; + double _TInf{}; + double _omega{}; + double _limitForStable{}; + double _initStateMin{}; + double _initStateMax{}; + double _activationThreshold{}; + + }; + + + template< class T > template< class GetQI, class AreCompatible > + void SubsetHopfieldNN<T>::calculateBestSet( AreCompatible areCompatible, GetQI getQI ){ + + + unsigned nAccepted=0; + unsigned nRejected=0; + unsigned nCompWithAll=0; + unsigned nIncompatible=0; + + + std::vector< T > elements = this->_elements; //this pointer is needed here, because of the template! + + unsigned nElements = elements.size(); + + // the information for the Hopfield Neural Network: + + std::vector < std::vector <bool> > G; // a matrix telling, if two neurons (elements) are compatible + G.resize( nElements ); + for (unsigned i=0; i<nElements; i++) G[i].resize( elements.size() ); + + std::vector < double > QI ; // the quality indicators of the neurons (elements) + QI.resize( nElements ); + + std::vector < double > states; // the initial state to start from. + states.resize( nElements ); + + + + + /**********************************************************************************************/ + /* 1. Find out which elements are compatible and get the QIs */ + /**********************************************************************************************/ + + + for ( unsigned i=0; i < nElements ; i++){ //over all elements + + + T elementA = elements[i]; //the track we want to look at. + + // Get the quality + QI[i] = getQI( elementA ); + + //streamlog_out(DEBUG3) << "QI of element " << i << " = " << QI[i] << "\n"; + + + // Set an initial state + states[i] = CLHEP::RandFlat::shoot ( _initStateMin , _initStateMax ); //random ( uniformly ) values from initStateMin to initStateMax + + + // Fill the states in the G matrix. (whether two elements are compatible or not + for ( unsigned j=i+1; j < nElements ; j++ ){ // over all elements that come after the current one (the elements before get filled automatically because of symmetry) + + T elementB = elements[j]; // the track we check if it is in conflict with trackA + + if ( areCompatible( elementA , elementB ) ){ + + G[i][j] = 0; + G[j][i] = 0; + + } + else{ + + G[i][j] = 1; + G[j][i] = 1; + + } + + } + + } + + // output of the G matrix: + if( !G.empty() ){ + + //streamlog_out(DEBUG2) << "G:\n"; + + + for ( unsigned i=0; i < G.size(); i++ ){ + + + for ( unsigned j=0; j < G[i].size(); j++ ){ + + //streamlog_out(DEBUG2) << G[i][j] << " "; + + } + + //streamlog_out(DEBUG2) << "\n"; + + } + + } + // output, where one sees, what elements are incompatible with what others: + if( !G.empty() ){ + + //streamlog_out(DEBUG2) << "Incompatible ones:\n"; + + + for ( unsigned i=0; i < G.size(); i++ ){ + + //streamlog_out(DEBUG2) << "Element " << i << ":\t"; + + for ( unsigned j=0; j < G[i].size(); j++ ){ + + //if( G[i][j] ) streamlog_out(DEBUG2) << j << ", "; + + } + + //streamlog_out(DEBUG2) << "\n"; + + } + + } + + + /**********************************************************************************************/ + /* 2. Save elements, that are compatible with all others */ + /**********************************************************************************************/ + + for( unsigned i=0; i < elements.size(); i++ ){ + + + bool isCompatibleWithAll = true; + + //check if this track is compatible with all others + for( unsigned j=0; j < elements.size(); j++){ + + //G[i][j] == 0 i and j are compatible, if G[i][j] == 1 i and j are incompatible + if( (i != j) && G[i][j] ){ + + isCompatibleWithAll = false; + break; + + } + + } + + + if ( isCompatibleWithAll ){ //if it is compatible with all others, we don't need the Hopfield Neural Net, we can just save it + + + //add the track to the good ones + this->_acceptedElements.push_back( elements[i] ); + nCompWithAll++; + + + //And now erase it from the ones we will still check: + elements.erase( elements.begin() + i ); + states.erase( states.begin() + i ); + QI.erase( QI.begin() + i ); + + for( unsigned j=0; j<G.size(); j++ ) G[j].erase( G[j].begin() + i ); + G.erase( G.begin() + i ); + + i--; + + } + else{ + + nIncompatible++; + + } + + } + + + //streamlog_out( DEBUG3 ) << nCompWithAll << " elements are compatible with all others, " << nIncompatible + //<< " elements are interfering and will be checked for the best subset\n"; + + + + /**********************************************************************************************/ + /* 3. Let the Neural Network perform to find the best subset */ + /**********************************************************************************************/ + + if( !elements.empty() ){ + + HopfieldNeuralNet net( G , QI , states , _omega); + + net.setT ( _TStart ); + net.setTInf( _TInf ); + net.setLimitForStable( _limitForStable ); + + unsigned nIterations=1; + + //streamlog_out(DEBUG1) << "states: ( "; + //for ( unsigned int i=0; i< states.size(); i++) streamlog_out(DEBUG1) << states[i] << " "; + //streamlog_out(DEBUG1) << ")\n"; + + while ( !net.doIteration() ){ // while the Neural Net is not (yet) stable + + nIterations++; + + std::vector <double> newStates = net.getStates(); + + //streamlog_out(DEBUG1) << "states: ( "; + + //for ( unsigned int i=0; i< newStates.size(); i++) streamlog_out(DEBUG1) << newStates[i] << " "; + + //streamlog_out(DEBUG1) << ")\n"; + + } + + + + //streamlog_out( DEBUG3 ) << "Hopfield Neural Network is stable after " << nIterations << " iterations.\n"; + + + + + /**********************************************************************************************/ + /* 4. Now just sort the elements into accepted and rejected ones */ + /**********************************************************************************************/ + + + states = net.getStates(); + + + + for ( unsigned i=0; i < states.size(); i++ ){ + + + if ( states[i] >= _activationThreshold ){ + + this->_acceptedElements.push_back( elements[i] ); + nAccepted++; + + } + else{ + + this->_rejectedElements.push_back( elements[i] ); + nRejected++; + + } + + } + + } + + + //streamlog_out( DEBUG3 ) << "Hopfield Neural Network accepted " << nAccepted + //<< " elements and rejected " << nRejected << " elements of all in all " + //<< nAccepted + nRejected << "incomaptible elements.\n"; + + //streamlog_out( DEBUG3 ) << "So in sum " << nAccepted + nCompWithAll + //<< " elements survived and " << nRejected << " elements got rejected.\n"; + + + } + + +} + + +#endif + diff --git a/Utilities/KiTrack/KiTrack/SubsetSimple.h b/Utilities/KiTrack/KiTrack/SubsetSimple.h new file mode 100644 index 0000000000000000000000000000000000000000..a552162150682557be6982e380c7dbdcc84787d9 --- /dev/null +++ b/Utilities/KiTrack/KiTrack/SubsetSimple.h @@ -0,0 +1,186 @@ +#ifndef SubsetSimple_h +#define SubsetSimple_h + +#include <algorithm> + +//#include "marlin/VerbosityLevels.h" + +#include "KiTrack/Subset.h" + +namespace KiTrack { + + + template <class T, class QI > + struct SorterQI + { + SorterQI( QI getQI ): _getQI( getQI ){} + + bool operator()( T a, T b ){ return ( _getQI( a ) > _getQI( b ) ); } + + QI _getQI; + }; + + + /** A class to get the best subset by taking the element with the highest quality + * indicator and throwing away all incompatible ones. + * On the remaining elements repeat the procedure. + * + */ + template <class T > + class SubsetSimple : public Subset<T> { + + public: + + /** Calculates the best set using a very simple method. After this the results can be accessed with + * the getAccepted() and getRejected() methods (provided by the baseclass Subset). + * + * This is a templated class to allow the reuse with objects from different. + * The goal is this: if you have a set of things that are somehow compatible or incompatible + * with each other and you want a subset that only contains compatible ones and has a high quality, to find + * this subset. + * + * For example: you plan a concert where a lot of different artists shall perform together. You have 20 that + * you are interested in asking. BUT: not all of them get along together very well. So artist 1 might be incompatible + * with artist 2 and 7 for some arbitrary reasons. And artist 2 is incompatible with artist 1,3 and 13 and so on. + * In order not to completely mess up the concert you can only invite artists who are entirely compatible with each other. + * AND: not all artists are equal: some are really famous and some are pretty mediocre. + * So you want to find a set of artists with the highest possible quality which is completely compatible. + * + * This is done by this class. + * + * The algorithm used for it is this: take the element with the highest quality and accept it. Reject all + * other elements that are incompatible with it. From the remaining elements redo the same with the next best + * element. + * In our artist example: take the biggest star and throw out all he doesn't get allong with. From the remaining + * artists (those who do get along with the biggest star) pick next famous one. Once again kick out all that + * don't get along with him and so on. + * + * In order to work it needs to know two things: how to calculate the quality of an element and how to determine + * if two elements are compatible. These are of course things the user has to provide. + * For both a functor object is needed. + * + * Here is how it could look like in the artist example: + * +\verbatim + +class AristQI{ + +public: + + // returns the quality of an artist (a value between 0 and 1, 0 being bad and 1 being fantastic) + inline double operator()( Artist artist ){ + + return artist.numberOfFans()/nPeopleOnEarth; // a number between 0 and 1 + + } + +}; + +class ArtistCompatibility{ + +public: + + // returns whether two artists are compatible + inline bool operator()( Artist artistA, Artist artistB ){ + + if( artistA.hates( artistB ) ) return false; + else return true; + + } + +}; + + +//Somewhere within the program: + +ArtistCompatibility comp; +ArtistQI qi; + +SubsetHopfieldNN< Artist > subset; +subset.add( vecOfArtists ); +subset.calculateBestSet( comp, qi ); + +std::vector< Artist > artistsToInvite = subset.getAccepted(); +std::vector< Artist > artistsToStayAtHome = subset.getRejected(); + + +\endverbatim + * + * + * + * @param areCompatible a functor of type bool( T, T ) that should tell whether two elements are compatible + * or not. + * + * @param getQI a functor of type double( T ) that returns the quality of an element and should range between 0 and 1. + */ + template< class GetQI, class AreCompatible > + void calculateBestSet( AreCompatible areCompatible, GetQI getQI ); + }; + + template<class T> template<class GetQI, class AreCompatible> + void SubsetSimple<T>::calculateBestSet( AreCompatible areCompatible, GetQI getQI ){ + + + unsigned nAccepted=0; + unsigned nRejected=0; + + + + std::vector< T > elements = this->_elements; + + // sort the vector from big QI to small QI + SorterQI< T, GetQI > sorterQI( getQI ); + sort( elements.begin(), elements.end() , sorterQI ); + + //std::cout << "DEBUG: SubsetSimple::calculateBestSet The elements and their QIs sorted:" << std::endl; + for( unsigned i=0; i < elements.size(); i++ ){ + double qi = getQI( elements[i] ); + //std::cout << "DEBUG: SubsetSimple::calculateBestSet " << elements[i] << "\t" << qi << std::endl; + } + + /*The idea here is: the first track is (now that we sorted) the one with the highest + * QI. Check all other tracks if they are complatible with it. + * If one of them is incompatible throw it away. Once done with that, store the + * first track as accepted (and delete it from the vector) and do it once more for + * the new highest QI track. + * Repeat until all tracks are stored. + */ + while( elements.size() > 0 ){ + + + // check all elements with smaller QI if they are compatible + for( unsigned i=1; i < elements.size(); i++){ + + + if( areCompatible( elements[0] , elements[i] ) == false ){ // the track is incompatible + + // reject it + nRejected++; + this->_rejectedElements.push_back( elements[i] ); + + //std::cout << "DEBUG: SubsetSimple::calculateBestSet " << "reject " << elements[i] << std::endl; + // and delete it from the elements we are looking at + elements.erase( elements.begin() + i ); + i--; + + } + + } + + // store the first element + //std::cout << "DEBUG: SubsetSimple::calculateBestSet " << "accept " << elements[0] << std::endl; + nAccepted++; + this->_acceptedElements.push_back( elements[0] ); + + // delete it from the current tracks + elements.erase( elements.begin() ); + + } + + //std::cout << "DEBUG: SubsetSimple::calculateBestSet " << "SubsetSimple accepted " << nAccepted + // << " elements and rejected " << nRejected << " elements of all in all " + // << nAccepted + nRejected << " elements." << std::endl; + + } +} // end namespace +#endif diff --git a/Utilities/KiTrack/Tools/FTDHelixFitter.h b/Utilities/KiTrack/Tools/FTDHelixFitter.h new file mode 100644 index 0000000000000000000000000000000000000000..6050ae018a1a29e5aa0e9d9a73cf63a86678ee58 --- /dev/null +++ b/Utilities/KiTrack/Tools/FTDHelixFitter.h @@ -0,0 +1,65 @@ +#ifndef FTDHelixFitter_h +#define FTDHelixFitter_h + +#include "edm4hep/Track.h" +#include "edm4hep/TrackerHitConst.h" + +class FTDHelixFitterException : public std::exception { + protected: + std::string message ; + + FTDHelixFitterException(){ /*no_op*/ ; } + + public: + virtual ~FTDHelixFitterException() { /*no_op*/; } + + FTDHelixFitterException( const std::string& text ){ + message = "FTDHelixFitterException: " + text ; + } + + virtual const char* what() const noexcept { return message.c_str() ; } + +}; + +/** A class to make it quick to fit a track or hits and get back the chi2 and Ndf values and + * also bundle the code used for that, so it doesn't have to be copied all over the places. + * Uses a helix fit from the MarlinTrk class HelixFit.cc + * It is named FTDHelixFitter, because it makes some assumptions about the hits, that come from them + * being on the FTD. Specifically the errors passed to the helix fit are calculated on the assumption, + * that du and dv are errors in the xy plane. + * If this class is intended to be used for hits on different detectors, a careful redesign is necessary! + */ +class FTDHelixFitter{ + public: + + FTDHelixFitter( edm4hep::Track* track ) ; + FTDHelixFitter( std::vector<edm4hep::ConstTrackerHit> trackerHits ) ; + + + double getChi2(){ return _chi2; } + int getNdf(){ return _Ndf; } + + float getOmega(){ return _omega; } + float getTanLambda(){ return _tanLambda; } + float getPhi0(){ return _phi0; } + float getD0(){ return _d0; } + float getZ0(){ return _z0; } + + private: + + void fit(); + + double _chi2; + int _Ndf; + + float _omega; + float _tanLambda; + float _phi0; + float _d0; + float _z0; + + std::vector< edm4hep::ConstTrackerHit > _trackerHits; + +}; + +#endif diff --git a/Utilities/KiTrack/Tools/Fitter.h b/Utilities/KiTrack/Tools/Fitter.h new file mode 100644 index 0000000000000000000000000000000000000000..461d735d286184936604b4eb148b93d9a7e16220 --- /dev/null +++ b/Utilities/KiTrack/Tools/Fitter.h @@ -0,0 +1,129 @@ +#ifndef Fitter_h +#define Fitter_h + +#include "TrackSystemSvc/IMarlinTrkSystem.h" +#include "TrackSystemSvc/IMarlinTrack.h" +#include "edm4hep/Track.h" +//#include "lcio.h" + +#include "Math/ProbFunc.h" + + +//using namespace lcio; + + + +class FitterException : public std::exception { + + +protected: + std::string message ; + + FitterException(){ /*no_op*/ ; } + +public: + virtual ~FitterException() { /*no_op*/; } + + FitterException( const std::string& text ){ + message = "FitterException: " + text ; + } + + virtual const char* what() const noexcept { return message.c_str() ; } + +}; + + + +/** A class to store additional information together with a TrackState, namely the chi2 value and Ndf + */ +class TrackStatePlus{ + + + +public: + + const edm4hep::TrackState* getTrackState() const {return _trackState; } + double getChi2() const {return _chi2;} + int getNdf() const {return _Ndf;} + + TrackStatePlus( const edm4hep::TrackState* trackState, double chi2, int Ndf ): + _trackState( trackState ), _chi2( chi2 ), _Ndf( Ndf ){} + + + +private: + + const edm4hep::TrackState* _trackState; + double _chi2; + int _Ndf; + + +}; + + +/** A class to make it quick to fit a track or hits and get back the chi2, Ndf and chi2prob values and + * also bundle the code used for that, so it doesn't have to be copied all over the places. + */ +class Fitter{ + + +public: + + Fitter( edm4hep::Track* track , MarlinTrk::IMarlinTrkSystem* trkSystem ); + Fitter( std::vector < edm4hep::ConstTrackerHit > trackerHits, MarlinTrk::IMarlinTrkSystem* trkSystem ); + Fitter( edm4hep::Track* track , MarlinTrk::IMarlinTrkSystem* trkSystem, int VXDFlag ); + + + double getChi2Prob( int trackStateLocation ) ; + double getChi2( int trackStateLocation ) ; + int getNdf( int trackStateLocation ) ; + + //TODO: maybe add methods for custom points (location: TrackState::AtOther) In that case, the point would have to + // be passed as well. (or only the point is passed) + + const edm4hep::TrackState* getTrackState( int trackStateLocation ) ; + + ~Fitter(){ + + for( unsigned i=0; i<_trackStatesPlus.size(); i++ ){ + + delete _trackStatesPlus[i]->getTrackState(); + delete _trackStatesPlus[i]; + + } + _trackStatesPlus.clear(); + + delete _marlinTrk; + + } + +private: + + void init_BField(); + + const TrackStatePlus* getTrackStatePlus( int trackStateLocation ) ; + + void fit(); + + void fitVXD(); + + static float _bField; + + + std::vector< edm4hep::ConstTrackerHit > _trackerHits; + + /** here the created TrackStates (plus) are stored */ + std::vector< const TrackStatePlus* > _trackStatesPlus; + + MarlinTrk::IMarlinTrkSystem* _trkSystem; + + MarlinTrk::IMarlinTrack* _marlinTrk; + + // No copy constructor or assignment needed so far. so private for safety + // If they are needed, they need to be implemented in a clean way first! + Fitter( const Fitter& f ){}; + Fitter& operator= ( Fitter const& f ){return *this;} + +}; + +#endif diff --git a/Utilities/KiTrack/Tools/KiTrackMarlinTools.h b/Utilities/KiTrack/Tools/KiTrackMarlinTools.h new file mode 100644 index 0000000000000000000000000000000000000000..f4b582928e31485985445d945aa07d34c833a749 --- /dev/null +++ b/Utilities/KiTrack/Tools/KiTrackMarlinTools.h @@ -0,0 +1,97 @@ +#ifndef KiTrackMarlinTools_h +#define KiTrackMarlinTools_h + +#include <string> +#include <set> +#include <vector> +#include <map> +//#include <sstream> + +#include "edm4hep/TrackerHit.h" +#include "edm4hep/Track.h" + +#include "ILDImpl/FTDHitSimple.h" +#include "ILDImpl/VXDHitSimple.h" +#include "KiTrack/ITrack.h" + +using namespace KiTrack; + +namespace KiTrackMarlin{ + +/** @return information about the contents of the passed CellID0 */ +std::string getCellID0Info( int cellID0 ); + +/** @return the layer given by the cellID0 */ +int getCellID0Layer( int cellID0 ); + +/** Generates a root file with a specified name and with a single tree . + * If a rootfile with the same name already exists, a number will be appended + * to it, so the old one doesn't get lost. + * So if I create myRoot.root and it already exists, the old one will be renamed to + * "myRoot1.root". + * If "myRoot1.root" already exists, "myRoot2.root" will be created. + * + * So after we did this for some time, we end up with a lot of root files with numbers. + * The one without a number appended is the newest one. + * The one with the number 1 appended is the oldest, 2 is newer than 1, 3 is newer than 2 and so on. + * + * @param branchNames A set of all the branchnames that should be created in the tree + * + * @param createNew Whether to create a new root file or create the tree and branches in an existing one + */ +void setUpRootFile( std::string fileNamePath, std::string treeName , std::set<std::string> branchNames = std::set<std::string>() , bool createNew=true ); + + +/** Saves values to a tree in a rootfile. + * + * @param fileNamePath the name (path) of the rootfile + * + * @param treeName the name of the tree + * + * @param map_name_data a map of key = name of what we save , mapped value = value we want to save + * + */ +void saveToRoot( std::string fileNamePath, std::string treeName , std::map < std::string , float > map_name_data ); + +void saveToRoot( std::string rootFileName, std::string treeName , std::vector < std::map < std::string , float > > rootDataVec ); + + + + +/** method that compares two TrackerHits. + * + * @return true if |a.z| < |b.z| , i.e. true if a is nearer to z=0 than b is + */ +//bool compare_TrackerHit_z( edm4hep::ConstTrackerHit* a, edm4hep::ConstTrackerHit* b ); +bool compare_TrackerHit_z( edm4hep::ConstTrackerHit& a, edm4hep::ConstTrackerHit& b ); + +/** method that compares two TrackerHits. + * + * @return true if |a.R| < |b.R| , i.e. true if a has smaller radius than b + * + * to be used at the VXD-SIT system + */ +bool compare_TrackerHit_R( edm4hep::ConstTrackerHit& a, edm4hep::ConstTrackerHit& b ); + + +FTDHitSimple* createVirtualIPHit( int side , const SectorSystemFTD* sectorSystemFTD ); + +VXDHitSimple* createVirtualIPHit( const SectorSystemVXD* sectorSystemVXD ); + + +std::string getPositionInfo( edm4hep::ConstTrackerHit* hit ); + +std::string getPositionInfo( IHit* hit ); + +std::string getTrackHitInfo( ITrack* track ); + +std::string getTrackHitInfo( edm4hep::Track* track ); + +} // end of namespace KiTrackMarlin + + + + +#endif + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.cc b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.cc new file mode 100644 index 0000000000000000000000000000000000000000..9bf3a11f9aaf7a3c3245c29b195e01f5c99a2ce7 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.cc @@ -0,0 +1,84 @@ +#include "Criteria/Crit2_DeltaPhi.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + +Crit2_DeltaPhi::Crit2_DeltaPhi ( float deltaPhiMin , float deltaPhiMax ){ + + + _deltaPhiMax = deltaPhiMax; + _deltaPhiMin = deltaPhiMin; + _name = "Crit2_DeltaPhi"; + _type = "2Hit"; + + _saveValues = false; + +} + + + +bool Crit2_DeltaPhi::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments + + + + IHit* a = parent->getHits()[0]; + IHit* b = child-> getHits()[0]; + + float ax = a->getX(); + float ay = a->getY(); + + + float bx = b->getX(); + float by = b->getY(); + + + + float phia = atan2( ay, ax ); + float phib = atan2( by, bx ); + float deltaPhi = phia-phib; + if (deltaPhi > M_PI) deltaPhi -= 2*M_PI; //to the range from -pi to pi + if (deltaPhi < -M_PI) deltaPhi += 2*M_PI; //to the range from -pi to pi + + if (( by*by + bx*bx < 0.0001 )||( ay*ay + ax*ax < 0.0001 )) deltaPhi = 0.; // In case one of the hits is too close to the origin + + deltaPhi = 180.*fabs( deltaPhi ) / M_PI; + if (_saveValues) _map_name_value["Crit2_DeltaPhi"]= deltaPhi; + + + + + + if ( deltaPhi > _deltaPhiMax ) return false; + + if ( deltaPhi < _deltaPhiMin ) return false; + + + + } + else{ + + std::stringstream s; + s << "Crit2_DeltaPhi::This criterion needs 2 segments with 1 hit each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.h b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.h new file mode 100644 index 0000000000000000000000000000000000000000..342e7750db14af2da438982d603d4c5f06d091e5 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi.h @@ -0,0 +1,38 @@ +#ifndef Crit2_DeltaPhi_h +#define Crit2_DeltaPhi_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the difference between the \f$ \phi \f$ angles of two hits in degrees. + * The \f$ \phi \f$ is the angle in the xy plane w.r.t. the positive x axis. + * \f[ \phi = atan2(y,x) \f] + */ + class Crit2_DeltaPhi : public ICriterion{ + + + + public: + + Crit2_DeltaPhi ( float deltaPhiMin , float deltaPhiMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit2_DeltaPhi(){}; + + + private: + + float _deltaPhiMax{}; + float _deltaPhiMin{}; + + + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.cc b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.cc new file mode 100644 index 0000000000000000000000000000000000000000..a94b0ea99e5036dcaf0bd49c6f8c0d3440dfa31b --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.cc @@ -0,0 +1,78 @@ +#include "Criteria/Crit2_DeltaPhi_MV.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + +Crit2_DeltaPhi_MV::Crit2_DeltaPhi_MV ( float deltaPhiMin , float deltaPhiMax ){ + + + _deltaPhiMax = deltaPhiMax; + _deltaPhiMin = deltaPhiMin; + _name = "Crit2_DeltaPhi_MV"; + _type = "2Hit"; + + _saveValues = false; + +} + + + +bool Crit2_DeltaPhi_MV::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments + + IHit* a = parent->getHits()[0]; + IHit* b = child->getHits()[0]; + + double phia = a->getPhi(); + double phib = b->getPhi(); + + double deltaPhi = phia-phib; + + if (deltaPhi > M_PI) deltaPhi -= 2*M_PI; //to the range from -pi to pi + if (deltaPhi < -M_PI) deltaPhi += 2*M_PI; //to the range from -pi to pi + + float ax = a->getX(); + float ay = a->getY(); + float bx = b->getX(); + float by = b->getY(); + + if (( by*by + bx*bx < 0.0001 )||( ay*ay + ax*ax < 0.0001 )) deltaPhi = 0.; // In case one of the hits is too close to the origin + + deltaPhi = 180.*fabs( deltaPhi ) / M_PI; + if (_saveValues) _map_name_value["Crit2_DeltaPhi_MV"]= deltaPhi; + + + if ( deltaPhi > _deltaPhiMax ) return false; + + if ( deltaPhi < _deltaPhiMin ) return false; + + + } + + + else{ + + std::stringstream s; + s << "Crit2_DeltaPhi_MV::This criterion needs 2 segments with 1 hit each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.h b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.h new file mode 100644 index 0000000000000000000000000000000000000000..3dee9bad833ba8c0972ed5e510a2a681b1bc3783 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaPhi_MV.h @@ -0,0 +1,38 @@ +#ifndef Crit2_DeltaPhi_MV_h +#define Crit2_DeltaPhi_MV_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the difference between the \f$ \phi \f$ angles of two hits in degrees. + * The \f$ \phi \f$ is the angle in the xy plane w.r.t. the positive x axis. + * \f[ \phi = atan2(y,x) \f] + */ + class Crit2_DeltaPhi_MV : public ICriterion{ + + + + public: + + Crit2_DeltaPhi_MV ( float deltaPhiMin , float deltaPhiMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit2_DeltaPhi_MV(){}; + + + private: + + float _deltaPhiMax{}; + float _deltaPhiMin{}; + + + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.cc b/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.cc new file mode 100644 index 0000000000000000000000000000000000000000..64190dc6bcd259735ac07395dfde82b0311d825a --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.cc @@ -0,0 +1,81 @@ +#include "Criteria/Crit2_DeltaRho.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + +Crit2_DeltaRho::Crit2_DeltaRho ( float deltaRhoMin , float deltaRhoMax ){ + + + _deltaRhoMax = deltaRhoMax; + _deltaRhoMin = deltaRhoMin; + + _name = "Crit2_DeltaRho"; + _type = "2Hit"; + + _saveValues = false; + +} + + + +bool Crit2_DeltaRho::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments + + + + IHit* a = parent->getHits()[0]; + IHit* b = child-> getHits()[0]; + + float ax = a->getX(); + float ay = a->getY(); + + float bx = b->getX(); + float by = b->getY(); + + //the distance to (0,0) in the xy plane + float rhoA = sqrt( ax*ax + ay*ay ); + float rhoB = sqrt( bx*bx + by*by ); + + float deltaRho = rhoA - rhoB; + + //first check, if the distance to (0,0) rises --> such a combo could not reach the IP + if (_saveValues){ + _map_name_value["Crit2_DeltaRho_rhoParent"] = rhoA; + _map_name_value["Crit2_DeltaRho_rhoChild"] = rhoB; + _map_name_value["Crit2_DeltaRho"] = deltaRho; + } + + + + if ( deltaRho > _deltaRhoMax ) return false; + if ( deltaRho < _deltaRhoMin ) return false; + + + + } + else{ + + std::stringstream s; + s << "Crit2_DeltaRho::This criterion needs 2 segments with 1 hit each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.h b/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.h new file mode 100644 index 0000000000000000000000000000000000000000..3b65daecc133f9b6d6712fb2c9a22858405b8d5f --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaRho.h @@ -0,0 +1,36 @@ +#ifndef Crit2_DeltaRho_h +#define Crit2_DeltaRho_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the difference of the sqrt(x^2 + y^2) of two hits. + */ + class Crit2_DeltaRho : public ICriterion{ + + + + public: + + Crit2_DeltaRho ( float deltaRhoMin , float deltaRhoMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit2_DeltaRho(){}; + + + private: + + float _deltaRhoMax{}; + float _deltaRhoMin{}; + + + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.cc b/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.cc new file mode 100644 index 0000000000000000000000000000000000000000..5d0f0463a2a677c886224c894501788b7d39104c --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.cc @@ -0,0 +1,84 @@ +#include "Criteria/Crit2_DeltaTheta_MV.h" + +#include <cmath> +#include <sstream> +//#include <iostream> // for debugging + +using namespace KiTrack; + +Crit2_DeltaTheta_MV::Crit2_DeltaTheta_MV ( float deltaThetaMin , float deltaThetaMax ){ + + + _deltaThetaMax = deltaThetaMax; + _deltaThetaMin = deltaThetaMin; + _name = "Crit2_DeltaTheta_MV"; + _type = "2Hit"; + + _saveValues = false; + +} + + + +bool Crit2_DeltaTheta_MV::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments + + + IHit* a = parent->getHits()[0]; + IHit* b = child->getHits()[0]; + + + double thetaa = a->getTheta(); + double thetab = b->getTheta(); + + //streamlog_out(DEBUG4) << " theta a = " << (180*thetaa)/M_PI << " theta b = " << (180*thetab)/M_PI << std::endl ; + + double deltaTheta = thetaa-thetab; + + if (deltaTheta > M_PI) deltaTheta -= 2*M_PI; //to the range from -pi to pi + if (deltaTheta < -M_PI) deltaTheta += 2*M_PI; //to the range from -pi to pi + + float ax = a->getX(); + float ay = a->getY(); + float bx = b->getX(); + float by = b->getY(); + + if (( by*by + bx*bx < 0.0001 )||( ay*ay + ax*ax < 0.0001 )) deltaTheta = 0.; // In case one of the hits is too close to the origin + + deltaTheta = 180.*fabs( deltaTheta ) / M_PI; + if (_saveValues) _map_name_value["Crit2_DeltaTheta_MV"]= deltaTheta; + + + if ( deltaTheta > _deltaThetaMax ) return false; + + if ( deltaTheta < _deltaThetaMin ) return false; + + //streamlog_out(DEBUG4) << " delta theta " << deltaTheta << " max " << _deltaThetaMax << " min " << _deltaThetaMin << std::endl ; + + + } + + else{ + + std::stringstream s; + s << "Crit2_DeltaTheta_MV::This criterion needs 2 segments with 1 hit each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.h b/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.h new file mode 100644 index 0000000000000000000000000000000000000000..3f9a0494d39012c34e9daf7881851da43abeeefc --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_DeltaTheta_MV.h @@ -0,0 +1,38 @@ +#ifndef Crit2_DeltaTheta_MV_h +#define Crit2_DeltaTheta_MV_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the difference between the \f$ \theta \f$ angles of two hits in degrees. + * The \f$ \theta \f$ is the angle in the xy plane w.r.t. the positive x axis. + * \f[ \theta = atan2(y,x) \f] + */ + class Crit2_DeltaTheta_MV : public ICriterion{ + + + + public: + + Crit2_DeltaTheta_MV ( float deltaThetaMin , float deltaThetaMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit2_DeltaTheta_MV(){}; + + + private: + + float _deltaThetaMax{}; + float _deltaThetaMin{}; + + + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.cc b/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.cc new file mode 100644 index 0000000000000000000000000000000000000000..95f5e7d26c612080998e18c0c6136abdf8bda2b7 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.cc @@ -0,0 +1,74 @@ +#include "Criteria/Crit2_Distance_MV.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + +Crit2_Distance_MV::Crit2_Distance_MV ( float deltaPos2Min , float deltaPos2Max ){ + + + _deltaPos2Max = deltaPos2Max; + _deltaPos2Min = deltaPos2Min; + _name = "Crit2_Distance_MV"; + _type = "2Hit"; + + _saveValues = false; + +} + + + +bool Crit2_Distance_MV::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments + + IHit* a = parent->getHits()[0]; + IHit* b = child->getHits()[0]; + + float ax = a->getX(); + float ay = a->getY(); + float bx = b->getX(); + float by = b->getY(); + + double posa = sqrt(ax*ax + ay*ay); + double posb = sqrt(bx*bx + by*by); + + double deltaPos2 = (posa-posb) * (posa-posb) ; + + if (( by*by + bx*bx < 0.0001 )||( ay*ay + ax*ax < 0.0001 )) deltaPos2 = 0.; // In case one of the hits is too close to the origin + + if (_saveValues) _map_name_value["Crit2_Distance_MV"]= deltaPos2; + + + if ( deltaPos2 > _deltaPos2Max ) return false; + + if ( deltaPos2 < _deltaPos2Min ) return false; + + + } + + + else{ + + std::stringstream s; + s << "Crit2_Distance_MV::This criterion needs 2 segments with 1 hit each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.h b/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.h new file mode 100644 index 0000000000000000000000000000000000000000..6463acb2417765ec960d8af3450b087594e3f909 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_Distance_MV.h @@ -0,0 +1,38 @@ +#ifndef Crit2_Distance_MV_h +#define Crit2_Distance_MV_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the difference between the \f$ \phi \f$ angles of two hits in degrees. + * The \f$ \phi \f$ is the angle in the xy plane w.r.t. the positive x axis. + * \f[ \phi = atan2(y,x) \f] + */ + class Crit2_Distance_MV : public ICriterion{ + + + + public: + + Crit2_Distance_MV ( float deltaPos2Min , float deltaPos2Max ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit2_Distance_MV(){}; + + + private: + + float _deltaPos2Max{}; + float _deltaPos2Min{}; + + + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.cc b/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.cc new file mode 100644 index 0000000000000000000000000000000000000000..0c8baf1cb29f1e19b86513ddc7ce356ea445a6a4 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.cc @@ -0,0 +1,125 @@ +#include "Criteria/Crit2_HelixWithIP.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + +using namespace KiTrack; + +Crit2_HelixWithIP::Crit2_HelixWithIP ( float ratioMin , float ratioMax ){ + + + _ratioMax = ratioMax; + _ratioMin = ratioMin; + + _name = "Crit2_HelixWithIP"; + _type = "2Hit"; + + _saveValues = false; + +} + + + +bool Crit2_HelixWithIP::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments + + + + IHit* a = parent->getHits()[0]; + IHit* b = child-> getHits()[0]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + + + float ratio = 1.; + + try{ + + SimpleCircle circle ( 0. , 0. , ax , ay , bx , by ); + + float x = circle.getCenterX(); + float y = circle.getCenterY(); + + + //calculate the angle in the circle from the IP to the child hit: + + //vector from the center of circle to the IP + float ux = 0. - x; + float uy = 0. - y; + + //vector from the center of circle to the child + float vx = bx - x; + float vy = by - y; + + //vector from the center of circle to the parent + float wx = ax - x; + float wy = ay - y; + + //the angle between u and v (angle between two vectors: cos(alpha) = u*v/|u||v| ) + float alpha1 = acos ( (ux*vx + uy*vy ) / sqrt(( ux*ux + uy*uy ) * ( vx*vx + vy*vy )) ); + + //the angle between v and w + float alpha2 = acos ( (vx*wx + vy*wy ) / sqrt(( vx*vx + vy*vy ) * ( wx*wx + wy*wy )) ); + + float deltaz1 = bz - 0.; + float deltaz2 = az - bz; + + + + if ( ( alpha2 != 0) && (deltaz1 != 0) ) ratio = ( alpha1 * deltaz2 ) / ( alpha2 * deltaz1 ); + + + + + } + catch ( InvalidParameter ){ + + + } + + + + + if (_saveValues) _map_name_value["Crit2_HelixWithIP"]= ratio; + + + if ( ratio > _ratioMax ) return false; + + if ( ratio < _ratioMin ) return false; + + + + } + else{ + + std::stringstream s; + s << "Crit2_HelixWithIP::This criterion needs 2 segments with 1 hit each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.h b/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.h new file mode 100644 index 0000000000000000000000000000000000000000..2f888e15710551ce99618e2d228f5da93d242e1f --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_HelixWithIP.h @@ -0,0 +1,43 @@ +#ifndef Crit2_HelixWithIP_h +#define Crit2_HelixWithIP_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: Check if two hits are compatible with a helix crossing the IP. + * The procedure is this: a circle is calculated from the two hits and the IP. + * The angle between the center of the circle and two hits is calles alpha here. + * alpha between IP and the first hit is proportional to the z-distance of the IP + * and the first hit in the same way alpha between the first and second hit should + * be proportional to the z-distance of those hits. The value calculated is + * \f[ \frac{ \frac{\alpha_1}{\Delta z_1} }{ \frac{\alpha_2}{\Delta z_2} } \simeq 1 \f] + * and is 1 for a perfect helix around the z - axis. + */ + class Crit2_HelixWithIP : public ICriterion{ + + + + public: + + Crit2_HelixWithIP ( float ratioMin , float ratioMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit2_HelixWithIP(){}; + + + private: + + float _ratioMax{}; + float _ratioMin{}; + + + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.cc b/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.cc new file mode 100644 index 0000000000000000000000000000000000000000..781e95b8a6c817114a1c4efe7c2e23c32f1f9960 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.cc @@ -0,0 +1,82 @@ +#include "Criteria/Crit2_RZRatio.h" + +#include <cmath> +#include <sstream> + + +using namespace KiTrack; + +Crit2_RZRatio::Crit2_RZRatio ( float ratioMin, float ratioMax ){ + + + _ratioMax = ratioMax; + _ratioMin = ratioMin; + + _name = "Crit2_RZRatio"; + _type = "2Hit"; + + _saveValues = false; + + + +} + + +bool Crit2_RZRatio::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments + + + IHit* a = parent->getHits()[0]; + IHit* b = child-> getHits()[0]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + // the square is used, because it is faster to calculate with the squares than with sqrt, which takes some time! + double ratioSquared = 0.; + if ( az-bz != 0. ) ratioSquared = ( (ax-bx)*(ax-bx) + (ay-by)*(ay-by) + (az-bz)*(az-bz) ) / ( (az-bz) * ( az-bz ) ); + + + if (_saveValues) _map_name_value[ "Crit2_RZRatio"] = sqrt( ratioSquared ); + + + + if ( ratioSquared > _ratioMax * _ratioMax ) return false; + if ( ratioSquared < _ratioMin * _ratioMin ) return false; + + + + } + else{ + + std::stringstream s; + s << "Crit2_RZRatio::This criterion needs 2 segments with 1 hit each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + + + + + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.h b/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.h new file mode 100644 index 0000000000000000000000000000000000000000..1d1ea36f6f468d59d3622047739f72ab009ed8f7 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_RZRatio.h @@ -0,0 +1,35 @@ +#ifndef Crit2_RZRatio_h +#define Crit2_RZRatio_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: distance of two hits divided by their z-distance. + * \f[ \frac{\sqrt{ \Delta x^2 + \Delta y^2 + \Delta z^2 }}{\left| \Delta z \right|}\f] + */ + class Crit2_RZRatio : public ICriterion{ + + + + public: + + Crit2_RZRatio ( float ratioMin, float ratioMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit2_RZRatio(){}; + + private: + + float _ratioMax{}; + float _ratioMin{}; + + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.cc b/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.cc new file mode 100644 index 0000000000000000000000000000000000000000..f52351ef169c09aca3881a6956c530a5ec24c46c --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.cc @@ -0,0 +1,90 @@ +#include "Criteria/Crit2_StraightTrackRatio.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + +Crit2_StraightTrackRatio::Crit2_StraightTrackRatio ( float ratioMin, float ratioMax ){ + + + _ratioMax = ratioMax; + _ratioMin = ratioMin; + + _name = "Crit2_StraightTrackRatio"; + _type = "2Hit"; + + _saveValues = false; + +} + + + +bool Crit2_StraightTrackRatio::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 1 )&&( child->getHits().size() == 1 )){ //a criterion for 1-segments + + + + IHit* a = parent->getHits()[0]; + IHit* b = child-> getHits()[0]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + //the distance to (0,0) in the xy plane + double rhoASquared = ax*ax + ay*ay; + double rhoBSquared = bx*bx + by*by; + + + + + if (_saveValues){ + _map_name_value["Crit2_StraightTrackRatio"]= 1.; + + } + + + if( (rhoBSquared >0.) && ( az != 0. ) ){ //prevent division by 0 + + // the square is used, because it is faster to calculate with the squares than with sqrt, which takes some time! + double ratioSquared = ( ( rhoASquared * ( bz*bz ) ) / ( rhoBSquared * ( az*az ) ) ); + + if (_saveValues) _map_name_value["Crit2_StraightTrackRatio"] = sqrt(ratioSquared); + + + if ( ratioSquared > _ratioMax * _ratioMax ) return false; + + if ( ratioSquared < _ratioMin * _ratioMin ) return false; + + } + + } + else{ + + std::stringstream s; + s << "Crit2_StraightTrackRatio::This criterion needs 2 segments with 1 hit each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + + diff --git a/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.h b/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.h new file mode 100644 index 0000000000000000000000000000000000000000..3d46c21509bbda09bbf3e302cacd0839ad6e90f2 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit2_StraightTrackRatio.h @@ -0,0 +1,41 @@ +#ifndef Crit2_StraightTrackRatio_h +#define Crit2_StraightTrackRatio_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: for straight tracks: if the line between the two hits points towards IP. + * Calculated is + * + * \f[ \frac{ \frac{\rho_1}{z_1} }{ \frac{\rho_2}{z_2} } \simeq 1 \f] + * + * , where \f$ \rho = \sqrt{ x^2 + y^2 }\f$ + */ + class Crit2_StraightTrackRatio : public ICriterion{ + + + + public: + + Crit2_StraightTrackRatio ( float ratioMin, float ratioMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit2_StraightTrackRatio(){}; + + + private: + + float _ratioMax{}; + float _ratioMin{}; + + + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.cc b/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.cc new file mode 100644 index 0000000000000000000000000000000000000000..2f3c42037fdbfceedbc108fdf4777a4a150780dc --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.cc @@ -0,0 +1,121 @@ +#include "Criteria/Crit3_2DAngle.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + +Crit3_2DAngle::Crit3_2DAngle ( float angleMin, float angleMax ){ + + + _cosAngleMin = cos ( angleMax * M_PI / 180. ); + _cosAngleMax = cos ( angleMin * M_PI / 180. ); + + _name = "Crit3_2DAngle"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_2DAngle::areCompatible( Segment* parent , Segment* child ) { + + + //this is not written very beautiful, because this code gets called often and needs to be fast. + //But it's just a simple angle calculation of two vectors cos(alpha) = u*v/|u||v| + // + //Because of speed, I avoided using stuff like sqrt or cos or something in here. + //That's why it may look a bit odd. + + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + + float bx = b->getX(); + float by = b->getY(); + + float cx = c->getX(); + float cy = c->getY(); + + + float ux = bx - ax; + float uy = by - ay; + + + float vx = cx - bx; + float vy = cy - by; + + + //In the numerator there is the vector product of u and v + double numerator= ux*vx + uy*vy; + + //In the denominator there are the lengths of u and v (here squared) + double uSquared= ux*ux + uy*uy; + double vSquared= vx*vx + vy*vy; + + + + double denomSquared = uSquared * vSquared; + + if (_saveValues){ + + _map_name_value["Crit3_2DAngle_cos2DAngleSquared"] = 1.; + _map_name_value["Crit3_2DAngle"] = 0.; + + } + + if ( denomSquared > 0.){ //don't divide by 0 + + double cosThetaSquared = numerator * numerator / ( uSquared * vSquared ); + if( cosThetaSquared > 1. ) cosThetaSquared = 1; // prevent rounding errors: cosTheta can mathematically never be bigger than 1!!! + + if (_saveValues){ + + _map_name_value["Crit3_2DAngle_cos2DAngleSquared"] = cosThetaSquared; + _map_name_value["Crit3_2DAngle"] = acos( sqrt( cosThetaSquared ) ) * 180. / M_PI; + + } + + if (cosThetaSquared < _cosAngleMin*_cosAngleMin) return false; + if (cosThetaSquared > _cosAngleMax*_cosAngleMax) return false; + + } + + + + + + + } + else{ + + std::stringstream s; + s << "Crit3_2DAngle::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.h b/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.h new file mode 100644 index 0000000000000000000000000000000000000000..666f5fed91a59ad03bfef152b1d70ba796dfb857 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_2DAngle.h @@ -0,0 +1,36 @@ +#ifndef Crit3_2DAngle_h +#define Crit3_2DAngle_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the angle between two 2-segments in the xy - plane + */ + class Crit3_2DAngle : public ICriterion{ + + + + public: + + /** + * @param angleMax the maximum angle between 2 2-segments in grad + */ + Crit3_2DAngle ( float angleMin, float angleMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_2DAngle(){}; + + private: + + float _cosAngleMin{}; + float _cosAngleMax{}; + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.cc b/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.cc new file mode 100644 index 0000000000000000000000000000000000000000..a70c962d6a370375e1c6a4f22bd6761168eb9970 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.cc @@ -0,0 +1,134 @@ +#include "Criteria/Crit3_2DAngleTimesR.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + + +using namespace KiTrack; + +Crit3_2DAngleTimesR::Crit3_2DAngleTimesR ( float angleMin, float angleMax ){ + + + _angleMin = angleMin; + _angleMax = angleMax; + + _name = "Crit3_2DAngleTimesR"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_2DAngleTimesR::areCompatible( Segment* parent , Segment* child ) { + + + //this is not written very beautiful, because this code gets called often and needs to be fast. + //But it's just a simple angle calculation of two vectors cos(alpha) = u*v/|u||v| + // + //Because of speed, I avoided using stuff like sqrt or cos or something in here. + //That's why it may look a bit odd. + + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + + float bx = b->getX(); + float by = b->getY(); + + float cx = c->getX(); + float cy = c->getY(); + + + float ux = bx - ax; + float uy = by - ay; + + + float vx = cx - bx; + float vy = cy - by; + + + //In the numerator there is the vector product of u and v + double numerator= ux*vx + uy*vy; + + //In the denominator there are the lengths of u and v (here squared) + double uSquared= ux*ux + uy*uy; + double vSquared= vx*vx + vy*vy; + + + + double denomSquared = uSquared * vSquared; + + if (_saveValues){ + + _map_name_value["Crit3_2DAngleTimesR"] = 0.; + + } + + if ( denomSquared > 0.){ //don't divide by 0 + + double cosThetaSquared = numerator * numerator / ( uSquared * vSquared ); + if( cosThetaSquared > 1. ) cosThetaSquared = 1; // prevent rounding errors: cosTheta can mathematically never be bigger than 1!!! + double angle = acos( sqrt( cosThetaSquared ) ) * 180. / M_PI; + + try{ + + SimpleCircle circle ( ax , ay , bx , by , cx , cy ); + + double R = circle.getRadius(); + + double angleTimesR = R * angle; + + if (_saveValues){ + + _map_name_value["Crit3_2DAngleTimesR"] = angleTimesR; + + } + + if ( angleTimesR < _angleMin ) return false; + if ( angleTimesR > _angleMax ) return false; + + } + catch( InvalidParameter ){ + + + } + + + } + + + } + else{ + + std::stringstream s; + s << "Crit3_2DAngleTimesR::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.h b/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.h new file mode 100644 index 0000000000000000000000000000000000000000..8025583fcc9122b43344d4ce739deee0e0953864 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_2DAngleTimesR.h @@ -0,0 +1,36 @@ +#ifndef Crit3_2DAngleTimesR_h +#define Crit3_2DAngleTimesR_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the angle in the xy plane between two 2-segments multiplied by the radius of the circle they form + */ + class Crit3_2DAngleTimesR : public ICriterion{ + + + + public: + + /** + * @param angleMax the maximum angle between 2 2-segments in grad times radius + */ + Crit3_2DAngleTimesR ( float angleMin, float angleMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_2DAngleTimesR(){}; + + private: + + float _angleMin{}; + float _angleMax{}; + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.cc b/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.cc new file mode 100644 index 0000000000000000000000000000000000000000..bbe254fd19fe669f4614a835a082c83f245a76a7 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.cc @@ -0,0 +1,124 @@ +#include "Criteria/Crit3_3DAngle.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + +Crit3_3DAngle::Crit3_3DAngle ( float angleMin, float angleMax ){ + + + _cosAngleMin = cos ( angleMax * M_PI / 180. ); + _cosAngleMax = cos ( angleMin * M_PI / 180. ); + + _name = "Crit3_3DAngle"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_3DAngle::areCompatible( Segment* parent , Segment* child ) { + + + //this is not written very beautiful, because this code gets called often and needs to be fast. + //But it's just a simple angle calculation of two vectors cos(alpha) = u*v/|u||v| + // + //Because of speed, I avoided using stuff like sqrt or cos or something in here. + //That's why it may look a bit odd. + + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + + float ux = bx - ax; + float uy = by - ay; + float uz = bz - az; + + float vx = cx - bx; + float vy = cy - by; + float vz = cz - bz; + + //In the numerator there is the vector product of u and v + double numerator= ux*vx + uy*vy + uz*vz; + + //In the denominator there are the lengths of u and v (here squared) + double uSquared= ux*ux + uy*uy + uz*uz; + double vSquared= vx*vx + vy*vy + vz*vz; + + + + double denomSquared = uSquared * vSquared; + + if (_saveValues){ + + _map_name_value["Crit3_3DAngle_cos3DAngleSquared"] = 1.; + _map_name_value["Crit3_3DAngle"] = 0.; + + } + + if ( denomSquared > 0.){ //don't divide by 0 + + double cosThetaSquared = numerator * numerator / ( uSquared * vSquared ); + if( cosThetaSquared > 1. ) cosThetaSquared = 1; // prevent rounding errors: cosTheta can mathematically never be bigger than 1!!! + + if (_saveValues){ + + _map_name_value["Crit3_3DAngle_cos3DAngleSquared"] = cosThetaSquared; + _map_name_value["Crit3_3DAngle"] = acos( sqrt( cosThetaSquared ) ) * 180. / M_PI; + + } + + if (cosThetaSquared < _cosAngleMin*_cosAngleMin) return false; + if (cosThetaSquared > _cosAngleMax*_cosAngleMax) return false; + + } + + + + + + + } + else{ + + std::stringstream s; + s << "Crit3_3DAngle::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.h b/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.h new file mode 100644 index 0000000000000000000000000000000000000000..1c24922d247b751db7b01d380483ec1f6e040c5b --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_3DAngle.h @@ -0,0 +1,36 @@ +#ifndef Crit3_3DAngle_h +#define Crit3_3DAngle_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the angle between two 2-segments + */ + class Crit3_3DAngle : public ICriterion{ + + + + public: + + /** + * @param angleMax the maximum angle between 2 2-segments in grad + */ + Crit3_3DAngle ( float angleMin, float angleMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_3DAngle(){}; + + private: + + float _cosAngleMin{}; + float _cosAngleMax{}; + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.cc b/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.cc new file mode 100644 index 0000000000000000000000000000000000000000..ff52c6f534bbab99b91293d8efea1fcdfcec8e36 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.cc @@ -0,0 +1,136 @@ +#include "Criteria/Crit3_3DAngleTimesR.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + + +using namespace KiTrack; + +Crit3_3DAngleTimesR::Crit3_3DAngleTimesR ( float angleMin, float angleMax ){ + + + _angleMin = angleMin; + _angleMax = angleMax; + + _name = "Crit3_3DAngleTimesR"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_3DAngleTimesR::areCompatible( Segment* parent , Segment* child ) { + + + + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + + float ux = bx - ax; + float uy = by - ay; + float uz = bz - az; + + float vx = cx - bx; + float vy = cy - by; + float vz = cz - bz; + + //In the numerator there is the vector product of u and v + double numerator= ux*vx + uy*vy + uz*vz; + + //In the denominator there are the lengths of u and v (here squared) + double uSquared= ux*ux + uy*uy + uz*uz; + double vSquared= vx*vx + vy*vy + vz*vz; + + + + double denomSquared = uSquared * vSquared; + + if (_saveValues){ + + _map_name_value["Crit3_3DAngleTimesR"] = 0.; + + } + + if ( denomSquared > 0.){ //don't divide by 0 + + double cosThetaSquared = numerator * numerator / ( uSquared * vSquared ); + if( cosThetaSquared > 1. ) cosThetaSquared = 1; // prevent rounding errors: cosTheta can mathematically never be bigger than 1!!! + double angle = acos( sqrt( cosThetaSquared ) ) * 180. / M_PI; + + + try{ + + SimpleCircle circle ( ax , ay , bx , by , cx , cy ); + + double R = circle.getRadius(); + + double angleTimesR = R * angle; + + if (_saveValues){ + + _map_name_value["Crit3_3DAngleTimesR"] = angleTimesR; + + } + + if ( angleTimesR < _angleMin ) return false; + if ( angleTimesR > _angleMax ) return false; + + } + catch( InvalidParameter ){ + + + } + + + } + + + + + + } + else{ + + std::stringstream s; + s << "Crit3_3DAngleTimesR::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.h b/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.h new file mode 100644 index 0000000000000000000000000000000000000000..3a366a0dfd21e6c371582ea7403ecde2c811c9fa --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_3DAngleTimesR.h @@ -0,0 +1,36 @@ +#ifndef Crit3_3DAngleTimesR_h +#define Crit3_3DAngleTimesR_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: the angle between two 2-segments multiplied by the radius of the circle the segments form + */ + class Crit3_3DAngleTimesR : public ICriterion{ + + + + public: + + /** + * @param angleMax the maximum angle between 2 2-segments in grad times the radius of the circle the segments form + */ + Crit3_3DAngleTimesR ( float angleMin, float angleMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_3DAngleTimesR(){}; + + private: + + float _angleMin{}; + float _angleMax{}; + + }; + +} + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.cc b/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.cc new file mode 100644 index 0000000000000000000000000000000000000000..aec9768f4fc8e7ef17f051af81437ba94cedc6e7 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.cc @@ -0,0 +1,91 @@ +#include "Criteria/Crit3_ChangeRZRatio.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + + +Crit3_ChangeRZRatio::Crit3_ChangeRZRatio( float minChange , float maxChange ){ + + + _ratioChangeMaxSquared = maxChange*maxChange; + _ratioChangeMinSquared = minChange*minChange; + + _name = "Crit3_ChangeRZRatio"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_ChangeRZRatio::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + + + // The rz ratios squared + + double ratioSquaredParent = 0.; + if ( az-bz != 0. ) ratioSquaredParent = ( (ax-bx)*(ax-bx) + (ay-by)*(ay-by) + (az-bz)*(az-bz) ) / ( (az-bz) * ( az-bz ) ); + + double ratioSquaredChild = 0.; + if ( cz-bz != 0. ) ratioSquaredChild = ( (cx-bx)*(cx-bx) + (cy-by)*(cy-by) + (cz-bz)*(cz-bz) ) / ( (cz-bz) * ( cz-bz ) ); + + double ratioOfRZRatioSquared = 0.; + + if (ratioSquaredChild != 0.) ratioOfRZRatioSquared = ratioSquaredParent / ratioSquaredChild; + + if (_saveValues) { + + _map_name_value["Crit3_ChangeRZRatio_ratioOfRZRatioSquared"] = ratioOfRZRatioSquared; + _map_name_value["Crit3_ChangeRZRatio"] = sqrt( ratioOfRZRatioSquared ); + + } + + if ( ratioOfRZRatioSquared > _ratioChangeMaxSquared ) return false; + if ( ratioOfRZRatioSquared < _ratioChangeMinSquared ) return false; + + + } + else{ + + std::stringstream s; + s << "Crit3_ChangeRZRatio::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + + return true; + + +} diff --git a/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.h b/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.h new file mode 100644 index 0000000000000000000000000000000000000000..a218523be509159e1402b2fadff3171a0b5347b5 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_ChangeRZRatio.h @@ -0,0 +1,48 @@ +#ifndef Crit2_ChangeRZRatio_h +#define Crit2_ChangeRZRatio_h + +#include "Criteria/ICriterion.h" + + +namespace KiTrack{ + + /** Criterion: the change of the ratio of the distance of two hits over the z distance + */ + class Crit3_ChangeRZRatio : public ICriterion{ + + + + public: + + Crit3_ChangeRZRatio ( float minChange , float maxChange ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_ChangeRZRatio(){}; + + + private: + + float _ratioChangeMaxSquared{}; + float _ratioChangeMinSquared{}; + + + + }; + +} + + + + + + + + + + + + + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.cc b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.cc new file mode 100644 index 0000000000000000000000000000000000000000..2e2486d30a565169ebd0e343bd2e1b3f1170aef5 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.cc @@ -0,0 +1,90 @@ +#include "Criteria/Crit3_IPCircleDist.h" + + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + +using namespace KiTrack; + + +Crit3_IPCircleDist::Crit3_IPCircleDist( float distToCircleMin , float distToCircleMax ){ + + _distToCircleMax = distToCircleMax; + _distToCircleMin = distToCircleMin; + + _name = "Crit3_IPCircleDist"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_IPCircleDist::areCompatible( Segment* parent , Segment* child ) { + + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + + float bx = b->getX(); + float by = b->getY(); + + float cx = c->getX(); + float cy = c->getY(); + + + try{ + + SimpleCircle circle ( ax , ay , bx , by , cx , cy ); + + double x = circle.getCenterX(); + double y = circle.getCenterY(); + double R = circle.getRadius(); + + double circleDistToIP = fabs( R - sqrt (x*x+y*y) ); + + if (_saveValues) _map_name_value["Crit3_IPCircleDist"] = circleDistToIP; + + if ( circleDistToIP > _distToCircleMax ) return false; + if ( circleDistToIP < _distToCircleMin ) return false; + + } + catch ( InvalidParameter ){ + + + if (_saveValues) _map_name_value["Crit3_IPCircleDist"] = 0.; + + } + + + + } + else{ + + std::stringstream s; + s << "Crit3_IPCircleDist::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + } + + + return true; + + +} diff --git a/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.h b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.h new file mode 100644 index 0000000000000000000000000000000000000000..0896906922fae2a85cd997868e512d9708d61f89 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDist.h @@ -0,0 +1,47 @@ +#ifndef Crit2_IPCircleDist_h +#define Crit2_IPCircleDist_h + +#include "Criteria/ICriterion.h" + + +namespace KiTrack{ + + /** Criterion: the distance of the IP from the circle the 3 hits form (in the xy plane) + */ + class Crit3_IPCircleDist : public ICriterion{ + + + + public: + + Crit3_IPCircleDist ( float distToCircleMin , float distToCircleMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_IPCircleDist(){}; + + + private: + + float _distToCircleMax{}; + float _distToCircleMin{}; + + + }; + +} + + + + + + + + + + + + + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.cc b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.cc new file mode 100644 index 0000000000000000000000000000000000000000..cbda61eccf4d9fd74b29eb8c4a27503b508b35d5 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.cc @@ -0,0 +1,90 @@ +#include "Criteria/Crit3_IPCircleDistTimesR.h" + + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + +using namespace KiTrack; + + +Crit3_IPCircleDistTimesR::Crit3_IPCircleDistTimesR( float distToCircleMin , float distToCircleMax ){ + + _distToCircleMax = distToCircleMax; + _distToCircleMin = distToCircleMin; + + _name = "Crit3_IPCircleDistTimesR"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_IPCircleDistTimesR::areCompatible( Segment* parent , Segment* child ) { + + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + + float bx = b->getX(); + float by = b->getY(); + + float cx = c->getX(); + float cy = c->getY(); + + + try{ + + SimpleCircle circle ( ax , ay , bx , by , cx , cy ); + + double x = circle.getCenterX(); + double y = circle.getCenterY(); + double R = circle.getRadius(); + + double circleDistToIPTimesR = fabs( R - sqrt (x*x+y*y) ) * R; + + if (_saveValues) _map_name_value["Crit3_IPCircleDistTimesR"] = circleDistToIPTimesR; + + if ( circleDistToIPTimesR > _distToCircleMax ) return false; + if ( circleDistToIPTimesR < _distToCircleMin ) return false; + + } + catch ( InvalidParameter ){ + + + if (_saveValues) _map_name_value["Crit3_IPCircleDistTimesR"] = 0.; + + } + + + + } + else{ + + std::stringstream s; + s << "Crit3_IPCircleDistTimesR::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + } + + + return true; + + +} diff --git a/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.h b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.h new file mode 100644 index 0000000000000000000000000000000000000000..3800ed9c35865896ac3d563ca1611310f61fca0c --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_IPCircleDistTimesR.h @@ -0,0 +1,40 @@ +#ifndef Crit3_IPCircleDistTimesR_h +#define Crit3_IPCircleDistTimesR_h + +#include "Criteria/ICriterion.h" + + +namespace KiTrack{ + + /** Criterion: the distance of the circle formed by the two segments from the IP multiplied by R + */ + class Crit3_IPCircleDistTimesR : public ICriterion{ + + + + public: + + Crit3_IPCircleDistTimesR ( float distToCircleMin , float distToCircleMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_IPCircleDistTimesR(){}; + + + private: + + float _distToCircleMax{}; + float _distToCircleMin{}; + + + }; + +} + + + + + + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.cc b/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.cc new file mode 100644 index 0000000000000000000000000000000000000000..d2523735aedcb3ec9ac1c4911edaae4080e79606 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.cc @@ -0,0 +1,93 @@ +#include "Criteria/Crit3_NoZigZag_MV.h" + +#include <cmath> +#include <sstream> + +#include "TVector3.h" + + +using namespace KiTrack; + +Crit3_NoZigZag_MV::Crit3_NoZigZag_MV ( float prodMin , float prodMax ){ + + + _prodMin = prodMin; + _prodMax = prodMax; + + _name = "Crit3_NoZigZag_MV"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_NoZigZag_MV::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //this is a criterion for 2-segments + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + double thetaa = a->getTheta(); + double thetab = b->getTheta(); + double thetac = c->getTheta(); + + + double angleXY1 = thetac - thetab; //the angle between 2-segments in the xy plane + double angleXY2 = thetab - thetaa; + + + if ( a->isVirtual() ) { angleXY2 = 0 ; } + + angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY1 > M_PI) angleXY1 -= 2*M_PI; //to the range from -pi to pi + + angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY2 > M_PI) angleXY2 -= 2*M_PI; //to the range from -pi to pi + + + // to grad + angleXY1 *= 180./M_PI; + angleXY2 *= 180./M_PI; + + float prod = angleXY1 * angleXY2; // if the direction of curvature stays the same, both anlges have the same sign-> and therefore the product is positive + + + //streamlog_out(DEBUG4) << " parent layer " << Layerc << " theta " << (180*thetac)/M_PI << " child first hit layer " << Layera << " theta = " << (180*thetaa)/M_PI << " child second hit layer " << Layerb << " theta = " << (180*thetab)/M_PI << " angleXY1 " << angleXY1 << " angleXY2 " << angleXY2 << " prod " << prod << std::endl ; + + + + if (_saveValues) _map_name_value["Crit3_NoZigZag_MV_angle1"] = angleXY1; + if (_saveValues) _map_name_value["Crit3_NoZigZag_MV_angle2"] = angleXY2; + if (_saveValues) _map_name_value["Crit3_NoZigZag_MV"] = prod; + + if ( prod < _prodMin ) return false; + if ( prod > _prodMax ) return false; + + + + } + else{ + + std::stringstream s; + s << "Crit3_NoZigZag_MV::This criterion needs 2 segments with 2 mini-vectors each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + return true; + + + +} diff --git a/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.h b/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.h new file mode 100644 index 0000000000000000000000000000000000000000..3dcf6f89a00e4617317bf82d26c41b0403af0a7a --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_NoZigZag_MV.h @@ -0,0 +1,39 @@ +#ifndef Crit3_NoZigZag_MV_h +#define Crit3_NoZigZag_MV_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: forbids zig zagging: measure the angles in the xy plane, transpose them to the range from -pi to pi + * and multiply: if there is a zigzag, the sign of the angle switches and the product of both angles becomes + * negative. + */ + class Crit3_NoZigZag_MV : public ICriterion{ + + + + public: + + /** + * @param prodMin the minimum product of the two angles in degrees + * + * @param prodMax the maxinum product of the two angles in degrees + */ + Crit3_NoZigZag_MV ( float prodMin , float prodMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_NoZigZag_MV(){}; + + private: + + float _prodMin{}; + float _prodMax{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Crit3_PT.cc b/Utilities/KiTrack/src/Criteria/Crit3_PT.cc new file mode 100644 index 0000000000000000000000000000000000000000..7b22dadecbac586cb53d1c1cde5e463dd086d2a0 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_PT.cc @@ -0,0 +1,99 @@ +#include "Criteria/Crit3_PT.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + +using namespace KiTrack; + + +Crit3_PT::Crit3_PT( float ptMin , float ptMax , float Bz ){ + + _ptMin = ptMin; + _ptMax = ptMax; + _Bz = Bz; + + _name = "Crit3_PT"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_PT::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + + float bx = b->getX(); + float by = b->getY(); + + float cx = c->getX(); + float cy = c->getY(); + + + try{ + + SimpleCircle circle ( ax , ay , bx , by , cx , cy ); + + + double R = circle.getRadius(); + + + // check if pt is bigger than _ptMin + // + // |omega| = K*Bz/pt + // R = pt / (K*Bz) + // pt = R * K *Bz + // + + const double K= 0.00029979; //K depends on the used units + + double pt = R * K * _Bz; + + if (_saveValues) _map_name_value["Crit3_PT"] = pt; + + if ( pt < _ptMin ) return false; + if ( pt > _ptMax ) return false; + + + } + catch ( InvalidParameter ){ + + if (_saveValues) _map_name_value["Crit3_PT"] = 0.; + + } + + + + } + else{ + + std::stringstream s; + s << "Crit3_PT::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + +} diff --git a/Utilities/KiTrack/src/Criteria/Crit3_PT.h b/Utilities/KiTrack/src/Criteria/Crit3_PT.h new file mode 100644 index 0000000000000000000000000000000000000000..46e4f0f25b488e1f1990880686d6c8d82bcc9d2c --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_PT.h @@ -0,0 +1,48 @@ +#ifndef Crit2_PT_h +#define Crit2_PT_h + +#include "Criteria/ICriterion.h" + + +namespace KiTrack{ + + /** Criterion: the transversal momentum + */ + class Crit3_PT : public ICriterion{ + + + + public: + + Crit3_PT ( float ptMin , float ptMax , float Bz = 3.5 ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_PT(){}; + + + private: + + float _ptMin{}; + float _ptMax{}; + float _Bz{}; + + + }; + +} + + + + + + + + + + + + + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.cc b/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.cc new file mode 100644 index 0000000000000000000000000000000000000000..da92109102e0e3200de3657666bae6a6977d5109 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.cc @@ -0,0 +1,99 @@ +#include "Criteria/Crit3_PT_MV.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + +using namespace KiTrack; + + +Crit3_PT_MV::Crit3_PT_MV( float ptMin , float ptMax , float Bz ){ + + _ptMin = ptMin; + _ptMax = ptMax; + _Bz = Bz; + + _name = "Crit3_PT_MV"; + _type = "3Hit"; + + _saveValues = false; + +} + + + +bool Crit3_PT_MV::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 2 )&&( child->getHits().size() == 2 )){ //a criterion for 2-segments + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = parent-> getHits()[1]; + + float ax = a->getX(); + float ay = a->getY(); + + float bx = b->getX(); + float by = b->getY(); + + float cx = c->getX(); + float cy = c->getY(); + + + try{ + + SimpleCircle circle ( ax , ay , bx , by , cx , cy ); + + + double R = circle.getRadius(); + + + // check if pt is bigger than _ptMin + // + // |omega| = K*Bz/pt + // R = pt / (K*Bz) + // pt = R * K *Bz + // + + const double K= 0.00029979; //K depends on the used units + + double pt = R * K * _Bz; + + if (_saveValues) _map_name_value["Crit3_PT_MV"] = pt; + + if ( pt < _ptMin ) return false; + if ( pt > _ptMax ) return false; + + + } + catch ( InvalidParameter ){ + + if (_saveValues) _map_name_value["Crit3_PT_MV"] = 0.; + + } + + + + } + else{ + + std::stringstream s; + s << "Crit3_PT_MV::This criterion needs 2 segments with 2 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + +} diff --git a/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.h b/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.h new file mode 100644 index 0000000000000000000000000000000000000000..86ef036949fd3040aca6bdc03c9a361c2a28950e --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit3_PT_MV.h @@ -0,0 +1,48 @@ +#ifndef Crit2_PT_MV_h +#define Crit2_PT_MV_h + +#include "Criteria/ICriterion.h" + + +namespace KiTrack{ + + /** Criterion: the transversal momentum + */ + class Crit3_PT_MV : public ICriterion{ + + + + public: + + Crit3_PT_MV ( float ptMin , float ptMax , float Bz = 3.5 ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit3_PT_MV(){}; + + + private: + + float _ptMin{}; + float _ptMax{}; + float _Bz{}; + + + }; + +} + + + + + + + + + + + + + +#endif + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.cc b/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.cc new file mode 100644 index 0000000000000000000000000000000000000000..b406bf8899f8b85cc80fd7e78735f4fdf8645ce4 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.cc @@ -0,0 +1,101 @@ +#include "Criteria/Crit4_2DAngleChange.h" + +#include <cmath> +#include <sstream> + +#include "TVector3.h" + + +using namespace KiTrack; + +Crit4_2DAngleChange::Crit4_2DAngleChange ( float changeMin , float changeMax ){ + + + _changeMax = changeMax; + _changeMin = changeMin; + + _name = "Crit4_2DAngleChange"; + _type = "4Hit"; + + _saveValues = false; + +} + + + +bool Crit4_2DAngleChange::areCompatible( Segment* parent , Segment* child ) { + + + if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = child->getHits()[2]; + IHit* d = parent-> getHits()[2]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + float dx = d->getX(); + float dy = d->getY(); + float dz = d->getZ(); + + + + TVector3 outerVec (bx-ax , by-ay , bz-az ); + TVector3 middleVec (cx-bx , cy-by , cz-bz ); + TVector3 innerVec (dx-cx , dy-cy , dz-cz ); + + + + + double angleXY1 = outerVec.Phi()-middleVec.Phi(); //the angle between 2-segments in the xy plane + double angleXY2 = middleVec.Phi()-innerVec.Phi(); + + angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY1 > M_PI) angleXY1 -= 2*M_PI; //to the range from -pi to pi + + angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY2 > M_PI) angleXY2 -= 2*M_PI; //to the range from -pi to pi + + + float ratioOf2DAngles = angleXY1 / angleXY2 ; + + if (_saveValues) _map_name_value["Crit4_2DAngleChange"] = ratioOf2DAngles; + + if ( ratioOf2DAngles > _changeMax ) return false; + if ( ratioOf2DAngles < _changeMin ) return false; + + + + } + else{ + + std::stringstream s; + s << "Crit4_2DAngleChange::This criterion needs 2 segments with 3 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.h b/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.h new file mode 100644 index 0000000000000000000000000000000000000000..c3bcb65d91115a67f580a728fcbeea539a5de034 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_2DAngleChange.h @@ -0,0 +1,35 @@ +#ifndef Crit4_2DAngleChange_h +#define Crit4_2DAngleChange_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: change of the angle (in the xy plane) between segments in the xy plane + */ + class Crit4_2DAngleChange : public ICriterion{ + + + + public: + + /** + * @param changeMax + */ + Crit4_2DAngleChange ( float changeMin , float changeMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit4_2DAngleChange(){}; + + private: + + float _changeMin{}; + float _changeMax{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.cc b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.cc new file mode 100644 index 0000000000000000000000000000000000000000..d6a8c5da94d7024e20aaf1d7d50cad70a60688c8 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.cc @@ -0,0 +1,101 @@ +#include "Criteria/Crit4_3DAngleChange.h" + +#include <cmath> +#include <sstream> + +#include "TVector3.h" + + +using namespace KiTrack; + +Crit4_3DAngleChange::Crit4_3DAngleChange ( float changeMin , float changeMax ){ + + + _changeMax = changeMax; + _changeMin = changeMin; + + _name = "Crit4_3DAngleChange"; + _type = "4Hit"; + + _saveValues = false; + +} + + + +bool Crit4_3DAngleChange::areCompatible( Segment* parent , Segment* child ) { + + + if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = child->getHits()[2]; + IHit* d = parent-> getHits()[2]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + float dx = d->getX(); + float dy = d->getY(); + float dz = d->getZ(); + + + + TVector3 outerVec (bx-ax , by-ay , bz-az ); + TVector3 middleVec (cx-bx , cy-by , cz-bz ); + TVector3 innerVec (dx-cx , dy-cy , dz-cz ); + + + + + double angleXY1 = outerVec.Angle( middleVec ); + double angleXY2 = middleVec.Angle( innerVec ); + + angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY1 > M_PI) angleXY1 -= 2*M_PI; //to the range from -pi to pi + + angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY2 > M_PI) angleXY2 -= 2*M_PI; //to the range from -pi to pi + + + float ratioOf3DAngles = angleXY1 / angleXY2 ; + + if (_saveValues) _map_name_value["Crit4_3DAngleChange"] = ratioOf3DAngles; + + if ( ratioOf3DAngles > _changeMax ) return false; + if ( ratioOf3DAngles < _changeMin ) return false; + + + + } + else{ + + std::stringstream s; + s << "Crit4_3DAngleChange::This criterion needs 2 segments with 3 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.h b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.h new file mode 100644 index 0000000000000000000000000000000000000000..84351869d0c6cf55af4baace5591b72208aa539c --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChange.h @@ -0,0 +1,35 @@ +#ifndef Crit4_3DAngleChange_h +#define Crit4_3DAngleChange_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: change of the angle between segments + */ + class Crit4_3DAngleChange : public ICriterion{ + + + + public: + + /** + * @param changeMax + */ + Crit4_3DAngleChange ( float changeMin , float changeMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit4_3DAngleChange(){}; + + private: + + float _changeMin{}; + float _changeMax{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.cc b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.cc new file mode 100644 index 0000000000000000000000000000000000000000..ade7136d923f5656b6f69db0b03efedd0332e0a4 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.cc @@ -0,0 +1,124 @@ +#include "Criteria/Crit4_3DAngleChangeNormed.h" + +#include <cmath> +#include <sstream> + +#include "TVector3.h" +#include "Criteria/SimpleCircle.h" + + +using namespace KiTrack; + +Crit4_3DAngleChangeNormed::Crit4_3DAngleChangeNormed ( float changeMin , float changeMax ){ + + + _changeMax = changeMax; + _changeMin = changeMin; + + _name = "Crit4_3DAngleChangeNormed"; + _type = "4Hit"; + + _saveValues = false; + +} + + + +bool Crit4_3DAngleChangeNormed::areCompatible( Segment* parent , Segment* child ) { + + + if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = child->getHits()[2]; + IHit* d = parent-> getHits()[2]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + float dx = d->getX(); + float dy = d->getY(); + float dz = d->getZ(); + + + + TVector3 outerVec (bx-ax , by-ay , bz-az ); + TVector3 middleVec (cx-bx , cy-by , cz-bz ); + TVector3 innerVec (dx-cx , dy-cy , dz-cz ); + + + + + double angleXY1 = outerVec.Angle( middleVec ); + double angleXY2 = middleVec.Angle( innerVec ); + + angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY1 > M_PI) angleXY1 -= 2*M_PI; //to the range from -pi to pi + + angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY2 > M_PI) angleXY2 -= 2*M_PI; //to the range from -pi to pi + + + try{ + + SimpleCircle circle1 ( ax , ay , bx , by , cx , cy ); + SimpleCircle circle2 ( bx , by , cx , cy , dx , dy ); + + + float R = ( circle1.getRadius() + circle2.getRadius() ) / 2.; + + + float ratioOf3DAngles = angleXY1 / angleXY2 ; + + float ratioNormed = ( (ratioOf3DAngles -1. ) * R ) + 1; + + if (_saveValues) _map_name_value["Crit4_3DAngleChangeNormed"] = ratioNormed; + + if ( ratioNormed > _changeMax ) return false; + if ( ratioNormed < _changeMin ) return false; + + } + catch ( InvalidParameter ){ + + if (_saveValues) _map_name_value["Crit4_3DAngleChangeNormed"] = 0.; + + + } + + + + + + + } + else{ + + std::stringstream s; + s << "Crit4_3DAngleChangeNormed::This criterion needs 2 segments with 3 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.h b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.h new file mode 100644 index 0000000000000000000000000000000000000000..691d0060b003be00040acf0fdcd36ee19212f4be --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_3DAngleChangeNormed.h @@ -0,0 +1,35 @@ +#ifndef Crit4_3DAngleChangeNormed_h +#define Crit4_3DAngleChangeNormed_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: check for the change of the 3D angle and normalise it with R + */ + class Crit4_3DAngleChangeNormed : public ICriterion{ + + + + public: + + /** + * @param changeMax + */ + Crit4_3DAngleChangeNormed ( float changeMin , float changeMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit4_3DAngleChangeNormed(){}; + + private: + + float _changeMin{}; + float _changeMax{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.cc b/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.cc new file mode 100644 index 0000000000000000000000000000000000000000..2f0ecbac2a1218c3a6741a23af607848b2a54b7a --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.cc @@ -0,0 +1,110 @@ +#include "Criteria/Crit4_DistOfCircleCenters.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + + +using namespace KiTrack; + +Crit4_DistOfCircleCenters::Crit4_DistOfCircleCenters ( float distMin , float distMax ){ + + + _distMax = distMax; + _distMin = distMin; + + _name = "Crit4_DistOfCircleCenters"; + _type = "4Hit"; + + _saveValues = false; + + +} + + + +bool Crit4_DistOfCircleCenters::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = child->getHits()[2]; + IHit* d = parent-> getHits()[2]; + + + + float ax = a->getX(); + float ay = a->getY(); +// float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); +// float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); +// float cz = c->getZ(); + + float dx = d->getX(); + float dy = d->getY(); +// float dz = d->getZ(); + + + + try{ + + SimpleCircle circle1 ( ax , ay , bx , by , cx , cy ); + SimpleCircle circle2 ( bx , by , cx , cy , dx , dy ); + + + float X1 = circle1.getCenterX(); + float Y1 = circle1.getCenterY(); + + float X2 = circle2.getCenterX(); + float Y2 = circle2.getCenterY(); + + + float distOfCircleCenters = sqrt( (X2-X1)*(X2-X1) + (Y2-Y1)*(Y2-Y1) ); + + if (_saveValues) _map_name_value["Crit4_DistOfCircleCenters"] = distOfCircleCenters; + + + if ( distOfCircleCenters > _distMax ) return false; + if ( distOfCircleCenters < _distMin ) return false; + + } + catch ( InvalidParameter ){ + + if (_saveValues) _map_name_value["Crit4_DistOfCircleCenters"] = 0.; + + + } + + + } + else{ + + std::stringstream s; + s << "Crit4_DistOfCircleCenters::This criterion needs 2 segments with 3 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() <<" hit segment (child)."; + + + + throw BadSegmentLength( s.str() ); + + + } + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.h b/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.h new file mode 100644 index 0000000000000000000000000000000000000000..c7d4a943f977894fafbc43a4a32f0b6063a11bb4 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_DistOfCircleCenters.h @@ -0,0 +1,35 @@ +#ifndef Crit4_DistOfCircleCenters_h +#define Crit4_DistOfCircleCenters_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: make circles from the semgments and measure the distances of their centers + */ + class Crit4_DistOfCircleCenters : public ICriterion{ + + + + public: + + /** + * @param distMax + */ + Crit4_DistOfCircleCenters ( float distMin , float distMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit4_DistOfCircleCenters(){}; + + private: + + float _distMax{}; + float _distMin{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.cc b/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.cc new file mode 100644 index 0000000000000000000000000000000000000000..b993f45e8707057bb1160d1d6787169f57bace4e --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.cc @@ -0,0 +1,119 @@ +#include "Criteria/Crit4_DistToExtrapolation.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" +#include "TVector3.h" + + + +using namespace KiTrack; + +Crit4_DistToExtrapolation::Crit4_DistToExtrapolation ( float distMin , float distMax ){ + + + _distMin = distMin; + _distMax = distMax; + + _name = "Crit4_DistToExtrapolation"; + _type = "4Hit"; + + _saveValues = false; + +} + + + +bool Crit4_DistToExtrapolation::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = child->getHits()[2]; + IHit* d = parent-> getHits()[2]; + + float ax = a->getX(); + float ay = a->getY(); +// float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + float dx = d->getX(); + float dy = d->getY(); + float dz = d->getZ(); + + try{ + + SimpleCircle circle ( ax , ay , bx , by , cx , cy ); + + + double centerX = circle.getCenterX(); + double centerY = circle.getCenterY(); + double R = circle.getRadius(); + + TVector3 u ( bx - centerX , by - centerY , bz ); + TVector3 v ( cx - centerX , cy - centerY , cz ); + + + double deltaPhiParent = v.Phi() - u.Phi(); //angle in xy plane from center of circle, between point 2 and 3 + + // use this angle and the distance to the next layer to extrapolate + double zDistParent = fabs( cz - bz ); + double zDistChild = fabs( dz - cz ); + + double deltaPhiChild = deltaPhiParent * zDistChild / zDistParent ; + + double phiChild = v.Phi() + deltaPhiChild; + + double xChildPred = centerX + R* cos(phiChild); + double yChildPred = centerY + R* sin(phiChild); + + + double DistToPrediction = sqrt ( ( xChildPred- dx )*( xChildPred- dx ) + ( yChildPred- dy )*( yChildPred- dy ) ); + double distNormed = DistToPrediction / zDistChild; + + if (_saveValues) _map_name_value["Crit4_DistToExtrapolation"] = distNormed; + + if ( distNormed > _distMax ) return false; + if ( distNormed < _distMin ) return false; + + } + catch ( InvalidParameter ){ + + if (_saveValues) _map_name_value["Crit4_DistToExtrapolation"] = -1.; + + } + + } + else{ + + std::stringstream s; + s << "Crit4_DistToExtrapolation::This criterion needs 2 segments with 3 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.h b/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.h new file mode 100644 index 0000000000000000000000000000000000000000..726e44341d0d6233b8d311388ad439e71b5f49b1 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_DistToExtrapolation.h @@ -0,0 +1,37 @@ +#ifndef Crit4_DistToExtrapolation_h +#define Crit4_DistToExtrapolation_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: use the first 3 hits to extrapolate the location in xy for a given z of the last hit. + * Then measure the distance from the extrapolation to the hit. (Also divide by the z distance to the last hit, + * in order to take into account that with farther distances the accuracy drops) + */ + class Crit4_DistToExtrapolation : public ICriterion{ + + + + public: + + /** + * @param distMax + */ + Crit4_DistToExtrapolation ( float distMin , float distMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit4_DistToExtrapolation(){}; + + private: + + float _distMin{}; + float _distMax{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.cc b/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.cc new file mode 100644 index 0000000000000000000000000000000000000000..3f00d4bec153862dcd8b574d0e9474cda63ac0c5 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.cc @@ -0,0 +1,108 @@ +#include "Criteria/Crit4_NoZigZag.h" + +#include <cmath> +#include <sstream> + +#include "TVector3.h" + + +using namespace KiTrack; + +Crit4_NoZigZag::Crit4_NoZigZag ( float prodMin , float prodMax ){ + + + _prodMin = prodMin; + _prodMax = prodMax; + + _name = "Crit4_NoZigZag"; + _type = "4Hit"; + + _saveValues = false; + +} + + + +bool Crit4_NoZigZag::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = child->getHits()[2]; + IHit* d = parent-> getHits()[2]; + + float ax = a->getX(); + float ay = a->getY(); + float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + float dx = d->getX(); + float dy = d->getY(); + float dz = d->getZ(); + + + + TVector3 outerVec (bx-ax , by-ay , bz-az ); + TVector3 middleVec (cx-bx , cy-by , cz-bz ); + TVector3 innerVec (dx-cx , dy-cy , dz-cz ); + + + + + double angleXY1 = outerVec.Phi()-middleVec.Phi(); //the angle between 2-segments in the xy plane + double angleXY2 = middleVec.Phi()-innerVec.Phi(); + + angleXY1 -= 2*M_PI*floor( angleXY1 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY1 > M_PI) angleXY1 -= 2*M_PI; //to the range from -pi to pi + + angleXY2 -= 2*M_PI*floor( angleXY2 /2. /M_PI ); //to the range from 0 to 2pi + if (angleXY2 > M_PI) angleXY2 -= 2*M_PI; //to the range from -pi to pi + + + // to grad + angleXY1 *= 180./M_PI; + angleXY2 *= 180./M_PI; + + float prod = angleXY1 * angleXY2; // if the direction of curvature stays the same, both anlges have the same sign-> and therefore the product is positive + + if (_saveValues) _map_name_value["Crit4_NoZigZag_angle1"] = angleXY1; + if (_saveValues) _map_name_value["Crit4_NoZigZag_angle2"] = angleXY2; + if (_saveValues) _map_name_value["Crit4_NoZigZag"] = prod; + + if ( prod < _prodMin ) return false; + if ( prod > _prodMax ) return false; + + + + } + else{ + + std::stringstream s; + s << "Crit4_NoZigZag::This criterion needs 2 segments with 3 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.h b/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.h new file mode 100644 index 0000000000000000000000000000000000000000..5ca64ceed9f8ae00006d8d3c28786e3f7b8df3e4 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_NoZigZag.h @@ -0,0 +1,39 @@ +#ifndef Crit4_NoZigZag_h +#define Crit4_NoZigZag_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: forbids zig zagging: measure the angles in the xy plane, transpose them to the range from -pi to pi + * and multiply: if there is a zigzag, the sign of the angle switches and the product of both angles becomes + * negative. + */ + class Crit4_NoZigZag : public ICriterion{ + + + + public: + + /** + * @param prodMin the minimum product of the two angles in degrees + * + * @param prodMax the maxinum product of the two angles in degrees + */ + Crit4_NoZigZag ( float prodMin , float prodMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit4_NoZigZag(){}; + + private: + + float _prodMin{}; + float _prodMax{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.cc b/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.cc new file mode 100644 index 0000000000000000000000000000000000000000..e6c4db2172ca3a4edcd4fe836bcb62898749bc39 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.cc @@ -0,0 +1,120 @@ +#include "Criteria/Crit4_PhiZRatioChange.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" +#include "TVector3.h" + + + +using namespace KiTrack; + +Crit4_PhiZRatioChange::Crit4_PhiZRatioChange ( float changeMin , float changeMax ){ + + + _changeMin = changeMin; + _changeMax = changeMax; + + _name = "Crit4_PhiZRatioChange"; + _type = "4Hit"; + + _saveValues = false; + +} + + + +bool Crit4_PhiZRatioChange::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = child->getHits()[2]; + IHit* d = parent-> getHits()[2]; + + float ax = a->getX(); + float ay = a->getY(); +// float az = a->getZ(); + + float bx = b->getX(); + float by = b->getY(); + float bz = b->getZ(); + + float cx = c->getX(); + float cy = c->getY(); + float cz = c->getZ(); + + float dx = d->getX(); + float dy = d->getY(); + float dz = d->getZ(); + + try{ + + SimpleCircle circle1 ( ax , ay , bx , by , cx , cy ); + SimpleCircle circle2 ( bx , by , cx , cy , dx , dy ); + + + float X1 = circle1.getCenterX(); + float Y1 = circle1.getCenterY(); + float X2 = circle2.getCenterX(); + float Y2 = circle2.getCenterY(); + + + + TVector3 u ( bx - X1, by - Y1 , 0.); //vector from center of circle to point + TVector3 v ( cx - X1, cy - Y1 , 0.); + float zDist1 = fabs( cz - bz ); + float phi1 = u.Angle( v ); + float phiZRatio1 = phi1 / zDist1; + + TVector3 s ( cx - X2, cy - Y2 , 0.); //vector from center of circle to point + TVector3 t ( dx - X2, dy - Y2 , 0.); + float zDist2 = fabs( dz - cz ); + float phi2 = s.Angle( t ); + float phiZRatio2 = phi2 / zDist2; + + + float ratioOfPhiZRatio = phiZRatio1 / phiZRatio2; + + if (_saveValues) _map_name_value["Crit4_PhiZRatioChange"] = ratioOfPhiZRatio; + + + + if ( ratioOfPhiZRatio > _changeMax ) return false; + if ( ratioOfPhiZRatio < _changeMin ) return false; + + } + catch ( InvalidParameter ){ + + if (_saveValues) _map_name_value["Crit4_PhiZRatioChange"] = 1.; + + } + + + + } + else{ + + std::stringstream s; + s << "Crit4_PhiZRatioChange::This criterion needs 2 segments with 3 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.h b/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.h new file mode 100644 index 0000000000000000000000000000000000000000..d8f41b1c0a8a6f3739a44509e0a7d2af5bafb5cd --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_PhiZRatioChange.h @@ -0,0 +1,35 @@ +#ifndef Crit4_PhiZRatioChange_h +#define Crit4_PhiZRatioChange_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: check for the change of \f$ \frac{\phi}{Z} \f$. (\f$ \phi \f$ = angle in the circle formed by the hits) + */ + class Crit4_PhiZRatioChange : public ICriterion{ + + + + public: + + /** + * @param changeMax + */ + Crit4_PhiZRatioChange ( float changeMin , float changeMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit4_PhiZRatioChange(){}; + + private: + + float _changeMin{}; + float _changeMax{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Crit4_RChange.cc b/Utilities/KiTrack/src/Criteria/Crit4_RChange.cc new file mode 100644 index 0000000000000000000000000000000000000000..ea7e4257b13ce6fd399d485ec5623a2f239e3dbd --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_RChange.cc @@ -0,0 +1,97 @@ +#include "Criteria/Crit4_RChange.h" + +#include <cmath> +#include <sstream> + +#include "Criteria/SimpleCircle.h" + + + +using namespace KiTrack; + +Crit4_RChange::Crit4_RChange ( float changeMin , float changeMax ){ + + + _changeMin = changeMin; + _changeMax = changeMax; + + _name = "Crit4_RChange"; + _type = "4Hit"; + + _saveValues = false; + +} + + + +bool Crit4_RChange::areCompatible( Segment* parent , Segment* child ) { + + + + if (( parent->getHits().size() == 3 )&&( child->getHits().size() == 3 )){ //this is a criterion for 3-segments + + + + IHit* a = child->getHits()[0]; + IHit* b = child->getHits()[1]; + IHit* c = child->getHits()[2]; + IHit* d = parent-> getHits()[2]; + + float ax = a->getX(); + float ay = a->getY(); + + float bx = b->getX(); + float by = b->getY(); + + float cx = c->getX(); + float cy = c->getY(); + + float dx = d->getX(); + float dy = d->getY(); + + try{ + + SimpleCircle circle1 ( ax , ay , bx , by , cx , cy ); + SimpleCircle circle2 ( bx , by , cx , cy , dx , dy ); + + float R1 = circle1.getRadius(); + float R2 = circle2.getRadius(); + + float ratioOfR = 1.; + if (R2 > 0) ratioOfR = R1/R2; + + if (_saveValues) _map_name_value["Crit4_RChange"] = ratioOfR; + + + + if ( ratioOfR > _changeMax ) return false; + if ( ratioOfR < _changeMin ) return false; + + } + catch ( InvalidParameter ){ + + if (_saveValues) _map_name_value["Crit4_RChange"] = 1.; + + } + + } + else{ + + std::stringstream s; + s << "Crit4_RChange::This criterion needs 2 segments with 3 hits each, passed was a " + << parent->getHits().size() << " hit segment (parent) and a " + << child->getHits().size() << " hit segment (child)."; + + + throw BadSegmentLength( s.str() ); + + + } + + + return true; + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/Crit4_RChange.h b/Utilities/KiTrack/src/Criteria/Crit4_RChange.h new file mode 100644 index 0000000000000000000000000000000000000000..3b4c1d8bd0bc14a50def74a5aa79dab904d3960d --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Crit4_RChange.h @@ -0,0 +1,35 @@ +#ifndef Crit4_RChange_h +#define Crit4_RChange_h + + +#include "Criteria/ICriterion.h" + +namespace KiTrack{ + + /** Criterion: check for the change of the radii of the circles that can be made from the 3-hit segments + */ + class Crit4_RChange : public ICriterion{ + + + + public: + + /** + * @param changeMax + */ + Crit4_RChange ( float changeMin , float changeMax ); + + virtual bool areCompatible( Segment* parent , Segment* child ); + + virtual ~Crit4_RChange(){}; + + private: + + float _changeMin{}; + float _changeMax{}; + + }; + +} + +#endif diff --git a/Utilities/KiTrack/src/Criteria/Criteria.cc b/Utilities/KiTrack/src/Criteria/Criteria.cc new file mode 100644 index 0000000000000000000000000000000000000000..f8ea29a23b3bbe6e524a0d73967860dc83826296 --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/Criteria.cc @@ -0,0 +1,278 @@ +#include "Criteria/Criteria.h" +#include "Criteria/ICriterion.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" + +using namespace KiTrack; + +std::set< std::string > Criteria::getAllCriteriaNames(){ + + + std::set< std::string > critNames; + + critNames.insert( "Crit2_RZRatio" ); + critNames.insert( "Crit2_StraightTrackRatio" ); + critNames.insert( "Crit2_DeltaPhi" ); + critNames.insert( "Crit2_HelixWithIP" ); + critNames.insert( "Crit2_DeltaRho" ); + + critNames.insert( "Crit3_ChangeRZRatio" ); + critNames.insert( "Crit3_PT" ); + critNames.insert( "Crit3_2DAngle" ); + critNames.insert( "Crit3_2DAngleTimesR" ); + critNames.insert( "Crit3_3DAngle" ); + critNames.insert( "Crit3_3DAngleTimesR" ); + critNames.insert( "Crit3_IPCircleDist" ); + critNames.insert( "Crit3_IPCircleDistTimesR" ); + + + critNames.insert( "Crit4_2DAngleChange" ); + critNames.insert( "Crit4_3DAngleChange" ); + critNames.insert( "Crit4_3DAngleChangeNormed" ); + critNames.insert( "Crit4_DistToExtrapolation" ); + critNames.insert( "Crit4_PhiZRatioChange" ); + critNames.insert( "Crit4_DistOfCircleCenters" ); + critNames.insert( "Crit4_NoZigZag" ); + critNames.insert( "Crit4_RChange" ); + + // MiniVector based Cellular Automaton for VXD + + critNames.insert( "Crit2_DeltaPhi_MV" ); + critNames.insert( "Crit2_Distance_MV" ); + critNames.insert( "Crit2_DeltaTheta_MV" ); + critNames.insert( "Crit3_NoZigZag_MV" ); + critNames.insert( "Crit3_PT_MV" ); + + return critNames; + +} + + +std::set < std::string > Criteria::getTypes(){ + + std::set< std::string > critNames = getAllCriteriaNames(); + std::set< std::string > types; + + std::set< std::string >::iterator it; + + + for( it = critNames.begin(); it != critNames.end(); it++ ){ + + + ICriterion* crit = Criteria::createCriterion( *it ); + + types.insert( crit->getType() ); + + delete crit; + + + } + + return types; + + +} + + +std::set< std::string > Criteria::getCriteriaNames( std::string type ){ + + + std::set< std::string > criteria; + std::set< std::string > critNames = getAllCriteriaNames(); + + + std::set< std::string >::iterator it; + + for( it = critNames.begin(); it != critNames.end(); it++ ){ + + + ICriterion* crit = Criteria::createCriterion( *it ); + + if ( crit->getType() == type ) criteria.insert( *it ); + + delete crit; + + } + + return criteria; + + + + +} + + +ICriterion* Criteria::createCriterion( std::string critName, float min , float max ) { + + + + if ( critName == "Crit2_RZRatio" ) return ( new Crit2_RZRatio( min , max ) ); + + else if ( critName == "Crit2_StraightTrackRatio" ) return ( new Crit2_StraightTrackRatio( min , max ) ); + + else if ( critName == "Crit2_DeltaPhi" ) return ( new Crit2_DeltaPhi( min , max ) ); + + else if ( critName == "Crit2_HelixWithIP" ) return ( new Crit2_HelixWithIP( min , max ) ); + + else if ( critName == "Crit2_DeltaRho" ) return ( new Crit2_DeltaRho( min , max ) ); + + else if ( critName == "Crit3_ChangeRZRatio" ) return ( new Crit3_ChangeRZRatio( min , max ) ); + + else if ( critName == "Crit3_PT" ) return ( new Crit3_PT( min , max ) ); + + else if ( critName == "Crit3_2DAngle" ) return ( new Crit3_2DAngle( min , max ) ); + + else if ( critName == "Crit3_2DAngleTimesR" ) return ( new Crit3_2DAngleTimesR( min , max ) ); + + else if ( critName == "Crit3_3DAngle" ) return ( new Crit3_3DAngle( min , max ) ); + + else if ( critName == "Crit3_3DAngleTimesR" ) return ( new Crit3_3DAngleTimesR( min , max ) ); + + else if ( critName == "Crit3_IPCircleDist" ) return ( new Crit3_IPCircleDist( min , max ) ); + + else if ( critName == "Crit3_IPCircleDistTimesR" ) return ( new Crit3_IPCircleDistTimesR( min , max ) ); + + else if ( critName == "Crit4_2DAngleChange" ) return ( new Crit4_2DAngleChange( min , max ) ); + + else if ( critName == "Crit4_3DAngleChange" ) return ( new Crit4_3DAngleChange( min , max ) ); + + else if ( critName == "Crit4_3DAngleChangeNormed" ) return ( new Crit4_3DAngleChangeNormed( min , max ) ); + + else if ( critName == "Crit4_DistToExtrapolation" ) return ( new Crit4_DistToExtrapolation( min , max ) ); + + else if ( critName == "Crit4_PhiZRatioChange" ) return ( new Crit4_PhiZRatioChange( min , max ) ); + + else if ( critName == "Crit4_DistOfCircleCenters" ) return ( new Crit4_DistOfCircleCenters( min , max ) ); + + else if ( critName == "Crit4_NoZigZag" ) return ( new Crit4_NoZigZag( min , max ) ); + + else if ( critName == "Crit4_RChange" ) return ( new Crit4_RChange( min , max ) ); + + // Mini-Vector based + + else if ( critName == "Crit2_DeltaPhi_MV" ) return ( new Crit2_DeltaPhi_MV( min , max ) ); + + else if ( critName == "Crit2_Distance_MV" ) return ( new Crit2_Distance_MV( min , max ) ); + + else if ( critName == "Crit2_DeltaTheta_MV" ) return ( new Crit2_DeltaTheta_MV( min , max ) ); + + else if ( critName == "Crit3_NoZigZag_MV" ) return ( new Crit3_NoZigZag_MV( min , max ) ); + + else if ( critName == "Crit3_PT_MV" ) return ( new Crit3_PT_MV( min , max ) ); + + else { + + std::string s = "Criteria::The criterion \"" + critName + + "\" is not known. Make sure the class Criteria has this criterion listed in the createCriterion method"; + + throw UnknownCriterion( s ); + + } + + + + +} + + + +std::vector< std::string > Criteria::getAllCriteriaNamesVec(){ + + std::vector < std::string > allCriteriaNamesVec; + std::set< std::string > critNames = getAllCriteriaNames(); + + + std::set< std::string >::iterator it; + + for( it = critNames.begin(); it != critNames.end(); it++ ){ + + + allCriteriaNamesVec.push_back( *it ); + + } + + return allCriteriaNamesVec; + +} + + +void Criteria::getLeftRight( std::string critName, float & left, float & right ){ + + + if ( critName == "Crit2_RZRatio" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit2_RZRatio" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit2_StraightTrackRatio" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit2_DeltaPhi" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit2_HelixWithIP" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit2_DeltaRho" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit3_ChangeRZRatio" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit3_PT" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit3_2DAngle" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit3_2DAngleTimesR" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit3_3DAngle" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit3_3DAngleTimesR" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit3_IPCircleDist" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit3_IPCircleDistTimesR" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit4_2DAngleChange" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit4_3DAngleChange" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit4_3DAngleChangeNormed" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit4_DistToExtrapolation" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit4_PhiZRatioChange" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit4_DistOfCircleCenters" ) { left = 0.; right = 1.; } + + else if ( critName == "Crit4_NoZigZag" ) { left = 0.5; right = 0.5; } + + else if ( critName == "Crit4_RChange" ) { left = 0.5; right = 0.5; } + + else { left = 0.5; right = 0.5; } + + +} + + diff --git a/Utilities/KiTrack/src/Criteria/SimpleCircle.cc b/Utilities/KiTrack/src/Criteria/SimpleCircle.cc new file mode 100644 index 0000000000000000000000000000000000000000..77d1a8bdc20acae267d511b1a59b2257f31c179c --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/SimpleCircle.cc @@ -0,0 +1,90 @@ +#include "Criteria/SimpleCircle.h" + +#include <cmath> +#include <sstream> + + + +using namespace KiTrack; + +SimpleCircle::SimpleCircle( double x1 , double y1 , double x2 , double y2 , double x3, double y3 ) { + + + + // 1. check if they are not in a line, i.e. the slopes are parallel (or two or more points are identical) + + if ( (x2 -x1)*(y3 - y2) == (x3 - x2)*(y2 - y1) ){ + + + std::stringstream s; + + s << "SimpleCircle::The 3 points are on one line in xy-space: x1 = " + << x1 + << ", y1 = " << y1 + << ", x2 = " << x2 + << ", y2 = " << y2 + << ", x3 = " << x3 + << ", y3 = " << y3; + + throw InvalidParameter( s.str() ); + + + } + + + _R = 0; + _centerX = 0.; + _centerY = 0.; + + + _x1 = x1; + _y1 = y1; + _x2 = x2; + _y2 = y2; + _x3 = x3; + _y3 = y3; + + + //check if x1 and x2 or x2 and x3 are equal. If they are, swap them around, so that those are not 0. (or else the slopes get infinite) + // note that x1==x2==x3 is not possible as they would need to be on a line for that (and parallel, which we checked) + + if ( x1 == x2 ) { // x1 and x2 have the same x --> we swap the points around (still it stays the same circle) so the + // that they are now x1 and x3. because the line x1->x3 (i.e. its slope) isn't used in the calculations --> we don't care if it's zero. + + + _x2 = x3; + _y2 = y3; + _x3 = x2; + _y3 = y2; + + } + else if ( x2 == x3 ) { // x1 and x2 have the same x --> we swap the points around (still it stays the same circle) so the + // that they are now x1 and x3. because the line x1->x3 (i.e. its slope) isn't used in the calculations --> we don't care if it's zero. + + + _x2 = x1; + _y2 = y1; + _x1 = x2; + _y1 = y2; + + } + + + + double ma = (_y2-_y1)/(_x2-_x1); //slope + double mb = (_y3-_y2)/(_x3-_x2); + + + _centerX = ( ma*mb*(_y1-_y3) + mb*(_x1+_x2) - ma*(_x2+_x3) )/( 2.*(mb-ma)); + _centerY = (-1./ma) * ( _centerX - (_x1+_x2)/2. ) + (_y1+_y2)/2; + + _R = sqrt (( _x1 - _centerX )*( _x1 - _centerX ) + ( _y1 - _centerY )*( _y1 - _centerY )); + + + + + + + +} + diff --git a/Utilities/KiTrack/src/Criteria/SimpleCircle.h b/Utilities/KiTrack/src/Criteria/SimpleCircle.h new file mode 100644 index 0000000000000000000000000000000000000000..2c7d2da20cae8afb192f2994d8fd0012c33c88bc --- /dev/null +++ b/Utilities/KiTrack/src/Criteria/SimpleCircle.h @@ -0,0 +1,55 @@ +#ifndef SimpleCircle_h +#define SimpleCircle_h + +#include "KiTrack/KiTrackExceptions.h" + +namespace KiTrack{ + +/** A simple class representing a circle. + * + * In the constructor it builds a cricle from 3 2-dimensional points. + * After that, the parameters can be read out (radius and position of the center) + */ +class SimpleCircle { + + + + public: + + + SimpleCircle ( double x1 , double y1 , double x2 , double y2 , double x3, double y3 ) ; + + double getRadius() {return _R;}; + double getCenterX() {return _centerX;}; + double getCenterY() {return _centerY;}; + + private: + + + double _R{}; + double _centerX{}; + double _centerY{}; + + double _x1{}; + double _x2{}; + double _x3{}; + + double _y1{}; + double _y2{}; + double _y3{}; + + + +}; + + + + +} // end of namespace KiTrack + + + + +#endif + + diff --git a/Utilities/KiTrack/src/ILDImpl/#FTDTrack.cc# b/Utilities/KiTrack/src/ILDImpl/#FTDTrack.cc# new file mode 100644 index 0000000000000000000000000000000000000000..6d928c374e857ebcc3f08f657a8f873024955dbb --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/#FTDTrack.cc# @@ -0,0 +1,132 @@ +#include "ILDImpl/FTDTrack.h" + + +#include <algorithm> +#include <math.h> + +//#include "UTIL/LCTrackerConf.h" + +// Root, for calculating the chi2 probability. +#include "Math/ProbFunc.h" + + + +using namespace KiTrackMarlin; + +/** @return if the absolute z value of hit a is bigger than that of hit b */ +bool compare_IHit_z( IHit* a, IHit* b ){ + + return ( fabs( a->getZ() ) < fabs( b->getZ() ) ); //compare their z values + +} + + + +FTDTrack::FTDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem ){ + + _trkSystem = trkSystem; + _chi2Prob = 0.; + + _lcioTrack = new edm4hep::Track(); + + +} + +FTDTrack::FTDTrack( std::vector< IFTDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ){ + + + _trkSystem = trkSystem; + _chi2Prob = 0.; + + _lcioTrack = new edm4hep::Track(); + + for( unsigned i=0; i < hits.size(); i++ ){ + + addHit( hits[i] ); + + + } + +} + + +FTDTrack::FTDTrack( const FTDTrack& f ){ + + //make a new copied lcio track + _lcioTrack = new edm4hep::Track( *f._lcioTrack ); + + + _hits = f._hits; + _chi2Prob = f._chi2Prob; + _trkSystem = f._trkSystem; + +} + +FTDTrack & FTDTrack::operator= (const FTDTrack & f){ + + if (this == &f) return *this; //protect against self assignment + + //make a new copied lcio track + _lcioTrack = new edm4hep::Track( *f._lcioTrack ); + + + _hits = f._hits; + _chi2Prob = f._chi2Prob; + _trkSystem = f._trkSystem; + + return *this; + +} + + + +void FTDTrack::addHit( IFTDHit* hit ){ + if ( hit != NULL ){ + _hits.push_back( hit ); + // and sort the track again + sort( _hits.begin(), _hits.end(), compare_IHit_z ); + _lcioTrack->addToTrackerHits( *hit->getTrackerHit() ); + } +} + + + + + +void FTDTrack::fit() { + + + Fitter fitter( _lcioTrack , _trkSystem ); + + + _lcioTrack->setChi2( fitter.getChi2( 1/*by fucd AtIP=1 in LCIO, changed to CepC rule in future: lcio::TrackState::AtIP*/ ) ); + _lcioTrack->setNdf( fitter.getNdf( 1/*lcio::TrackState::AtIP*/ ) ); + _chi2Prob = fitter.getChi2Prob( 1/*lcio::TrackState::AtIP*/ ); + + edm4hep::TrackState trkState( *fitter.getTrackState( 1/*lcio::TrackState::AtIP*/ ) ) ; + trkState.location = 1/*lcio::TrackState::AtIP*/ ; + _lcioTrack->addToTrackStates( trkState ); + + +} + + +double FTDTrack::getQI() const{ + + + double QI = _chi2Prob; + + // make sure QI is between 0 and 1 + if (QI > 1. ) QI = 1.; + if (QI < 0. ) QI = 0.; + + return QI; + +} + + + + + + + diff --git a/Utilities/KiTrack/src/ILDImpl/FTDHit01.cc b/Utilities/KiTrack/src/ILDImpl/FTDHit01.cc new file mode 100644 index 0000000000000000000000000000000000000000..a5eaab1ca29a184eb0ff8cc2e457ee7f03450b42 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/FTDHit01.cc @@ -0,0 +1,44 @@ +#include "ILDImpl/FTDHit01.h" + + +#include "UTIL/ILDConf.h" + +using namespace KiTrackMarlin; + + +FTDHit01::FTDHit01( edm4hep::TrackerHit trackerHit , const SectorSystemFTD* const sectorSystemFTD ){ + + + _sectorSystemFTD = sectorSystemFTD; + + _trackerHit = trackerHit; + + //Set the position of the FTDHit01 + const edm4hep::Vector3d& pos= trackerHit.getPosition(); + _x = pos[0]; + _y = pos[1]; + _z = pos[2]; + + + //find out layer, module, sensor + + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + + cellID.setValue( trackerHit.getCellID() ); + + _side = cellID[ UTIL::ILDCellID0::side ]; + _module = cellID[ UTIL::ILDCellID0::module ]; + _sensor = cellID[ UTIL::ILDCellID0::sensor ] - 1; + _layer = cellID[ UTIL::ILDCellID0::layer ] + 1; + + + calculateSector(); + + + //We assume a real hit. If it is virtual, this has to be set. + _isVirtual = false; + + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/FTDHitSimple.cc b/Utilities/KiTrack/src/ILDImpl/FTDHitSimple.cc new file mode 100644 index 0000000000000000000000000000000000000000..57824a74192e879dc69f0cbee2f6760125269794 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/FTDHitSimple.cc @@ -0,0 +1,30 @@ +#include "ILDImpl/FTDHitSimple.h" + + +using namespace KiTrackMarlin; + +FTDHitSimple::FTDHitSimple( float x , float y , float z , int side, unsigned layer , unsigned module, unsigned sensor, const SectorSystemFTD* const sectorSystemFTD ){ + + + _sectorSystemFTD = sectorSystemFTD; + + _x = x; + _y = y; + _z = z; + + + _side = side; + _layer = layer; + _module = module; + _sensor = sensor; + + + calculateSector(); + + + //We assume a real hit. If it is virtual, this has to be set. + _isVirtual = false; + + +} + diff --git a/Utilities/KiTrack/src/ILDImpl/FTDNeighborPetalSecCon.cc b/Utilities/KiTrack/src/ILDImpl/FTDNeighborPetalSecCon.cc new file mode 100644 index 0000000000000000000000000000000000000000..30e8014743765c756d5257d44465fdf6cc7edd51 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/FTDNeighborPetalSecCon.cc @@ -0,0 +1,56 @@ +#include "ILDImpl/FTDNeighborPetalSecCon.h" + + +using namespace KiTrackMarlin; + + +FTDNeighborPetalSecCon::FTDNeighborPetalSecCon( const SectorSystemFTD* sectorSystemFTD ){ + + _sectorSystemFTD = sectorSystemFTD; + +} + + + +std::set< int > FTDNeighborPetalSecCon::getTargetSectors ( int sector ){ + + + + std::set <int> targetSectors; + + + int side = _sectorSystemFTD->getSide( sector ); + unsigned layer = _sectorSystemFTD->getLayer( sector ); + unsigned petal = _sectorSystemFTD->getModule( sector ); +// unsigned sensor = _sectorSystemFTD->getSensor( sector ); + +// unsigned nLayers = _sectorSystemFTD->getNumberOfLayers(); + unsigned nPetals = _sectorSystemFTD->getNumberOfModules(); + unsigned nSensors = _sectorSystemFTD->getNumberOfSensors(); + + + unsigned petalToTheLeft = petal - 1; //the names left and right are arbitrary, as it of course depends on from where one looks. + unsigned petalToTheRight = petal + 1; + + //Now we have to make sure that we didn't leave the petal range 0 to nPetals-1 + if (petal == 0) petalToTheLeft = nPetals - 1; + if (petal == nPetals - 1) petalToTheRight = 0; + + + + for ( unsigned iSensor=0; iSensor < nSensors ; iSensor++ ){ //over all sensors + + + targetSectors.insert( _sectorSystemFTD->getSector ( side , layer , petalToTheLeft , iSensor ) ); + targetSectors.insert( _sectorSystemFTD->getSector ( side , layer , petalToTheRight , iSensor ) ); + + } + + + + return targetSectors; + + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/FTDSectorConnector.cc b/Utilities/KiTrack/src/ILDImpl/FTDSectorConnector.cc new file mode 100644 index 0000000000000000000000000000000000000000..4e887e00dfa1667835fb9bca6b8e78683fd772de --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/FTDSectorConnector.cc @@ -0,0 +1,92 @@ +#include "ILDImpl/FTDSectorConnector.h" + + +using namespace KiTrackMarlin; + + + +FTDSectorConnector::FTDSectorConnector( const SectorSystemFTD* sectorSystemFTD , unsigned layerStepMax , unsigned petalStepMax, unsigned lastLayerToIP){ + + _sectorSystemFTD = sectorSystemFTD; + _layerStepMax = layerStepMax; + _lastLayerToIP = lastLayerToIP; + _petalStepMax = petalStepMax; + +} + + + +std::set< int > FTDSectorConnector::getTargetSectors ( int sector ){ + + + + std::set <int> targetSectors; + + + int side = _sectorSystemFTD->getSide( sector ); + unsigned layer = _sectorSystemFTD->getLayer( sector ); + unsigned module = _sectorSystemFTD->getModule( sector ); +// unsigned sensor = _sectorSystemFTD->getSensor( sector ); + +// unsigned nLayers = _sectorSystemFTD->getNumberOfLayers(); + unsigned nModules = _sectorSystemFTD->getNumberOfModules(); + unsigned nSensors = _sectorSystemFTD->getNumberOfSensors(); + + + for( unsigned layerStep = 1; layerStep <= _layerStepMax; layerStep++ ){ + + + + if ( layer >= layerStep +1 ){ //other wise the we could jump past layer 1, ( layer 0 is covered below) + + + unsigned layerTarget = layer - layerStep; + + + for ( unsigned iSensor=0; iSensor < nSensors ; iSensor++){ //over all sensors + + + for ( int iPetal= int(module) - _petalStepMax; iPetal <= int(module) + int(_petalStepMax) ; iPetal++ ){ + + //if iPetal is out of the range from 0 to nModules-1, move it back there. + //And of course use a different variable for that. + //(Or else we would create and endless loop: imagine we have iPetal = 16 and set it back to 0--> the loop will continue from there until it reaches 16 again and so on...) + int iModule = iPetal; + while( iModule < 0 ) iModule+= nModules; + while( iModule >= int(nModules) ) iModule -= nModules; + + targetSectors.insert( _sectorSystemFTD->getSector ( side , layerTarget , iModule , iSensor ) ); + + } + + } + + } + + } + + //Allow jumping to layer 0 from layer _lastLayerToIP or less + if ( ( layer >= 1 )&& ( layer <= _lastLayerToIP ) ){ + + + unsigned layerTarget = 0; + + for ( unsigned iModule=0; iModule < nModules ; iModule++){ //over all modules + + for ( unsigned iSensor=0; iSensor < nSensors ; iSensor++ ){ //over all sensors + + + targetSectors.insert( _sectorSystemFTD->getSector ( side , layerTarget , iModule , iSensor ) ); + + } + + } + + } + + return targetSectors; + + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/FTDTrack.cc b/Utilities/KiTrack/src/ILDImpl/FTDTrack.cc new file mode 100644 index 0000000000000000000000000000000000000000..6d928c374e857ebcc3f08f657a8f873024955dbb --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/FTDTrack.cc @@ -0,0 +1,132 @@ +#include "ILDImpl/FTDTrack.h" + + +#include <algorithm> +#include <math.h> + +//#include "UTIL/LCTrackerConf.h" + +// Root, for calculating the chi2 probability. +#include "Math/ProbFunc.h" + + + +using namespace KiTrackMarlin; + +/** @return if the absolute z value of hit a is bigger than that of hit b */ +bool compare_IHit_z( IHit* a, IHit* b ){ + + return ( fabs( a->getZ() ) < fabs( b->getZ() ) ); //compare their z values + +} + + + +FTDTrack::FTDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem ){ + + _trkSystem = trkSystem; + _chi2Prob = 0.; + + _lcioTrack = new edm4hep::Track(); + + +} + +FTDTrack::FTDTrack( std::vector< IFTDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ){ + + + _trkSystem = trkSystem; + _chi2Prob = 0.; + + _lcioTrack = new edm4hep::Track(); + + for( unsigned i=0; i < hits.size(); i++ ){ + + addHit( hits[i] ); + + + } + +} + + +FTDTrack::FTDTrack( const FTDTrack& f ){ + + //make a new copied lcio track + _lcioTrack = new edm4hep::Track( *f._lcioTrack ); + + + _hits = f._hits; + _chi2Prob = f._chi2Prob; + _trkSystem = f._trkSystem; + +} + +FTDTrack & FTDTrack::operator= (const FTDTrack & f){ + + if (this == &f) return *this; //protect against self assignment + + //make a new copied lcio track + _lcioTrack = new edm4hep::Track( *f._lcioTrack ); + + + _hits = f._hits; + _chi2Prob = f._chi2Prob; + _trkSystem = f._trkSystem; + + return *this; + +} + + + +void FTDTrack::addHit( IFTDHit* hit ){ + if ( hit != NULL ){ + _hits.push_back( hit ); + // and sort the track again + sort( _hits.begin(), _hits.end(), compare_IHit_z ); + _lcioTrack->addToTrackerHits( *hit->getTrackerHit() ); + } +} + + + + + +void FTDTrack::fit() { + + + Fitter fitter( _lcioTrack , _trkSystem ); + + + _lcioTrack->setChi2( fitter.getChi2( 1/*by fucd AtIP=1 in LCIO, changed to CepC rule in future: lcio::TrackState::AtIP*/ ) ); + _lcioTrack->setNdf( fitter.getNdf( 1/*lcio::TrackState::AtIP*/ ) ); + _chi2Prob = fitter.getChi2Prob( 1/*lcio::TrackState::AtIP*/ ); + + edm4hep::TrackState trkState( *fitter.getTrackState( 1/*lcio::TrackState::AtIP*/ ) ) ; + trkState.location = 1/*lcio::TrackState::AtIP*/ ; + _lcioTrack->addToTrackStates( trkState ); + + +} + + +double FTDTrack::getQI() const{ + + + double QI = _chi2Prob; + + // make sure QI is between 0 and 1 + if (QI > 1. ) QI = 1.; + if (QI < 0. ) QI = 0.; + + return QI; + +} + + + + + + + diff --git a/Utilities/KiTrack/src/ILDImpl/IMiniVector.h b/Utilities/KiTrack/src/ILDImpl/IMiniVector.h new file mode 100644 index 0000000000000000000000000000000000000000..af8142ba70466b5af84b6a6fd6e05da143b35925 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/IMiniVector.h @@ -0,0 +1,63 @@ +#ifndef IMiniVector_h +#define IMiniVector_h + +#include <iostream> + +#include "edm4hep/TrackerHit.h" + +#include "KiTrack/IHit.h" +#include "ILDImpl/MiniVector.h" + +#include "ILDImpl/SectorSystemVXD.h" + +namespace KiTrackMarlin{ + + + /** An interface for a mini-vector for the ILD + */ + class IMiniVector : public IHit{ + + + public: + + + MiniVector* getMiniVector() { return _miniVector; }; + + + int getTheta() { return _theta; } + unsigned getPhi() { return _phi; } + + + //void setLayer( unsigned layer ){ _layer = layer; calculateSector();} + //void setPhi( unsigned phi ){ _phi = phi; calculateSector();} + //void setTheta( unsigned theta ){ _theta = theta; calculateSector();} + void setLayer( unsigned layer ){ _layer = layer; } + void setPhi( unsigned phi ){ _phi = phi; } + void setTheta( unsigned theta ){ _theta = theta; } + + + virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemVXD; }; + + protected: + + MiniVector* _miniVector; + + + int _layer; + int _phi; + int _theta; + + const SectorSystemVXD* _sectorSystemVXD; + + /** Calculates and sets the sector number + */ + + //void calculateSector(){ _sector = _sectorSystemMV->getSector( _layer, _phi, _theta ); } + + }; + +} + + +#endif + diff --git a/Utilities/KiTrack/src/ILDImpl/IVXDHit.h b/Utilities/KiTrack/src/ILDImpl/IVXDHit.h new file mode 100644 index 0000000000000000000000000000000000000000..dcbecd9e9c0a1d92199895e52f33c34934de07e0 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/IVXDHit.h @@ -0,0 +1,53 @@ +#ifndef IVXDHit_h +#define IVXDHit_h + +#include <iostream> + +#include "edm4hep/TrackerHit.h" +//#include "lcio.h" + +#include "KiTrack/IHit.h" + +#include "ILDImpl/SectorSystemVXD.h" + +namespace KiTrackMarlin{ + /** An interface for a hit for the ILD using an lcio TrackerHit as basis. + * + * It comes along with a layer, phi and theta. + */ + class IVXDHit : public IHit{ + public: + + edm4hep::TrackerHit* getTrackerHit() { return _trackerHit; }; + + int getTheta() { return _theta; } + unsigned getPhi() { return _phi; } + + //void setLayer( unsigned layer ){ _layer = layer; calculateSector();} + //void setPhi( unsigned phi ){ _phi = phi; calculateSector();} + //void setTheta( unsigned theta ){ _theta = theta; calculateSector();} + void setLayer( unsigned layer ){ _layer = layer; } + void setPhi( unsigned phi ){ _phi = phi; } + void setTheta( unsigned theta ){ _theta = theta; } + + + virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemVXD; }; + + protected: + + edm4hep::TrackerHit* _trackerHit; + + int _layer; + int _phi; + int _theta; + + const SectorSystemVXD* _sectorSystemVXD; + + /** Calculates and sets the sector number + */ + + //void calculateSector(){ _sector = _sectorSystemVXD->getSector( _layer, _phi, _theta ); } + }; +} +#endif + diff --git a/Utilities/KiTrack/src/ILDImpl/MiniVector.cc b/Utilities/KiTrack/src/ILDImpl/MiniVector.cc new file mode 100644 index 0000000000000000000000000000000000000000..3d7840a2d440a9e801bcadcf61bed648e39dfadb --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/MiniVector.cc @@ -0,0 +1,139 @@ +#include <ILDImpl/MiniVector.h> + +#include "TrackSystemSvc/IMarlinTrack.h" +#include "CLHEP/Vector/ThreeVector.h" + +using namespace KiTrack; +using namespace KiTrackMarlin; + +MiniVector::MiniVector(edm4hep::TrackerHit * outer, edm4hep::TrackerHit * inner) { + HitVec.push_back(outer); + HitVec.push_back(inner); +} + + +MiniVector::MiniVector( TrackerHitVec hitPair){ + + HitVec = hitPair ; + +} + +MiniVector::~MiniVector(){ + +} + + +double * MiniVector::getPosition(){ + + double x_outer = HitVec[0]->getPosition()[0]; + double y_outer = HitVec[0]->getPosition()[1]; + double z_outer = HitVec[0]->getPosition()[2]; + + double x_inner = HitVec[1]->getPosition()[0]; + double y_inner = HitVec[1]->getPosition()[1]; + double z_inner = HitVec[1]->getPosition()[2]; + + double *_pos = new double[3] ; + + //_pos[0] = (x_outer - x_inner)/2. ; + //_pos[1] = (y_outer - y_inner)/2. ; + //_pos[2] = (z_outer - z_inner)/2. ; + + _pos[0] = x_inner ; + _pos[1] = y_inner ; + _pos[2] = z_inner ; + + return _pos ; + +} + + +TrackerHitVec MiniVector::getTrackerHitVec(){ + + return HitVec ; + +} + + + +double MiniVector::getPhi(){ + + double x_outer = HitVec[0]->getPosition()[0]; + double y_outer = HitVec[0]->getPosition()[1]; + + double x_inner = HitVec[1]->getPosition()[0]; + double y_inner = HitVec[1]->getPosition()[1]; + + double phiMV = atan2((y_outer-y_inner),(x_outer-x_inner)) ; + + //std::cout << " outer x,y " << x_outer << " , " << y_outer << " inner x,y " << x_inner << " , " << y_inner << std::endl ; + + //std::cout << " Calling MiniVector::getPhi, returning " << phiMV << std::endl ; + + return phiMV ; + +} + +double MiniVector::getTheta(){ + + double x_outer = HitVec[0]->getPosition()[0]; + double y_outer = HitVec[0]->getPosition()[1]; + double z_outer = HitVec[0]->getPosition()[2]; + + double x_inner = HitVec[1]->getPosition()[0]; + double y_inner = HitVec[1]->getPosition()[1]; + double z_inner = HitVec[1]->getPosition()[2]; + + double thetaMV = atan2(sqrt((x_outer-x_inner)*(x_outer-x_inner) + (y_outer-y_inner)*(y_outer-y_inner)),(z_outer-z_inner)) ; + + return thetaMV ; + +} + + +double * MiniVector::getXYZ(){ + + double x_outer = HitVec[0]->getPosition()[0]; + double y_outer = HitVec[0]->getPosition()[1]; + double z_outer = HitVec[0]->getPosition()[2]; + + double x_inner = HitVec[1]->getPosition()[0]; + double y_inner = HitVec[1]->getPosition()[1]; + double z_inner = HitVec[1]->getPosition()[2]; + + double *xyz = new double[3] ; + + xyz[0] = x_outer - x_inner ; + xyz[1] = y_outer - y_inner ; + xyz[2] = z_outer - z_inner ; + + + return xyz ; + +} + + +double MiniVector::get3DAngleMV(MiniVector *MinVec2){ + + double *xyz1 = new double[3] ; + xyz1 = this->getXYZ() ; + CLHEP::Hep3Vector v1( xyz1[0], xyz1[1], xyz1[2] ) ; + + double *xyz2 = new double[3] ; + xyz2 = MinVec2->getXYZ() ; + + CLHEP::Hep3Vector v2( xyz2[0], xyz2[1], xyz2[2] ) ; + + double ScalarProd = v1.dot(v2); + double magV1 = v1.r(); + double magV2 = v2.r(); + + std::cout << "####### MINIVECTOR::get3DAngle, Scalar product " << ScalarProd << " mag. of the instantiate mv " << magV1 << " mag. of the second mv " << magV2 << std::endl ; + + double Angle3D = acos(ScalarProd / (magV1*magV2)) ; + + return Angle3D ; + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/MiniVector.h b/Utilities/KiTrack/src/ILDImpl/MiniVector.h new file mode 100644 index 0000000000000000000000000000000000000000..40c2e369c918597911fb1afc4bb1d8eb87011c58 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/MiniVector.h @@ -0,0 +1,67 @@ +#ifndef MINIVECTOR_H +#define MINIVECTOR_H 1 + +#include <iostream> +#include <sstream> +#include <string> +#include <edm4hep/TrackerHit.h> +//#include "UTIL/LCTrackerConf.h" +#include "KiTrack/IHit.h" + +#include "ILDImpl/SectorSystemVXD.h" + +#include <vector> +#include <math.h> + +typedef std::vector<edm4hep::TrackerHit*> TrackerHitVec; + +namespace KiTrackMarlin{ + class MiniVector : public IHit{ + public: + TrackerHitVec HitVec ; + + // Class constructor + MiniVector(edm4hep::TrackerHit * outer, edm4hep::TrackerHit * inner); + + MiniVector(TrackerHitVec hitPair); + + ~MiniVector(); + + // returns the TrackerHitVec + TrackerHitVec getTrackerHitVec() ; + + // Gives the layer of the inner hit + //int getLayer() ; + + // Gives the azimuth angle of the mini-vector + double getPhi() ; + + // Gives the polar angle of the mini-vector + double getTheta() ; + + // Gives the 2-D angle between two minivectors + //double get2DAngle(MiniVector MinVec1, MiniVector MinVec2) ; + + // Gives the 3-D angle between two minivectors + double get3DAngleMV(MiniVector *MinVec2) ; + + double * getXYZ() ; + + // Gives the position of the mini-vector + double * getPosition() ; + + virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemVXD; }; + + + protected: + + const SectorSystemVXD* _sectorSystemVXD; + + }; + +} + + + + +#endif diff --git a/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.cc b/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.cc new file mode 100644 index 0000000000000000000000000000000000000000..10d7ea3c7f3c222ab1030964cd6d7f5c1d32e15e --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.cc @@ -0,0 +1,59 @@ +#include "ILDImpl/MiniVectorHit01.h" +#include "ILDImpl/SectorSystemVXD.h" + +//#include "UTIL/LCTrackerConf.h" +#include <UTIL/ILDConf.h> + +#include <iostream> +#include <algorithm> +#include <cmath> +#include <climits> + +using namespace KiTrackMarlin; + +typedef std::vector<edm4hep::TrackerHit*> TrackerHitVec; + +MiniVectorHit01::MiniVectorHit01( MiniVector* miniVector , const SectorSystemVXD* const sectorSystemVXD ){ + + + _sectorSystemVXD = sectorSystemVXD; + + _miniVector = miniVector; + + _phiMV = miniVector->getPhi() ; + + _thetaMV = miniVector->getTheta() ; + + TrackerHitVec HitVec = miniVector->getTrackerHitVec(); + + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + cellID.setValue( HitVec[1]->getCellID() ); + + int _layer = cellID[ UTIL::ILDCellID0::layer ] ; // +1 to take into account the IP (considered as layer 0 ) + int det_id = 0 ; + det_id = cellID[UTIL::ILDCellID0::subdet] ; + if ( det_id == UTIL::ILDDetID::SIT) { _layer = _layer + 6; } + + //Set the position of the VXDHit01 + const double* pos= miniVector->getPosition(); + _x = pos[0]; + _y = pos[1]; + _z = pos[2]; + + double _cosTheta = cos(miniVector->getTheta()); + double _phi = miniVector->getPhi(); + double _theta = miniVector->getTheta() ; + + if (_phi < 0.) _phi = _phi + 2*M_PI; + + // YV, for debugging. Calculate sector here and not through the IVXHit base class + //calculateSector(); + _sector = _sectorSystemVXD->getSector( _layer, _phi, _cosTheta ); + + //We assume a real hit. If it is virtual, this has to be set. + _isVirtual = false; + + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.h b/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.h new file mode 100644 index 0000000000000000000000000000000000000000..e3e50afda6e3738b0faf3597a15b2583fae678b1 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/MiniVectorHit01.h @@ -0,0 +1,16 @@ +#ifndef MiniVectorHit01_h +#define MiniVectorHit01_h + +#include "ILDImpl/IMiniVector.h" + +namespace KiTrackMarlin{ + /** A class for mini-vectors in the VXD - SIT system (the 01 is just for historical reasons and may be renamed) + */ + class MiniVectorHit01 : public IMiniVector{ + public: + + MiniVectorHit01( MiniVector* miniVector , const SectorSystemVXD* const sectorSystemVXD ); + }; +} +#endif + diff --git a/Utilities/KiTrack/src/ILDImpl/SectorSystemFTD.cc b/Utilities/KiTrack/src/ILDImpl/SectorSystemFTD.cc new file mode 100644 index 0000000000000000000000000000000000000000..ff064859ef34fcba614a1371d9e9ebe80c30abb7 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/SectorSystemFTD.cc @@ -0,0 +1,183 @@ +#include "ILDImpl/SectorSystemFTD.h" + +#include <sstream> + +using namespace KiTrackMarlin; + + +SectorSystemFTD::SectorSystemFTD( unsigned nLayers , unsigned nModules , unsigned nSensors ): + + +_nModules( nModules ), +_nSensors( nSensors ){ + + _nLayers = nLayers; + _sectorMax = 2*nLayers*nModules*nSensors - 1; + +} + + + +int SectorSystemFTD::getSector( int side, unsigned layer , unsigned module , unsigned sensor )const { + + //check if the values passed are okay: + if ( ( side!= 1 )&&( side != -1 ) ){ + + + std::stringstream s; + s << "Side has to be either +1 or -1 and not " << side; + throw OutOfRange( s.str() ); + + } + + if ( layer >= _nLayers ){ + + std::stringstream s; + s << "Layer " << layer << " is too big, the outermost layer is layer " << _nLayers - 1; + throw OutOfRange( s.str() ); + + } + + if ( module >= _nModules ){ + + std::stringstream s; + s << "Module " << module << " is too big, the highest module is module " << _nModules - 1; + throw OutOfRange( s.str() ); + + } + + if ( sensor >= _nSensors ){ + + std::stringstream s; + s << "Sensor " << sensor << " is too big, the highest sensor is sensor " << _nSensors - 1; + throw OutOfRange( s.str() ); + + } + + unsigned multiplicator=1; + + + int sector = sensor; + multiplicator *= _nSensors; //there are nSensors possible values for sensor + + sector += module * multiplicator; + multiplicator *= _nModules; + + sector += layer * multiplicator; + multiplicator *= _nLayers; + + + sector += ( (side + 1 )/2 ) * multiplicator; // (side+1) /2 gives 0 for backward (-1) and 1 for forward (+1) + /* + streamlog_out( DEBUG0 ) << " Sector of side " << side + << ", layer " << layer + << ", module " << module + << ", sensor " << sensor + << " == " << sector << "\n"; + */ + + return sector; + +} + + + + + + +int SectorSystemFTD::getSide( int sector ) const { + + checkSectorIsInRange( sector ); + + + + int side = ( sector / ( _nSensors * _nModules * _nLayers ) ) % 2; //this is an integerdivision --> we will get the floor authomatically + + side = side*2 - 1 ; //from 0 and 1 to -1 and 1 + +// streamlog_out( DEBUG0 ) << "\n Sector " << sector << " == Side " << side; + + return side; + +} + +unsigned SectorSystemFTD::getLayer( int sector ) const { + + checkSectorIsInRange( sector ); + + unsigned layer = ( sector / ( _nSensors * _nModules ) ) % _nLayers; //this is an integerdivision --> we will get the floor authomatically + +// streamlog_out( DEBUG0 ) << "\n Sector " << sector << " == Layer " << layer; + + return layer; + + +} + +unsigned SectorSystemFTD::getModule( int sector ) const { + + + checkSectorIsInRange( sector ); + + unsigned module = ( sector / ( _nSensors ) ) % _nModules; //this is an integerdivision --> we will get the floor authomatically + +// streamlog_out( DEBUG0 ) << "\n Sector " << sector << " == Module " << module; + + return module; + + + +} +unsigned SectorSystemFTD::getSensor( int sector ) const { + + + checkSectorIsInRange( sector ); + + unsigned sensor = ( sector ) % _nSensors; + +// streamlog_out( DEBUG0 ) << "\n Sector " << sector << " == Sensor " << sensor; + + return sensor; + +} + + +void SectorSystemFTD::checkSectorIsInRange( int sector ) const { + + + if ( sector > _sectorMax ){ + + std::stringstream s; + s << "SectorSystemFTD:\n Sector " + << sector << " is too big, the highest possible number for a sector in this configuration of FTDSegRepresentation is" + << _sectorMax + << ".\nThe configuration is: nLayers = " << _nLayers + << ", nModules = " << _nModules + << ", nSensors = " << _nSensors + << "\n With 2 sides (forward and backward) this gives sectors from 0 to 2*" + << _nLayers << "*" + << _nModules << "*" + << _nSensors << " -1 = " << 2*_nLayers*_nModules*_nSensors -1 ; + throw OutOfRange( s.str() ); + + } + +} + +std::string SectorSystemFTD::getInfoOnSector( int sector ) const{ + + + std::stringstream s; + s << " (si" << getSide(sector) + << ",la" << getLayer(sector) + << ",mo" << getModule(sector) + << ",se" << getSensor(sector) + << ")"; + + + return s.str(); + + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/SectorSystemVXD.cc b/Utilities/KiTrack/src/ILDImpl/SectorSystemVXD.cc new file mode 100644 index 0000000000000000000000000000000000000000..305d37c3dcbdba928ade34ada120c1eb969ab2f5 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/SectorSystemVXD.cc @@ -0,0 +1,201 @@ +#include "ILDImpl/SectorSystemVXD.h" + +#include <sstream> +#include <cmath> + +using namespace KiTrackMarlin; + + +SectorSystemVXD::SectorSystemVXD( unsigned nLayers, unsigned nDivisionsInPhi, unsigned nDivisionsInTheta ){ + + _nLayers = nLayers; + _nDivisionsInPhi = nDivisionsInPhi ; + _nDivisionsInTheta = nDivisionsInTheta ; + _sectorMax = _nLayers + _nLayers*_nDivisionsInPhi + _nLayers*_nDivisionsInPhi*_nDivisionsInTheta ; + +} + +unsigned SectorSystemVXD::getNLayers() const { + + return _nLayers ; + +} + +unsigned SectorSystemVXD::getPhiSectors() const { + + return _nDivisionsInPhi ; + +} + + +unsigned SectorSystemVXD::getThetaSectors() const { + + return _nDivisionsInTheta ; + +} + + +unsigned SectorSystemVXD::getLayer( int sector ) const { + + //std::cout << " SectorSystemVXD::getLayer total no of layers = " << _nLayers << " n divisions in phi = " << _nDivisionsInPhi << " sector = " << sector << std::endl ; + + int theta = sector/(_nLayers*_nDivisionsInPhi) ; + + int phi = ((sector - (theta*_nLayers*_nDivisionsInPhi)) / _nLayers) ; + + int Layer = sector - (theta*_nLayers*_nDivisionsInPhi) - (phi*_nLayers) ; + + //std::cout << " SectorSystemVXD::getLayer " << Layer << " total no of layers = " << _nLayers << " iPhi = " << phi << " iTheta = " << theta << " n divisions in phi = " << _nDivisionsInPhi << " sector = " << sector << std::endl ; + + return Layer ; + +} + + +unsigned SectorSystemVXD::getPhi( int sector) const { + + int theta = sector/(_nLayers*_nDivisionsInPhi) ; + + int Phi = ((sector - (theta*_nLayers*_nDivisionsInPhi)) / _nLayers) ; + + //std::cout << " SectorSystemVXD::getPhi " << Phi << std::endl ; + + return Phi ; + +} + + +unsigned SectorSystemVXD::getTheta( int sector ) const { + + int Theta = sector/(_nLayers*_nDivisionsInPhi) ; + + //std::cout << " SectorSystemVXD::getTheta " << Theta << std::endl ; + + return Theta ; + +} + + +int SectorSystemVXD::getSector( int layer , int phi , int theta ) const { + + //std::cout << "getting sector : layer " << layer << " phi " << phi << " theta " << theta << std::endl ; + + if ( layer >= _nLayers ){ + + std::stringstream s; + s << "Layer " << layer << " is too big, the outermost layer is layer " << _nLayers - 1 ; + throw OutOfRange( s.str() ); + + } + + + if ( phi >= _nDivisionsInPhi ){ + + std::stringstream s; + s << "Phi " << phi << " is too big, the highest phi division is " << _nDivisionsInPhi ; + throw OutOfRange( s.str() ); + + } + + + + if ( theta >= _nDivisionsInTheta ){ + + std::stringstream s; + s << "Theta " << theta << " is too big, the highest theta division is " << _nDivisionsInTheta ; + + throw OutOfRange( s.str() ); + //std::cout << " ####3 calling getSector function $$$$$$$$$$" << std::endl ; + } + + int sector = layer + _nLayers*phi + _nLayers*_nDivisionsInPhi*theta ; + //std::cout << " did you call me? I am the Theta version, give you the sector " << sector << std::endl ; + + return sector ; + +} + + +int SectorSystemVXD::getSector( int layer , double phi , double cosTheta ) const { + + + double _dPhi = (2*M_PI)/_nDivisionsInPhi; + double _dTheta = 2.0/_nDivisionsInTheta; + int iPhi = int(phi / _dPhi); + int iTheta = int ((cosTheta + double(1.0))/_dTheta); + + //std::cout << "getting sector : layer " << layer << " phi " << iPhi << " theta " << iTheta << std::endl ; + + if ( layer >= _nLayers ){ + + std::stringstream s; + s << "Layer " << layer << " is too big, the outermost layer is layer " << _nLayers - 1 ; + throw OutOfRange( s.str() ); + + } + + + if ( iPhi >= _nDivisionsInPhi ){ + + std::stringstream s; + s << "Phi " << iPhi << " is too big, the highest phi division is " << _nDivisionsInPhi ; + throw OutOfRange( s.str() ); + + } + + + + if ( iTheta >= _nDivisionsInTheta ){ + + std::stringstream s; + s << "Theta " << iTheta << " is too big, the highest theta division is " << _nDivisionsInTheta ; + + throw OutOfRange( s.str() ); + //std::cout << " ####3 calling getSector function $$$$$$$$$$" << std::endl ; + } + + int sector = layer + _nLayers*iPhi + _nLayers*_nDivisionsInPhi*iTheta ; + //std::cout << " did you call me? I am the cosTheta version, give you the sector " << sector << std::endl ; + + return sector ; + +} + + + +void SectorSystemVXD::checkSectorIsInRange( int sector ) const { + + + if ( sector > _sectorMax ){ + + std::stringstream s; + s << "SectorSystemVXS:\n Sector " + << sector << " is too big, the highest possible number for a sector in this configuration of VXD - SIT is" + << _sectorMax + << ".\nThe configuration is: nLayers = " << _nLayers + << ", n divisions in phi = " << _nDivisionsInPhi + << ", n divisions in theta = " << _nDivisionsInTheta + << _nLayers + _nLayers*_nDivisionsInPhi + _nLayers*_nDivisionsInPhi*_nDivisionsInTheta ; + throw OutOfRange( s.str() ); + + } + +} + + +std::string SectorSystemVXD::getInfoOnSector( int sector ) const{ + + + std::stringstream s; + s << " (layer" << getLayer(sector ) + << ",theta" << getTheta(sector ) + << ",phi" << getPhi(sector ) + << ")"; + + + return s.str(); + + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/VXDHit01.cc b/Utilities/KiTrack/src/ILDImpl/VXDHit01.cc new file mode 100644 index 0000000000000000000000000000000000000000..f6e67e95974d78d0e57ea740e501df2142a0e507 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/VXDHit01.cc @@ -0,0 +1,67 @@ +#include "ILDImpl/VXDHit01.h" +#include "ILDImpl/SectorSystemVXD.h" + +//#include "UTIL/LCTrackerConf.h" +#include <UTIL/ILDConf.h> + +#include <iostream> +#include <algorithm> +#include <cmath> +#include <climits> + +using namespace KiTrackMarlin; + + +VXDHit01::VXDHit01( edm4hep::TrackerHit* trackerHit , const SectorSystemVXD* const sectorSystemVXD ){ + + + _sectorSystemVXD = sectorSystemVXD; + + _trackerHit = trackerHit; + + //Set the position of the VXDHit01 + const edm4hep::Vector3d& pos= trackerHit->getPosition(); + _x = pos[0]; + _y = pos[1]; + _z = pos[2]; + + + //find out layer, module, sensor + + UTIL::BitField64 cellID( UTIL::ILDCellID0::encoder_string ); + + //cellID.setValue( trackerHit->getCellID0() ); + _layer = cellID[ UTIL::ILDCellID0::layer ] + 1 ; // + 1 to take into account the IP (considered as layer 0 ) + //_layer = cellID[ LCTrackerCellID::layer() ]; + int det_id = 0 ; + det_id = cellID[UTIL::ILDCellID0::subdet] ; + if ( det_id == UTIL::ILDDetID::SIT) { _layer = _layer + 6; } // need to find a more elegant way... + + + double radius = 0; + + for (int i=0; i<3; ++i) { + radius += pos[i]*pos[i]; + } + + radius = sqrt(radius); + + double _cosTheta = (pos[2]/radius); + double _phi = atan2(pos[1],pos[0]); + double _theta = acos( _cosTheta ) ; + + if (_phi < 0.) _phi = _phi + 2*M_PI; + + // YV, for debugging. Calculate sector here and not through the IVXHit base class + //calculateSector(); + + _sector = _sectorSystemVXD->getSector( _layer, _phi, _cosTheta ); + + + //We assume a real hit. If it is virtual, this has to be set. + _isVirtual = false; + + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/VXDHit01.h b/Utilities/KiTrack/src/ILDImpl/VXDHit01.h new file mode 100644 index 0000000000000000000000000000000000000000..dbcc828f742d649235b1936d4e582c41dc5ef803 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/VXDHit01.h @@ -0,0 +1,23 @@ +#ifndef VXDHit01_h +#define VXDHit01_h + +#include "ILDImpl/IVXDHit.h" + +namespace KiTrackMarlin{ + /** A class for hits in the VXD (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 VXD start with 1 in the CellID0, if this changes, this has to be modified) + */ + class VXDHit01 : public IVXDHit{ + public: + + VXDHit01( edm4hep::TrackerHit* trackerHit , const SectorSystemVXD* const sectorSystemVXD ); + }; + //void setSectorisationInPhi(int PhiSectors); + //void setSectorisationInTheta(int ThetaSectors); +} +#endif + diff --git a/Utilities/KiTrack/src/ILDImpl/VXDHitSimple.cc b/Utilities/KiTrack/src/ILDImpl/VXDHitSimple.cc new file mode 100644 index 0000000000000000000000000000000000000000..857e67842f2f821e59bb6becf42c443a05c0fbaa --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/VXDHitSimple.cc @@ -0,0 +1,29 @@ +#include "ILDImpl/VXDHitSimple.h" + + +using namespace KiTrackMarlin; + +VXDHitSimple::VXDHitSimple( float x , float y , float z , int layer , int phi, int theta, const SectorSystemVXD* const sectorSystemVXD ){ + + + _sectorSystemVXD = sectorSystemVXD; + + _x = x; + _y = y; + _z = z; + + + _layer = layer; + _phi = phi; + _theta = theta; + + _sector = _sectorSystemVXD->getSector( layer, phi, theta ); // maybe a good idea to calculate a sector for the IP hit as well + //calculateSector(); + + + //We assume a real hit. If it is virtual, this has to be set. + _isVirtual = false; + + +} + diff --git a/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.cc b/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.cc new file mode 100644 index 0000000000000000000000000000000000000000..4237c06a313e16b9f405681ae90e782c47609e81 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.cc @@ -0,0 +1,100 @@ +#include "ILDImpl/VXDSectorConnector.h" + + +using namespace KiTrackMarlin; + + +// Constructor +VXDSectorConnector::VXDSectorConnector( const SectorSystemVXD* sectorSystemVXD , unsigned layerStepMax, unsigned lastLayerToIP, int neighPhi, int neighTheta, int layerMax ){ + + _sectorSystemVXD = sectorSystemVXD ; + _layerStepMax = layerStepMax ; + _lastLayerToIP = lastLayerToIP ; + + _nLayers = sectorSystemVXD->getNLayers(); + _nDivisionsInPhi = sectorSystemVXD->getPhiSectors(); + _nDivisionsInTheta = sectorSystemVXD->getThetaSectors(); + _neighPhi = neighPhi ; + _neighTheta = neighTheta ; + _layerMax = layerMax ; +} + + + +std::set< int > VXDSectorConnector::getTargetSectors ( int sector ){ + + + std::set <int> targetSectors; + + //std::cout << " check : n layers " << _nLayers << " n phi divisions " << _nDivisionsInPhi << " n theta divisions " << _nDivisionsInTheta << std::endl ; + + // Decode the sector integer, and take the layer, phi and theta bin + + int iTheta = sector/(_nLayers*_nDivisionsInPhi) ; + + int iPhi = ((sector - (iTheta*_nLayers*_nDivisionsInPhi)) / _nLayers) ; + + int layer = sector - (iTheta*_nLayers*_nDivisionsInPhi) - (iPhi*_nLayers) ; + + // search for sectors at the neighbouring theta nad phi bins + + int iPhi_Up = iPhi + _neighPhi; + int iPhi_Low = iPhi - _neighPhi; + int iTheta_Up = iTheta + _neighTheta; + int iTheta_Low = iTheta - _neighTheta; + if (iTheta_Low < 0) iTheta_Low = 0; + if (iTheta_Up >= _nDivisionsInTheta) iTheta_Up = _nDivisionsInTheta-1; + + //************************************************************************************* + + //streamlog_out(DEBUG2) << " checking sector " << sector << " layer " << layer << " phi " << iPhi << " theta " << iTheta <<std::endl ; + + for( unsigned layerStep = 1; layerStep <= _layerStepMax; layerStep++ ){ + + if ( layer >= layerStep ){ // +1 makes sense if I use IP as innermost layer + + unsigned layerTarget = layer - layerStep; + + if (layerTarget >= 0 && layerTarget < _layerMax ){ // just a test to run cellular automaton over the whole VXD - SIT + + for (int iPhi = iPhi_Low ; iPhi <= iPhi_Up ; iPhi++){ + + int ip = iPhi; + + // catch wrap-around + if (ip < 0) ip = _nDivisionsInPhi-1; + if (ip >= _nDivisionsInPhi) ip = ip - _nDivisionsInPhi; + + for (int iTheta = iTheta_Low ; iTheta <= iTheta_Up ; iTheta++){ + + targetSectors.insert( _sectorSystemVXD->getSector ( layerTarget , ip , iTheta ) ); + + } + } + } + } + } + + + if ( layer > 0 && ( layer <= _lastLayerToIP ) ){ + + unsigned layerTarget = 0; + + for (int ip = iPhi_Low ; ip <= iPhi_Up ; ip++){ + + for (int iTheta = iTheta_Low ; iTheta <= iTheta_Up ; iTheta++){ + + //streamlog_out(DEBUG1) << " VXDSectorConnector: from layer " << layer << " to layer " << layerTarget << std::endl ; + + targetSectors.insert( 0 ) ; + } + } + } + + + return targetSectors; + + +} + + diff --git a/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.h b/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.h new file mode 100644 index 0000000000000000000000000000000000000000..27ef66f7daffed7d09c76ee2d8957bde26197dc5 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/VXDSectorConnector.h @@ -0,0 +1,51 @@ +#ifndef VXDSectorConnector_h +#define VXDSectorConnector_h + +#include "KiTrack/ISectorConnector.h" + +#include "ILDImpl/SectorSystemVXD.h" + + + +namespace KiTrackMarlin{ + + /** Used to connect two sectors on the VXD. + * + * + * Allows: + * + * - going to layers on the inside (how far see constructor) + * - jumping to the IP (from where see constructor) + */ + class VXDSectorConnector : public ISectorConnector{ + + + public: + + VXDSectorConnector ( const SectorSystemVXD* sectorSystemVXD , unsigned layerStepMax, unsigned lastLayerToIP, int neighPhi = 8, int neighTheta = 1, int layerMax = 10 ) ; + + /** @return a set of all sectors that are connected to the passed sector */ + virtual std::set <int> getTargetSectors ( int sector ); + + virtual ~VXDSectorConnector(){}; + + private: + + const SectorSystemVXD* _sectorSystemVXD; + + unsigned _layerStepMax; + unsigned _nLayers; + unsigned _lastLayerToIP; + unsigned _nDivisionsInPhi ; + unsigned _nDivisionsInTheta ; + int _layerMax ; + int _neighTheta ; + int _neighPhi ; + }; + + +} + + +#endif + diff --git a/Utilities/KiTrack/src/ILDImpl/VXDTrack.cc b/Utilities/KiTrack/src/ILDImpl/VXDTrack.cc new file mode 100644 index 0000000000000000000000000000000000000000..b00b855e9500d3177b4fd9bc2ed404447bf87287 --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/VXDTrack.cc @@ -0,0 +1,201 @@ +#include "ILDImpl/VXDTrack.h" + +#include <algorithm> + +//#include "UTIL/LCTrackerConf.h" + +// Root, for calculating the chi2 probability. +#include "Math/ProbFunc.h" + + + +using namespace KiTrackMarlin; + +// FIX ME +/** @return if the radius of hit a is bigger than that of hit b */ + +bool compare_IHit_R_3Dhits( IHit* a, IHit* b ){ + + double r2_a = fabs((a->getX()*a->getX()) + (a->getY()*a->getY())); + double r2_b = fabs((b->getX()*b->getX()) + (b->getY()*b->getY())); + + return ( r2_a < r2_b ); //compare their radii + +} + + + +VXDTrack::VXDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem ){ + + _trkSystem = trkSystem; + _chi2Prob = 0.; + + _lcioTrack = new edm4hep::Track(); + +} +/* +VXDTrack::VXDTrack( std::vector< IVXDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ){ + + + _trkSystem = trkSystem; + _chi2Prob = 0.; + + _lcioTrack = new TrackImpl(); + + for( unsigned i=0; i < hits.size(); i++ ){ + + addHit( hits[i] ); + + + } + +} +*/ + +VXDTrack::VXDTrack( std::vector< IMiniVector* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ){ + + + _trkSystem = trkSystem; + _chi2Prob = 0.; + + _lcioTrack = new edm4hep::Track(); + + for( unsigned i=0; i < hits.size(); i++ ){ + + addHit( hits[i] ); + + + } + +} + + + + +VXDTrack::VXDTrack( const VXDTrack& f ){ + + //make a new copied lcio track + _lcioTrack = new edm4hep::Track( *f._lcioTrack ); + + + _hits = f._hits; + _chi2Prob = f._chi2Prob; + _trkSystem = f._trkSystem; + +} + +VXDTrack & VXDTrack::operator= (const VXDTrack & f){ + + if (this == &f) return *this; //protect against self assignment + + //make a new copied lcio track + _lcioTrack = new edm4hep::Track( *f._lcioTrack ); + + + _hits = f._hits; + _chi2Prob = f._chi2Prob; + _trkSystem = f._trkSystem; + + return *this; + +} + + +/* +void VXDTrack::addHit( IVXDHit* hit ){ + + + + if ( hit != NULL ){ + + _hits.push_back( hit ); + + // and sort the track again + sort( _hits.begin(), _hits.end(), compare_IHit_R_3Dhits ); + + + _lcioTrack->addHit( hit->getTrackerHit() ); + + } + +} +*/ + + + +void VXDTrack::addHit( IMiniVector* MV ){ + + + + if ( MV != NULL ){ + + _hits.push_back( MV ); // so to be able to check the tracks compatibilty + + MiniVector *MinVec = MV->getMiniVector(); + TrackerHitVec HitVec = MinVec->getTrackerHitVec() ; + + + for (TrackerHitVec::iterator it = HitVec.begin(); it != HitVec.end() ; ++it ){ + + edm4hep::TrackerHit *trkHit = *it ; + + //_trkhits.push_back( trkHit ); + + _lcioTrack->addToTrackerHits( *trkHit ); + + } + + // and sort the track again + //sort( _trkhits.begin(), _trkhits.end(), compare_IHit_R_3Dhits ); + + } + +} + + + + + +void VXDTrack::fit() { + + + Fitter fitter( _lcioTrack , _trkSystem , 1 ); + + + _lcioTrack->setChi2( fitter.getChi2( 1/*lcio::TrackState::AtIP*/ ) ); + _lcioTrack->setNdf( fitter.getNdf( 1/*lcio::TrackState::AtIP*/ ) ); + _chi2Prob = fitter.getChi2Prob( 1/*lcio::TrackState::AtIP*/ ); + + edm4hep::TrackState trkState( *fitter.getTrackState( 1/*lcio::TrackState::AtIP*/ ) ) ; + trkState.location = 1/*TrackState::AtIP*/; + _lcioTrack->addToTrackStates( trkState ); + +} + + +double VXDTrack::getQI() const{ + + + double QI = _chi2Prob; + + // make sure QI is between 0 and 1 + if (QI > 1. ) QI = 1.; + if (QI < 0. ) QI = 0.; + + return QI; + +} + +/* +double VXDTrack::getPT() const{ + + double Omega = _lcioTrack->getOmega(); + double PT = fabs((0.3*3.5)/(1000*Omega)); + + return PT ; + +} +*/ + + + diff --git a/Utilities/KiTrack/src/ILDImpl/VXDTrack.h b/Utilities/KiTrack/src/ILDImpl/VXDTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..ad57501fccf42b3dc362c96fee346fd476b2120e --- /dev/null +++ b/Utilities/KiTrack/src/ILDImpl/VXDTrack.h @@ -0,0 +1,89 @@ +#ifndef VXDTrack_h +#define VXDTrack_h + +#include "edm4hep/Track.h" +#include "edm4hep/TrackerHit.h" +#include "TrackSystemSvc/IMarlinTrkSystem.h" +#include "TrackSystemSvc/IMarlinTrack.h" + +#include <vector> + +#include "ILDImpl/IVXDHit.h" +#include "ILDImpl/IMiniVector.h" +#include "KiTrack/ITrack.h" + +#include "Tools/Fitter.h" + +//#include "SpacePointBuilder.h" +// CLHEP tools +#include "CLHEP/Vector/ThreeVector.h" +#include "CLHEP/Matrix/SymMatrix.h" +#include "CLHEP/Matrix/Matrix.h" + + +namespace KiTrackMarlin{ + /** A class for ITracks containing an lcio::Track at core + */ + class VXDTrack : public ITrack { + public: + + /** @param trkSystem An IMarlinTrkSystem, which is needed for fitting of the tracks + */ + VXDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem ); + + /** @param hits The hits the track consists of + * @param trkSystem An IMarlinTrkSystem, which is needed for fitting of the tracks + */ + //VXDTrack( std::vector< IVXDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ); + VXDTrack( std::vector< IMiniVector* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem ); + VXDTrack( const VXDTrack& f ); + VXDTrack & operator= (const VXDTrack & f); + + /** @return a track in the lcio format + */ + edm4hep::Track* getLcioTrack(){ return ( _lcioTrack );} + + //void addHit( IVXDHit* hit ); + void addHit( IMiniVector* MV ); + + 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 std::vector< IMiniVector* > getMVs() const { + std::vector<IMiniVector*> mvhits; + for(unsigned i=0; i<_hits.size();i++) mvhits.push_back( _hits[i] ); + return mvhits; + } + + virtual double getQI() const; + + /** Fits the track and sets chi2, Ndf etc. + */ + virtual void fit() ; + + virtual ~VXDTrack(){ delete _lcioTrack; } + + protected: + /** the hits the track consists of + */ + //std::vector< IVXDHit* > _hits; + std::vector< IMiniVector* > _hits; + + edm4hep::Track* _lcioTrack; + + // for fitting + MarlinTrk::IMarlinTrkSystem* _trkSystem; + + double _chi2Prob; + }; +} +#endif + + diff --git a/Utilities/KiTrack/src/KiTrack/Automaton.cc b/Utilities/KiTrack/src/KiTrack/Automaton.cc new file mode 100644 index 0000000000000000000000000000000000000000..870f276acf15ff3fe646141e081c13c6a14ff3a9 --- /dev/null +++ b/Utilities/KiTrack/src/KiTrack/Automaton.cc @@ -0,0 +1,498 @@ +#include "KiTrack/Automaton.h" + +#include <iostream> +//#include "marlin/VerbosityLevels.h" + +using namespace KiTrack; + +void Automaton::addSegment ( Segment* segment ){ + if ( segment->getLayer() >= _segments.size() ) { //in case this layer is not included so far + _segments.resize( segment->getLayer() + 1 ); //resize the vector, so that the layer of the segment is now included + } + + _segments[ segment->getLayer() ].push_back ( segment ); + + _nConnections += segment->getChildren().size(); +} + +void Automaton::lengthenSegments(){ + + // Info A: On skipped layers + // ^^^^^^^^^^^^^^^^^^^^^^^^^^ + // + // (read this only if you are interested on how the number of skipped layers is determined) + // + // The skipped layers are always between the innermost two hits of a segment. + // Why? Because the connection between those two hits is the thing that differs + // from its parent. Let's assume two 5-segments like those: + // / // + // \\ // + // // // + // \\ _layer 2 // + // / _layer 1 // + // You see how they overlap with all of their hits except the inner one of the child + // and the outer one of the parent. As the layer they are on equals the layer of the + // innermost point, the child will have layer 1 and the parent layer 2. + // (The choice of assigning the layer number of the innermost point and not the outermost + // is arbitrary, it could be the other way as well.) + // + // Now suppose the child skips layer 1: ( in this example a kink in the segment means the layer is hit, + // no kink means it is left out.) + // + // / // + // \\ // + // // // + // \\ _layer 2 // + // / _layer 1 // + // / _layer 0 // + // + // That means the child has now layer 0 and the parent layer 2. + // This is no problem, the segment class has an outer and an inner state (simulating skipped layers) + // instead of just an int. (to be more precise it has a vector containing the inner state and every layer left out) + // Now when we want to make 6-segments (I know the numbers are high, but they help visualising), we would connect + // parent and child to a new segment. + // + // + // / // + // \ // + // / // + // \ _layer 2 // + // / _layer 1 // + // / _layer 0 // + // + // So how many layers does this track skip: again 1 layer, so we need a state vector with 2 elements. + // (one for layer 0, one for layer 1) + // + // So we don't care if there are any other skipped layers in the outer part of the segment, we only care about that + // bit that won't overlap with parents. + // So the easy recipe for the number of skipped layers after making a segment longer is: + // Compare the layer before ( 2 ) to the layer after ( 0 ). The skipped layers are the difference -1 + // ( 2 - 0 - 1 = 1 --> segment->setSkippedLayers( 1 ); + + //std::cout << "Combining the shorter segments to longer ones\n"; + + //----------------------------------------------------------------------------------------------// + // // + // first: we create a new vector of a list of segments // + // to have somewhere we can put the longer segments // + // // + //----------------------------------------------------------------------------------------------// + + std::vector < std::list < Segment* > > longerSegments; + + if( _segments.size() > 0 ) longerSegments.resize ( _segments.size() -1 ); //This will have one layer less + + //----------------------------------------------------------------------------------------------// + // // + // next: find all the longer segments and store them in the new vector[][] // + // // + //----------------------------------------------------------------------------------------------// + + unsigned nLongerSegments=0; + unsigned nShorterSegments= _segments[0].size(); + + for (unsigned layer = 1; layer < _segments.size(); layer++){ //over all layers where there still can be something below + std::list<Segment*> segments = _segments[layer]; + for ( std::list<Segment*>::iterator iSeg=segments.begin(); iSeg != segments.end(); iSeg++){ //over all segments in this layer + nShorterSegments++; + + Segment* parent = *iSeg; + + std::list <Segment*> children = parent->getChildren(); + + for ( std::list<Segment*>::iterator iChild=children.begin(); iChild !=children.end(); iChild++){ //over all children of this parent + Segment* child = *iChild; + + //Combine the parent and the child to form a new longer segment + + //take all the hits from the parent + std::vector < IHit* > hits = parent->getHits(); + + //and also add the inner hit from the child + hits.insert( hits.begin(), child->getHits().at(0) ); + + //make the new (longer) segment + Segment* newSegment = new Segment ( hits ); + nLongerSegments++; + + //set the layer to the layer of the childsegment + unsigned newLayer = child->getLayer(); + newSegment->setLayer ( newLayer ); + + // Set the skipped layers. For an explanation see Info A above + int skippedLayers = parent->getLayer() - child->getLayer() - 1; + if( skippedLayers < 0 ) throw InvalidParameter( "skippedLayers can't be < 0!" ); + newSegment->setSkippedLayers( unsigned(skippedLayers) ); // + /* + std::cout << "Created longer segment: " << parent->getHits().size() + << "hits -->" << newSegment->getHits().size() + << " hits, layer = " << newLayer + << ", skipped layers = " << skippedLayers <<"\n"; + std::cout << "Combined: " << child->getInfo() << "<--with-->" << parent->getInfo() << "\n"; + */ + // In a next step we want to again establish the conenctions between the longer segments (so we can do the + // Automaton and later combine them and then do it all again... ). + // If we just created the Segments and dumped the old ones, we would have no idea what of the new, longer + // Segments we can connect. + // We could add some other container to store the possible connections of the longer Segments, but maybe + // it's the easiest approach to use, what is already there: the shorter Segments. + // + // So when we combine two shorter segments, we store the new longer Segment as a parent or child. + // Child, when the longer Segment goes on towards the inside, Parent if it continues on to the outside. + // So the shorter Segments kind of act as joints, that hold the longer Segments together. + // + // Let's visulaize that, so that it makes more sense: + // Let's have a look at 3 2-hit segments: + // + // / 2-hit-Segment A + // \ 2-hit-Segment B + // / 2-hit-Segment C + // + // Obviously we can make 2 3-hit segments out of this: + // + // / --> / 3-hit-Segment D + // \ \ \ . + // / --> / 3-hit-Segment E + // + // In the 2-hit-Segment B we store the 3-hit-Segments D and E as parent and child (while deleting A and C + // as parent and child, because that is now not needed anymore ) + // + // So when we want to connect the 3-hit-Segments, all we have to do is iterate over all 2-hit-Segments which + // then only have 3-hit-Segments as parents and children. + // When we come to Segment B, we see that D is a parent and E is a child, thus we connect them. Or to be more + // precise, we connect them, if the criteria do say so. + // + // So, yes B acts like a joint connecting D and E + // + // Erase the connection from the child to the parent segment and replace it with a link to the new + // (longer) segment. ( and vice versa ) This way we can connect the longer segments easily after. + child->deleteParent( parent ); + child->addParent ( newSegment ); + parent->deleteChild ( child ); + parent->addChild ( newSegment ); + // So now the new longer segment is a child of the old parent and a parent of the childsegment. + + + // Save the new segment in the new vector[][] + longerSegments[newLayer].push_back( newSegment ); + } + } + } + + //std::cout << " Made " << nLongerSegments << " longer segments from " << nShorterSegments << " shorter segments.\n"; + + //----------------------------------------------------------------------------------------------// + // // + // Connect the new (longer) segments // + // // + //----------------------------------------------------------------------------------------------// + + //std::cout << "Next connecting the new longer segments\n"; + + unsigned nConnections=0; + unsigned nPossibleConnections=0; + + for ( unsigned layer = 1; layer + 1 < _segments.size(); layer++ ){ // over all layers (of course the first and the last ones are spared out because there is nothing more above or below + std::list<Segment*> segments = _segments[layer]; + for ( std::list<Segment*>::iterator iSeg=segments.begin(); iSeg != segments.end(); iSeg++ ){ //over all (short) segments in this layer + Segment* segment = *iSeg; + + std::list<Segment*> parents = segment->getParents(); + std::list<Segment*> children = segment->getChildren(); + + for ( std::list<Segment*>::iterator iParent = parents.begin(); iParent != parents.end(); iParent++ ){ // over all parents of the segment + Segment* parent = *iParent; + for ( std::list<Segment*>::iterator iChild = children.begin(); iChild != children.end(); iChild++ ){ // over all children of the segment + Segment* child = *iChild; + + // Check if they are compatible + bool areCompatible = true; + ICriterion* theFailedCrit = NULL; + + //check all criteria (or at least until one returns false) + for ( unsigned iCrit = 0; iCrit < _criteria.size(); iCrit++ ){ + if ( _criteria[iCrit]->areCompatible ( parent , child ) == false ){ + areCompatible = false; + theFailedCrit = _criteria[iCrit]; + break; + } + } + + if ( areCompatible ){ + //connect parent and child (i.e. connect the longer segments we previously created) + child->addParent( parent ); + parent->addChild( child ); + + nConnections++; + + //std::cout << "Connected: " << child->getInfo() << "<--with-->" << parent->getInfo() << "\n"; + } + else{ + //std::cout << "NOT Connected: " << child->getInfo() << "<--XXXX-->" << parent->getInfo() << "\n"; + //if( theFailedCrit != NULL ) std::cout << "Failed first at criterion: " << theFailedCrit->getName() << "\n"; + } + + nPossibleConnections++; + } + } + } + } + _nConnections = nConnections; + + //std::cout << "Made " << nConnections << " of " << nPossibleConnections << " possible connections \n"; + + //----------------------------------------------------------------------------------------------// + // // + // Finally: replace the vector<list<segment*>> of the old segments with the new one // + // // + //----------------------------------------------------------------------------------------------// + + //delete all old Segments: + for( unsigned i=0; i<_segments.size(); i++){ + std::list<Segment*>& segments = _segments[i]; + for ( std::list<Segment*>::iterator iSeg=segments.begin(); iSeg != segments.end(); iSeg++ ){ + Segment* segment = *iSeg; + delete segment; + } + segments.clear(); + } + + // And replace with the newer ones + _segments = longerSegments; +} + +void Automaton::doAutomaton(){ + + bool hasChanged = true; + int nIterations = -1; + + while ( hasChanged == true ){ //repeat this until no more changes happen (this should always be equal or smaller to the number of layers - 1 + hasChanged = false; + nIterations++; + + for ( int layer = _segments.size()-1; layer >= 0; layer--){ //for all layers from outside in + std::list <Segment*> segments = _segments[layer]; + for ( std::list<Segment*>::iterator iSeg=segments.begin(); iSeg!= segments.end(); iSeg++ ){ //for all segments in the layer + Segment* parent= *iSeg; + + //Simulate skipped layers + std::vector < int >& state = parent->getState(); + + for ( int j= state.size()-1; j>=1; j--){ + if ( state[j] == state[j-1] ){ + state[j]++; + hasChanged = true; //something changed + } + } + + if ( parent->isActive() ){ + bool isActive = false; //whether the segment is active (i.e. still changing). This will be changed in the for loop, if it is active + + //Check if there is a neighbor + std::list <Segment*> children = parent->getChildren(); + + for ( std::list<Segment*>::iterator iChild=children.begin(); iChild != children.end(); iChild++ ){// for all children + Segment* child = *iChild; + + if ( child->getOuterState() == parent->getInnerState() ){ //Only if they have the same state + parent->raiseState(); //So it has a neighbor --> raise the state + + hasChanged = true; //something changed + isActive = true; + + break; //It has a neighbor, we raised the state, so we need not check again in this iteration + } + } + + parent->setActive( isActive ); + } + } + } + } + + //std::cout << "Automaton performed using " << nIterations << " iterations.\n"; +} + +void Automaton::cleanBadStates(){ + + unsigned nErasedSegments = 0; + unsigned nKeptSegments = 0; + + for( unsigned layer=0; layer < _segments.size(); layer++ ){//for every layer + std::list <Segment*> & segments = _segments[layer]; // We want to change things in the original list! Therefore the reference operator + for( std::list<Segment*>::iterator iSeg= segments.begin(); iSeg != segments.end(); iSeg++ ){//over every segment + Segment* segment = *iSeg; + + if( segment->getInnerState() == (int) layer ){ //the state is alright (equals the layer), this segment is good + nKeptSegments++; + } + else { //state is wrong, delete the segment + nErasedSegments++; + + //erase it from all its children + std::list <Segment*> children = segment->getChildren(); + + for (std::list<Segment*>::iterator iChild = children.begin(); iChild != children.end(); iChild++ ){ + (*iChild)->deleteParent ( segment ); + _nConnections--; + } + + //erase it from all its parents + std::list <Segment*> parents = segment->getParents(); + + for (std::list<Segment*>::iterator iParent = parents.begin(); iParent!= parents.end(); iParent++){ + (*iParent)->deleteChild ( segment ); + _nConnections--; + } + + //erase from the automaton + delete *iSeg; + iSeg = segments.erase( iSeg ); // erase the segment and update the iterator (updating is important!!!) + } + } + } + + //std::cout << "Erased segments because of bad states= " << nErasedSegments << "\n"; + //std::cout << "Kept segments because of good states= " << nKeptSegments << "\n"; +} + +void Automaton::resetStates(){ + for ( unsigned layer = 0; layer < _segments.size(); layer++ ){ //over all layers + std::list<Segment*> segments = _segments[layer]; + + for ( std::list<Segment*>::iterator iSeg = segments.begin(); iSeg != segments.end(); iSeg++ ){ //over all segments in the layer + (*iSeg)->resetState(); + (*iSeg)->setActive( true ); + } + } +} + +void Automaton::cleanBadConnections(){ + + unsigned nConnectionsKept = 0; + unsigned nConnectionsErased = 0; + + for ( int layer = _segments.size()-1 ; layer >= 1 ; layer-- ){ //over all layers from outside in. And there's no need to check layer 0, as it has no children. + std::list<Segment*> segments = _segments[layer]; + for ( std::list<Segment*>::iterator iSeg = segments.begin(); iSeg!=segments.end(); iSeg++ ){ // over all segments in the layer + Segment* parent = *iSeg; + std::list < Segment* > children = parent->getChildren(); + + for ( std::list<Segment*>::iterator iChild = children.begin(); iChild != children.end(); iChild++ ){ //over all children the segment has got + Segment* child = *iChild; + + bool areCompatible = true; //whether segment and child are compatible + + //check all criteria (or at least until the first false pops up) + for ( unsigned iCrit=0; iCrit < _criteria.size() ; iCrit++ ){ + if ( _criteria[iCrit]->areCompatible( parent , child ) == false ){ + areCompatible = false; + break; //no need to continue, now that we know, they're not compatible + } + } + + if ( areCompatible == false ){ // they are not compatible --> erase the connection + nConnectionsErased++; + _nConnections--; + + //erase the connection: + parent->deleteChild ( child ); + child->deleteParent ( parent ); + + //A small note here: although we deleted a child from the vector, this doesn't mean we have to do iSeg--! + //Because we copied the value of segment->getChildren to the vector children. And this one doesn't change! + } + else{ + nConnectionsKept++; + } + } + } + } + + //std::cout << "Erased bad connections= " << nConnectionsErased << "\n"; + //std::cout << "Kept good connections= " << nConnectionsKept << "\n"; +} + +std::vector < std::vector< IHit* > > Automaton::getTracksOfSegment ( Segment* segment, std::vector< IHit*> hits , unsigned minHits ){ + + std::vector < std::vector< IHit* > > tracks; //the vector of the tracks to be returned + + std::vector <IHit*> segHits = segment->getHits(); // the hits of the segment + + //add the outer hit + if ( segHits.back()->isVirtual() == false ) hits.push_back ( segHits.back() ); //Of course add only real hits to the track + + std::list <Segment*> children = segment->getChildren(); + + if ( children.empty() ){ //No more children --> we are at the bottom --> start a new Track here + //add the rest of the hits to the vector + for ( int i = segHits.size()-2 ; i >= 0; i--){ + if ( segHits[i]->isVirtual() == false ) hits.push_back ( segHits[i] ); + } + + if ( hits.size() >= minHits ){ + //add this to the tracks + tracks.push_back ( hits ); + } + } + else{// there are still children below --> so just take all their tracks and do it again + for ( std::list<Segment*>::iterator iChild=children.begin(); iChild!= children.end(); iChild++){ //for all children + std::vector < std::vector< IHit* > > newTracks = getTracksOfSegment( *iChild , hits ); + for (unsigned int j=0; j < newTracks.size(); j++){//for all the tracks of the child + tracks.push_back ( newTracks[j] ); + } + } + } + + return tracks; +} + +std::vector < std::vector< IHit* > > Automaton::getTracks( unsigned minHits ){ + + std::vector < std::vector< IHit* > > tracks; + std::vector <IHit*> emptyHitVec; + + for ( unsigned layer = 0 ; layer < _segments.size() ; layer++ ){ //over all layers + std::list<Segment*> segments = _segments[layer]; + for ( std::list<Segment*>::iterator iSeg = segments.begin(); iSeg != segments.end(); iSeg++ ){ //over all segments + Segment* segment = *iSeg; + // by fucd: comment "if" in new ILC version of Automaton, why? + if ( segment->getParents().empty() ){ // if it has no parents it is the end of a possible track + // get the tracks from the segment + std::vector < std::vector< IHit* > > newTracks = getTracksOfSegment( segment , emptyHitVec , minHits ); + + // and add them to the vector of all tracks + tracks.insert( tracks.end() , newTracks.begin() , newTracks.end() ); + } + } + } + return tracks; +} + +std::vector <const Segment*> Automaton::getSegments() const{ + + std::vector <const Segment*> segments; + + for( unsigned layer=0; layer < _segments.size(); layer++ ){ + segments.insert( segments.end() , _segments[layer].begin() , _segments[layer].end() ); + } + + return segments; +} + +Automaton::~Automaton(){ + //delete the segments + for( unsigned layer=0; layer < _segments.size(); layer++){ //over all layers + std::list<Segment*> segments = _segments[layer]; + for( std::list<Segment*>::iterator iSeg = segments.begin(); iSeg!=segments.end(); iSeg++ ){ //over all segments + delete *iSeg; + } + } +} + + + + + + + diff --git a/Utilities/KiTrack/src/KiTrack/HopfieldNeuralNet.cc b/Utilities/KiTrack/src/KiTrack/HopfieldNeuralNet.cc new file mode 100644 index 0000000000000000000000000000000000000000..6597b191957b8fe61e67f41e72e0967845be834a --- /dev/null +++ b/Utilities/KiTrack/src/KiTrack/HopfieldNeuralNet.cc @@ -0,0 +1,217 @@ +#include "KiTrack/HopfieldNeuralNet.h" + +#include <cmath> +#include <iostream> +#include <algorithm> +#include <sstream> +#include <random> + + +using namespace KiTrack; + +HopfieldNeuralNet::HopfieldNeuralNet( std::vector < std::vector <bool> > G , std::vector < double > QI , std::vector < double > states , double omega) { + + unsigned int nNeurons = G.size(); + + + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Check the validity of the input parameters + + + std::stringstream s; + s << "HopfieldNeuralNet: "; + + // Is G a square matrix? + for( unsigned i=0; i< nNeurons; i++ ){ + + if( G[i].size() != nNeurons ){ + + s << "G must be a square matrix!!! G[" << i << "].size() == " << G[i].size() << " != G.size() (" << nNeurons << ")\n"; + throw InvalidParameter( s.str() ); + + } + + } + + // Does the QI vector have the right size? + if( QI.size() != nNeurons ){ + + s << "The QI vector must have the same size as G! QI.size() == " << QI.size() << " != G.size() (" << nNeurons << ")\n"; + throw InvalidParameter( s.str() ); + + } + + // Are all the Quality Indicators in the range 0 - 1 + for( unsigned i=0; i< nNeurons; i++ ){ + + if( ( QI[i] < 0. ) || ( QI[i] > 1. ) ){ + + s << "The QI must be between 0 and 1, QI[" << i << "] == " << QI[i] << " is not a valid value!\n"; + + } + + } + + // Does the states vector have the right size? + if( states.size() != nNeurons ){ + + s << "The vector of the states must have the same size as G! states.size() == " << states.size() << " != G.size() (" << nNeurons << ")\n"; + throw InvalidParameter( s.str() ); + + } + + // Are all the states in the range 0 - 1 + for( unsigned i=0; i< nNeurons; i++ ){ + + if( ( states[i] < 0. ) || ( states[i] > 1. ) ){ + + s << "The states must be between 0 and 1, states[" << i << "] == " << states[i] << " is not a valid value!\n"; + + } + + } + + // Is omega in the range from 0 to 1 + if( ( omega < 0. ) || ( omega > 1. ) ){ + + s << "Omega must be in the range from 0 to 1, omega == " << omega << " is not a valid value!\n"; + + } + // End of checking the parameters + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + _omega = omega; + _States = states; + + // resize the vectors. + _States.resize( nNeurons ); + _w0.resize( nNeurons ); + _W.resize( nNeurons ); + _order.resize( nNeurons); + + for ( unsigned int i =0; i < nNeurons; i++){ + + // resize the vectors of the matrix W + _W[i].resize( nNeurons ); + + + // initialise the order vector + _order[i]=i; //the order now is 0,1,2,3... (will be changed to a random sequence in the iteration) + + } + + + //calculate _w0 + for (unsigned int i=0; i < QI.size(); i++) _w0[i] = omega * QI[i]; + + + + // Build the W matrix. (the matrix of the influences including their force) + + double comp = 1; + if (nNeurons > 0 ) comp = (1. - omega) / double (nNeurons); + + + for (unsigned int i=0; i< nNeurons ; i++){ + + for (unsigned int j=0; j< nNeurons ; j++){ + + if (i == j) _W[i][j] = 0.; //diagonal elements are 0 --> whatever the matrix G says here is ignored. + + else{ + + if ( G[i][j] == 1 ) _W[i][j] = -1; //Neurons are incompatible + + else _W[i][j] = comp; //Neurons are compatible + + } + + } + + } + + + + + + _T = 0; + _TInf = 0; + + _isStable = false; + _limitForStable = 0.01; + + + +} + + + +double HopfieldNeuralNet::activationFunction ( double state , double T ){ + + + double y = 1; + + if (T > 0) y = 0.5 * ( 1 + tanh( state / T ) ); //if T==0 tanh( infinity ) gives 1. + + + return y; + + +} + + + + +bool HopfieldNeuralNet::doIteration(){ + + _isStable = true; + + // initialize the random generator + std::random_device rng; + std::mt19937 urng(rng()); + + shuffle ( _order.begin() , _order.end() , urng ); //shuffle the order + + for (unsigned int i=0; i<_States.size() ; i++){ //for all entries of the vector + + unsigned iNeuron = _order[i]; + + + double y; + + y = _w0[iNeuron]; + + //matrix vector multiplication (or one line of it to be precise) + for (unsigned int j=0; j< _W[iNeuron].size(); j++){ + + y += _W[iNeuron][j] * _States[j]; + + } + + y = activationFunction ( y , _T ); + + // check if the change was big enough that the Network is not stable + if ( fabs( _States[iNeuron] - y ) > _limitForStable ) _isStable = false; + + // update the state + _States[iNeuron] = y; + + } + + + + // after the iteration, we need to calculate a new tempereatur _T + + _T = 0.5* ( _T + _TInf); + + + return _isStable; + +} + + + + + + diff --git a/Utilities/KiTrack/src/KiTrack/IHit.cc b/Utilities/KiTrack/src/KiTrack/IHit.cc new file mode 100644 index 0000000000000000000000000000000000000000..e4381d8451767e0e940ae1d7166c95491ab6d0f5 --- /dev/null +++ b/Utilities/KiTrack/src/KiTrack/IHit.cc @@ -0,0 +1,28 @@ +#include "KiTrack/IHit.h" + +#include <cmath> +#include <sstream> + +using namespace KiTrack; + +float IHit::distTo( IHit* otherHit ){ + + + + float dx = otherHit->getX() - _x; + float dy = otherHit->getY() - _y; + float dz = otherHit->getZ() - _z; + + return sqrt( dx*dx + dy*dy + dz*dz ); + +} + +std::string IHit::getPositionInfo(){ + + std::stringstream info; + + info << "(" << _x << "," << _y << "," << _z << ")"; + + return info.str(); + +} \ No newline at end of file diff --git a/Utilities/KiTrack/src/KiTrack/Segment.cc b/Utilities/KiTrack/src/KiTrack/Segment.cc new file mode 100644 index 0000000000000000000000000000000000000000..0fd8916fe3f4ba9e66babca559599df41fc8503b --- /dev/null +++ b/Utilities/KiTrack/src/KiTrack/Segment.cc @@ -0,0 +1,67 @@ +#include "KiTrack/Segment.h" + +#include <sstream> + +using namespace KiTrack; + +Segment::Segment( std::vector <IHit*> hits){ + + _hits = hits; + + _state.push_back(0); + + _children.clear(); + _parents.clear(); + + _active = true; + + _layer=0; +} + + + +Segment::Segment( IHit* hit){ + + _hits.push_back( hit) ; + _state.push_back(0); + _children.clear(); + _parents.clear(); + + _active = true; + + _layer=0; +} + + + +void Segment::resetState(){ + + + for ( unsigned i = 0; i <_state.size(); i++){ + + _state[i] = 0; + + } + +} + +std::string Segment::getInfo(){ + + + std::stringstream info; + + for( unsigned i=0; i<_hits.size(); i++ ) info << _hits[i]->getPositionInfo(); + + info << "["; + for( unsigned i=0; i+1<_state.size(); i++ ) info << _state[i] << ","; + info << _state.back() << "]"; + + return info.str(); + + +} + + + + + diff --git a/Utilities/KiTrack/src/KiTrack/SegmentBuilder.cc b/Utilities/KiTrack/src/KiTrack/SegmentBuilder.cc new file mode 100644 index 0000000000000000000000000000000000000000..7a19c4df88a13c8d3835ee9330f5c3d32ae3e557 --- /dev/null +++ b/Utilities/KiTrack/src/KiTrack/SegmentBuilder.cc @@ -0,0 +1,117 @@ +#include "KiTrack/SegmentBuilder.h" + +// ----- include for verbosity dependend logging --------- +//#include "marlin/VerbosityLevels.h" +#include <iostream> + +using namespace KiTrack; + +SegmentBuilder::SegmentBuilder( std::map< int , std::vector< IHit* > > map_sector_hits ): + _map_sector_hits( map_sector_hits){} + +Automaton SegmentBuilder::get1SegAutomaton(){ + /**********************************************************************************************/ + /* Create and fill a map for the segments */ + /**********************************************************************************************/ + std::map< int , std::vector< IHit* > >::iterator itSecHit; // Sec = sector , Hit = hits + std::map< int , std::vector< Segment* > > map_sector_segments; + std::map< int , std::vector< Segment* > > ::iterator itSecSeg; // Sec = sector , Seg = segments + + unsigned nCreatedSegments=0; + + for ( itSecHit = _map_sector_hits.begin(); itSecHit!=_map_sector_hits.end(); itSecHit++ ){ //over all sectors + // All the hits in the sector + int sector = itSecHit->first; + std::vector <IHit*> hits = itSecHit->second; + for ( unsigned int i=0; i < hits.size(); i++ ){ //over every hit in the sector + // create a Segment + Segment* segment = new Segment( hits[i] ); + segment->setLayer( hits[i]->getLayer() ); + + // Store the segment in its map + map_sector_segments[sector].push_back( segment ); + + nCreatedSegments++; + } + } + + //std::cout << " Number of created 1-segments: " << nCreatedSegments <<"\n"; + + /**********************************************************************************************/ + /* Now check all 1-Segments and connect them to others */ + /* Afterwards store them in an Automaton */ + /**********************************************************************************************/ + + unsigned nConnections=0; + unsigned nStoredSegments = 0; + + Automaton automaton; + + for ( itSecSeg = map_sector_segments.begin(); itSecSeg != map_sector_segments.end(); itSecSeg++ ){ // over all sectors + // All the segments with one certain code + int sector = itSecSeg->first; + std::vector <Segment*> segments = itSecSeg->second; + + // Now find out, what the allowed codes to connect to are: + std::set <int> targetSectors; + + for ( unsigned i=0; i < _sectorConnectors.size(); i++ ){ // over all IHitConnectors + // get the allowed targets + std::set <int> newTargetSectors = _sectorConnectors[i]->getTargetSectors( sector ); + + //insert them into our set + targetSectors.insert( newTargetSectors.begin() , newTargetSectors.end() ); + } + + for ( unsigned int i=0; i< segments.size(); i++ ){ //over all segments within the sector + Segment* parent = segments[i]; + + for ( std::set<int>::iterator itTarg = targetSectors.begin(); itTarg!=targetSectors.end(); itTarg++ ){ // over all target codes + int targetSector = *itTarg; + std::vector <Segment*> targetSegments = map_sector_segments[ targetSector ]; + + for ( unsigned int j=0; j < targetSegments.size(); j++ ){ // over all segments in the target sector + Segment* child = targetSegments[j]; + bool areCompatible = true; + ICriterion* theFailedCrit = NULL; + + for (unsigned int iCrit = 0; iCrit < _criteria.size(); iCrit++){ + if ( _criteria[iCrit]->areCompatible( parent , child ) == false ){ + areCompatible = false; + theFailedCrit = _criteria[iCrit]; + break; + } + } + + if ( areCompatible ){ //the connection was successful + parent->addChild( child ); + child->addParent( parent ); + + nConnections++; + //std::cout << "Connected: " << child->getInfo() << "<--with-->" << parent->getInfo() << "\n"; + } + else{ + //std::cout << "NOT Connected: " << child->getInfo() << "<--XXXX-->" << parent->getInfo() << "\n"; + //if( theFailedCrit != NULL ) std::cout << "Failed first at criterion: " << theFailedCrit->getName() << "\n"; + } + } + } + + // Store the segment in the automaton + automaton.addSegment( parent ); + nStoredSegments++; + } + } + + //std::cout << "Number of connections made " << nConnections <<"\n"; + //std::cout << "Number of 1-segments, that got stored in the automaton: " << nStoredSegments <<"\n"; + + return automaton; +} + + + + + + + diff --git a/Utilities/KiTrack/src/Tools/FTDHelixFitter.cc b/Utilities/KiTrack/src/Tools/FTDHelixFitter.cc new file mode 100644 index 0000000000000000000000000000000000000000..2f0492a067d0757784ca357bc1845919276d5dfe --- /dev/null +++ b/Utilities/KiTrack/src/Tools/FTDHelixFitter.cc @@ -0,0 +1,124 @@ +#include "Tools/FTDHelixFitter.h" + +#include <sstream> +#include <algorithm> +#include <cmath> + +#include "edm4hep/TrackerHit.h" +#include "UTIL/BitSet32.h" +#include "UTIL/ILDConf.h" +#include "UTIL/LCTrackerConf.h" +//#include "marlin/VerbosityLevels.h" +#include "TrackSystemSvc/HelixFit.h" + +#include "Tools/KiTrackMarlinTools.h" + + +FTDHelixFitter::FTDHelixFitter( std::vector<edm4hep::ConstTrackerHit> trackerHits ){ + _trackerHits = trackerHits; + fit(); +} + +FTDHelixFitter::FTDHelixFitter( edm4hep::Track* track ){ + _trackerHits.clear(); + //int nHits = track->trackerHits_size(); + std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(_trackerHits)); + //for(int i=0;i<nHits;i++){ + // edm4hep::ConstTrackerHit* hit = &track->getTrackerHits(i); + // _trackerHits.push_back(hit); + //} + fit(); +} + +void FTDHelixFitter::fit(){ + std::sort( _trackerHits.begin(), _trackerHits.end(), KiTrackMarlin::compare_TrackerHit_z ); + + int nHits = _trackerHits.size(); + int iopt = 2; + float chi2RPhi; + float chi2Z; + + if( nHits < 3 ){ + std::stringstream s; + s << "FTDHelixFitter::fit(): Cannot fit less with less than 3 hits. Number of hits = " << nHits << "\n"; + + throw FTDHelixFitterException( s.str() ); + } + + double* xh = new double[nHits]; + double* yh = new double[nHits]; + float* zh = new float[nHits]; + double* wrh = new double[nHits]; + float* wzh = new float[nHits]; + float* rh = new float[nHits]; + float* ph = new float[nHits]; + + float par[5]; + float epar[15]; + + for( int i=0; i<nHits; i++ ){ + edm4hep::ConstTrackerHit hit = _trackerHits[i]; + + xh[i] = hit.getPosition()[0]; + yh[i] = hit.getPosition()[1]; + zh[i] = hit.getPosition()[2]; + + float resZ = 0.1; + wzh[i] = 1.0/( resZ * resZ ); + + rh[i] = float(sqrt(xh[i]*xh[i]+yh[i]*yh[i])); + ph[i] = atan2(yh[i],xh[i]); + if (ph[i] < 0.) ph[i] = 2.*M_PI + ph[i]; + + if( UTIL::BitSet32( hit.getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ){ + float sigX = hit.getCovMatrix()[0]; + float sigY = hit.getCovMatrix()[2]; + wrh[i] = 1/sqrt( sigX*sigX + sigY*sigY ); + } + else { + //TrackerHitPlane* hitPlane = dynamic_cast<TrackerHitPlane*>( hit ); + //wrh[i] = double(1.0/( hitPlane->getdU()*hitPlane->getdU() + hitPlane->getdV()*hitPlane->getdV() ) ); + wrh[i] = double(1.0/( hit.getCovMatrix(2)*hit.getCovMatrix(2) + hit.getCovMatrix(5)*hit.getCovMatrix(5) )); + } + } + + MarlinTrk::HelixFit helixFitter; + + helixFitter.fastHelixFit(nHits, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z); + par[3] = par[3]*par[0]/fabs(par[0]); + + _omega = par[0]; + _tanLambda = par[1]; + _phi0 = par[2]; + _d0 = par[3]; + _z0 = par[4]; + + float chi2 = chi2RPhi+chi2Z; + int Ndf = 2*nHits-5; + + delete[] xh; + delete[] yh; + delete[] zh; + delete[] wrh; + delete[] wzh; + delete[] rh; + delete[] ph; + xh = NULL; + yh = NULL; + zh = NULL; + wrh = NULL; + wzh = NULL; + rh = NULL; + ph = NULL; + + //streamlog_out(DEBUG1) << "chi2 = " << chi2 << ", Ndf = " << Ndf << "\n"; + + _chi2 = chi2; + _Ndf = Ndf; + + return; +} + + + + diff --git a/Utilities/KiTrack/src/Tools/Fitter.cc b/Utilities/KiTrack/src/Tools/Fitter.cc new file mode 100644 index 0000000000000000000000000000000000000000..13ae3aabe0f057acb5a701f0fe08d8b173252a49 --- /dev/null +++ b/Utilities/KiTrack/src/Tools/Fitter.cc @@ -0,0 +1,598 @@ +#include "Tools/Fitter.h" + +#include <algorithm> + +//#include "marlin/Global.h" +//#include "UTIL/LCTrackerConf.h" +#include <UTIL/ILDConf.h> + +#include <DD4hep/DD4hepUnits.h> +#include <DD4hep/Detector.h> + +#include "TrackSystemSvc/HelixTrack.h" +#include "DataHelper/Navigation.h" +#include "Tools/KiTrackMarlinTools.h" + +typedef std::vector<edm4hep::ConstTrackerHit> TrackerHitVec; +using namespace MarlinTrk; + +// by fucd: 3.5->3.0 default, will be read from GeoSvc +// if compare to Marlin, should change to 3.5 +float Fitter::_bField = 3.5;//later on overwritten with the value read by geo file + +void Fitter::init_BField(){ + + // B field from DD4hep + /* + dd4hep::Detector & lcdd = dd4hep::Detector::getInstance(); + const double pos[3]={0,0,0}; + double bFieldVec[3]={0,0,0}; + lcdd.field().magneticField(pos,bFieldVec); // get the magnetic field vector from DD4hep + _bField = bFieldVec[2]/dd4hep::tesla; // z component at (0,0,0) + */ + +} + +bool compare_TrackerHit_z( edm4hep::TrackerHit* a, edm4hep::TrackerHit* b ){ + return ( fabs(a->getPosition()[2]) < fabs( b->getPosition()[2]) ); //compare their z values +} + +bool compare_TrackerHit_R( edm4hep::TrackerHit* a, edm4hep::TrackerHit* b ){ + double Rad_a2 = (a->getPosition()[0]*a->getPosition()[0]) + (a->getPosition()[1]*a->getPosition()[1]) ; + double Rad_b2 = (b->getPosition()[0]*b->getPosition()[0]) + (b->getPosition()[1]*b->getPosition()[1]) ; + + return ( Rad_a2 < Rad_b2 ); //compare their radii +} + +Fitter::Fitter( edm4hep::Track* track , MarlinTrk::IMarlinTrkSystem* trkSystem ): _trkSystem( trkSystem ){ + _trackerHits.clear(); + + std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(_trackerHits)); + //_trackerHits = track->getTrackerHits(); + + fit(); +} + +Fitter::Fitter( edm4hep::Track* track , MarlinTrk::IMarlinTrkSystem* trkSystem, int VXDFlag ): _trkSystem( trkSystem ){ + _trackerHits.clear(); + std::copy(track->trackerHits_begin(), track->trackerHits_end(), std::back_inserter(_trackerHits)); + //_trackerHits = track->getTrackerHits(); + fitVXD(); +} + +Fitter::Fitter( std::vector<edm4hep::ConstTrackerHit> trackerHits , MarlinTrk::IMarlinTrkSystem* trkSystem ): _trkSystem( trkSystem ){ + _trackerHits = trackerHits; + fit(); +} + +void Fitter::fitVXD(){ + //create the MarlinTrk + _marlinTrk = _trkSystem->createTrack(); + + /**********************************************************************************************/ + /* Add the hits to the MarlinTrack */ + /**********************************************************************************************/ + + // hits are in reverse order + std::sort( _trackerHits.begin(), _trackerHits.end(), KiTrackMarlin::compare_TrackerHit_R ); + // now at [0] is the hit with the smallest |z| and at [1] is the one with a bigger |z| and so on + // So the direction of the hits when following the index from 0 on is: + // from inside out: from the IP into the distance. + // (It is important to keep in mind, in which direction we fit, when using MarlinTrk) + + TrackerHitVec::iterator it; + + unsigned number_of_added_hits = 0; + unsigned ndof_added = 0; + std::vector< edm4hep::TrackerHit* > added_hits; + std::vector< edm4hep::TrackerHit* > added_hits_2D; + + for( it = _trackerHits.begin() ; it != _trackerHits.end() ; ++it ) { + edm4hep::TrackerHit* trkHit = Navigation::Instance()->GetTrackerHit((*it).getObjectID()); + bool isSuccessful = false; + + if( UTIL::BitSet32( trkHit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ){ //it is a composite spacepoint + //Split it up and hits to the MarlinTrk + std::vector< edm4hep::TrackerHit* > rawHits; + //const LCObjectVec rawObjects = trkHit->getRawHits(); + //for( unsigned k=0; k<rawObjects.size(); k++ ) rawHits.push_back( dynamic_cast< TrackerHit* >( rawObjects[k] ) ); + int nRawHit = trkHit->rawHits_size(); + for( unsigned k=0; k< nRawHit; k++ ){ + edm4hep::TrackerHit* rawHit = Navigation::Instance()->GetTrackerHit(trkHit->getRawHits(k)); + rawHits.push_back(rawHit); + } + std::sort( rawHits.begin(), rawHits.end(), compare_TrackerHit_R ); + + for( unsigned k=0; k< rawHits.size(); k++ ){ + if( _marlinTrk->addHit( rawHits[k] ) == IMarlinTrack::success ){ + isSuccessful = true; //if at least one hit from the spacepoint gets added + ++ndof_added; // 1 degree of freedom for each strip hit + } + else{ + //std::cout << "Cannot addHit " << rawHits[k]->id() << " to MarlinTrk" << std::endl; + } + } + } + else { // normal non composite hit + if (_marlinTrk->addHit( trkHit ) == 0) { + isSuccessful = true; + ndof_added += 2; + } + } + + if (isSuccessful) { + added_hits.push_back(trkHit); + ++number_of_added_hits; + } + else{ + //std::cout << "DEBUG Fitter::fit(): Hit " << it - _trackerHits.begin() << " Dropped " << std::endl; + } + } + + if( ndof_added < 6 ) { + std::stringstream s; + s << "Fitter::fit(): Cannot fit less with less than 6 degrees of freedom. Number of hits = " << number_of_added_hits << " ndof = " << ndof_added << "\n"; + + throw FitterException( s.str() ); + } + + /**********************************************************************************************/ + /* Create a helix from the first, last and middle hit */ + /**********************************************************************************************/ + + for (unsigned ihit=0; ihit <added_hits.size(); ++ihit) { + // check if this a space point or 2D hit + if(UTIL::BitSet32( added_hits[ihit]->getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] == false ){ + // then add to the list + added_hits_2D.push_back(added_hits[ihit]); + + } + } + + // initialise with space-points not strips + // make a helix from 3 hits to get a trackstate + const edm4hep::Vector3d x1 = added_hits_2D[0]->getPosition(); + const edm4hep::Vector3d x2 = added_hits_2D[ added_hits_2D.size()/2 ]->getPosition(); + const edm4hep::Vector3d x3 = added_hits_2D.back()->getPosition(); + + init_BField(); + HelixTrack helixTrack( x1, x2, x3, _bField, HelixTrack::forwards ); + + helixTrack.moveRefPoint(0.0, 0.0, 0.0); + + //const float referencePoint[3] = { float(helixTrack.getRefPointX()) , float(helixTrack.getRefPointY() ), float(helixTrack.getRefPointZ() )}; + edm4hep::Vector3f referencePoint = { float(helixTrack.getRefPointX()) , float(helixTrack.getRefPointY() ), float(helixTrack.getRefPointZ() )}; + + /**********************************************************************************************/ + /* Create a TrackStateImpl from the helix values and use it to initalise the fit */ + /**********************************************************************************************/ + std::array<float,15> covMatrix; + + for (unsigned icov = 0; icov<covMatrix.size(); ++icov) { + covMatrix[icov] = 0; + } + + covMatrix[0] = ( 1.e6 ); //sigma_d0^2 + covMatrix[2] = ( 1.e2 ); //sigma_phi0^2 + covMatrix[5] = ( 1.e-4 ); //sigma_omega^2 + covMatrix[9] = ( 1.e6 ); //sigma_z0^2 + covMatrix[14] = ( 1.e2 ); //sigma_tanl^2 + + + edm4hep::TrackState trackState = {0/*TrackState::AtOther*/, + helixTrack.getD0(), + helixTrack.getPhi0(), + helixTrack.getOmega(), + helixTrack.getZ0(), + helixTrack.getTanLambda(), + referencePoint, + covMatrix}; + + //init_BField(); + _marlinTrk->initialise( trackState, _bField, IMarlinTrack::backward ) ; + + // _marlinTrk->initialise( IMarlinTrack::backward ) ; + + /**********************************************************************************************/ + /* Do the fit */ + /**********************************************************************************************/ + + int fit_status = 0; + + try{ + + fit_status = _marlinTrk->fit() ; + + } + catch( MarlinTrk::Exception& e ){ + + std::stringstream s; + s << "Fitter::fit(): Couldn't fit, MarlinTrk->fit() gave: " << e.what() << "\n"; + throw FitterException( s.str() ); + + } + + if( fit_status != IMarlinTrack::success ){ + + std::stringstream s; + s << "Fitter::fit(): MarlinTrk->fit() wasn't successful, fit_status = " << fit_status << "\n"; + throw FitterException( s.str() ); + + } + + + // fitting finished get hits in the fit for safety checks: + + std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit; + + // remember the hits are ordered in the order in which they were fitted + // here we are fitting inwards so the first is the last and vice verse + + _marlinTrk->getHitsInFit(hits_in_fit); + + if( hits_in_fit.size() < 3 ) { + + + std::stringstream s; + s << "Fitter::fit() Less than 3 hits in fit: Only " << hits_in_fit.size() << + " of " << _trackerHits.size() << " hits\n"; + + throw FitterException( s.str() ); + + } + edm4hep::TrackerHit* first_hit_in_fit = hits_in_fit.back().first; + if (!first_hit_in_fit) { + throw FitterException( std::string("Fitter::fit(): TrackerHit pointer to first hit == NULL ") ) ; + } + + + edm4hep::TrackerHit* last_hit_in_fit = hits_in_fit.front().first; + if (!last_hit_in_fit) { + throw FitterException( std::string("Fitter::fit(): TrackerHit pointer to last hit == NULL ") ) ; + } + + return; +} + + + +void Fitter::fit(){ + //create the MarlinTrk + _marlinTrk = _trkSystem->createTrack(); + + /**********************************************************************************************/ + /* Add the hits to the MarlinTrack */ + /**********************************************************************************************/ + + // hits are in reverse order + std::sort( _trackerHits.begin(), _trackerHits.end(), KiTrackMarlin::compare_TrackerHit_z ); + // now at [0] is the hit with the smallest |z| and at [1] is the one with a bigger |z| and so on + // So the direction of the hits when following the index from 0 on is: + // from inside out: from the IP into the distance. + // (It is important to keep in mind, in which direction we fit, when using MarlinTrk) + + TrackerHitVec::iterator it; + + unsigned number_of_added_hits = 0; + unsigned ndof_added = 0; + std::vector<edm4hep::TrackerHit*> added_hits; + + for( it = _trackerHits.begin() ; it != _trackerHits.end() ; ++it ) { + edm4hep::TrackerHit* trkHit = Navigation::Instance()->GetTrackerHit((*it).getObjectID()); + bool isSuccessful = false; + //std::cout << "Hit " << trkHit->id() << " " << trkHit->getPosition() << std::endl; + if( UTIL::BitSet32( trkHit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ){ //it is a composite spacepoint + //Split it up and hits to the MarlinTrk + std::vector<edm4hep::TrackerHit*> rawHits; + //const LCObjectVec rawObjects = trkHit->getRawHits(); + //for( unsigned k=0; k<rawObjects.size(); k++ ) rawHits.push_back( dynamic_cast< TrackerHit* >( rawObjects[k] ) ); + int nRawHit = trkHit->rawHits_size(); + for( unsigned k=0; k< nRawHit; k++ ){ + edm4hep::TrackerHit* rawHit = Navigation::Instance()->GetTrackerHit(trkHit->getRawHits(k)); + //std::cout << "Raw Hit " << rawHit->id() << " " << rawHit->getPosition() << std::endl; + rawHits.push_back(rawHit); + } + std::sort( rawHits.begin(), rawHits.end(), compare_TrackerHit_z ); + + for( unsigned k=0; k< rawHits.size(); k++ ){ + if( _marlinTrk->addHit( rawHits[k] ) == IMarlinTrack::success ){ + isSuccessful = true; //if at least one hit from the spacepoint gets added + ++ndof_added; // 1 degree of freedom for each strip hit + } + else{ + //std::cout << "Cannot addHit " << rawHits[k]->id() << " to MarlinTrk" << std::endl; + } + } + } + else { // normal non composite hit + + if (_marlinTrk->addHit( trkHit ) == 0) { + isSuccessful = true; + ndof_added += 2; + } + } + + if (isSuccessful) { + added_hits.push_back(trkHit); + ++number_of_added_hits; + } + else{ + //std::cout << "DEBUG: Fitter::fit(): Hit " << it - _trackerHits.begin() << " Dropped " << std::endl; + } + } + + if( ndof_added < 6 ) { + std::stringstream s; + s << "Fitter::fit(): Cannot fit less with less than 6 degrees of freedom. Number of hits = " << number_of_added_hits << " ndof = " << ndof_added << "\n"; + + throw FitterException( s.str() ); + } + + /**********************************************************************************************/ + /* Create a helix from the first, last and middle hit */ + /**********************************************************************************************/ + + // initialise with space-points not strips + // make a helix from 3 hits to get a trackstate + const edm4hep::Vector3d x1 = added_hits[0]->getPosition(); + const edm4hep::Vector3d x2 = added_hits[ added_hits.size()/2 ]->getPosition(); + const edm4hep::Vector3d x3 = added_hits.back()->getPosition(); + + init_BField(); + HelixTrack helixTrack( x1, x2, x3, _bField, HelixTrack::forwards ); + + helixTrack.moveRefPoint(0.0, 0.0, 0.0); + + //const float referencePoint[3] = { float(helixTrack.getRefPointX()) , float(helixTrack.getRefPointY()) , float(helixTrack.getRefPointZ()) }; + edm4hep::Vector3f referencePoint = { float(helixTrack.getRefPointX()) , float(helixTrack.getRefPointY()) , float(helixTrack.getRefPointZ()) }; + + /**********************************************************************************************/ + /* Create a TrackStateImpl from the helix values and use it to initalise the fit */ + /**********************************************************************************************/ + std::array<float,15> covMatrix; + for (unsigned icov = 0; icov<covMatrix.size(); ++icov) { + covMatrix[icov] = 0; + } + + covMatrix[0] = ( 1.e6 ); //sigma_d0^2 + covMatrix[2] = ( 1.e2 ); //sigma_phi0^2 + covMatrix[5] = ( 1.e-4 ); //sigma_omega^2 + covMatrix[9] = ( 1.e6 ); //sigma_z0^2 + covMatrix[14] = ( 1.e2 ); //sigma_tanl^2 + + edm4hep::TrackState trackState = {0/*TrackState::AtOther*/, + helixTrack.getD0(), + helixTrack.getPhi0(), + helixTrack.getOmega(), + helixTrack.getZ0(), + helixTrack.getTanLambda(), + referencePoint, + covMatrix}; + + //init_BField(); + _marlinTrk->initialise( trackState, _bField, IMarlinTrack::backward ) ; + + // _marlinTrk->initialise( IMarlinTrack::backward ) ; + + /**********************************************************************************************/ + /* Do the fit */ + /**********************************************************************************************/ + int fit_status = 0; + + try{ + fit_status = _marlinTrk->fit() ; + } + catch( MarlinTrk::Exception& e ){ + std::stringstream s; + s << "Fitter::fit(): Couldn't fit, MarlinTrk->fit() gave: " << e.what() << "\n"; + throw FitterException( s.str() ); + } + + if( fit_status != IMarlinTrack::success ){ + std::stringstream s; + s << "Fitter::fit(): MarlinTrk->fit() wasn't successful, fit_status = " << fit_status << "\n"; + throw FitterException( s.str() ); + } + + // fitting finished get hits in the fit for safety checks: + + std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit; + + // remember the hits are ordered in the order in which they were fitted + // here we are fitting inwards so the first is the last and vice verse + + _marlinTrk->getHitsInFit(hits_in_fit); + + if( hits_in_fit.size() < 3 ) { + std::stringstream s; + s << "Fitter::fit() Less than 3 hits in fit: Only " << hits_in_fit.size() + << " of " << _trackerHits.size() << " hits\n"; + + throw FitterException( s.str() ); + } + edm4hep::TrackerHit* first_hit_in_fit = hits_in_fit.back().first; + if (!first_hit_in_fit) { + throw FitterException( std::string("Fitter::fit(): TrackerHit pointer to first hit == NULL ") ) ; + } + + edm4hep::TrackerHit* last_hit_in_fit = hits_in_fit.front().first; + if (!last_hit_in_fit) { + throw FitterException( std::string("Fitter::fit(): TrackerHit pointer to last hit == NULL ") ) ; + } + + return; +} + + +const edm4hep::TrackState* Fitter::getTrackState( int trackStateLocation ){ + return getTrackStatePlus( trackStateLocation )->getTrackState(); +} + +double Fitter::getChi2Prob( int trackStateLocation ){ + return ROOT::Math::chisquared_cdf_c( getChi2( trackStateLocation ) , getNdf( trackStateLocation ) ); +} + +double Fitter::getChi2( int trackStateLocation ){ + return getTrackStatePlus( trackStateLocation )->getChi2(); +} + +int Fitter::getNdf( int trackStateLocation ){ + return getTrackStatePlus( trackStateLocation )->getNdf(); +} + + +const TrackStatePlus* Fitter::getTrackStatePlus( int trackStateLocation ){ + // check if there is already an entry with this trackState location + for( unsigned i=0; i<_trackStatesPlus.size(); i++ ){ + if( _trackStatesPlus[i]->getTrackState()->location == trackStateLocation ){ + return _trackStatesPlus[i]; + } + } + + // If we reach this point, obviously no trackState with the given location has been created so far + // Thus we create it now + edm4hep::TrackState* trackState = new edm4hep::TrackState; + int return_code = 0; + double chi2; + int ndf; + switch( trackStateLocation ){ + case 1/*lcio::TrackState::AtIP*/:{ + const edm4hep::Vector3d point(0.,0.,0.); // nominal IP + + return_code = _marlinTrk->propagate(point, *trackState, chi2, ndf ) ; + + if (return_code != MarlinTrk::IMarlinTrack::success ) { + delete trackState; + + std::stringstream s; + s << "Fitter::getTrackStatePlus(): Couldn't create TrackState at IP, return code from propagation = " << return_code << "\n"; + throw FitterException( s.str() ); + + break; + } + else{ + trackState->location = trackStateLocation; + TrackStatePlus* trackStatePlus = new TrackStatePlus( trackState, chi2, ndf ); + _trackStatesPlus.push_back( trackStatePlus ); + return trackStatePlus; + } + } + case 2/*lcio::TrackState::AtFirstHit*/:{ + std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit; + + // remember the hits are ordered in the order in which they were fitted + // here we are fitting inwards so the first is the last and vice verse + _marlinTrk->getHitsInFit(hits_in_fit); + + edm4hep::TrackerHit* first_hit_in_fit = hits_in_fit.back().first; + + return_code = _marlinTrk->getTrackState(first_hit_in_fit, *trackState, chi2, ndf ) ; + + if(return_code !=MarlinTrk::IMarlinTrack::success){ + + delete trackState; + + std::stringstream s; + s << "Fitter::getTrackStatePlus(): Couldn't create TrackState at first hit, return code from propagation = " << return_code << "\n"; + throw FitterException( s.str() ); + + break; + } + else{ + trackState->location = trackStateLocation; + TrackStatePlus* trackStatePlus = new TrackStatePlus( trackState, chi2, ndf ); + _trackStatesPlus.push_back( trackStatePlus ); + return trackStatePlus; + } + } + case 3/*lcio::TrackState::AtLastHit*/:{ + std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit; + _marlinTrk->getHitsInFit(hits_in_fit); + + edm4hep::TrackerHit* last_hit_in_fit = hits_in_fit.front().first; + + return_code = _marlinTrk->getTrackState(last_hit_in_fit, *trackState, chi2, ndf ) ; + + if(return_code !=MarlinTrk::IMarlinTrack::success){ + delete trackState; + + std::stringstream s; + s << "Fitter::getTrackStatePlus(): Couldn't create TrackState at last hit, return code from propagation = " << return_code << "\n"; + throw FitterException( s.str() ); + + break; + } + else{ + trackState->location = trackStateLocation; + TrackStatePlus* trackStatePlus = new TrackStatePlus( trackState, chi2, ndf ); + _trackStatesPlus.push_back( trackStatePlus ); + return trackStatePlus; + } + break; + } + case 4/*lcio::TrackState::AtCalorimeter*/:{ + std::vector<std::pair<edm4hep::TrackerHit*, double> > hits_in_fit; + _marlinTrk->getHitsInFit(hits_in_fit); + + edm4hep::TrackerHit* last_hit_in_fit = hits_in_fit.front().first; + + UTIL::BitField64 encoder( UTIL::ILDCellID0::encoder_string ) ; + encoder.reset() ; // reset to 0 + + // ================== need to get the correct ID(s) for the calorimeter face ============================ + unsigned ecal_barrel_face_ID = UTIL::ILDDetID::ECAL ; + //unsigned ecal_endcap_face_ID = UTIL::ILDDetID::ECAL_ENDCAP ; + //========================================================================================================= + + encoder[UTIL::ILDCellID0::subdet] = ecal_barrel_face_ID ; + encoder[UTIL::ILDCellID0::side] = UTIL::ILDDetID::barrel; + encoder[UTIL::ILDCellID0::layer] = 0 ; + + int detElementID = 0; + return_code = _marlinTrk->propagateToLayer(encoder.lowWord(), last_hit_in_fit, *trackState, chi2, ndf, detElementID, IMarlinTrack::modeForward ) ; + + if (return_code == MarlinTrk::IMarlinTrack::no_intersection ) { // try forward or backward + //encoder[UTIL::ILDCellID0::subdet] = ecal_endcap_face_ID ; + + const edm4hep::TrackState* trkStateLastHit = getTrackStatePlus( 3/*lcio::TrackState::AtLastHit*/ )->getTrackState(); + + if (trkStateLastHit->tanLambda>0) { + encoder[UTIL::ILDCellID0::side] = UTIL::ILDDetID::fwd; + } + else{ + encoder[UTIL::ILDCellID0::side] = UTIL::ILDDetID::bwd; + } + return_code = _marlinTrk->propagateToLayer(encoder.lowWord(), last_hit_in_fit, *trackState, chi2, ndf, detElementID, IMarlinTrack::modeForward ) ; + } + + if(return_code !=MarlinTrk::IMarlinTrack::success){ + delete trackState; + + std::stringstream s; + s << "Fitter::getTrackStatePlus(): Couldn't create TrackState at Calorimeter, return code from propagation = " << return_code << "\n"; + throw FitterException( s.str() ); + break; + } + else{ + trackState->location = trackStateLocation; + TrackStatePlus* trackStatePlus = new TrackStatePlus( trackState, chi2, ndf ); + _trackStatesPlus.push_back( trackStatePlus ); + return trackStatePlus; + } + } + default:{ + std::stringstream s; + s << "Creation of a trackState for the given location " << trackStateLocation + << " is not yet implemented for the class Fitter. \nImplemented are: AtIP, AtFirstHit, AtLastHit, AtCalorimeter.\n" + << "If another location is desired, it must be implemented in the method Fitter::getTrackStatePlus.\n"; + + throw FitterException( s.str() ); + return NULL; + } + } + + return NULL; // if we haven't returned so far, there was no success, so we return NULL +} + + + diff --git a/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.cc.bak b/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.cc.bak new file mode 100644 index 0000000000000000000000000000000000000000..9ff3a2424354e226e71bebd0f1edcb34a3160bb6 --- /dev/null +++ b/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.cc.bak @@ -0,0 +1,122 @@ +#include "Tools/KiTrackMarlinCEDTools.h" + +#include <cmath> + +#include <CLHEP/Random/RandFlat.h> + +#include "MarlinCED.h" + + +void KiTrackMarlin::drawAutomatonSegments( const Automaton& automaton ){ + + + std::vector< const Segment* > segments = automaton.getSegments(); + + + for( unsigned i=0 ; i < segments.size(); i++ ){ + + + const Segment* segment = segments[i]; + std::vector < IHit* > hits = segment->getHits(); + + + if ( hits.size() == 1){ //exactly one hit, so draw a point + + + IHit* a = hits[0]; + ced_hit( a->getX() ,a->getY() , a->getZ() , 0 , 3 ,0xff0000 ); + + + } + else{ //more than one point or no points + + for( unsigned j=1 ; j< hits.size() ; j++ ){ // over all hits in the segment (as we connect it with the previous we start with hit 1) + + IHit* a = hits[j]; + IHit* b = hits[j-1]; + + + unsigned int color=0; + unsigned int red=0; + unsigned int blue=0; + unsigned int green=0; + + float p = sqrt ((float) segment->getInnerState() / (float) ( 7 )); + + green = unsigned( ceil ( (1.-p) * 255 ) ); + red = unsigned( floor( 255*p ) ); + blue = unsigned( ceil ( (1.-p) * 255 ) ); + + color = red * 256*256 + green * 256 + blue; + + + ced_line_ID( a->getX() ,a->getY() , a->getZ() , b->getX() ,b->getY() , b->getZ() , 2 , segment->getInnerState()+2 , color, 0); + + } + + } + + } + + +} + + + +void KiTrackMarlin::drawTrack( ITrack* track, int color ){ + + + std::vector < IHit* > hits = track->getHits(); + + for( unsigned j=1 ; j< hits.size() ; j++ ){ // over all hits in the segment (as we connect it with the previous we start with hit 1) + + IHit* a = hits[j]; + IHit* b = hits[j-1]; + + ced_line_ID( a->getX() ,a->getY() , a->getZ() , b->getX() ,b->getY() , b->getZ() , 2 , 5 , color, 0); + + } + + + + +} + + +void KiTrackMarlin::drawTrackRandColor( ITrack* track ){ + + + int red = 0; + int green = 0; + int blue = 0; + + int dist = 0; + int distmin = 60; + + while( dist < distmin ){ + + red = CLHEP::RandFlat::shootInt(256); + green = CLHEP::RandFlat::shootInt(256); + blue = CLHEP::RandFlat::shootInt(256); + + + dist = std::abs( red - green ); + if( std::abs( green - blue ) > dist ) dist = std::abs( green - blue ); + if( std::abs( red - blue ) > dist ) dist = std::abs( red - blue ); + + } + + int color = red * 256*256 + green * 256 + blue; + drawTrack( track, color ); + + + +} + + + + + + + + diff --git a/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.h b/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.h new file mode 100644 index 0000000000000000000000000000000000000000..e2f3ad2921b12821b9ba0255cc95b74223aeac7b --- /dev/null +++ b/Utilities/KiTrack/src/Tools/KiTrackMarlinCEDTools.h @@ -0,0 +1,31 @@ +#ifndef KiTrackMarlinCEDTools_h +#define KiTrackMarlinCEDTools_h + +#include "KiTrack/Automaton.h" +#include "KiTrack/ITrack.h" + +using namespace KiTrack; + +namespace KiTrackMarlin{ + + + + /** + * Draws the segments of an automaton. + * Segments will be colored according to their state. + * Also the higher the state, the thicker the line. + */ + void drawAutomatonSegments( const Automaton& automaton ); + + /** + * Draws a track by making straight lines between the hits + */ + void drawTrack( ITrack* track, int color = 0x00ff00 ); + + /** Draw a track in a random color, but not too bright */ + void drawTrackRandColor( ITrack* track ); + +} + +#endif + diff --git a/Utilities/KiTrack/src/Tools/KiTrackMarlinTools.cc b/Utilities/KiTrack/src/Tools/KiTrackMarlinTools.cc new file mode 100644 index 0000000000000000000000000000000000000000..7bb007c96e255170a4319635c87d1875ed4776fb --- /dev/null +++ b/Utilities/KiTrack/src/Tools/KiTrackMarlinTools.cc @@ -0,0 +1,262 @@ +#include "Tools/KiTrackMarlinTools.h" + +#include <sstream> +#include <fstream> +#include <cmath> + +#include "TROOT.h" +#include "TTree.h" +#include "TFile.h" + +#include "UTIL/LCTrackerConf.h" + +using namespace KiTrackMarlin; + + +std::string KiTrackMarlin::getCellID0Info( int cellID0 ){ + + std::stringstream s; + + //find out layer, module, sensor + UTIL::BitField64 cellID( UTIL::LCTrackerCellID::encoding_string() ); + cellID.setValue( cellID0 ); + + int subdet = cellID[ UTIL::LCTrackerCellID::subdet() ] ; + int side = cellID[ UTIL::LCTrackerCellID::side() ]; + int module = cellID[ UTIL::LCTrackerCellID::module() ]; + int sensor = cellID[ UTIL::LCTrackerCellID::sensor() ]; + int layer = cellID[ UTIL::LCTrackerCellID::layer() ]; + + s << "(su" << subdet << ",si" << side << ",la" << layer << ",mo" << module << ",se" << sensor << ")"; + + return s.str(); + +} + +int KiTrackMarlin::getCellID0Layer( int cellID0 ){ + + + UTIL::BitField64 cellID( UTIL::LCTrackerCellID::encoding_string() ); + cellID.setValue( cellID0 ); + + return cellID[ UTIL::LCTrackerCellID::layer() ]; + + +} + + + + +void KiTrackMarlin::setUpRootFile( std::string rootNamePath, std::string treeName , std::set<std::string> branchNames , bool createNew ){ + + + std::string fileNamePath = rootNamePath.substr( 0 , rootNamePath.find_last_of(".") ); + + + + std::ifstream rf ((fileNamePath + ".root").c_str()); //rf for RootFile + if ((rf) && (createNew)) { // The file already exists and we don't want to append + + int i=0; + std::stringstream newname; + while (rf){ //Try adding a number starting from 1 to the filename until no file with this name exists and use this. + + rf.close(); + i++; + newname.str(""); + newname << fileNamePath << i << ".root"; + + rf.open( newname.str().c_str() ); + + } + rename ( (fileNamePath + ".root").c_str() , newname.str().c_str()); //renames the file in the way,so that our new file can have it's name + //and not ovrewrite it. + + } + + float x = 0; + + std::string modus = "RECREATE"; + if ( !createNew ) modus = "UPDATE"; + + TFile* myRootFile = new TFile((fileNamePath + ".root").c_str(), modus.c_str() ); //Make new file or update it + TTree* myTree; + + myTree = new TTree(treeName.c_str(),"My tree"); //make a new tree + + //create the branches: + + std::set < std::string >::iterator it; + + + for ( it = branchNames.begin() ; it != branchNames.end() ; it++ ){ + + + myTree->Branch( (*it).c_str() , &x ); + + } + + + myTree->Write("",TObject::kOverwrite); + myRootFile->Close(); + +} + + + + + +void KiTrackMarlin::saveToRoot( std::string rootFileName, std::string treeName , std::map < std::string , float > map_name_data ){ + std::map < std::string , float >::iterator it; + + TFile* myRootFile = new TFile( rootFileName.c_str(), "UPDATE"); //add values to the root file + TTree* myTree = dynamic_cast <TTree*>( myRootFile->Get( treeName.c_str()) ); + + if( myTree == NULL ){ + std::cout << "ERROR: KiTrackMarlin::saveToRoot could not get tree " << treeName << std::endl; + return; + } + + for( it = map_name_data.begin() ; it != map_name_data.end() ; it++){ + myTree->SetBranchAddress( it->first.c_str(), & it->second ); + } + + myTree->Fill(); + myTree->Write("",TObject::kOverwrite); + + myRootFile->Close(); +} + +void KiTrackMarlin::saveToRoot( std::string rootFileName, std::string treeName , std::vector < std::map < std::string , float > > rootDataVec ){ + std::map < std::string , float >::iterator it; + + TFile* myRootFile = new TFile( rootFileName.c_str(), "UPDATE"); //add values to the root file + TTree* myTree = dynamic_cast <TTree*>( myRootFile->Get( treeName.c_str()) ); + + if( myTree == NULL ){ + std::cout << "ERROR: KiTrackMarlin::saveToRoot could not get tree " << treeName << std::endl; + return; + } + + for( unsigned i=0; i<rootDataVec.size(); i++ ){ //for all entries + std::map < std::string , float > map_name_data = rootDataVec[i]; + for( it = map_name_data.begin() ; it != map_name_data.end() ; it++){ // for all data in the entrie + myTree->SetBranchAddress( it->first.c_str(), & it->second ); + } + myTree->Fill(); + } + myTree->Write("",TObject::kOverwrite); + myRootFile->Close(); +} + + +//bool KiTrackMarlin::compare_TrackerHit_z( edm4hep::ConstTrackerHit* a, edm4hep::ConstTrackerHit* b ){ +// return ( fabs(a->getPosition()[2]) < fabs( b->getPosition()[2]) ); //compare their z values +//} + +bool KiTrackMarlin::compare_TrackerHit_z( edm4hep::ConstTrackerHit& a, edm4hep::ConstTrackerHit& b ){ + return ( fabs(a.getPosition()[2]) < fabs( b.getPosition()[2]) ); +} + +bool KiTrackMarlin::compare_TrackerHit_R( edm4hep::ConstTrackerHit& a, edm4hep::ConstTrackerHit& b ){ + double Rad_a2 = (a.getPosition()[0]*a.getPosition()[0]) + (a.getPosition()[1]*a.getPosition()[1]) ; + double Rad_b2 = (b.getPosition()[0]*b.getPosition()[0]) + (b.getPosition()[1]*b.getPosition()[1]) ; + + return ( Rad_a2 < Rad_b2 ); //compare their radii +} + + + +FTDHitSimple* KiTrackMarlin::createVirtualIPHit( int side , const SectorSystemFTD* sectorSystemFTD ){ + + unsigned layer = 0; + unsigned module = 0; + unsigned sensor = 0; + FTDHitSimple* virtualIPHit = new FTDHitSimple( 0.,0.,0., side , layer , module , sensor , sectorSystemFTD ); + + + virtualIPHit->setIsVirtual ( true ); + + return virtualIPHit; + +} + + +VXDHitSimple* KiTrackMarlin::createVirtualIPHit( const SectorSystemVXD* sectorSystemVXD ){ + + int layer = 0 ; + int phi = 0 ; + int theta = 0 ; + + VXDHitSimple* virtualIPHit = new VXDHitSimple( 0.,0.,0., layer, phi, theta, sectorSystemVXD ); + + virtualIPHit->setIsVirtual ( true ); + + return virtualIPHit; + +} + + +std::string KiTrackMarlin::getPositionInfo( edm4hep::ConstTrackerHit* hit ){ + + std::stringstream info; + + double x = hit->getPosition()[0]; + double y = hit->getPosition()[1]; + double z = hit->getPosition()[2]; + + info << "(" << x << "," << y << "," << z << ")"; + + return info.str(); + +} + +std::string KiTrackMarlin::getPositionInfo( IHit* hit ){ + + std::stringstream info; + + double x = hit->getX(); + double y = hit->getY(); + double z = hit->getZ(); + + info << "(" << x << "," << y << "," << z << ")"; + + return info.str(); + +} + + +std::string KiTrackMarlin::getTrackHitInfo( ITrack* track){ + + std::stringstream info; + + std::vector< IHit* > hits = track->getHits(); + + for( unsigned i=0; i < hits.size(); i++ ){ + + info << getPositionInfo( hits[i] ); + + }; + + return info.str(); + + +} + +std::string KiTrackMarlin::getTrackHitInfo( edm4hep::Track* track){ + std::stringstream info; + //std::vector< edm4hep::TrackerHit* > hits; + unsigned int nHits = track->trackerHits_size(); + for(unsigned i=0; i<nHits; i++){ + edm4hep::ConstTrackerHit hit = track->getTrackerHits(i); + info << getPositionInfo(&hit); + } + + //for( unsigned i=0; i < hits.size(); i++ ){ + // info << getPositionInfo( hits[i] ); + //}; + + return info.str(); +} + + diff --git a/Utilities/KiTrack/src/Tools/Timer.cc b/Utilities/KiTrack/src/Tools/Timer.cc new file mode 100644 index 0000000000000000000000000000000000000000..2597141d60505a18b88bc698e2ba6cef90d0eb0d --- /dev/null +++ b/Utilities/KiTrack/src/Tools/Timer.cc @@ -0,0 +1,127 @@ +#include "Tools/Timer.h" + +#include <string> +#include <fstream> +#include <iterator> +#include <cstdlib> +#include <iostream> + +#define FINE_GRAINED_LINUX_TIMING + +#include <ctime> +#include <sys/times.h> +#include <unistd.h> + +using namespace std; +using namespace KiTrackMarlin; + +namespace { + #ifdef FINE_GRAINED_LINUX_TIMING + static unsigned cyc_hi = 0; + static unsigned cyc_lo = 0; + + void access_counter(unsigned *hi, unsigned *lo) + { + asm("rdtsc; movl %%edx,%0; movl %%eax,%1" + : "=r" (*hi), "=r" (*lo) + : + : "%edx", "%eax"); + } + + double get_counter() + { + unsigned ncyc_hi, ncyc_lo; + unsigned hi, lo, borrow; + access_counter(&ncyc_hi, &ncyc_lo); + lo = ncyc_lo - cyc_lo; + borrow = lo > ncyc_lo; + hi = ncyc_hi - cyc_hi - borrow; + return (double) hi * (1 << 30) * 4 + lo; + } + #else + clock_t before; + #endif +} + +double Timer::cpuMHz() +{ + static double ret=-1.; + if ( ret > -.5 ) return ret; + string input="Unknow CPU"; + { + ifstream cpuinfo("/proc/cpuinfo"); + if ( cpuinfo.is_open() ) + { + cpuinfo.unsetf( ios::skipws ); + istream_iterator<char> sbegin(cpuinfo),send; + copy(sbegin,send,inserter(input,input.end())); + cpuinfo.close(); + }; + } + + size_t i = input.find("model name"); + if (i!=string::npos ) + { + i = input.find("@ ",i); + if ( i != string::npos ) + { + size_t j = input.find("GHz",i); + //cout << "[debug] i=" << i << " j=" << j << " string=" << input.substr(i+1,j-i-1) << "X" << endl; + return 1000.*atof(input.substr(i+1,j-i-1).c_str() ); + }; + + } + + i = input.find("cpu MHz"); + if (i==string::npos) + { + cout << "[Timer] /proc/cpuinfo does not contain cpu speed..." << endl; + ret=0.; + }; + i = input.find(":",i); + ret=atof(input.substr(i+1,input.find("/n",i)-i).c_str()); + return ret; +} + +void Timer::start_counter() +{ + #ifdef FINE_GRAINED_LINUX_TIMING + access_counter(&cyc_hi, &cyc_lo); + #else + tms buf; + times( &buf ); + before = buf.tms_utime; + #endif +} + +double Timer::lap() +{ + #ifdef FINE_GRAINED_LINUX_TIMING + return get_counter() / cpuMHz() / 1.e6; + #else + tms buf; + times ( &buf ); + clock_t after = buf.tms_utime; + static float cps=sysconf(_SC_CLK_TCK); + double t = ( after - before ) / cps; + return t; + #endif +} + +double Timer::ticks() +{ + #ifdef FINE_GRAINED_LINUX_TIMING + return get_counter(); + #else + tms buf; + times ( &buf ); + clock_t after = buf.tms_utime; + // static float cps=sysconf(_SC_CLK_TCK); + double t = ( after - before ); + return t; + #endif +} + +#ifdef FINE_GRAINED_LINUX_TIMING +#undef FINE_GRAINED_LINUX_TIMING +#endif diff --git a/Utilities/KiTrack/src/Tools/Timer.h b/Utilities/KiTrack/src/Tools/Timer.h new file mode 100644 index 0000000000000000000000000000000000000000..7c3cd3bd0422ddaef7ab5a6f30adef6dfce9912a --- /dev/null +++ b/Utilities/KiTrack/src/Tools/Timer.h @@ -0,0 +1,22 @@ +#ifndef dataharvester_Timer_H_ +#define dataharvester_Timer_H_ + +namespace KiTrackMarlin { +class Timer { +public: + /** + * A fast, precise timer + * Works on linux only + * + * Author: Wolfgang Waltenberger + */ + static void start_counter(); + + /// Return what the harvester thinks is the CPU frequency. + static double cpuMHz(); + static double lap(); //< lapsed time, in seconds. + static double ticks(); //< lapsed time, in clock ticks. +}; +} + +#endif // dataharvester_Timer_H_ diff --git a/Utilities/KiTrack/src/Tools/VXDHelixFitter.cc.bak b/Utilities/KiTrack/src/Tools/VXDHelixFitter.cc.bak new file mode 100644 index 0000000000000000000000000000000000000000..515a80298c3ae1531e4a4a9a0c35367b21ce844a --- /dev/null +++ b/Utilities/KiTrack/src/Tools/VXDHelixFitter.cc.bak @@ -0,0 +1,190 @@ +#include "Tools/VXDHelixFitter.h" + +#include <sstream> +#include <algorithm> +#include <cmath> + +#include "edm4hep/TrackerHit.h" +#include "UTIL/ILDConf.h" +#include "UTIL/LCTrackerConf.h" +//#include "marlin/VerbosityLevels.h" +#include "TrackSystemSvc/HelixFit.h" + +#include "Tools/KiTrackMarlinTools.h" + + +VXDHelixFitter::VXDHelixFitter( std::vector< TrackerHit* > trackerHits ){ + + _trackerHits = trackerHits; + + fit(); + +} + +VXDHelixFitter::VXDHelixFitter( Track* track ){ + + _trackerHits = track->getTrackerHits(); + + fit(); + +} + +void VXDHelixFitter::fit(){ + + std::vector< TrackerHit* > trackerHits2D ; + + for (unsigned ihit=0; ihit <_trackerHits.size(); ++ihit) { + + // check if this a space point or 2D hit + if(UTIL::BitSet32( _trackerHits[ihit]->getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] == false ){ + // then add to the list + trackerHits2D.push_back(_trackerHits[ihit]); + + } + } + + std::sort( trackerHits2D.begin(), trackerHits2D.end(), KiTrackMarlin::compare_TrackerHit_R ); + + int nHits = trackerHits2D.size(); + + int iopt = 2; + float chi2RPhi; + float chi2Z; + + // DEBUG + //streamlog_out(DEBUG4) << " no of hits fitted " << nHits << std::endl ; + + if( nHits < 3 ){ + + std::stringstream s; + s << "VXDHelixFitter::fit(): Cannot fit less with less than 3 hits. Number of hits = " << nHits << "\n"; + + throw VXDHelixFitterException( s.str() ); + + } + + double* xh = new double[nHits]; + double* yh = new double[nHits]; + float* zh = new float[nHits]; + double* wrh = new double[nHits]; + float* wzh = new float[nHits]; + float* rh = new float[nHits]; + float* ph = new float[nHits]; + + float par[5]; + float epar[15]; + + for( int i=0; i<nHits; i++ ){ + + TrackerHit* hit = trackerHits2D[i]; + + xh[i] = hit->getPosition()[0]; + yh[i] = hit->getPosition()[1]; + zh[i] = float(hit->getPosition()[2]); + + //wrh[i] = double(1.0/(hit->getResolutionRPhi()*hit->getResolutionRPhi())); + //wzh[i] = 1.0/(hit->getResolutionZ()*hit->getResolutionZ()); + //wrh[i] = double(1.0/(sqrt((hit->getCovMatrix()[0]*hit->getCovMatrix()[0]) + (hit->getCovMatrix()[2]*hit->getCovMatrix()[2])))); + //wzh[i] = 1.0/(hit->getCovMatrix()[5]); + + rh[i] = float(sqrt(xh[i]*xh[i]+yh[i]*yh[i])); + ph[i] = atan2(yh[i],xh[i]); + if (ph[i] < 0.) + ph[i] = 2.*M_PI + ph[i]; + + // Just to debug the resolutions + //streamlog_out(DEBUG4) << " hit's radius " << rh[i] << " R-phi uncertainty " << wrh[i] << " Z uncertainty " << wzh[i] << " Cov[0] " << hit->getCovMatrix()[0] << " Cov[2] " << hit->getCovMatrix()[2] << " Cov[5] " << hit->getCovMatrix()[5] << std::endl ; + + // check for composite spacepoints + if( BitSet32( hit->getType() )[ UTIL::ILDTrkHitTypeBit::COMPOSITE_SPACEPOINT ] ){ + + //streamlog_out(DEBUG4) << " COMPOSITE SPACEPOINT radius: " << rh[i] << std::endl ; + + float sigX = hit->getCovMatrix()[0]; + float sigY = hit->getCovMatrix()[2]; + wrh[i] = 1/sqrt( sigX*sigX + sigY*sigY ); + wzh[i] = 1.0/(hit->getCovMatrix()[5]); + + //streamlog_out(DEBUG4) << " SPACEPOINT:: hit's radius " << rh[i] << " R-phi uncertainty " << wrh[i] << " Z uncertainty " << wzh[i] << " res RPhi " << sqrt( sigX*sigX + sigY*sigY ) << " res Z " << (hit->getCovMatrix()[5]) << std::endl ; + + } + else if ( BitSet32( hit->getType() )[ UTIL::ILDTrkHitTypeBit::ONE_DIMENSIONAL ] ) { + + // YV: FIXME: very crude hack, hard coded the SIT strip digital resolution in V + //streamlog_out(DEBUG4) << " 1D hit radius: " << rh[i] << std::endl ; + + //TrackerHitPlane* hitPlane = dynamic_cast<TrackerHitPlane*>( hit ); + //wrh[i] = double(1.0/( hitPlane->getdU()*hitPlane->getdU() )); + wrh[i] = double(1.0/( hit->getCovMatrix(2)*hit->getCovMatrix(2) )); + double resZ = 92.0 / std::sqrt( 12. ) ; + //double resZ = 0.003 ; + wzh[i] = 1.0/( resZ * resZ ); + + //streamlog_out(DEBUG4) << " 1Dimensional TRACKERHITPLANE:: hit's radius " << rh[i] << " R-phi uncertainty " << wrh[i] << " Z uncertainty " << wzh[i] << " dU " << hitPlane->getdU() << " dV " << resZ << " 1/du^2 "<< (1/(hitPlane->getdU()*hitPlane->getdU())) << " 1/dv^2 "<< wzh[i] << std::endl ; + + } + + else { + + //streamlog_out(DEBUG4) << " 2D hit radius: " << rh[i] << std::endl ; + //TrackerHitPlane* hitPlane = dynamic_cast<TrackerHitPlane*>( hit ); + //wrh[i] = double(1.0/( hitPlane->getdU()*hitPlane->getdU() )); + //wzh[i] = wrh[i]; // pixel VXD + wrh[i] = double(1.0/( hit->getCovMatrix(2)*hit->getCovMatrix(2) )); + wzh[i] = double(1.0/( hit->getCovMatrix(5)*hit->getCovMatrix(5) )); + + //streamlog_out(DEBUG4) << "2D pixel TRACKERHITPLANE:: hit's radius " << rh[i] << " R-phi uncertainty " << wrh[i] << " Z uncertainty " << wzh[i] << " dU " << hitPlane->getdU() << " dV " << hitPlane->getdV() << " 1/du^2 "<< (1/(hitPlane->getdU()*hitPlane->getdU())) << " 1/dv^2 "<< (1/(hitPlane->getdV()*hitPlane->getdV())) << std::endl ; + + } + } + + + + + MarlinTrk::HelixFit helixFitter; + + helixFitter.fastHelixFit(nHits, xh, yh, rh, ph, wrh, zh, wzh,iopt, par, epar, chi2RPhi, chi2Z); + par[3] = par[3]*par[0]/fabs(par[0]); + + _omega = par[0]; + _tanLambda = par[1]; + _phi0 = par[2]; + _d0 = par[3]; + _z0 = par[4]; + + float chi2 = chi2RPhi+chi2Z; + int Ndf = 2*nHits-5; + + + + + delete[] xh; + delete[] yh; + delete[] zh; + delete[] wrh; + delete[] wzh; + delete[] rh; + delete[] ph; + xh = NULL; + yh = NULL; + zh = NULL; + wrh = NULL; + wzh = NULL; + rh = NULL; + ph = NULL; + + + //streamlog_out(DEBUG4) << "chi2 rphi = " << chi2RPhi << ", chi2 Z = " << chi2Z << ", Ndf = " << Ndf << "\n"; + + _chi2 = chi2; + _Ndf = Ndf; + + return; + + + +} + + + + diff --git a/Utilities/KiTrack/src/Tools/VXDHelixFitter.h b/Utilities/KiTrack/src/Tools/VXDHelixFitter.h new file mode 100644 index 0000000000000000000000000000000000000000..cf066262e62f12be1ddeedc1417e814825dbd8b7 --- /dev/null +++ b/Utilities/KiTrack/src/Tools/VXDHelixFitter.h @@ -0,0 +1,82 @@ +#ifndef VXDHelixFitter_h +#define VXDHelixFitter_h + +#include "edm4hep/Track.h" +#include "edm4hep/TrackerHit.h" + +//#include "lcio.h" + + + +//using namespace lcio; + + + +class VXDHelixFitterException : public std::exception { + + +protected: + std::string message ; + + VXDHelixFitterException(){ /*no_op*/ ; } + +public: + virtual ~VXDHelixFitterException() { /*no_op*/; } + + VXDHelixFitterException( const std::string& text ){ + message = "VXDHelixFitterException: " + text ; + } + + virtual const char* what() const noexcept { return message.c_str() ; } + +}; + + + +/** A class to make it quick to fit a track or hits and get back the chi2 and Ndf values and + * also bundle the code used for that, so it doesn't have to be copied all over the places. + * Uses a helix fit from the MarlinTrk class HelixFit.cc + * It is named VXDHelixFitter, because it makes some assumptions about the hits, that come from them + * being on the VXD. Specifically the errors passed to the helix fit are calculated on the assumption, + * that du and dv are errors in the xy plane. + * If this class is intended to be used for hits on different detectors, a careful redesign is necessary! + */ +class VXDHelixFitter{ + + +public: + + VXDHelixFitter( edm4hep::Track* track ) ; + VXDHelixFitter( std::vector < edm4hep::TrackerHit* > trackerHits ) ; + + + double getChi2(){ return _chi2; } + int getNdf(){ return _Ndf; } + + float getOmega(){ return _omega; } + float getTanLambda(){ return _tanLambda; } + float getPhi0(){ return _phi0; } + float getD0(){ return _d0; } + float getZ0(){ return _z0; } + +private: + + + + void fit(); + + double _chi2; + int _Ndf; + + float _omega; + float _tanLambda; + float _phi0; + float _d0; + float _z0; + + std::vector< edm4hep::TrackerHit* > _trackerHits; + + +}; + +#endif