diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b02527456f9d5851e674ad2fafe3ce8ccaf3724c..2a8e44b726fd3929ab64e3a3a2cd96bd67033013 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -104,6 +104,7 @@ build:ubuntu: - source SetEnv.sh - echo $LD_LIBRARY_PATH - cd $CI_PROJECT_DIR + - source build/config.sh - ./macro/gitlab_test.sh allow_failure: true <<: *only-default diff --git a/CMakeLists.txt b/CMakeLists.txt index 2871cee11c0390b70c50ec97c491fcba9db97ab7..3011e32b1b8b04fd794743eec095475affb820e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR) # Set name of our project to “SPDROOT". Has to be done # after check of cmake version since this is a new feature -project(SPDROOT) +PROJECT(SPDROOT) + +IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + SET(CMAKE_INSTALL_PREFIX /opt/spdroot/ CACHE PATH "SpdRoot install prefix" FORCE) +ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) #set(CMAKE_VERBOSE_MAKEFILE true) include(CMakeParseArguments) @@ -59,7 +63,7 @@ Check_Compiler() set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib") set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin") set(INCLUDE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/include") -Set(VMCWORKDIR ${CMAKE_SOURCE_DIR}) +Set(VMCWORKDIR ${CMAKE_INSTALL_PREFIX}) Option(USE_PATH_INFO "Information from PATH and LD_LIBRARY_PATH are used." OFF) If(USE_PATH_INFO) Set(PATH "$PATH") @@ -92,23 +96,8 @@ CHECK_EXTERNAL_PACKAGE_INSTALL_DIR() # mandatory find_package2(PUBLIC ROOT VERSION 6.10.00 REQUIRED) -#find_package2(PUBLIC FairLogger VERSION 1.2.0 REQUIRED) find_package2(PUBLIC Pythia6) find_package2(PUBLIC Pythia8) -#find_package2(PUBLIC Protobuf) -#find_package2(PUBLIC msgpack) -#find_package2(PUBLIC FlatBuffers) -#find_package(ROOT 5.32.00 REQUIRED) -#find_package(ROOT REQUIRED) -#find_package(Pythia8) -#find_package(Pythia6 REQUIRED) -#find_package(GENERATORS REQUIRED) -#find_package(GEANT3) -#find_package(GEANT4 REQUIRED) -#find_package(GEANT4DATA) -#find_package(GEANT4VMC REQUIRED) -#find_package(CLHEP) - find_package2(PUBLIC Geant3) if(Geant3_FOUND) @@ -130,18 +119,6 @@ Set(Geant4_INCLUDE_DIRS "$ENV{SIMPATH}/include/Geant4") Set(Geant4VMC_INCLUDE_DIRS "$ENV{SIMPATH}/include/geant4vmc") Set(Geant4VMC_LIBRARY_DIR "$ENV{SIMPATH}/lib") -#if(Geant4VMC_FOUND) -# Set(Geant4VMC_LIBRARY_DIR "$ENV{SIMPATH}/lib") -#Endif() -#if(Geant4VMC_FOUND) -# Set(Geant4VMC_LIBRARY_DIR "${Geant4VMC_DIR}/${Geant4VMC_CMAKE_INSTALL_LIBDIR}") -# Set(Geant4VMC_SHARE_DIR "${Geant4VMC_DIR}/share") -# Find_Path(Geant4VMC_MACRO_DIR NAMES g4libs.C PATHS -# ${Geant4VMC_SHARE_DIR}/Geant4VMC-${Geant4VMC_VERSION}/examples/macro -# NO_DEFAULT_PATH -# ) -#Endif() - Set(Boost_NO_SYSTEM_PATHS TRUE) Set(Boost_NO_BOOST_CMAKE TRUE) If(${ROOT_LIBRARY_DIR} MATCHES /lib/root) @@ -174,6 +151,7 @@ Message(":: SYSTEM_INCLUDE_DIR : ${SYSTEM_INCLUDE_DIRECTORIES}") Message(":: BASE_INCLUDE_DIR : ${BASE_INCLUDE_DIRECTORIES}") Message(":: CMAKE_SOURCE_DIR : ${CMAKE_SOURCE_DIR}") Message(":: CMAKE_CURRENT_BINARY_DIR : ${CMAKE_CURRENT_BINARY_DIR}") +Message(":: CMAKE_INSTALL_PREFIX : ${CMAKE_INSTALL_PREFIX}") # Set the library version in the main CMakeLists.txt SET(FAIRROOT_MAJOR_VERSION 0) @@ -189,9 +167,8 @@ SET(FAIRROOT_LIBRARY_PROPERTIES ${FAIRROOT_LIBRARY_PROPERTIES} #Generate_Version_Info() SET(_LIBDIR ${CMAKE_BINARY_DIR}/lib) -SET(LD_LIBRARY_PATH ${_LIBDIR} ${LD_LIBRARY_PATH}) - -#install(DIRECTORY geometry DESTINATION spd_install ) +SET(LD_LIBRARY_PATH ${_LIBDIR} ${SIMPATH}/lib ${LD_LIBRARY_PATH}) +SET(PATH ${CMAKE_SOURCE_DIR} ${CMAKE_INSTALL_PREFIX}/bin ${PATH}) # Check if the compiler support specific C++11 features # Up to now this is only a check since the code does not use @@ -229,6 +206,7 @@ add_subdirectory (proc) add_subdirectory (reco) add_subdirectory (spddisplay) + ################################################################################ if(PROJECT_PACKAGE_DEPENDENCIES) message(STATUS " ") @@ -346,6 +324,70 @@ if(BUILD_DOXYGEN) endif(BUILD_DOXYGEN) WRITE_CONFIG_FILE(config.sh) +WRITE_CONFIG_FILE(config.sh_install) + +file(APPEND ${CMAKE_BINARY_DIR}/config.sh "export VMCWORKDIR=${CMAKE_SOURCE_DIR}\n") +file(APPEND ${CMAKE_BINARY_DIR}/config.sh "export SPDROOTPATH=${CMAKE_SOURCE_DIR}\n") +file(APPEND ${CMAKE_BINARY_DIR}/config.sh "export GEOMPATH=${CMAKE_SOURCE_DIR}/geometry\n") +file(APPEND ${CMAKE_BINARY_DIR}/config.sh "export MAGFPATH=${CMAKE_SOURCE_DIR}/input\n") +file(APPEND ${CMAKE_BINARY_DIR}/config.sh "export ROOT_INCLUDE_PATH=${CMAKE_SOURCE_DIR}/install:${ROOT_INCLUDE_PATH}\n") + +file(APPEND ${CMAKE_BINARY_DIR}/config.sh_install "export SPDROOTPATH=${VMCWORKDIR}\n") +file(APPEND ${CMAKE_BINARY_DIR}/config.sh_install "export GEOMPATH=${VMCWORKDIR}/share/geometry\n") +file(APPEND ${CMAKE_BINARY_DIR}/config.sh_install "export MAGFPATH=${VMCWORKDIR}/share/input\n") +file(APPEND ${CMAKE_BINARY_DIR}/config.sh_install "export ROOT_INCLUDE_PATH=${VMCWORKDIR}/install:${ROOT_INCLUDE_PATH}\n") + +Install(FILES ${CMAKE_BINARY_DIR}/config.sh_install + DESTINATION bin + RENAME SetEnv.sh + ) + +Install(FILES spdroot.py + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + DESTINATION bin + ) + +Install(FILES macro/rootlogon.C macro/rootlogoff.C + DESTINATION macro/ + ) + +Install(DIRECTORY gconfig + DESTINATION . + ) + +Install(FILES macro/SimuQsl.C + DESTINATION share/examples/ + ) + +Install(DIRECTORY macro/fullchain macro/primgen macro/tracking macro/vertexrec + DESTINATION share/examples + PATTERN ".svn" EXCLUDE) + + +Install(DIRECTORY geometry + DESTINATION share/ + PATTERN ".svn" EXCLUDE) + +Install(DIRECTORY input + DESTINATION share/ + PATTERN ".svn" EXCLUDE) + +Install(FILES ${CMAKE_BINARY_DIR}/check_system.sh + DESTINATION bin + ) + +Install(FILES ${CMAKE_BINARY_DIR}/check_system.csh + DESTINATION bin + ) + +Install(FILES ${CMAKE_BINARY_DIR}/check_system.sh + DESTINATION . + ) + +Install(FILES ${CMAKE_BINARY_DIR}/check_system.csh + DESTINATION . + ) + configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_BINARY_DIR}/CTestCustom.cmake diff --git a/SetEnv.sh b/SetEnv.sh index 24964d4a7337ec96a43b07ab1b67e53105ec5132..a2ffe9e4381df8b102d3fcff6dd89a88e0422239 100644 --- a/SetEnv.sh +++ b/SetEnv.sh @@ -6,10 +6,15 @@ export FAIRROOTPATH=/opt/fairroot/install export PATH="${SIMPATH}/bin:$PATH" export LD_LIBRARY_PATH="${SIMPATH}/lib:$LD_LIBRARY_PATH" -if [ -f build/config.sh ] -then -source build/config.sh -a -fi +#if [ -f build/config.sh ] +#then +#source build/config.sh -a +#fi -export GEOMPATH="${VMCWORKDIR}/geometry" +#export GEOMPATH="${VMCWORKDIR}/geometry" +#export MAGFPATH="${VMCWORKDIR}/input" +#export PATH="${VMCWORKDIR}:$PATH" + +#echo actual path to geometry and materials: $GEOMPATH +#echo actual path to magnetic field maps: $MAGFPATH diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index d53ee8cae32281bd1350f3b611a18233fbdee0d0..1df852a4ed4cd82a1d739a1fb0346c3f4611facd 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -57,7 +57,25 @@ geometry/SpdGeoVVolume.cxx region/SpdRegion.cxx checks/SpdGeoScanner.cxx +) +set(HEADERS +checks/SpdGeoScanner.h +geometry/SpdGeoBuilder.h +geometry/SpdGeoMapper.h +geometry/SpdGeoTable.h +geometry/SpdGeoVolPars.h +geometry/SpdGeoVVolume.h +geometry/SpdNodesIdTable.h +region/SpdRegion.h +SpdCommonGeoMapper.h +SpdDetector.h +SpdGlobals.h +SpdModulesMap.h +SpdPassiveModule.h +SpdRunAna.h +SpdRunSim.h +SpdStack.h ) set(LINKDEF SpdCommonLinkDef.h) diff --git a/common/SpdCommonGeoMapper.cxx b/common/SpdCommonGeoMapper.cxx index b1dacaa8659a72b3c2dae2c58d737384dde9fd3d..69ab3678e8f0960aafa9083e032475d5d44015ec 100644 --- a/common/SpdCommonGeoMapper.cxx +++ b/common/SpdCommonGeoMapper.cxx @@ -8,6 +8,7 @@ #include "FairGeoLoader.h" #include "FairGeoInterface.h" +#include "FairGeoMedia.h" #include "SpdCommonGeoMapper.h" #include "SpdPassiveModule.h" @@ -35,7 +36,7 @@ TGeoVolume* SpdCommonGeoMapper::theMasterVolume = 0; /*==================================================================*/ Int_t SpdCommonGeoMapper::theNGeoSectors = 8; // > 2 and < 13 -Double_t SpdCommonGeoMapper::theSectorClearance = 5.; // cm +Double_t SpdCommonGeoMapper::theSectorClearance = 2.5; // cm /*============================= PIPE ===============================*/ @@ -401,16 +402,64 @@ TString SpdCommonGeoMapper::GetMasterVolumeName() } //_____________________________________________________________________________ -void SpdCommonGeoMapper::OpenGeometry() -{ +void SpdCommonGeoMapper::OpenGeometry(TString media) +{ + if (media.IsWhitespace()) media = "media.geo"; + + Bool_t found = false; + + TString medfile; + while (true) + { + // if absolute path + if (media.BeginsWith("/") ) { + if (!gSystem->AccessPathName(media.Data())) { + medfile = media; + found = true; + break; + } + } + + // if GEOMPATH is set + TString mpath = getenv("GEOMPATH"); + mpath.ReplaceAll("//","/"); + if (!mpath.IsNull() ) { + if (!mpath.EndsWith("/")) mpath += "/"; + medfile = mpath + media; + if (!gSystem->AccessPathName(medfile.Data())) { found = true; break; } + } + + // if file was not found look it in the standard path + medfile = TString(getenv("VMCWORKDIR"))+"/geometry/"; + medfile += media; + if (!gSystem->AccessPathName(medfile.Data())) { found = true; break; } + + // if file was not found set default + medfile = TString(getenv("VMCWORKDIR"))+"/geometry/media.geo"; + cout << "-I- <SpdCommonGeoMapper::OpenGeometry> File " << media << " not found." + << " Set default media file. " << endl; + break; + } + + cout << "-I- <SpdCommonGeoMapper::OpenGeometry> Media file: " << medfile << endl; + FairGeoLoader* loader = FairGeoLoader::Instance(); if (!loader) loader = new FairGeoLoader("TGeo","Geo Loader"); FairGeoInterface* GeoInterface = loader->getGeoInterface(); - GeoInterface->setMediaFile(TString(gSystem->Getenv("VMCWORKDIR"))+"/geometry/media.geo"); + GeoInterface->setMediaFile(medfile); GeoInterface->readMedia(); } +//_____________________________________________________________________________ +TString SpdCommonGeoMapper::GetActualMediaFileName() const +{ + FairGeoLoader* loader = FairGeoLoader::Instance(); + if (!loader) return ""; + FairGeoInterface* GeoInterface = loader->getGeoInterface(); + return GeoInterface->getMedia()->getInputFile(); +} + //_____________________________________________________________________________ void SpdCommonGeoMapper::DefineTorGeometrySet(Int_t type) { @@ -789,6 +838,8 @@ void SpdCommonGeoMapper::DefineHybGeometrySet(Int_t type) if (type == 2) { + theHybMagnetDefGeoType = 2; + theTsTBDefGeoType = 2; // TsTB theTsTBLen2 = 236.; // (510) cm @@ -813,7 +864,7 @@ void SpdCommonGeoMapper::DefineHybGeometrySet(Int_t type) return; } - cout << "-W- <SpdCommonGeoMapper::DefineSolGeometrySet> " + cout << "-W- <SpdCommonGeoMapper::DefineHybGeometrySet> " << "Unknown geometry set: " << type << endl; theTsTBDefGeoType = 0; @@ -825,6 +876,134 @@ void SpdCommonGeoMapper::DefineHybGeometrySet(Int_t type) } +//_____________________________________________________________________________ +void SpdCommonGeoMapper::DefineQslGeometrySet() +{ + if (!thePassives.empty()) { + map <SpdPassiveModule*, module_info*>::iterator it = thePassives.begin(); + for ( ; it != thePassives.end(); it++) { + if (it->first->IsGeometryLocked()) { + cout << "-W- <SpdCommonGeoMapper::DefineQslGeometrySet>" + << "Geometry is locked (passives)" << endl; + return; + } + } + } + + if (!theDetectors.empty()) { + SpdGeoMapper* mapper; + map <SpdDetector*, module_info*>::iterator it = theDetectors.begin(); + for ( ; it != theDetectors.end(); it++) { + mapper = it->first->GetMapper(); + if (mapper && mapper->IsGeometryLocked()) { + cout << "-W- <SpdCommonGeoMapper::DefineQslGeometrySet> " + << "Geometry is locked (detectors)" << endl; + return; + } + } + } + + cout << "-I- <SpdCommonGeoMapper::DefineQslGeometrySet> " << endl; + + theSolMagnetDefGeoType = 0; + theTsSBDefGeoType = 0; + theTsSECDefGeoType = 0; + theEcalSBDefGeoType = 0; + theEcalSECDefGeoType = 0; + theRsSBDefGeoType = 0; + theRsSECDefGeoType = 0; + + /*=================================================================*/ + + thePipeDefGeoType = 4; + + theTorBasketDefGeoType = 0; + theTorMagnetDefGeoType = 0; + + /*========================= MAGNET =================================*/ + + theHybMagnetDefGeoType = 3; + + theHybMagnetDistToAxis = 40.; // cm + theHybMagnetDistToAxis1 = 125.; // cm + theHybMagnetDistToAxis2 = 185.; // cm + + theHybMagnetRingSize = 129.; // cm + + theHybMagnetCoilThickness = 8.; // cm + theHybMagnetCoilWidth = 10.; // cm + + /*===================== INNER TRACKING SYSTEM ======================*/ + + theItsDefGeoType = 3; // : 1 + + theItsNLayers = 5; + + theItsMinRadius = 5.0; // cm + theItsMaxRadius = 40.; // (60,TOR) cm + theItsMaxLength = 200.; // cm + + /*=========== TSTB (TOROIDAL TRACKING SYSTEM BARREL) ===============*/ + + theTsTBDefGeoType = 2; // TsTB + + theTsTBLen2 = 236.; // (510,TOR) cm + theTsTBSize2 = 85.4; // (160,HYB) cm + theTsTBWidth2 = 45.; // (95,HYB) cm + + theTsTBMakeOffset2 = kTRUE; + + /*========== TSTEC (TOROIDAL TRACKING SYSTEM ENDCAPS) =============*/ + + theTsTECDefGeoType = 3; // TsTEC + + theTsTECMinDist3 = 118.; // (0) cm + theTsTECLength3 = 53.6; // (200,HYB) cm + + theTsTECSize = 92.4; // (170,HYB) cm -> 85.4/Cos(22.5*DegToRad()) = 92.436293905 + theTsTECWidth = 82.4; // (160,HYB) cm + + /*===== ECALTB (TOROIDAL ELECTROMAGNETIC CALORIMETER BARREL) =======*/ + + theEcalTBDefGeoType = 2; + + theEcalTBBaseMaterial = "air"; + + theEcalTBLen2 = 403.2; // (510,TOR) cm + theEcalTBSize2 = 175.4; // (265,TOR) cm + theEcalTBWidth2 = 40.0; // (60,TOR) cm + + /*===== ECALTEC (TOROIDAL ELECTROMAGNETIC CALORIMETER ENDCAPS) =====*/ + + theEcalTECDefGeoType = 1; + + theEcalTECBaseMaterial = "air"; + + theEcalTECMinDist1 = 201.6; // (320,HYB) cm + + theEcalTECSize = 175.4; // (265,HYB) cm + theEcalTECWidth = 165.4; // (255,HYB) cm + theEcalTECThickness = 45.; // (60,HYB) cm + + /*============ RSTB (TOROIDAL RANGE SYSTEM BARREL) =================*/ + + theRsTBDefGeoType = 2; + + theRsTBLen2 = 493.2; // (510,TOR) cm + theRsTBSize2 = 314.4; // (340,TOR) cm + theRsTBWidth2 = 139.0; // (60,TOR) cm + + /*============ RSTEC (TOROIDAL RANGE SYSTEM ENDCAPS) ===============*/ + + theRsTECDefGeoType = 1; + + theRsTECMinDist1 = 246.6; // (400,HYB) cm + + theRsTECSize = 314.4; // (419,HYB) cm + theRsTECWidth = 304.4; // (409,HYB) cm + theRsTECThickness = 139.0; // (110.5,HYB) cm +} + //_____________________________________________________________________________ void SpdCommonGeoMapper::SetTorHybridGeoPars() { @@ -1051,16 +1230,10 @@ SpdDetector* SpdCommonGeoMapper::SearchForActive(Int_t id) const } //_____________________________________________________________________________ -void SpdCommonGeoMapper::UnsetMaterials(Bool_t precise, TString option) +void SpdCommonGeoMapper::UnsetMaterials(Bool_t precise, TString option, + Bool_t active, Bool_t passive) { - if (!thePassives.empty()) { - map <SpdPassiveModule*, module_info*>::iterator it = thePassives.begin(); - for ( ; it != thePassives.end(); it++) { - it->first->UnsetMaterials(precise); - } - } - - if (!theDetectors.empty()) { + if (active && !theDetectors.empty()) { SpdGeoMapper* mapper; map <SpdDetector*, module_info*>::iterator it = theDetectors.begin(); for ( ; it != theDetectors.end(); it++) { @@ -1068,6 +1241,17 @@ void SpdCommonGeoMapper::UnsetMaterials(Bool_t precise, TString option) mapper->UnsetMaterials(precise,option); } } + + if (passive && !thePassives.empty()) { + map <SpdPassiveModule*, module_info*>::iterator it = thePassives.begin(); + for ( ; it != thePassives.end(); it++) { + if (option == "air") it->first->UnsetMaterials("air"); + else { + if (precise) it->first->UnsetMaterials("vacuum2"); + else it->first->UnsetMaterials("vacuum"); + } + } + } } //_____________________________________________________________________________ diff --git a/common/SpdCommonGeoMapper.h b/common/SpdCommonGeoMapper.h index 35779a5f4c7d9a306432ca9d588f4cb57ea8309e..6daf7410a349eb656ca75035b3501643b12821a9 100644 --- a/common/SpdCommonGeoMapper.h +++ b/common/SpdCommonGeoMapper.h @@ -57,7 +57,7 @@ public: static Int_t GetItsDefGeoType() { return theItsDefGeoType; } static TString GetItsBaseMaterial() { return theItsBaseMaterial; } - static TString GetItsLadderMaterial() { return theItsLadderMaterial; } + static TString GetItsLadderMaterial() { return theItsLadderMaterial; } static TString GetItsSensorMaterial() { return theItsSensorMaterial; } static Int_t GetItsNLayers() { return theItsNLayers; } @@ -327,19 +327,21 @@ public: /*==================================================================*/ - void OpenGeometry(); + void OpenGeometry(TString media = "media.geo"); void DefineTorGeometrySet(Int_t type); void DefineSolGeometrySet(Int_t type); void DefineHybGeometrySet(Int_t type = 2); + void DefineQslGeometrySet(); void ConstructGeometry(); void AddPassive(SpdPassiveModule* module); void AddDetector(SpdDetector* detector); - void UnsetMaterials(Bool_t precise, TString option = "base"); - void SaveEmptyHits(Bool_t savehits = kTRUE); + void UnsetMaterials(Bool_t precise, TString option = "base", + Bool_t active = true, Bool_t passive = true); + void SaveEmptyHits(Bool_t savehits = true); void FillModulesMap(); @@ -359,6 +361,8 @@ public: SpdDetector** GetListOfDetectors(Int_t& nd); SpdPassiveModule** GetListOfPassives(Int_t& np); + TString GetActualMediaFileName() const; + struct module_info { module_info(): id_(kSpdUndefined){} diff --git a/common/SpdDetector.cxx b/common/SpdDetector.cxx index 3e05caaba26beb0690a27affe886106794fbfa50..519dfcc6bc5e3cc644d5292d018a6c83c18919e0 100644 --- a/common/SpdDetector.cxx +++ b/common/SpdDetector.cxx @@ -295,7 +295,7 @@ Bool_t SpdDetector::LoadParsFrom(SpdParSet* params) params->GetParameter("Detector/SaveDetIdOption",fSaveDetIdOption); CreateNodeIdTable(params); - + return kTRUE; } diff --git a/common/SpdDetector.h b/common/SpdDetector.h index c39a449bbe78b1e6c465351833822940805ae298..96d22afa7a0a6b050ef1a0a8881fb832372e7701 100644 --- a/common/SpdDetector.h +++ b/common/SpdDetector.h @@ -146,8 +146,8 @@ protected: /* Nodes Table */ - SpdNodesIdTable* fNodesIdTable; //!table [full node path,id] - Bool_t fNodesIdTableIsOwn; //!mark if NodesIdTable is own + SpdNodesIdTable* fNodesIdTable; //! table [full node path,id] + Bool_t fNodesIdTableIsOwn; //! mark if NodesIdTable is own ClassDef(SpdDetector,1) }; diff --git a/common/SpdGlobals.h b/common/SpdGlobals.h index ed3a112a0f665e7ba244d01116118bac59a43801..2674aeaf31d0e58e46d62b4bcf9e7ea468f21ef7 100644 --- a/common/SpdGlobals.h +++ b/common/SpdGlobals.h @@ -6,8 +6,8 @@ #include "FairVersion.h" #include "RVersion.h" -#define SPD_RELEASE 3.230 -#define SPD_RELEASE_DATE 28081900 +#define SPD_RELEASE 4.00 +#define SPD_RELEASE_DATE 080920 #define OLD_FAIRROOT_PRIMGEN_VERSION 0 diff --git a/common/SpdPassiveModule.cxx b/common/SpdPassiveModule.cxx index 395e1ed859d84a214d43c0e044184114072345f0..84be51d5b3ab6a40d74575a0c78b59baf7724e45 100644 --- a/common/SpdPassiveModule.cxx +++ b/common/SpdPassiveModule.cxx @@ -9,7 +9,8 @@ #include "SpdPassiveModule.h" #include "SpdCommonGeoMapper.h" -#include "SpdPassiveGeoPar.h" +#include "SpdParSetContFact.h" +#include "SpdPassiveGeoParSet.h" #include "FairGeoBuilder.h" #include "FairGeoMedia.h" @@ -24,7 +25,7 @@ ClassImp(SpdPassiveModule) //_____________________________________________________________________________ SpdPassiveModule::SpdPassiveModule():FairModule(),fGeoType(-1),fMasterVolume(0), -fModuleId(-1) +fModuleId(-1),fUnsetMedia("") { fName = ClassName(); fTitle = "SPD Passive Module"; @@ -34,7 +35,7 @@ fModuleId(-1) //_____________________________________________________________________________ SpdPassiveModule::SpdPassiveModule(const char* Name, const char* Prefix, Int_t ModId): -FairModule(Name,Prefix),fGeoType(-1),fMasterVolume(0),fModuleId(ModId) +FairModule(Name,Prefix),fGeoType(-1),fMasterVolume(0),fModuleId(ModId),fUnsetMedia("") { SpdCommonGeoMapper::Instance()->AddPassive(this); } @@ -49,9 +50,10 @@ SpdPassiveModule::~SpdPassiveModule() void SpdPassiveModule::Print(Option_t*) const { cout << "<SpdPassiveModule::Print>" << endl; - cout << " Geometry type: " << fGeoType << endl; - cout << " Name: " << fName << endl; - cout << " Id: " << fModuleId << endl; + cout << " Geometry type: " << fGeoType << endl; + cout << " Name: " << fName << endl; + cout << " Id: " << fModuleId << endl; + cout << " Unset material: " << fUnsetMedia << endl; } //_____________________________________________________________________________ @@ -70,7 +72,6 @@ TString SpdPassiveModule::FullName(TString name, Bool_t add_uscore) //_____________________________________________________________________________ TGeoMedium* SpdPassiveModule::FindMedium(TString& medname, TString default_med) { - TGeoMedium* med = 0; if (medname.IsWhitespace()) return 0; @@ -106,3 +107,30 @@ TGeoMedium* SpdPassiveModule::FindMedium(TString& medname, TString default_med) return FindMedium(medname,""); } +//_____________________________________________________________________________ +Bool_t SpdPassiveModule::FillParsIn(SpdPassiveGeoParSet* params) +{ + if (!params) return kFALSE; + + params->SetParameter(Form("%s/UnsetMedia",this->ClassName()),fUnsetMedia); + + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdPassiveModule::LoadParsFrom(SpdPassiveGeoParSet* params) +{ + if (!params) return kFALSE; + return kTRUE; +} + +//_____________________________________________________________________________________ +SpdPassiveGeoParSet* SpdPassiveModule::GetParameters() +{ + FairRun* run = FairRun::Instance(); + if (!run) return 0; + FairRuntimeDb* rtdb = run->GetRuntimeDb(); + if (!rtdb) return 0; + SpdPassiveGeoParSet* pars = (SpdPassiveGeoParSet*)(rtdb->getContainer("PassiveGeoParSet")); + return pars; +} diff --git a/common/SpdPassiveModule.h b/common/SpdPassiveModule.h index a94e67d361ba41e51bbc513ad5361fcf904f9e31..18a40a25bca2c0827c69cf24bf166b7d37de28fd 100644 --- a/common/SpdPassiveModule.h +++ b/common/SpdPassiveModule.h @@ -14,7 +14,7 @@ // // //////////////////////////////////////////////////////////////////////////////// -class SpdPassiveGeoPar; +class SpdPassiveGeoParSet; class SpdPassiveModule: public FairModule { @@ -32,8 +32,9 @@ public: virtual void SetGeometryType(Int_t/* type*/) {} - virtual void UnsetMaterials(Bool_t /*precise = kTRUE*/) {} - + virtual void UnsetMaterials(TString /*media*/) {} + virtual void ResetMaterials(/*set dafault materials*/) {} + /* ----- getters ------ */ virtual Bool_t IsGeometryLocked() const { return kFALSE; } @@ -46,18 +47,24 @@ public: const Char_t* GetPrefix() const { return fTitle.Data(); } - virtual void Print(Option_t*) const; + virtual void Print(Option_t*) const; + + virtual Bool_t FillParsIn(SpdPassiveGeoParSet* params); + virtual Bool_t LoadParsFrom(SpdPassiveGeoParSet* params); protected: - virtual TString FullName(TString name, Bool_t add_uscore = kFALSE); + SpdPassiveGeoParSet* GetParameters(); + virtual TString FullName(TString name, Bool_t add_uscore = kFALSE); virtual TGeoMedium* FindMedium(TString& medname, TString default_med); Int_t fGeoType; Int_t fModuleId; - TGeoVolume* fMasterVolume; + TGeoVolume* fMasterVolume; //! + TString fUnsetMedia; //! + ClassDef(SpdPassiveModule,1) }; diff --git a/common/SpdStack.cxx b/common/SpdStack.cxx index 6706b4b80e82505d1e245bd742a7d9a10695596f..9843179a1489fb448f79a0cec84ce435a8b963de 100644 --- a/common/SpdStack.cxx +++ b/common/SpdStack.cxx @@ -72,6 +72,8 @@ SpdStack::~SpdStack() //_____________________________________________________________________________________ void SpdStack::Reset() { + //cout << "<SpdStack::Reset>" << endl; + fIndex = 0; fCurrentTrack = -1; fNPrimaries = 0; @@ -80,9 +82,13 @@ void SpdStack::Reset() while (!fStack.empty() ) { fStack.pop(); } - fParticles->Clear(); - fTracks->Clear(); + Int_t nt = fTracks->GetEntriesFast(); + + fParticles->Delete(); + fTracks->Delete(); fPointsMap.clear(); + + //cout << "<SpdStack::Reset> " << nt << ", " << fTracks->GetEntriesFast() << endl; } //_____________________________________________________________________________________ @@ -215,7 +221,8 @@ Int_t SpdStack::GetCurrentParentTrackNumber() const TParticle* SpdStack::GetParticle(Int_t trackID) const { if (trackID < 0 || trackID >= fNParticles) { - Fatal("SpdStack::GetParticle", "Index out of range"); + //cout << trackID << "/" << fNParticles << endl; + Fatal("GetParticle", "Index out of range"); } return (TParticle*)fParticles->At(trackID); } @@ -287,7 +294,7 @@ void SpdStack::FillTrackArray() fStoreIter = fStoreMap.find(iPart); if (fStoreIter == fStoreMap.end()) { - Fatal("SpdStack::FillTrackArray","Particle not found in storage map."); + Fatal("FillTrackArray","Particle not found in storage map."); } Bool_t store = (*fStoreIter).second; @@ -344,7 +351,7 @@ void SpdStack::UpdateTrackIndex(TRefArray* detList) fIndexIter = fIndexMap.find(iMotherOld); if (fIndexIter == fIndexMap.end()) { - Fatal("SpdStack::UpdateTrackIndex", "Particle index not found in map"); + Fatal("UpdateTrackIndex", "Particle index not found in map"); } track->SetMotherId((*fIndexIter).second); @@ -377,7 +384,7 @@ void SpdStack::UpdateTrackIndex(TRefArray* detList) fIndexIter = fIndexMap.find(iTrack); if (fIndexIter == fIndexMap.end()) { - Fatal("SpdStack::UpdateTrackIndex", "Particle index not found in map"); + Fatal("UpdateTrackIndex", "Particle index not found in map"); } point->SetTrackID((*fIndexIter).second); diff --git a/common/geometry/SpdGeoMapper.cxx b/common/geometry/SpdGeoMapper.cxx index 7ffb994677ee9789c60191412b4b9a02abcda263..347ff6edd7a467e3cf1138eac2f0816b7bf6e5e5 100644 --- a/common/geometry/SpdGeoMapper.cxx +++ b/common/geometry/SpdGeoMapper.cxx @@ -279,6 +279,12 @@ Bool_t SpdGeoMapper::CheckGeoType(Int_t geotype, TString parname) void SpdGeoMapper::FillParametersIn(SpdParSet* params) { if (!params || !fParams) return; + + TString pname = Form("%sUnsetMedia",fGeoPrefix.Data()); + SpdParameter* par = GetParameter(pname); + if (par) *par = fUnsetMedia; + else fParams->Add(new SpdParameter(pname,fUnsetMedia)); + params->SetMapperParameters(fParams); } @@ -289,6 +295,16 @@ void SpdGeoMapper::LoadParametersFrom(SpdParSet* params) params->FillMapperParameters(fParams); } +//_____________________________________________________________________________ +void SpdGeoMapper::ResetMediaFromParams() +{ + if (!fParams) return; + TString pname = Form("%sUnsetMedia",fGeoPrefix.Data()); + SpdParameter* par = GetParameter(pname); + if (!par) return; + fUnsetMedia = par->Value(); +} + //_____________________________________________________________________________ void SpdGeoMapper::Print(Option_t*) const { diff --git a/common/geometry/SpdGeoMapper.h b/common/geometry/SpdGeoMapper.h index 1bc9f85de9647c4463fb595c361c4fa2c7569eab..634776b0d8ceca5f23ff3332dc6a6b167b172610 100644 --- a/common/geometry/SpdGeoMapper.h +++ b/common/geometry/SpdGeoMapper.h @@ -48,7 +48,8 @@ public: virtual void UnlockGeometry() { fLockGeometry = kFALSE; } virtual void UnsetMaterials(Bool_t /*precise = kTRUE*/, TString /*option = "base"*/) {} - + virtual void UnsetMaterials(TString option = "base") { UnsetMaterials(0,option); } + /* ------ getters ------ */ Int_t GetGeoType() const { return fGeoType; } @@ -86,6 +87,8 @@ public: virtual void FillParametersIn(SpdParSet* params); virtual void LoadParametersFrom(SpdParSet* params); + virtual void ResetMediaFromParams(); + virtual void Print(Option_t*) const; virtual void PrintVolPars(Int_t nvolumes = 0) const; diff --git a/common/geometry/SpdGeoTable.cxx b/common/geometry/SpdGeoTable.cxx index 2a40b6a6e944babff8b6d20394898f9382e5f944..d9f25502bc80ee39e498e0f1d022cfd1ba57b97d 100644 --- a/common/geometry/SpdGeoTable.cxx +++ b/common/geometry/SpdGeoTable.cxx @@ -244,6 +244,7 @@ Int_t SpdGeoTable::AddTableRec(Int_t geolevel, TString volname, TString motherna rec->fFirstNodeTableNum = rec1->GetLastNodeTableNum()+1; level.push_back(fTable->GetLast()); } + return 0; } //_____________________________________________________________________________ @@ -352,13 +353,13 @@ TString SpdGeoTable::GetNodeGeoPath(Long_t detTID) n = Long_t((detTID - sumn)/fTableDims[i]); - if (n < 1) { - fPathLevel = 0; + if (n < 1) { + fPathLevel = 0; return "MASTER"; - } - + } + sumn += n*fTableDims[i]; - glob_num = n; + glob_num = n; it = std::lower_bound(fTableGlobalNums[i].begin(),fTableGlobalNums[i].end(),glob_num); n = it - fTableGlobalNums[i].begin(); @@ -388,14 +389,17 @@ TString SpdGeoTable::GetNodeGeoPath(Long_t detTID) fPath[i+1].second = loc_num; fPathLevel++; - xrec = rec; - + xrec = rec; + //rec->Prn(rec->GetLocalNodeNum(glob_num),glob_num,loc_num); } + fPathLevel++; + TString geopath = GetCurrentPathString(); - //cout << "<GetNodeGeoPath> TID: " << detTID << " PATH: " << geopath << endl; + //cout << "-I- <SpdGeoTable::GetNodeGeoPath> TID: " << detTID << " PATH: " << geopath << " Level: " << fPathLevel << endl; + //cout << "-I- <SpdGeoTable::GetNodeGeoPath> TID: " << GetNodeTableNum(geopath) << endl; return geopath; } diff --git a/common/geometry/SpdGeoVVolume.cxx b/common/geometry/SpdGeoVVolume.cxx index 040781b25baad8a545d8fb17a332d303b1093a00..7640627fa3da07ddd572d75633a5d43114596f98 100644 --- a/common/geometry/SpdGeoVVolume.cxx +++ b/common/geometry/SpdGeoVVolume.cxx @@ -181,12 +181,12 @@ Bool_t SpdGeoVVolumeBox2D::GetCellPos(Int_t id, Double_t& x, Double_t& y, Double { switch (fAxes) { - case 0 : { GetCellPos(id,x,y); z = 0; return kTRUE; } - case 1 : { GetCellPos(id,z,x); y = 0; return kTRUE; } - case 2 : { GetCellPos(id,y,z); x = 0; return kTRUE; } - case 3 : { GetCellPos(id,y,x); z = 0; return kTRUE; } - case 4 : { GetCellPos(id,z,x); y = 0; return kTRUE; } - case 5 : { GetCellPos(id,z,y); x = 0; return kTRUE; } + case 0 : { z = 0; return GetCellPos(id,x,y); } + case 1 : { y = 0; return GetCellPos(id,z,x); } + case 2 : { x = 0; return GetCellPos(id,y,z); } + case 3 : { z = 0; return GetCellPos(id,y,x); } + case 4 : { y = 0; return GetCellPos(id,z,x); } + case 5 : { x = 0; return GetCellPos(id,z,y); } } GetCellPos(id,x,y); @@ -195,6 +195,44 @@ Bool_t SpdGeoVVolumeBox2D::GetCellPos(Int_t id, Double_t& x, Double_t& y, Double return kFALSE; } +//_____________________________________________________________________________ +Bool_t SpdGeoVVolumeBox2D::GetCellPos(Int_t id, Double_t* pos) const +{ + switch (fAxes) + { + case 0 : { pos[2] = 0; return GetCellPos(id,pos[0],pos[1]); } + case 1 : { pos[1] = 0; return GetCellPos(id,pos[2],pos[0]); } + case 2 : { pos[0] = 0; return GetCellPos(id,pos[1],pos[2]); } + case 3 : { pos[2] = 0; return GetCellPos(id,pos[1],pos[0]); } + case 4 : { pos[1] = 0; return GetCellPos(id,pos[2],pos[0]); } + case 5 : { pos[0] = 0; return GetCellPos(id,pos[2],pos[1]); } + } + + GetCellPos(id,pos[0],pos[1]); + pos[2] = 0; + + return kFALSE; +} + +//_____________________________________________________________________________ +Bool_t SpdGeoVVolumeBox2D::GetPos(Double_t id1, Double_t id2, Double_t* pos) const +{ + switch (fAxes) + { + case 0 : { pos[2] = 0; return GetPos(id1,id2,pos[0],pos[1]); } + case 1 : { pos[1] = 0; return GetPos(id1,id2,pos[2],pos[0]); } + case 2 : { pos[0] = 0; return GetPos(id1,id2,pos[1],pos[2]); } + case 3 : { pos[2] = 0; return GetPos(id1,id2,pos[1],pos[0]); } + case 4 : { pos[1] = 0; return GetPos(id1,id2,pos[2],pos[0]); } + case 5 : { pos[0] = 0; return GetPos(id1,id2,pos[2],pos[1]); } + } + + GetPos(id1,id2,pos[0],pos[1]); + pos[2] = 0; + + return kFALSE; +} + //_____________________________________________________________________________ void SpdGeoVVolumeBox2D::PrintVolume() const { @@ -242,6 +280,22 @@ Bool_t SpdGeoVVolumeBox2D::GetCellPos(Int_t id, Double_t& x1, Double_t& x2) cons return kTRUE; } +//_____________________________________________________________________________ +Bool_t SpdGeoVVolumeBox2D::GetPos(Double_t id1, Double_t id2, Double_t& x1, Double_t& x2) const +{ + x1 = 0; x2 = 0; + + if (id1 < 0 || !(id1 < Double_t(fN1))) return kFALSE; + if (id2 < 0 || !(id2 < Double_t(fN2))) return kFALSE; + + x1 = -0.5*fL1 + (id1 + 0.5)*fD1; + x2 = -0.5*fL2 + (id2 + 0.5)*fD2; + + //cout << "<SpdGeoVVolumeBox2D::GetPos> " << x1 << " " << x2 << endl; + + return kTRUE; +} + //_____________________________________________________________________________ const Char_t* SpdGeoVVolumeBox2D::GetAxes() const { diff --git a/common/geometry/SpdGeoVVolume.h b/common/geometry/SpdGeoVVolume.h index 5ca5a4690d06a520b4ccaca0b9d2babc6f127cb6..12e7136fe12d3ac97f0e157673ce9ee6e5ffbbbf 100644 --- a/common/geometry/SpdGeoVVolume.h +++ b/common/geometry/SpdGeoVVolume.h @@ -71,10 +71,14 @@ public: virtual Int_t GetCellId(Double_t x, Double_t y, Double_t z) const; virtual Bool_t GetCellPos(Int_t id, Double_t& x, Double_t& y, Double_t& z) const; + virtual Bool_t GetCellPos(Int_t id, Double_t* pos /*3-dim array*/) const; + virtual Bool_t GetPos(Double_t id1, Double_t id2, Double_t* pos /*3-dim array*/) const; Int_t GetCellId(Double_t x1, Double_t x2) const; Bool_t GetCellPos(Int_t id, Double_t& x1, Double_t& x2) const; - + + Bool_t GetPos(Double_t id1, Double_t id2, Double_t& x1, Double_t& x2) const; + inline Int_t CellId(Int_t id1, Int_t id2) const { return fN2 * id1 + id2;} inline void CellId(Int_t id, Int_t& id1, Int_t& id2) const { id1 = id/fN2; id2 = id%fN2; } diff --git a/doc/INSTALL_SPECIAL b/doc/INSTALL_SPECIAL deleted file mode 100644 index 9d5bb3bdc614110f8bf44b2ba887a21da3a0c704..0000000000000000000000000000000000000000 --- a/doc/INSTALL_SPECIAL +++ /dev/null @@ -1,121 +0,0 @@ - -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ --------------------------------------------------------------- + -+ | !!!!!!!!!!!!!!!!!! INSTALL (LXPUB) --- !!!!!!!!!!!!!!!!!!!!! | + -+ --------------------------------------------------------------- + -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -****************** -*** SPDROOT *** -****************** - -cd spdroot/ - -. SetEnv_lxpub.sh - -cat SetEnv_lxpub.sh ------------------------------------------- >>>>> - -#!/bin/bash - -export CXX=/opt/rh/devtoolset-1.1/root/usr/bin/g++ -export SIMPATH=/scrc/u/fair_install/fairsoft -export FAIRROOTPATH=/scrc/u/fair_install/fairsoft/FairRoot - -source build/config.sh - ------------------------------------------- <<<<< - -(delete build folder: rm -rf build/) - -mkdir build -cd build -cmake -DUSE_DIFFERENT_COMPILER=TRUE .. -make - -cd .. - -. build/config.sh - - -cd macro -root -l -root[0] .x run_sim.C - -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ --------------------------------------------------------------- + -+ | !!!!!!!!!!!!!!!!!! INSTALL (AFS) --- !!!!!!!!!!!!!!!!!!!!!!! | + -+ --------------------------------------------------------------- + -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -[I.] - -****************** -*** FAIRROOT *** -****************** - -copy FairRoot ti AFS-dirctory - -(decompress *tar.gz : tar xvfz FairRoot.tar.gz) - -export CXX=/usr/bin/g++ -export SIMPATH=/afs/.jinr.ru/fairsoft/may16p1_r5 - -#export CC=/opt/rh/devtoolset-4/root/usr/bin/gcc -#export CXX=/opt/rh/devtoolset-4/root/usr/bin/g++ - -#export SIMPATH=/afs/.jinr.ru/fairsoft/may16p1_r6 - -#export SIMPATH=/afs/.jinr.ru/compass/common/FSinstall - - -cd FairRoot - -1. Comment line in CMakeLists.txt: - - add_subdirectory (example) -> #add_subdirectory (example) - -2. mkdir build - cd build - cmake -DCMAKE_INSTALL_PREFIX="/afs/jinr.ru/user/a/avt/FairRoot/install/" .. - make - make install - -[II.] - -****************** -*** SPDROOT *** -****************** - -cd spdroot/ - -. SetEnv_afs.sh - -cat SetEnv_afs.sh ------------------------------------------- >>>>> - -#!/bin/bash - -export CXX=/usr/bin/g++ -export SIMPATH=/afs/jinr.ru/fairsoft/ -export FAIRROOTPATH=/afs/jinr.ru/user/a/avt/FairRoot/install - -source build/config.sh - ------------------------------------------- <<<<< - -(delete build folder: rm -rf build/) - -mkdir build -cd build -cmake .. -make - -cd .. - -. build/config.sh - -cd macro -root -l -root[0] .x run_sim.C - diff --git a/doc/ReleaseNotes.txt b/doc/ReleaseNotes.txt new file mode 100644 index 0000000000000000000000000000000000000000..9f1837d3a513afc05346580447b69bc5ea9cc778 --- /dev/null +++ b/doc/ReleaseNotes.txt @@ -0,0 +1,10 @@ +4.0.0 08.09.2020 +* Current В«CDR-likeВ» SPD geometry +* Full set of detectors except TOF, ZDC, BBC +* New quasi-solenoid magnetic field +* Very flexible and easy to change +* ECAL barrel and endcaps — geometry and simulation +* RS barrel and endcaps — geometry and simulation +* Secondary vertex reconstruction +* Event data model refined, but not final yet +* New building and installation prcedure (make install) diff --git a/doc/SPD_en.pdf b/doc/SPD_en.pdf deleted file mode 100644 index e6373fb34eb1e9c2935410ee5a98ad9f852969ca..0000000000000000000000000000000000000000 Binary files a/doc/SPD_en.pdf and /dev/null differ diff --git a/doc/SPD_ru.pdf b/doc/SPD_ru.pdf deleted file mode 100644 index 48e5e98788678854c5715fcb2af54aaa0ff51ba3..0000000000000000000000000000000000000000 Binary files a/doc/SPD_ru.pdf and /dev/null differ diff --git a/doc/SetEnv_afs.sh b/doc/SetEnv_afs.sh deleted file mode 100644 index 1a0d8f1ebcef4442d97ff355e3375b4152105fdc..0000000000000000000000000000000000000000 --- a/doc/SetEnv_afs.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -export CXX=/usr/bin/g++ -#export SIMPATH=/afs/.jinr.ru/fairsoft/may16p1_r6 -export SIMPATH=/afs/.jinr.ru/fairsoft/may16p1_r5 -export FAIRROOTPATH=/afs/jinr.ru/user/a/avt/FairRoot/install - -source build/config.sh \ No newline at end of file diff --git a/doc/SetEnv_lxpub.sh b/doc/SetEnv_lxpub.sh deleted file mode 100644 index f27dd4640a3f7bae1244b14c94dd126d8e628a2b..0000000000000000000000000000000000000000 --- a/doc/SetEnv_lxpub.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -export CXX=/opt/rh/devtoolset-1.1/root/usr/bin/g++ -export SIMPATH=/scrc/u/fair_install/fairsoft -export FAIRROOTPATH=/scrc/u/fair_install/fairsoft/FairRoot - -source build/config.sh \ No newline at end of file diff --git a/doc/pics/B_qsl.png b/doc/pics/B_qsl.png new file mode 100644 index 0000000000000000000000000000000000000000..6e8b0eeb3f1dd15c796d81a2ccbacece1b00df15 Binary files /dev/null and b/doc/pics/B_qsl.png differ diff --git a/doc/pics/B_qsl_old.png b/doc/pics/B_qsl_old.png new file mode 100644 index 0000000000000000000000000000000000000000..ab2af1f6a1c1e8092da5c643b9c2989a83ed9b6c Binary files /dev/null and b/doc/pics/B_qsl_old.png differ diff --git a/doc/pics/Its_top.png b/doc/pics/Its_top.png deleted file mode 100644 index 704602151a7e5cf5c01a14d7c38d4e461bbd4558..0000000000000000000000000000000000000000 Binary files a/doc/pics/Its_top.png and /dev/null differ diff --git a/doc/pics/RsBarrel.png b/doc/pics/RsBarrel.png new file mode 100644 index 0000000000000000000000000000000000000000..05cf4bd58cab6a847c0ab3544aefa488a2cc92d0 Binary files /dev/null and b/doc/pics/RsBarrel.png differ diff --git a/ecals/CMakeLists.txt b/ecals/CMakeLists.txt index 1be1dc42bfa07259521685088d3a35bffc93485a..119987f195329facdbdec0c66e55ab9b6e9d0651 100644 --- a/ecals/CMakeLists.txt +++ b/ecals/CMakeLists.txt @@ -50,6 +50,23 @@ ecps/SpdEcalSECHitProducer.cxx ) +set(HEADERS +barrel/SpdEcalSBGeoPar.h +barrel/SpdEcalSB.h +barrel/SpdEcalSBHit.h +barrel/SpdEcalSBHitProducer.h +barrel/SpdEcalSBParSet.h +barrel/SpdEcalSBPoint.h +ecps/SpdEcalSECGeoPar.h +ecps/SpdEcalSEC.h +ecps/SpdEcalSECHit.h +ecps/SpdEcalSECHitProducer.h +ecps/SpdEcalSECParSet.h +ecps/SpdEcalSECPoint.h +SpdEcalSContFact.h +SpdEcalSPointAn.h +) + Set(LINKDEF SpdEcalsLinkDef.h) Set(LIBRARY_NAME SpdEcals) Set(DEPENDENCIES Base SpdData SpdCommon SpdField) diff --git a/ecalt/CMakeLists.txt b/ecalt/CMakeLists.txt index a2799993e0df0ec09a6970997df8c4084ddfaeb3..7482c11eab6bc3748ce638eb97dc5b41760b5919 100644 --- a/ecalt/CMakeLists.txt +++ b/ecalt/CMakeLists.txt @@ -37,19 +37,43 @@ SpdEcalTContFact.cxx SpdEcalTPointAn.cxx barrel/SpdEcalTB.cxx +barrel/SpdEcalTB2.cxx barrel/SpdEcalTBParSet.cxx barrel/SpdEcalTBPoint.cxx +barrel/SpdEcalTB2Point.cxx barrel/SpdEcalTBHit.cxx barrel/SpdEcalTBHitProducer.cxx ecps/SpdEcalTEC.cxx -ecps/SpdEcalTECParSet.cxx +ecps/SpdEcalTEC2.cxx ecps/SpdEcalTECPoint.cxx +ecps/SpdEcalTEC2Point.cxx +ecps/SpdEcalTECParSet.cxx ecps/SpdEcalTECHit.cxx ecps/SpdEcalTECHitProducer.cxx ) +set(HEADERS +barrel/SpdEcalTB2.h +barrel/SpdEcalTB2Point.h +barrel/SpdEcalTB.h +barrel/SpdEcalTBHit.h +barrel/SpdEcalTBHitProducer.h +barrel/SpdEcalTBParSet.h +barrel/SpdEcalTBPoint.h +ecps/SpdEcalTEC2.h +ecps/SpdEcalTEC2Point.h +#ecps/SpdEcalTECGeoPar.h +ecps/SpdEcalTEC.h +ecps/SpdEcalTECHit.h +ecps/SpdEcalTECHitProducer.h +ecps/SpdEcalTECParSet.h +ecps/SpdEcalTECPoint.h +SpdEcalTContFact.h +SpdEcalTPointAn.h +) + Set(LINKDEF SpdEcaltLinkDef.h) Set(LIBRARY_NAME SpdEcalt) Set(DEPENDENCIES Base SpdData SpdCommon SpdGeometry SpdField) diff --git a/ecalt/SpdEcaltLinkDef.h b/ecalt/SpdEcaltLinkDef.h index 9080fd887760116635a9b8d6221dc58dbd21dde3..2a1f6073d8b8c909e0f9685ac4a515d314a57e2f 100644 --- a/ecalt/SpdEcaltLinkDef.h +++ b/ecalt/SpdEcaltLinkDef.h @@ -10,13 +10,17 @@ #pragma link C++ class SpdEcalTBParSet+; #pragma link C++ class SpdEcalTB+; +#pragma link C++ class SpdEcalTB2+; #pragma link C++ class SpdEcalTBPoint+; +#pragma link C++ class SpdEcalTB2Point+; #pragma link C++ class SpdEcalTBHit+; #pragma link C++ class SpdEcalTBHitProducer+; #pragma link C++ class SpdEcalTECParSet+; #pragma link C++ class SpdEcalTEC+; +#pragma link C++ class SpdEcalTEC2+; #pragma link C++ class SpdEcalTECPoint+; +#pragma link C++ class SpdEcalTEC2Point+; #pragma link C++ class SpdEcalTECHit+; #pragma link C++ class SpdEcalTECHitProducer+; diff --git a/ecalt/barrel/SpdEcalTB2.cxx b/ecalt/barrel/SpdEcalTB2.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a94ac56e776f338174c4252fae22de9866dd78cb --- /dev/null +++ b/ecalt/barrel/SpdEcalTB2.cxx @@ -0,0 +1,1326 @@ +// $Id$ +// Author: andre/artur 2020/07/31 + +#include "SpdEcalTB2.h" + +#include "FairVolume.h" +#include "FairGeoVolume.h" +#include "FairGeoNode.h" +#include "FairRootManager.h" +#include "FairGeoLoader.h" +#include "FairGeoInterface.h" +#include "FairGeoLoader.h" +#include "FairGeoBuilder.h" +#include "FairGeoMedia.h" +#include "FairRun.h" +#include "FairRunSim.h" +#include "FairRuntimeDb.h" + +#include "TRefArray.h" +#include "TClonesArray.h" +#include "TParticle.h" +#include "TVirtualMC.h" +#include "TGeoManager.h" +#include "TGeoBBox.h" +#include "TGeoPgon.h" +#include "TGeoCompositeShape.h" +#include "TGeoTube.h" +#include "TGeoArb8.h" +#include "TGeoMaterial.h" +#include "TGeoMedium.h" +#include "TMatrixD.h" + +#include "SpdEcalTB2.h" +#include "SpdEcalTB2Point.h" +#include "SpdEcalTB2GeoMapper.h" +#include "SpdCommonGeoMapper.h" +#include "SpdDetectorList.h" +#include "SpdStack.h" +#include "SpdParSet.h" +#include "SpdGeoFactory.h" + +#include <map> +#include <iostream> +#include <vector> +#include <tuple> + +using namespace std; + +using std::cout; +using std::endl; + +ClassImp(SpdEcalTB2) + +//_____________________________________________________________________________________ +SpdEcalTB2::SpdEcalTB2(): + + SpdDetector("Ecal barrel (tor)", kSpdEcalTB, kTRUE), + fTrackID(-1), + fDetID(-1),fBasketID(-1),fModuleZID(-1), fModulePhiID(-1), fCellID(-1), fLayerID(-1), fMatID(""), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1.), + fPointCollection(0), + fEnableWritingPointsScint(kTRUE), + fEnableWritingPointsAll(kFALSE), + fBasket(0), + fModule(0) +{ + SetParametersType("EcalTBParSet"); + + fNDataOut = 1; + fOutDataPointObject = "SpdEcalTB2Point"; + fUniqueModules.clear(); + +} + +//_____________________________________________________________________________________ +SpdEcalTB2::SpdEcalTB2(const char* name, Bool_t active): + + SpdDetector(name, kSpdEcalTB, active), + fTrackID(-1), + fDetID(-1),fBasketID(-1),fModuleZID(-1), fModulePhiID(-1), fCellID(-1), fLayerID(-1), fMatID(""), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1.), + fPointCollection(0), + fEnableWritingPointsScint(kTRUE), + fEnableWritingPointsAll(kFALSE), + fBasket(0), + fModule(0) +{ + SetParametersType("EcalTBParSet"); + + fNDataOut = 1; + fOutDataPointObject = "SpdEcalTB2Point"; + fUniqueModules.clear(); +} + +//_____________________________________________________________________________________ +SpdEcalTB2::~SpdEcalTB2() +{ + if (fPointCollection) { + fPointCollection->Delete(); + delete fPointCollection; + fPointCollection = 0; + } +} + +//_____________________________________________________________________________________ +void SpdEcalTB2::Initialize() +{ + cout << "\n*******************************************************************************" << endl; + cout << "************************* SpdEcalTB2::Initialize ******************************" << endl; + cout << "*******************************************************************************\n" << endl; + + // data collections + fPointCollection = new TClonesArray(fOutDataPointObject); + + // Initialize cell and fill parameters + SpdDetector::Initialize(); + + // SpdParSet* pars = GetParameters(); + // if (pars) pars->printParams(); +} + +//_____________________________________________________________________________________ +void SpdEcalTB2::Reset() +{ + fPointCollection->Clear(); +} + +//_____________________________________________________________________________________ +void SpdEcalTB2::Register() +{ + if (!fGeoMapper) return; + + if (fEnableWritingPointsScint) { + FairRootManager::Instance()->Register(fOutDataPointObject,"SpdEcalTB2", + fPointCollection, kTRUE); + } +} + +//_____________________________________________________________________________________ +Bool_t SpdEcalTB2::ProcessHits(FairVolume* vol) +{ + //cout << "<SpdEcalTB2::ProcessHits> " << endl; + + TString nodepath = gMC->CurrentVolPath(); + + //Set parameters at entrance of volume. Reset ELoss. + if (gMC->IsTrackEntering()) { + //cout << "track entering" << endl; + fELoss = 0.; + fTime = gMC->TrackTime() * 1.e9; // ns -> s + fLength = gMC->TrackLength(); + gMC->TrackPosition(fPos); + gMC->TrackMomentum(fMom); + } + + // Sum energy loss for all steps in the active volume + fELoss += gMC->Edep(); + + // Create SpdEcalTB2Point at exit of active volume + if ( gMC->IsTrackExiting() || + gMC->IsTrackStop() || + gMC->IsTrackDisappeared() ) + { + + if (!fSaveEmptyHits && fELoss == 0.) { return kFALSE; } + + fTrackID = gMC->GetStack()->GetCurrentTrackNumber(); + + fNodePath = gMC->CurrentVolPath(); + SpdGeopathParser parser; + parser.ParsePath(fNodePath); + + fDetID = kSpdEcalTB; + fBasketID = parser.Num(2, true); + + if (parser.VNum(3,true) == 0) { //only one unique module: fixed cell size + int rawModuleID = parser.Num(3, true); + fModuleZID = int(round(double(rawModuleID)/100)); + fModulePhiID = rawModuleID - fModuleZID*100; + } + else { //several unique modules + fModuleZID = parser.Num(3, true) / 100; + if (parser.Num(3,true) % 100 == 1) { + fModulePhiID = -parser.VNum(3, true); + } + else { + fModulePhiID = parser.VNum(3, true); + } + } + + fCellID = parser.Num(4, true); + fLayerID = parser.Num(5, true); + fMatID = parser.Name(5, true); + + //cout << " <<< BARREL >>> " << fMatID << " " << gMC->CurrentVolPath() << endl; + + assert(fMatID == "EcalBLeadCell" || fMatID == "EcalBScintCell"); + + if (fEnableWritingPointsAll) { + AddHit(); + } + else if (fEnableWritingPointsScint && fMatID == "EcalBScintCell") { + AddHit(); + } + + SpdStack* stack = (SpdStack*)gMC->GetStack(); + stack->AddPoint(kSpdEcalTB); + } + + return kTRUE; +} + +//_____________________________________________________________________________________ +void SpdEcalTB2::AddHit() +{ + static Bool_t addhit = (fOutDataPointObject == "SpdEcalTB2Point") ? kTRUE : kFALSE; + + if (!addhit) return; + + TClonesArray& clref = *fPointCollection; + Int_t size = clref.GetEntriesFast(); + + //cout << "SpdEcalTB2::AddHit: Adding hit: " << fTrackID << + // fPos.X() << " " << fPos.Y() << " " << fPos.Z() << " " << + // fMom.Px() << " " << fMom.Py() << " " << fMom.Pz() << " " << + // fTime << " " << fLength << " " << fELoss << " path = " << fNodePath <<"" << endl; + + new(clref[size]) SpdEcalTB2Point(fTrackID,fDetID,fBasketID,fModuleZID, fModulePhiID, fCellID, fLayerID, fMatID, + TVector3(fPos.X(),fPos.Y(),fPos.Z()), + TVector3(fMom.Px(),fMom.Py(),fMom.Pz()), + fTime, fLength, fELoss, fNodePath); +} + +//_____________________________________________________________________________________ +void SpdEcalTB2::EndOfEvent() +{ + Reset(); +} + +//_____________________________________________________________________________________ +void SpdEcalTB2::FinishRun() +{ + //SpdDetector::FinishRun(); + FillNodesTableIn(GetParameters()); +} + +//_____________________________________________________________________________________ +void SpdEcalTB2::ConstructGeometry() +{ + fMasterVolume = SpdCommonGeoMapper::Instance()->GetMasterVolume(); + + if (!fMasterVolume) { + cout << "-E- <SpdIts::ConstructGeometry> No MASTER volume " << endl; + return; + } + + if (!GetMapper()) return; + + if (!fGeoMapper->InitGeometry()) return; + + //fGeoMapper->Print(""); + + Int_t geo_type = fGeoMapper->GetGeoType(); + + ConstructGeometry_1(); + + fGeoMapper->LockGeometry(); + + cout << "\n*******************************************************************************" << endl; + cout << "********************** SpdEcalTB2::ConstructGeometry **************************" << endl; + cout << "********************** GEOMETRY TYPE: " << geo_type + << " ***************************************" << endl; + cout << "*******************************************************************************\n" << endl; +} + +//________________________________________________________________________________ +void SpdEcalTB2::ConstructGeometry_1() +{ + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + Bool_t forceCellSize = mapper->IsForceCellSize(); + + BuildBasket(); + + if (forceCellSize) { + fModule = BuildModule(); + fUniqueModules.push_back(fModule); + FillBasketFixedCells(fBasket,fModule); + } + else { + FillBasketTightly(fBasket); + } + + BuildBarrel(); +} + +//________________________________________________________________________________ +void SpdEcalTB2::FillBasketTightly(TGeoVolume* basketVolume) +{ + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + Int_t nSectors = mapper->GetNSectors(); + Double_t basketZSize = ((TGeoArb8*)basketVolume->GetShape())->GetDz()*2; + Double_t* basketVertices = ((TGeoArb8*)basketVolume->GetShape())->GetVertices(); + + assert(basketVertices[0] > basketVertices[2]); + assert(basketVertices[0] == -basketVertices[2]); + + Double_t basketPhiInnerSize = basketVertices[0] - basketVertices[2]; + Double_t doubleAngleBasket = 360./nSectors; + Double_t layerInnerSizeTheta = mapper->GetLayerInnerSizeTheta(); + Double_t layerInnerSizePhi = mapper->GetLayerInnerSizePhi(); + Double_t cellClearance = mapper->GetCellClearance(); + Double_t moduleClearance = mapper->GetModuleClearance(); + + Int_t nCellsTheta = int(basketZSize/(2*layerInnerSizeTheta + moduleClearance)); + Double_t moduleInnerSizeTheta = (basketZSize - nCellsTheta*moduleClearance)/nCellsTheta; + Int_t nCellsPhi = 2*int((basketPhiInnerSize/2)/(2*layerInnerSizePhi + moduleClearance)); + + cout << "-I- <SpdEcalTB2::FillBasketTightly> : the Z size of ECAL barrel modules is set to " + << (moduleInnerSizeTheta - cellClearance)/2 << " cm" << endl; + + vector<TGeoCombiTrans*> vectorTrans; + + for (int iphi = 0; iphi < nCellsPhi/2; ++iphi) { //stack to x+ + Double_t angleModuleCenter = iphi*(doubleAngleBasket/2)/(nCellsPhi/2); + Double_t angleModulePeriph = (iphi+1)*(doubleAngleBasket/2)/(nCellsPhi/2); + pair<TGeoCombiTrans*, TGeoVolume*> res = StackModuleInSector(basketVolume, angleModuleCenter, angleModulePeriph, moduleInnerSizeTheta); + vectorTrans.push_back(res.first); + fUniqueModules.push_back(res.second); + } + + for (int iv = 0; iv < fUniqueModules.size(); ++iv) { + fUniqueModules[iv]->SetName(("Module"+to_string(iv+1)).c_str()); + BuildModule(fUniqueModules[iv]); + } + + fModule = fUniqueModules[0]; + + for (int iv = 0; iv < vectorTrans.size(); ++iv) { + Double_t currZ = -basketZSize + moduleClearance/2 + moduleInnerSizeTheta/2; + for (int iz = 0; iz < nCellsTheta; ++iz) { + TGeoCombiTrans* currTrans = new TGeoCombiTrans(*(vectorTrans[iv])); + currTrans->SetDz(currZ); + TGeoCombiTrans* currTransMirror = (TGeoCombiTrans*)currTrans->MakeClone(); + currTransMirror->ReflectX(true); + basketVolume->AddNode(fUniqueModules[iv], (iz+1)*100, currTrans); + basketVolume->AddNode(fUniqueModules[iv], (iz+1)*100+1, currTransMirror); + currZ += moduleClearance + moduleInnerSizeTheta; + } + } +} + +//________________________________________________________________________________ +pair<TGeoCombiTrans*, TGeoVolume*> SpdEcalTB2::StackModuleInSector(TGeoVolume* basketVolume, + Double_t angleModuleCenter, Double_t angleModulePeriph, Double_t moduleInnerSizeTheta) +{ + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) Fatal("SpdEcalTB2::StackModuleInSector", "no mapper"); + + Int_t nLayers = mapper->GetNLayers(); + Double_t layer1SizeZ = mapper->GetLayer1SizeZ(); + Double_t layer2SizeZ = mapper->GetLayer2SizeZ(); + Double_t totalZSize = (layer1SizeZ + layer2SizeZ)*nLayers; + TString baseMedium = mapper->GetBaseMedium(); + TGeoMedium* Air = FindMedium(baseMedium, ""); + Double_t cellClearance = mapper->GetCellClearance(); + Double_t moduleClearance = mapper->GetModuleClearance(); + Bool_t trimModuleLength = mapper->IsTrimModuleLength(); + + Double_t basketZSize = ((TGeoArb8*)basketVolume->GetShape())->GetDz()*2; + Double_t* basketVertices = ((TGeoArb8*)basketVolume->GetShape())->GetVertices(); + assert(basketVertices[0] > basketVertices[2]); + assert(basketVertices[0] == -basketVertices[2]); + Double_t basketPhiInnerSize = basketVertices[0] - basketVertices[2]; + assert(basketVertices[5] > basketVertices[3]); + Double_t basketHeight = basketVertices[5] - basketVertices[3]; + assert(basketVertices[6] > basketVertices[4]); + Double_t basketPhiOuterSize = basketVertices[6] - basketVertices[4]; + Double_t yCoordBasketBottom = basketVertices[1]; + + Double_t yRayStart = yCoordBasketBottom - ((basketPhiInnerSize/2)/((basketPhiOuterSize - basketPhiInnerSize)/2))*basketHeight; + + Int_t stackingXdirection; + if (angleModulePeriph > 0) stackingXdirection = 1; + else stackingXdirection = -1; + + TVector3 vectorAtZeroAngle = TVector3(0, 1, 0); + TVector3 vectorUnitModuleCenter = vectorAtZeroAngle; vectorUnitModuleCenter.RotateZ(-TMath::DegToRad()*angleModuleCenter); + TVector3 vectorUnitModuleMiddle = vectorAtZeroAngle; vectorUnitModuleMiddle.RotateZ(-TMath::DegToRad()*(angleModuleCenter + angleModulePeriph)/2); + TVector3 vectorUnitModulePeriph = vectorAtZeroAngle; vectorUnitModulePeriph.RotateZ(-TMath::DegToRad()*angleModulePeriph); + + struct planeEq { //ax*x + ay*y = c + Double_t ax, ay, c; + }; + auto GetDistancePointLine2D = [](planeEq line, Double_t x, Double_t y) { + return fabs(line.ax*x + line.ay*y - line.c)/sqrt(line.ax*line.ax + line.ay*line.ay); + }; + + //get plane/line equations for left/right edge of module: crosses (0, yRayStart) + planeEq planeEqCenter = {vectorUnitModuleCenter.Y(), -vectorUnitModuleCenter.X(), -vectorUnitModuleCenter.X()*yRayStart}; + planeEq planeEqPeriph = {vectorUnitModulePeriph.Y(), -vectorUnitModulePeriph.X(), -vectorUnitModulePeriph.X()*yRayStart}; + planeEq planeEqMiddle = {vectorUnitModuleMiddle.Y(), -vectorUnitModuleMiddle.X(), -vectorUnitModuleMiddle.X()*yRayStart}; + + //find intersection with y = yCoordBasketBottom and y = yCoordBasketBottom+basketHeight of lines passing through yRayStart + Double_t xBottomPeriph = (planeEqPeriph.c - planeEqPeriph.ay*yCoordBasketBottom)/planeEqPeriph.ax; + if (stackingXdirection >= 0) xBottomPeriph -= (moduleClearance/2)/TMath::Cos(TMath::DegToRad()*angleModulePeriph); + else xBottomPeriph += (moduleClearance/2)/TMath::Cos(TMath::DegToRad()*angleModulePeriph); + + Double_t xTopCenter = (planeEqCenter.c - planeEqCenter.ay*(yCoordBasketBottom+basketHeight))/planeEqCenter.ax; + if (stackingXdirection >= 0) xTopCenter += (moduleClearance/2)/TMath::Cos(TMath::DegToRad()*angleModuleCenter); + else xTopCenter -= (moduleClearance/2)/TMath::Cos(TMath::DegToRad()*angleModuleCenter); + Double_t yTopCenter = yCoordBasketBottom + basketHeight; + + TVector3 vectorUnitBottomPeriphToHeight = TVector3(vectorUnitModuleMiddle.Y(), -vectorUnitModuleMiddle.X(), 0); + if (vectorUnitBottomPeriphToHeight.X()*stackingXdirection >= 0) { + vectorUnitBottomPeriphToHeight.SetX(-vectorUnitBottomPeriphToHeight.X()); + vectorUnitBottomPeriphToHeight.SetY(-vectorUnitBottomPeriphToHeight.Y()); + vectorUnitBottomPeriphToHeight.SetZ(-vectorUnitBottomPeriphToHeight.Z()); + } + + //get distance from point (xBottomPeriph, yCoordBasketBottom) to planeEqMiddle + Double_t distBottomPeriphToHeight = GetDistancePointLine2D(planeEqMiddle, xBottomPeriph, yCoordBasketBottom); + TVector3 vectorScaledInnerPhiToCenter = vectorUnitBottomPeriphToHeight; vectorScaledInnerPhiToCenter.SetMag(distBottomPeriphToHeight*2); + Double_t xBottomCenter = xBottomPeriph + vectorScaledInnerPhiToCenter.X(); + Double_t yBottomCenter = yCoordBasketBottom + vectorScaledInnerPhiToCenter.Y(); + + if (fabs(angleModuleCenter) < 1e-10 && fabs(xBottomCenter - stackingXdirection*moduleClearance/2) > 1e-10) { + Fatal("SpdEcalTB2::StackModuleInSector", "oops! for the first filled module, the bottom left x should zero! something is wrong!"); + } + + TVector3 vectorUnitTopCenterToHeight = TVector3(vectorUnitModuleMiddle.Y(), -vectorUnitModuleMiddle.X(), 0); //!!! + if (vectorUnitTopCenterToHeight.X()*stackingXdirection < 0) { + vectorUnitTopCenterToHeight.SetX(-vectorUnitTopCenterToHeight.X()); + vectorUnitTopCenterToHeight.SetY(-vectorUnitTopCenterToHeight.Y()); + vectorUnitTopCenterToHeight.SetZ(-vectorUnitTopCenterToHeight.Z()); + } + + Double_t distTopCenterToHeight = GetDistancePointLine2D(planeEqMiddle, xTopCenter, yTopCenter); + TVector3 vectorScaledOuterPhiToPeriph = vectorUnitTopCenterToHeight; vectorScaledOuterPhiToPeriph.SetMag(distTopCenterToHeight*2); + + Double_t xMiddleInnerPhi = xBottomPeriph + vectorScaledInnerPhiToCenter.X()/2; + Double_t yMiddleInnerPhi = yCoordBasketBottom + vectorScaledInnerPhiToCenter.Y()/2; + Double_t xMiddleOuterPhi = xTopCenter + vectorScaledOuterPhiToPeriph.X()/2; + Double_t yMiddleOuterPhi = yTopCenter + vectorScaledOuterPhiToPeriph.Y()/2; + + TVector3 vectorTrapezoidHeightToOuter = TVector3(xMiddleOuterPhi - xMiddleInnerPhi, yMiddleOuterPhi - yMiddleInnerPhi, 0); + Double_t trapezoidHeight = vectorTrapezoidHeightToOuter.Mag(); + + Double_t moduleOuterSizePhi = 2*distTopCenterToHeight; + Double_t moduleInnerSizePhi = 2*distBottomPeriphToHeight; + + //make a tgeovolume, remembering about all the conventions + //z ->-> from large to small side, X ~ theta, Y ~ phi, +-/--/-+/++ + + Double_t moduleVertices[16]; + moduleVertices[0] = moduleInnerSizeTheta/2; moduleVertices[1] = -moduleOuterSizePhi/2; + moduleVertices[2] = -moduleInnerSizeTheta/2; moduleVertices[3] = -moduleOuterSizePhi/2; + moduleVertices[4] = -moduleInnerSizeTheta/2; moduleVertices[5] = moduleOuterSizePhi/2; + moduleVertices[6] = moduleInnerSizeTheta/2; moduleVertices[7] = moduleOuterSizePhi/2; + + moduleVertices[8] = moduleInnerSizeTheta/2; moduleVertices[9] = -moduleInnerSizePhi/2; + moduleVertices[10] = -moduleInnerSizeTheta/2; moduleVertices[11] = -moduleInnerSizePhi/2; + moduleVertices[12] = -moduleInnerSizeTheta/2; moduleVertices[13] = moduleInnerSizePhi/2; + moduleVertices[14] = moduleInnerSizeTheta/2; moduleVertices[15] = moduleInnerSizePhi/2; + + TGeoVolume* moduleVolume = 0; + if (trimModuleLength) moduleVolume = gGeoManager->MakeArb8("MODULE", Air, trapezoidHeight/2, moduleVertices); + else { + Double_t outerPhi = moduleOuterSizePhi/2; + Double_t innerPhi = moduleInnerSizePhi/2; + Double_t innerPhi2 = outerPhi - (outerPhi - innerPhi)*totalZSize/trapezoidHeight; + moduleVertices[9] = -innerPhi; + moduleVertices[11] = -innerPhi; + moduleVertices[13] = innerPhi; + moduleVertices[15] = innerPhi; + moduleVolume = gGeoManager->MakeArb8("MODULE", Air, totalZSize/2, moduleVertices); + } + + TMatrixD matrixModule = GetMatrixToEmplaceModule(planeEqCenter.ax, planeEqCenter.ay, false, moduleVolume); + if (stackingXdirection < 0) matrixModule = GetMatrixToEmplaceModule(planeEqCenter.ax, planeEqCenter.ay, true, moduleVolume); + + if (angleModulePeriph > 0 && trimModuleLength) { + cout << "-I- <SpdEcalTB2::StackModuleInSector> : module П† size is set to " << (moduleInnerSizePhi - cellClearance)/2 << " cm, module length (in radial direction): " << trapezoidHeight << " cm" << endl; + } + if (angleModulePeriph > 0 && !trimModuleLength) { + cout << "-I- <SpdEcalTB2::StackModuleInSector> : module П† size is set to " << (moduleInnerSizePhi - cellClearance)/2 << " cm, module length (in radial direction): " << totalZSize << " cm" << endl; + } + + moduleVolume->SetLineColor(kBlue); + moduleVolume->SetFillColor(kBlue); + moduleVolume->SetTransparency(50); + + if (!trimModuleLength) { + vectorTrapezoidHeightToOuter.SetMag(totalZSize); + } + + Double_t xHeightMiddle = xMiddleInnerPhi + vectorTrapezoidHeightToOuter.X()/2; + Double_t yHeightMiddle = yMiddleInnerPhi + vectorTrapezoidHeightToOuter.Y()/2; + + TGeoRotation * rot = new TGeoRotation(); + rot->SetMatrix(matrixModule.GetMatrixArray()); + TGeoTranslation * trans = new TGeoTranslation(xHeightMiddle, yHeightMiddle, 0); + TGeoCombiTrans * combiTrans = new TGeoCombiTrans(*trans, *rot); + return make_pair(combiTrans, moduleVolume); +} + +//________________________________________________________________________________ +void SpdEcalTB2::BuildBasket() { + + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + Int_t nLayers = mapper->GetNLayers(); + Double_t layer1SizeZ = mapper->GetLayer1SizeZ(); + Double_t layer2SizeZ = mapper->GetLayer2SizeZ(); + TString baseMedium = mapper->GetBaseMedium(); + TGeoMedium* Air = FindMedium(baseMedium, ""); + Double_t lzsize = layer1SizeZ + layer2SizeZ; + Double_t tzsize = nLayers * lzsize; + Double_t barrelLength = mapper->GetBarrelLength(); + Double_t barrelRadius = mapper->GetBarrelOuterSize() - mapper->GetBarrelWidth(); + Double_t basketClearance = mapper->GetBasketClearance(); + Double_t sectorClearance = mapper->GetSectorClearance(); + Int_t nSectors = mapper->GetNSectors(); + Bool_t forceCellSize = mapper->IsForceCellSize(); + Double_t barrelModuleRadialSize = mapper->GetBarrelModuleRadialSize(); + + //get basket dimensions + Double_t basketHeight = (forceCellSize) ? tzsize : barrelModuleRadialSize; + Double_t basketZSize = barrelLength/2 - 2*basketClearance; + Double_t doubleAngleBasket = 360./nSectors; + Double_t angleSmallBasketFoundation = (180.0 - doubleAngleBasket)/2; + Double_t basketPhiInnerSize = 2*barrelRadius*TMath::Tan(TMath::DegToRad()*doubleAngleBasket/2) - sectorClearance/TMath::Sin(TMath::DegToRad()*angleSmallBasketFoundation); + Double_t basketPhiOuterSize = (basketPhiInnerSize + sectorClearance/TMath::Sin(TMath::DegToRad()*angleSmallBasketFoundation))*(barrelRadius + basketHeight)/barrelRadius - sectorClearance/TMath::Sin(TMath::DegToRad()*angleSmallBasketFoundation); + + Double_t basketVertices[16]; + + basketVertices[0] = basketPhiInnerSize/2; basketVertices[1] = barrelRadius; + basketVertices[2] = -basketPhiInnerSize/2; basketVertices[3] = barrelRadius; + basketVertices[4] = -basketPhiOuterSize/2; basketVertices[5] = barrelRadius + basketHeight; + basketVertices[6] = basketPhiOuterSize/2; basketVertices[7] = barrelRadius + basketHeight; + + basketVertices[8] = basketPhiInnerSize/2; basketVertices[9] = barrelRadius; + basketVertices[10] = -basketPhiInnerSize/2; basketVertices[11] = barrelRadius; + basketVertices[12] = -basketPhiOuterSize/2; basketVertices[13] = barrelRadius + basketHeight; + basketVertices[14] = basketPhiOuterSize/2; basketVertices[15] = barrelRadius + basketHeight; + + fBasket = gGeoManager->MakeArb8("EcalBasket", Air, basketZSize/2, basketVertices); + + fBasket->SetFillColor(kBlue); + fBasket->SetLineColor(kBlue); + fBasket->SetTransparency(50); +} + +//________________________________________________________________________________ +void SpdEcalTB2::BuildBarrel() { + + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + TString baseMedium = mapper->GetBaseMedium(); + TGeoMedium* Air = FindMedium(baseMedium, ""); + Int_t nSectors = mapper->GetNSectors(); + Double_t barrelLength = mapper->GetBarrelLength(); + + Int_t iCurrentBasket = 1; + for (int iphi = 0; iphi < nSectors; ++iphi) { + + TGeoTranslation* transBasketPos = new TGeoTranslation(0, 0, barrelLength/2); + TGeoTranslation* transBasketNeg = new TGeoTranslation(0, 0, -barrelLength/2); + TGeoRotation* rotationZY180 = new TGeoRotation(); + TGeoRotation* rotationZ = new TGeoRotation(); + rotationZY180->RotateY(180); + rotationZY180->RotateZ(iphi*360.0/nSectors); + rotationZ->RotateZ(iphi*360.0/nSectors); + TGeoCombiTrans * combiTransBasketY180 = new TGeoCombiTrans(*transBasketNeg, *rotationZY180); + TGeoCombiTrans * combiTransBasket = new TGeoCombiTrans(*transBasketPos, *rotationZ); + fMasterVolume->AddNode(fBasket, iCurrentBasket++, combiTransBasket); + fMasterVolume->AddNode(fBasket, iCurrentBasket++, combiTransBasketY180); + + } + +} + +//________________________________________________________________________________ +TMatrixD SpdEcalTB2::GetMatrixToEmplaceModule(Double_t ax, Double_t ay, + Bool_t rotateClockwise, TGeoVolume* moduleVolume) +{ + // + // return rotation matrix for given TGeoVolume (of shape TGeoArb8, trapezoid), such that: + // for module, rotated using this matrix, the projection of the module face, which goes along Z axis, + // on Z = 0 plane is parallel to the line, given by equation ax*x + ay*y = 0, where ax, ay + // are the arguments for this function; + // the argument rotateClockwise indicates whether the module should be placed clockwise + // of the line (true) or anti-clockwise (false) it is assumed that the face which will go along Z axis + // in the rotated module, goes along X axis for the unrotated module. + // It is assumed the two sides are properly centered around 0. + // + assert(TString(moduleVolume->GetShape()->ClassName()).CompareTo("TGeoArb8") == 0); + + TGeoArb8 * moduleShape = (TGeoArb8*)moduleVolume->GetShape(); + Double_t* moduleVertices = moduleShape->GetVertices(); + + //ASSUMING THE first 4 vertices are larger side + assert(fabs(moduleVertices[0]) >= fabs(moduleVertices[8])); + assert(fabs(moduleVertices[1]) >= fabs(moduleVertices[9])); + + //ASSUMING vertex 0 in +-, 1 in --, 2 in -+, 3 in ++ quadrant + assert(moduleVertices[0] > moduleVertices[2]); + assert(moduleVertices[5] > moduleVertices[3]); + assert(moduleVertices[6] > moduleVertices[4]); + assert(moduleVertices[7] > moduleVertices[1]); + assert(moduleVertices[0] >= moduleVertices[8]); + + Double_t thetaLargeEdge = moduleVertices[0] - moduleVertices[2]; + Double_t thetaSmallEdge = moduleVertices[8] - moduleVertices[10]; + Double_t phiLargeEdge = moduleVertices[7] - moduleVertices[1]; + Double_t phiSmallEdge = moduleVertices[15] - moduleVertices[9]; + + Double_t moduleLength = 2*moduleShape->GetDz(); + + //pick some triplet of vectors that go along edges of the unrotated module + TVector3 initialVector1 = TVector3(moduleVertices[0] - moduleVertices[8], + moduleVertices[1] - moduleVertices[9], + -moduleLength); + + TVector3 initialVector2 = TVector3(moduleVertices[2] - moduleVertices[0], moduleVertices[3] - moduleVertices[1], 0); + TVector3 initialVector3 = TVector3(moduleVertices[6] - moduleVertices[0], moduleVertices[7] - moduleVertices[1], 0); + TVector3 initialVectorMidfacePhi = TVector3(0, moduleVertices[1] - moduleVertices[9], -moduleLength); + TVector3 initialVectorMidfacePhi2 = TVector3(initialVectorMidfacePhi); + initialVectorMidfacePhi2.SetY(-initialVectorMidfacePhi2.Y()); + + TVector3 initialVectorMidfaceTheta = TVector3(moduleVertices[0] - moduleVertices[8], 0, -moduleLength); + TVector3 initialVectorMidfaceTheta2 = TVector3(initialVectorMidfaceTheta); + initialVectorMidfaceTheta2.SetX(-initialVectorMidfaceTheta2.X()); + + Double_t doubleAngleModulePhi = 2*TMath::ATan((0.5*phiLargeEdge - 0.5*phiSmallEdge)/moduleLength); + Double_t doubleAngleModuleTheta = 2*TMath::ATan((0.5*thetaLargeEdge - 0.5*thetaSmallEdge)/moduleLength); + + //get same triplet for rotated module using the plane equation + //first vector: bottom-to-top middle-edge at-leanwall vector of the trapezoid + y(x) component + TVector3 finalVector1 = TVector3(-ay, ax, 0); + finalVector1.SetMag(initialVectorMidfacePhi.Mag()); + if (rotateClockwise) { + finalVector1.SetZ(-moduleVertices[0] + moduleVertices[8]); + } + else { + finalVector1.SetZ(moduleVertices[0] - moduleVertices[8]); + } + + //second vector: pure Z/theta vector + TVector3 finalVector2; + if (rotateClockwise) finalVector2 = TVector3(0, 0, 1); + else finalVector2 = TVector3(0, 0, -1); + finalVector2.SetMag(initialVector2.Mag()); + + //second vector: phi+ vector, according to 2d plane equation + TVector3 finalVector3 = TVector3(ax, ay, 0); + if (rotateClockwise) finalVector3.RotateZ(doubleAngleModulePhi/2); + else finalVector3.RotateZ(-doubleAngleModulePhi/2); + + //save the orientation + if (finalVector3.X() > 0 && rotateClockwise) finalVector3 *= -1; + finalVector3.SetMag(initialVector3.Mag()); + + TMatrixD rotationMatrix = GetMatrixToRotateVectorTriplet(initialVector1, initialVector2, initialVector3, + finalVector1, finalVector2, finalVector3); + + return rotationMatrix; +} + +//_______________________________________________________________________________ +TMatrixD SpdEcalTB2::GetMatrixToRotateVectorTriplet(TVector3 initialVector1, TVector3 initialVector2, TVector3 initialVector3, + TVector3 finalVector1, TVector3 finalVector2, TVector3 finalVector3) +{ + Double_t tolerance = 1e-10; + + assert(fabs(finalVector1.Mag() - initialVector1.Mag()) < tolerance); + assert(fabs(finalVector2.Mag() - initialVector2.Mag()) < tolerance); + assert(fabs(finalVector3.Mag() - initialVector3.Mag()) < tolerance); + assert(fabs(initialVector1.Angle(initialVector2) - finalVector1.Angle(finalVector2)) < tolerance); + assert(fabs(initialVector1.Angle(initialVector3) - finalVector1.Angle(finalVector3)) < tolerance); + assert(fabs(initialVector2.Angle(initialVector3) - finalVector2.Angle(finalVector3)) < tolerance); + + const Double_t finalStateMatrixElements[9] = { + finalVector1.X(), finalVector2.X(), finalVector3.X(), + finalVector1.Y(), finalVector2.Y(), finalVector3.Y(), + finalVector1.Z(), finalVector2.Z(), finalVector3.Z() + }; + + TMatrixD finalStateMatrix = TMatrixD(3, 3, finalStateMatrixElements); // a[irow,icol] = elements[irow*no_cols+icol] + + const Double_t initialStateMatrixElements[9] = { + initialVector1.X(), initialVector2.X(), initialVector3.X(), + initialVector1.Y(), initialVector2.Y(), initialVector3.Y(), + initialVector1.Z(), initialVector2.Z(), initialVector3.Z() + }; + + TMatrixD initialStateMatrix = TMatrixD(3, 3, initialStateMatrixElements); // a[irow,icol] = elements[irow*no_cols+icol] + + TMatrixD initialStateMatrixInverted = initialStateMatrix.Invert(); + TMatrixD rotationMatrix = finalStateMatrix*initialStateMatrixInverted; + + TVector3 vectorColumn1 = TVector3(rotationMatrix[0][0], rotationMatrix[1][0], rotationMatrix[2][0]); + TVector3 vectorColumn2 = TVector3(rotationMatrix[0][1], rotationMatrix[1][1], rotationMatrix[2][1]); + TVector3 vectorColumn3 = TVector3(rotationMatrix[0][2], rotationMatrix[1][2], rotationMatrix[2][2]); + + assert(fabs(vectorColumn1.Angle(vectorColumn2) - TMath::Pi()/2) < tolerance); + assert(fabs(vectorColumn1.Angle(vectorColumn3) - TMath::Pi()/2) < tolerance); + assert(fabs(vectorColumn2.Angle(vectorColumn3) - TMath::Pi()/2) < tolerance); + + assert(fabs(vectorColumn1.Mag() - 1.) < tolerance); + assert(fabs(vectorColumn2.Mag() - 1.) < tolerance); + assert(fabs(vectorColumn3.Mag() - 1.) < tolerance); + + return rotationMatrix; +} + +//________________________________________________________________________________ +void SpdEcalTB2::GetEmplacedModulePosition(TGeoVolume* moduleVolume, + Double_t ax, Double_t ay, Double_t arhs, + Double_t ax2, Double_t ay2, Double_t arhs2, + Double_t & xMiddle, Double_t & yMiddle, + Double_t & ax_new, Double_t & ay_new, Double_t & arhs_new, + Double_t & xPlane2Bottom, Double_t & yPlane2Bottom, + Double_t & xPlane2Top, Double_t & yPlane2Top) +{ + // + // Place a module in its place. + // moduleVolume: module to place + // ax/ay/arhs: the equation that describes the plane that the face of the module should lean on (ax*x + ay*y = arhs) + // ax2/ay2/arhs2: this equation describes the plane that an edge (or a face) of the module should stand on, + // while leaning on the ax/ay/arhs plane. + // + + if (ax < 0 || ay < 0) { + Fatal("SpdEcalTB2::GetEmplacedModulePosition", + "can't stack module: function only valid for plane with ax >=0, ay >= 0"); + } + + // deltaXdirection/deltaYdirection: (+1/-1): sign of the X(Y) component of vector + // parallel to the module edge along the Z axis and starting at plane ax/ay/arhs + // rotateZdirection: (+1/-1): if +1, the module is placed clockwise of plane ax/ay/arhs. + // Else it is placed anticlockwise. + + Int_t deltaXdirection = -1; + Int_t deltaYdirection = -1; + Int_t rotateZdirection = 1; + + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) Fatal("SpdEcalTB2::GetEmplacedModulePosition", "no mapper"); + + Int_t nLayers = mapper->GetNLayers(); + Double_t layer1SizeZ = mapper->GetLayer1SizeZ(); + Double_t layer2SizeZ = mapper->GetLayer2SizeZ(); + Double_t lzsize = layer1SizeZ + layer2SizeZ; + Double_t tzsize = nLayers * lzsize; + + TGeoArb8 * moduleShape = (TGeoArb8*)moduleVolume->GetShape(); + Double_t* moduleVertices = moduleShape->GetVertices(); + + //ASSUMING THE first 4 vertices are larger side + assert(fabs(moduleVertices[0]) >= fabs(moduleVertices[8])); + assert(fabs(moduleVertices[1]) >= fabs(moduleVertices[9])); + + //ASSUMING vertex 0 in +-, 1 in --, 2 in -+, 3 in ++ quadrant + assert(moduleVertices[0] > moduleVertices[2]); + assert(moduleVertices[5] > moduleVertices[3]); + assert(moduleVertices[6] > moduleVertices[4]); + assert(moduleVertices[7] > moduleVertices[1]); + assert(moduleVertices[0] >= moduleVertices[8]); + + Double_t thetaLargeEdge = moduleVertices[0] - moduleVertices[2]; + Double_t thetaSmallEdge = moduleVertices[8] - moduleVertices[10]; + Double_t phiLargeEdge = moduleVertices[7] - moduleVertices[1]; + Double_t phiSmallEdge = moduleVertices[15] - moduleVertices[9]; + Double_t moduleLength = 2*moduleShape->GetDz(); + + Double_t angleTrapezoidPhi = TMath::ATan((0.5*phiLargeEdge - 0.5*phiSmallEdge)/moduleLength); + Double_t angleTrapezoidTheta = TMath::ATan((0.5*thetaLargeEdge - 0.5*thetaSmallEdge)/moduleLength); + + //given the plane equation ax/ay/arhs and the bottom plane, get the module center and the new plane + + TVector3 vectorMidfaceCenter = TVector3(ay, -ax, 0); //from inner(small) to outer(large) side of the trapezoid + if (vectorMidfaceCenter.Y() < 0) vectorMidfaceCenter *= -1; + + TVector3 vectorTrapezoidHeight = vectorMidfaceCenter; //from inner(small) to outer(large) side of the trapezoid + if (rotateZdirection > 0) { + vectorTrapezoidHeight.RotateZ(angleTrapezoidPhi); + } + else { + vectorTrapezoidHeight.RotateZ(-angleTrapezoidPhi); + } + TVector3 vectorMidfacePeriph(vectorMidfaceCenter); //from inner(small) to outer(large) side of the trapezoid + if (rotateZdirection > 0) { + vectorMidfacePeriph.RotateZ(2*angleTrapezoidPhi); + } + else { + vectorMidfacePeriph.RotateZ(-2*angleTrapezoidPhi); + } + + // !!! here +/- means in which quadrant we want to stick the module. All 4 +- combinations are solutions. + + Double_t deltaY = deltaYdirection*phiSmallEdge/sqrt(1 + vectorTrapezoidHeight.Y()*vectorTrapezoidHeight.Y()/(vectorTrapezoidHeight.X()*vectorTrapezoidHeight.X())); + Double_t deltaX; + if (deltaXdirection < 0) { + deltaX = -phiSmallEdge/sqrt(1 + vectorTrapezoidHeight.X()*vectorTrapezoidHeight.X()/(vectorTrapezoidHeight.Y()*vectorTrapezoidHeight.Y())); + } + else { + deltaX = phiSmallEdge/sqrt(1 + vectorTrapezoidHeight.X()*vectorTrapezoidHeight.X()/(vectorTrapezoidHeight.Y()*vectorTrapezoidHeight.Y())); + } + + //lower point at plane1. Weird expression but oh well + + Double_t yPlane1 = (arhs*(-ax2) - (-ax)*(arhs2 - deltaY*ay2 - (-deltaX)*(-ax2)))/(ay*(-ax2) - (-ax)*ay2); + Double_t xPlane1 = -(arhs*ay2 - ay*(arhs2 - deltaY*ay2 - (-deltaX)*(-ax2)))/((-ax)*ay2 - ay*(-ax2)); + + Double_t yInnerSideMiddle = yPlane1 + deltaY/2; + Double_t xInnerSideMiddle = xPlane1 + deltaX/2; + + // (0,0) -> (zInnerSideMiddle, xInnerSideMiddle) && plane2, + // x*zInnerSideMiddle - z*xInnerSideMiddle = 0 && plane2.ax*x + plane2.az*z = plane2.arhs + + yMiddle = yInnerSideMiddle + vectorTrapezoidHeight.Unit().Y()*tzsize/2; + xMiddle = xInnerSideMiddle + vectorTrapezoidHeight.Unit().X()*tzsize/2; + + yPlane2Bottom = yPlane1 + deltaY; + xPlane2Bottom = xPlane1 + deltaX; + + //get plane equation for peripheral side of the module -> will be used to place the next module + + ax_new = vectorMidfacePeriph.Y(); + ay_new = -vectorMidfacePeriph.X(); + arhs_new = ax_new*xPlane2Bottom + ay_new*yPlane2Bottom; + + Double_t sizePhiSide = tzsize/TMath::Cos(angleTrapezoidPhi); + vectorMidfacePeriph.SetMag(sizePhiSide); + + yPlane2Top = yPlane2Bottom + vectorMidfacePeriph.Y(); + xPlane2Top = xPlane2Bottom + vectorMidfacePeriph.X(); +} + +//________________________________________________________________________________ +void SpdEcalTB2::FillBasketFixedCells(TGeoVolume* basketVolume, TGeoVolume* moduleVolume) +{ + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + Double_t barrelInnerSize = mapper->GetBarrelOuterSize() - mapper->GetBarrelWidth(); + Double_t moduleClearance = mapper->GetModuleClearance(); + Int_t nSectors = mapper->GetNSectors(); + + TGeoArb8* moduleShape = (TGeoArb8*)moduleVolume->GetShape(); + Double_t* moduleVertices = moduleShape->GetVertices(); + Double_t moduleInnerSizeTheta = fabs(moduleVertices[0] - moduleVertices[2]); + Double_t moduleOuterSizeTheta = fabs(moduleVertices[8] - moduleVertices[10]); + assert(moduleInnerSizeTheta == moduleOuterSizeTheta); //non-projective geometry + + Double_t basketZSize = ((TGeoArb8*)basketVolume->GetShape())->GetDz()*2; + + Double_t* basketVertices = ((TGeoArb8*)basketVolume->GetShape())->GetVertices(); + + assert(basketVertices[0] > basketVertices[2]); + + Double_t basketPhiInnerSize = basketVertices[0] - basketVertices[2]; + + assert(basketVertices[5] > basketVertices[3]); + + Double_t basketHeight = basketVertices[5] - basketVertices[3]; + + assert(basketVertices[6] > basketVertices[4]); + + Double_t basketPhiOuterSize = basketVertices[6] - basketVertices[4]; + Double_t doubleAngleBasket = 360./nSectors; + + Double_t nmodulesZ = 0; //number of modules in a basket in Z direction + Double_t basketFilledZSize = moduleOuterSizeTheta; + + while (basketFilledZSize < basketZSize) { + nmodulesZ += 1; + basketFilledZSize += moduleOuterSizeTheta + moduleClearance; + } + + basketFilledZSize -= moduleOuterSizeTheta + moduleClearance; + nmodulesZ -= 1; + + Int_t iPhiModule = 1; + + struct planeEqY { //plane(line) equation of the form y = ax*x + c + Double_t ax; + Double_t c; + }; + + planeEqY basketRightEdge; + basketRightEdge.ax = basketHeight/(basketPhiOuterSize/2 - basketPhiInnerSize/2); + basketRightEdge.c = barrelInnerSize - (basketPhiInnerSize/2)*basketHeight/(basketPhiOuterSize/2 - basketPhiInnerSize/2); + planeEqY basketLeftEdge; + basketLeftEdge.ax = -basketRightEdge.ax; + basketLeftEdge.c = basketRightEdge.c; + + Double_t ax = 1; + Double_t ay = 0; + Double_t arhs = -moduleClearance/2; + + Double_t ax2 = 0; + Double_t ay2 = 1; + Double_t arhs2 = barrelInnerSize; + + Bool_t moduleInBasket = true; + while (moduleInBasket) { + + Double_t xMiddle, yMiddle, ax_new, ay_new, arhs_new, xPlane2Bottom, yPlane2Bottom, xPlane2Top, yPlane2Top; + + TMatrixD rotationMatrix = GetMatrixToEmplaceModule(ax, ay, true, moduleVolume); + + GetEmplacedModulePosition(moduleVolume, ax, ay, arhs, ax2, ay2, arhs2, + xMiddle, yMiddle, ax_new, ay_new, arhs_new, + xPlane2Bottom, yPlane2Bottom, xPlane2Top, yPlane2Top); + + ax = ax_new; + ay = ay_new; + arhs = arhs_new; + + //add clearance between modules and change arhs accordingly + Double_t angleBorderPlane = TMath::ATan(-ay/ax); + arhs += -ax*moduleClearance/TMath::Cos(angleBorderPlane); + + Bool_t bottomCornerInBasket = yPlane2Bottom > (basketLeftEdge.ax*xPlane2Bottom + basketLeftEdge.c); + Bool_t topCornerInBasket = yPlane2Top > (basketLeftEdge.ax*xPlane2Top + basketLeftEdge.c); + moduleInBasket = bottomCornerInBasket && topCornerInBasket; + + Double_t currZcenter = -basketZSize/2 + moduleOuterSizeTheta/2; + + if (moduleInBasket) { + + TGeoRotation * rot = new TGeoRotation(); + rot->SetMatrix(rotationMatrix.GetMatrixArray()); + + for (int iz = 0; iz < nmodulesZ; ++iz) { + TGeoTranslation * trans = new TGeoTranslation(xMiddle, yMiddle, currZcenter); + TGeoCombiTrans * combiTrans = new TGeoCombiTrans(*trans, *rot); + basketVolume->AddNode(moduleVolume, 100*(iz+1) + iPhiModule, combiTrans); + TGeoCombiTrans* combiTransMirror = (TGeoCombiTrans*)combiTrans->MakeClone(); + combiTransMirror->ReflectX(true); + basketVolume->AddNode(moduleVolume, 100*(iz+1) - iPhiModule, combiTransMirror); + currZcenter += moduleClearance + moduleOuterSizeTheta; + } + } + iPhiModule += 1; + } +} + +//_____________________________________________________________________________________ +Double_t SpdEcalTB2::LinearInterp(Double_t x1, Double_t x2, Double_t t) +{ + assert(t >= 0 && t <= 1); + return (t*x2 + (1-t)*x1); +} + +//_____________________________________________________________________________________ +void SpdEcalTB2::BuildModule(TGeoVolume* module) +{ + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + TString baseMedium = mapper->GetBaseMedium(); + TString absorberMedium = mapper->GetAbsorberMedium(); + TString scintMedium = mapper->GetScintMedium(); + TGeoMedium* Air = FindMedium(baseMedium, ""); + TGeoMedium* Lead = FindMedium(absorberMedium, baseMedium); + TGeoMedium* Scint = FindMedium(scintMedium, baseMedium); + Double_t layer1SizeZ = mapper->GetLayer1SizeZ(); + Double_t layer2SizeZ = mapper->GetLayer2SizeZ(); + Double_t cellClearance = mapper->GetCellClearance(); + + Double_t moduleZsize = ((TGeoArb8*)module->GetShape())->GetDz()*2; + Double_t* moduleVertices = ((TGeoArb8*)module->GetShape())->GetVertices(); + + assert(moduleVertices[0] == -moduleVertices[2]); + assert(moduleVertices[4] == -moduleVertices[6]); + assert(moduleVertices[1] == -moduleVertices[7]); + assert(moduleVertices[3] == -moduleVertices[5]); + + Double_t layerZSize = layer1SizeZ + layer2SizeZ; + + //build quarter of module into (+,-) quadrant + Double_t cellVertices[16]; + + cellVertices[0] = moduleVertices[0]; cellVertices[1] = moduleVertices[1]; + cellVertices[2] = cellClearance/2; cellVertices[3] = moduleVertices[3]; + cellVertices[4] = cellClearance/2; cellVertices[5] = -cellClearance/2; + cellVertices[6] = moduleVertices[6]; cellVertices[7] = -cellClearance/2; + + cellVertices[8] = moduleVertices[8]; cellVertices[9] = moduleVertices[9]; + cellVertices[10] = cellClearance/2; cellVertices[11] = moduleVertices[11]; + cellVertices[12] = cellClearance/2; cellVertices[13] = -cellClearance/2; + cellVertices[14] = moduleVertices[14]; cellVertices[15] = -cellClearance/2; + + TGeoVolume* cellVolume = gGeoManager->MakeArb8("Cell", Air, moduleZsize/2, cellVertices); + cellVolume->SetFillColor(kAzure+1); + cellVolume->SetLineColor(kAzure+1); + cellVolume->SetTransparency(50); + + Int_t currNlayers = floor(moduleZsize/layerZSize); + Double_t moduleZbegin = -moduleZsize/2; + Double_t moduleZend = moduleZsize/2; + + for (Int_t ilayer = 0; ilayer < currNlayers; ++ilayer) { + + Double_t layerZbegin = moduleZbegin + ilayer*(layerZSize); + Double_t layerZend = layerZbegin + layerZSize; + + Double_t layer1Zbegin = layerZbegin; + Double_t layer1Zend = layerZbegin + layer1SizeZ; + Double_t layer2Zbegin = layerZbegin + layer1SizeZ; + Double_t layer2Zend = layerZend; + + Double_t layer1Vertices[16]; + for (int iv = 0; iv < 8; ++iv) { + Double_t interpT = (layer1Zbegin - moduleZbegin)/(moduleZend - moduleZbegin); + if (ilayer == 0) interpT = 0.; + layer1Vertices[iv] = LinearInterp(cellVertices[iv], cellVertices[iv+8], interpT); + } + for (int iv = 8; iv < 16; ++iv) { + Double_t interpT = (layer1Zend - moduleZbegin)/(moduleZend - moduleZbegin); + layer1Vertices[iv] = LinearInterp(cellVertices[iv-8], cellVertices[iv], interpT); + } + + TGeoVolume* mat1layerVolume = gGeoManager->MakeArb8("EcalBLeadCell", Lead, layer1SizeZ/2, layer1Vertices); + + Double_t layer2Vertices[16]; + for (int iv = 0; iv < 8; ++iv) { + Double_t interpT = (layer2Zbegin - moduleZbegin)/(moduleZend - moduleZbegin); + layer2Vertices[iv] = LinearInterp(cellVertices[iv], cellVertices[iv+8], interpT); + } + for (int iv = 8; iv < 16; ++iv) { + Double_t interpT = (layer2Zend - moduleZbegin)/(moduleZend - moduleZbegin); + if (ilayer == currNlayers - 1) interpT = 1.; + layer2Vertices[iv] = LinearInterp(cellVertices[iv-8], cellVertices[iv], interpT); + } + TGeoVolume* mat2layerVolume = gGeoManager->MakeArb8("EcalBScintCell", Scint, layer2SizeZ/2, layer2Vertices); + + mat1layerVolume->SetFillColor(kBlue+2); + mat1layerVolume->SetLineColor(kBlue+2); + mat1layerVolume->SetTransparency(50); + + mat2layerVolume->SetFillColor(kCyan); + mat2layerVolume->SetLineColor(kCyan); + mat2layerVolume->SetTransparency(0); + + Double_t centerLayer = moduleZbegin + layerZSize/2 + ilayer*layerZSize; + Double_t centerMat1 = centerLayer - (layer1SizeZ+layer2SizeZ)/2 + layer1SizeZ/2; + Double_t centerMat2 = centerLayer + (layer1SizeZ+layer2SizeZ)/2 - layer2SizeZ/2; + cellVolume->AddNode(mat1layerVolume, ilayer+1, new TGeoTranslation(0, 0, centerMat1)); + cellVolume->AddNode(mat2layerVolume, ilayer+1, new TGeoTranslation(0, 0, centerMat2)); + + + if (fEnableWritingPointsAll) AddSensitiveVolume(mat1layerVolume); + if (fEnableWritingPointsScint) AddSensitiveVolume(mat2layerVolume); + } + + TGeoRotation* rotMirrorY = new TGeoRotation(); rotMirrorY->ReflectY(true); + TGeoRotation* rotMirrorX = new TGeoRotation(); rotMirrorX->ReflectX(true); + TGeoRotation* rotMirrorXY = new TGeoRotation(); rotMirrorXY->ReflectX(true); rotMirrorXY->ReflectY(true); + module->AddNode(cellVolume, 1, rotMirrorXY); + module->AddNode(cellVolume, 2, rotMirrorX); + module->AddNode(cellVolume, 3, rotMirrorY); + module->AddNode(cellVolume, 4, 0); +} + +//_____________________________________________________________________________________ +TGeoVolume* SpdEcalTB2::BuildModule() +{ + SpdEcalTB2GeoMapper* mapper = dynamic_cast<SpdEcalTB2GeoMapper*>(fGeoMapper); + if (!mapper) Fatal("SpdEcalTB2::BuildModule", "no mapper"); + + TString baseMedium = mapper->GetBaseMedium(); + TString absorberMedium = mapper->GetAbsorberMedium(); + TString scintMedium = mapper->GetScintMedium(); + + TGeoMedium* Air = FindMedium(baseMedium, ""); + TGeoMedium* Lead = FindMedium(absorberMedium, baseMedium); + TGeoMedium* Scint = FindMedium(scintMedium, baseMedium); + + Double_t layerInnerSizeTheta = mapper->GetLayerInnerSizeTheta(); + Double_t layerInnerSizePhi = mapper->GetLayerInnerSizePhi(); + Double_t layerOuterSizeTheta = mapper->GetLayerOuterSizeTheta(); + Double_t layerOuterSizePhi = mapper->GetLayerOuterSizePhi(); + Double_t cellClearance = mapper->GetCellClearance(); + + Int_t nLayers = mapper->GetNLayers(); + Double_t layer1SizeZ = mapper->GetLayer1SizeZ(); + Double_t layer2SizeZ = mapper->GetLayer2SizeZ(); + Double_t layerZSize = layer1SizeZ + layer2SizeZ; + Double_t totalZSize = nLayers * layerZSize; + + //build quarter of module into (+,+) quadrant + Double_t cellVertices[16]; + + cellVertices[0] = layerOuterSizeTheta + cellClearance/2; cellVertices[1] = cellClearance/2; + cellVertices[2] = cellClearance/2; cellVertices[3] = cellClearance/2; + cellVertices[4] = cellClearance/2; cellVertices[5] = layerOuterSizePhi + cellClearance/2; + cellVertices[6] = layerOuterSizeTheta + cellClearance/2; cellVertices[7] = layerOuterSizePhi + cellClearance/2; + + cellVertices[8] = layerInnerSizeTheta + cellClearance/2; cellVertices[9] = cellClearance/2; + cellVertices[10] = cellClearance/2; cellVertices[11] = cellClearance/2; + cellVertices[12] = cellClearance/2; cellVertices[13] = layerInnerSizePhi + cellClearance/2; + cellVertices[14] = layerInnerSizeTheta + cellClearance/2; cellVertices[15] = layerInnerSizePhi + cellClearance/2; + + TGeoVolume* cellVolume = gGeoManager->MakeArb8("Cell", Lead, totalZSize/2, cellVertices); + + // z ->-> from large to small side, X ~ theta, Y ~ phi + // dz (3rd argument) - half length in Z; + // xy[8][2] (4th argument) - vector of (x,y) coordinates of vertices: + // first four points (xy[i][j], i<4, j<2) are the (x,y) coordinates of the vertices sitting on the -dz plane; + // last four points (xy[i][j], i>=4, j<2) are the (x,y) coordinates of the vertices sitting on the +dz plane; + + Double_t moduleZbegin = -totalZSize/2; + Double_t moduleZend = totalZSize/2; + + for (Int_t ilayer = 0; ilayer < nLayers; ++ilayer) { + + Double_t layerZbegin = moduleZbegin + ilayer*(layerZSize); + Double_t layerZend = layerZbegin + layerZSize; + Double_t currZcenter = (layer1SizeZ + layer2SizeZ)*(-float(nLayers)/2 + 0.5 + ilayer); + + Double_t layer1Zbegin = layerZbegin; + Double_t layer1Zend = layerZbegin + layer1SizeZ; + Double_t layer2Zbegin = layerZbegin + layer1SizeZ; + Double_t layer2Zend = layerZend; + + Double_t layer1Vertices[16]; + for (int iv = 0; iv < 8; ++iv) { + Double_t interpT = (layer1Zbegin - moduleZbegin)/(moduleZend - moduleZbegin); + if (ilayer == 0) interpT = 0.; + layer1Vertices[iv] = LinearInterp(cellVertices[iv], cellVertices[iv+8], interpT); + } + for (int iv = 8; iv < 16; ++iv) { + Double_t interpT = (layer1Zend - moduleZbegin)/(moduleZend - moduleZbegin); + layer1Vertices[iv] = LinearInterp(cellVertices[iv-8], cellVertices[iv], interpT); + } + + TGeoVolume* mat1layerVolume = gGeoManager->MakeArb8("EcalBLeadCell", Lead, layer1SizeZ/2, layer1Vertices); + + Double_t layer2Vertices[16]; + for (int iv = 0; iv < 8; ++iv) { + Double_t interpT = (layer2Zbegin - moduleZbegin)/(moduleZend - moduleZbegin); + layer2Vertices[iv] = LinearInterp(cellVertices[iv], cellVertices[iv+8], interpT); + } + for (int iv = 8; iv < 16; ++iv) { + Double_t interpT = (layer2Zend - moduleZbegin)/(moduleZend - moduleZbegin); + if (ilayer == nLayers - 1) interpT = 1.; + layer2Vertices[iv] = LinearInterp(cellVertices[iv-8], cellVertices[iv], interpT); + } + TGeoVolume* mat2layerVolume = gGeoManager->MakeArb8("EcalBScintCell", Scint, layer2SizeZ/2, layer2Vertices); + + mat1layerVolume->SetFillColor(kBlue+4); + mat1layerVolume->SetLineColor(kBlue+4); + mat1layerVolume->SetTransparency(50); + + mat2layerVolume->SetFillColor(kCyan); + mat2layerVolume->SetLineColor(kCyan); + mat2layerVolume->SetTransparency(0); + + cellVolume->AddNode(mat1layerVolume, ilayer+1, + new TGeoTranslation(0, 0, currZcenter-(layer1SizeZ+layer2SizeZ)/2 + layer1SizeZ/2)); + cellVolume->AddNode(mat2layerVolume, ilayer+1, + new TGeoTranslation(0, 0, currZcenter+(layer1SizeZ+layer2SizeZ)/2 - layer2SizeZ/2)); + + if (fEnableWritingPointsAll) AddSensitiveVolume(mat1layerVolume); + if (fEnableWritingPointsScint) AddSensitiveVolume(mat2layerVolume); + } + + cellVolume->SetFillColor(kAzure+1); + cellVolume->SetLineColor(kAzure+1); + cellVolume->SetTransparency(50); + + Double_t moduleVertices[16]; + + moduleVertices[0] = layerOuterSizeTheta + cellClearance/2; moduleVertices[1] = -layerOuterSizePhi - cellClearance/2; + moduleVertices[2] = -layerOuterSizeTheta - cellClearance/2; moduleVertices[3] = -layerOuterSizePhi - cellClearance/2; + moduleVertices[4] = -layerOuterSizeTheta - cellClearance/2; moduleVertices[5] = layerOuterSizePhi + cellClearance/2; + moduleVertices[6] = layerOuterSizeTheta + cellClearance/2; moduleVertices[7] = layerOuterSizePhi + cellClearance/2; + + moduleVertices[8] = layerInnerSizeTheta + cellClearance/2; moduleVertices[9] = -layerInnerSizePhi - cellClearance/2; + moduleVertices[10] = -layerInnerSizeTheta - cellClearance/2; moduleVertices[11] = -layerInnerSizePhi - cellClearance/2; + moduleVertices[12] = -layerInnerSizeTheta - cellClearance/2; moduleVertices[13] = layerInnerSizePhi + cellClearance/2; + moduleVertices[14] = layerInnerSizeTheta + cellClearance/2; moduleVertices[15] = layerInnerSizePhi + cellClearance/2; + + TGeoVolume* moduleVolume = gGeoManager->MakeArb8("Module", Air, totalZSize/2, moduleVertices); + + //maintain convention left-to-right top-to-bottom + + TGeoRotation* rotMirrorY = new TGeoRotation(); rotMirrorY->ReflectY(true); + TGeoRotation* rotMirrorX = new TGeoRotation(); rotMirrorX->ReflectX(true); + TGeoRotation* rotMirrorXY = new TGeoRotation(); rotMirrorXY->ReflectX(true); rotMirrorXY->ReflectY(true); + moduleVolume->AddNode(cellVolume, 1, rotMirrorX); + moduleVolume->AddNode(cellVolume, 2, 0); + moduleVolume->AddNode(cellVolume, 3, rotMirrorXY); + moduleVolume->AddNode(cellVolume, 4, rotMirrorY); + + moduleVolume->SetTransparency(50); + moduleVolume->SetFillColor(kBlue); + moduleVolume->SetLineColor(kBlue); + + return moduleVolume; +} + +//_____________________________________________________________________________________ +SpdGeoMapper* SpdEcalTB2::GetMapper() +{ + if (fGeoMapper) return fGeoMapper; + + SpdGeoFactory* factory = SpdGeoFactory::Instance(); + + // search for mapper + fGeoMapper = factory->SearchForMapper("SpdEcalTB2GeoMapper"); + + // create default mapper + if (!fGeoMapper) fGeoMapper = factory->Mapper("SpdEcalTB2GeoMapper"); + + return fGeoMapper; +} + +//_____________________________________________________________________________ +Bool_t SpdEcalTB2::LoadParsFrom(SpdParSet* params) +{ + if (!params) return kFALSE; + + if (!SpdDetector::LoadParsFrom(params)) return kFALSE; + + TString mapper; + params->GetParameter("Mapper",mapper); + fGeoMapper = SpdGeoFactory::Instance()->Mapper(mapper); + if (fGeoMapper) fGeoMapper->LoadParametersFrom(params); + + fOutDataPointObject = "unknown"; + + if (fNDataOut < 1) return kTRUE; + + params->GetParameter("Detector/NOutData_1",fOutDataPointObject); + + return kTRUE; +} + +//_____________________________________________________________________________________ +TString SpdEcalTB2::GetDataOut(Int_t n) const +{ + if (n < 0 || n >= fNDataOut) return "unknown"; + return fOutDataPointObject; +} + +//_____________________________________________________________________________________ +TClonesArray* SpdEcalTB2::GetCollection(Int_t iColl) const +{ + return (iColl == 0) ? fPointCollection : 0; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________ +Int_t SpdEcalTB2::CreateMedium(const char* name) +{ + FairGeoLoader* geoLoad = FairGeoLoader::Instance(); + if (!geoLoad) return 0; + + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + if (!geoFace) return 0; + + FairGeoBuilder* geobuild = geoLoad->getGeoBuilder(); + if (!geobuild) return 0; + + FairGeoMedia* Media = geoFace->getMedia(); + if (!Media) return 0; + + return geobuild->createMedium(Media->getMedium(name)); +} + +//_____________________________________________________________________________ +TGeoVolume* SpdEcalTB2::GetModule(Int_t i = 0) const { + + if (i >= fUniqueModules.size()) { + cout << "-W- <SpdEcalTB2::GetModule> : module with id " << i << " not found, returning zero pointer" << endl; + return 0; + } + + return fUniqueModules[i]; +} + +//_____________________________________________________________________________ +void SpdEcalTB2::Print(Option_t*) const +{ + SpdDetector::Print(""); + + if (!fGeoMapper) return; + + TString divider('-',150); + + cout << "\n"; + + fGeoMapper->Print(""); + + cout << "\n"; + cout <<"\tNumber of unique modules: " << fUniqueModules.size() << endl; + cout << "\n"; + cout <<"\tCapacity (total): " << GetCapacity()*1e-6 << " [m^3] " << endl; + cout <<"\tMass (total): " << GetMass()*1e-3 << " [kg] " << endl; + cout <<"\tDensity (averaged): " << GetDensity() << " [g/cm^3] " << endl; + cout << "\n"; + + cout << "\n"; +} + diff --git a/ecalt/barrel/SpdEcalTB2.h b/ecalt/barrel/SpdEcalTB2.h new file mode 100644 index 0000000000000000000000000000000000000000..6ca6bb7bc8004ab13e795ee1ac721997125adb6b --- /dev/null +++ b/ecalt/barrel/SpdEcalTB2.h @@ -0,0 +1,149 @@ +// $Id$ +// Author: andre/artur 2020/07/31 + +#ifndef __SPDECALTB2_H__ +#define __SPDECALTB2_H__ + +#include <TLorentzVector.h> +#include <TString.h> +#include "FairDetector.h" +#include "SpdDetector.h" +#include "TGeoManager.h" +#include "TMatrixD.h" +#include <vector> +#include <tuple> +#include <set> + +using std::vector; +using std::set; +using std::tuple; +using std::pair; + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdEcalTB2 // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdEcalTB2Point; +class SpdEcalTB2Hits; + +class FairVolume; +class TClonesArray; +class TGeoMedium; +class TParticle; + + +class SpdEcalTB2: public SpdDetector { + +public: + + SpdEcalTB2(const char* Name, Bool_t Active); + SpdEcalTB2(); + + virtual ~SpdEcalTB2(); + + virtual void Initialize(); + virtual void Reset(); + virtual void Register(); + + virtual Bool_t ProcessHits(FairVolume* v = 0); + + virtual TString GetDataOut(Int_t n) const; + virtual TClonesArray* GetCollection(Int_t iColl) const; + + virtual SpdGeoMapper* GetMapper(); + + virtual void ConstructGeometry(); + + virtual void EndOfEvent(); + virtual void FinishRun(); + + virtual Bool_t LoadParsFrom(SpdParSet* params); + + virtual void Print(Option_t*) const; + + void EnableWritingPointsScint(Bool_t enable = true) { fEnableWritingPointsScint = enable; } + void EnableWritingPointsAll(Bool_t enable = true) { fEnableWritingPointsScint = enable; + fEnableWritingPointsAll = enable; } + + TGeoVolume* GetBasket() const { return fBasket; } + TGeoVolume* GetModule(Int_t i) const; + Int_t GetNModules() { return fUniqueModules.size(); } + +private: + + void AddHit(); + + /* Track information to be stored until the track leaves the active volume. */ + + Int_t fTrackID; //! track index + Int_t fDetID; //! detector id + Int_t fBasketID; //! basket id + Int_t fModuleZID; //! module Zid + Int_t fModulePhiID; //! module phi id + Int_t fCellID; //! cell id + Int_t fLayerID; //! layer number + TString fMatID; //! material + TLorentzVector fPos; //! position at entrance + TLorentzVector fMom; //! momentum at entrance + Double32_t fTime; //! time + Double32_t fLength; //! length + Double32_t fELoss; //! energy loss + TString fNodePath; //! + + Bool_t fEnableWritingPointsScint; + Bool_t fEnableWritingPointsAll; + + /* containers for data */ + + TString fOutDataPointObject; //! + TClonesArray* fPointCollection; //! + + SpdEcalTB2(const SpdEcalTB2&); + SpdEcalTB2& operator=(const SpdEcalTB2&); + + /* GEOMETRY */ + + void ConstructGeometry_1(); + + Int_t CreateMedium(const char* name); + + TMatrixD GetMatrixToRotateVectorTriplet(TVector3 initialVector1, TVector3 initialVector2, TVector3 initialVector3, + TVector3 finalVector1, TVector3 finalVector2, TVector3 finalVector3); + + TMatrixD GetMatrixToEmplaceModule(Double_t ax, Double_t ay, Bool_t rotateClockwise, TGeoVolume* moduleVolume); + + void GetEmplacedModulePosition(TGeoVolume* moduleVolume, + Double_t ax, Double_t ay, Double_t arhs, + Double_t ax2, Double_t ay2, Double_t arhs2, + Double_t & xMiddle, Double_t & yMiddle, + Double_t & ax_new, Double_t & ay_new, Double_t & arhs_new, + Double_t & xPlane2Bottom, Double_t & yPlane2Bottom, + Double_t & xPlane2Top, Double_t & yPlane2Top); + + void FillBasketFixedCells(TGeoVolume* basketVolume, TGeoVolume* moduleVolume); + void FillBasketTightly(TGeoVolume* basketVolume); + + pair <TGeoCombiTrans*, TGeoVolume*> StackModuleInSector(TGeoVolume* basketVolume, + Double_t angleModuleCenter, Double_t angleModulePeriph, Double_t moduleInnerSizeTheta); + + TGeoVolume* BuildModule(); + + void BuildModule(TGeoVolume* module); + void BuildBasket(); + void BuildBarrel(); + + Double_t LinearInterp(Double_t x1, Double_t x2, Double_t t); + + TGeoVolume* fBasket; //! + TGeoVolume* fModule; //! + vector<TGeoVolume*> fUniqueModules; //! + + ClassDef(SpdEcalTB2,1) +}; + + +#endif /* __SPDECALTB2_H__ */ diff --git a/ecalt/barrel/SpdEcalTB2Point.cxx b/ecalt/barrel/SpdEcalTB2Point.cxx new file mode 100644 index 0000000000000000000000000000000000000000..251b83bbbcac117056d50cd84244bda085353d63 --- /dev/null +++ b/ecalt/barrel/SpdEcalTB2Point.cxx @@ -0,0 +1,58 @@ +// $Id$ +// Author: andre 2020/07/31 + +#include "SpdEcalTB2Point.h" + +#include <iostream> +using std::cout; +using std::endl; + +ClassImp(SpdEcalTB2Point) + + +//_____________________________________________________________________________________ +SpdEcalTB2Point::SpdEcalTB2Point():FairMCPoint(), +fBasketID(0),fModuleZID(0),fModulePhiID(0),fCellID(0),fLayerID(0), +fMatID(""),fNodePath("") +{ + +} + +//_____________________________________________________________________________________ +SpdEcalTB2Point::SpdEcalTB2Point(Int_t trackID, Int_t detID, + Int_t basketID, Int_t moduleZID, Int_t modulePhiID, Int_t cellID, Int_t layerID, + TString matID, + TVector3 pos, TVector3 mom, Double_t tof, + Double_t length, Double_t eLoss, TString nodePath) +:FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), +fBasketID(basketID), fModuleZID(moduleZID), fModulePhiID(modulePhiID), fCellID(cellID), fLayerID(layerID), +fMatID(matID), fNodePath(nodePath) +{ + +} + +//_____________________________________________________________________________________ +SpdEcalTB2Point::~SpdEcalTB2Point() +{ + +} + +//_____________________________________________________________________________________ +void SpdEcalTB2Point::Print(const Option_t* opt) const +{ + cout << "<SpdEcalTB2Point::Print> " << endl; + cout << "\n"; + cout << " Track/DetectorID: " << fTrackID << "/" << fDetectorID << endl; + cout << " Basket: " << fBasketID << endl; + cout << " Module Z/П† ID: " << fModuleZID << "/" << fModulePhiID << endl; + cout << " Cell/Layer: " << fCellID << "/" << fLayerID << endl; + cout << " Material: " << fMatID << endl; + cout << " Node path: " << fNodePath << endl; + cout << " Position, Time: " << fX << ", " << fY << ", " << fZ << " [cm] " + << fTime << " [ns] " << endl; + cout << " Momentum: " << fPx << ", " << fPy << ", " << fPz << " [GeV]" << endl; + cout << " Energy loss: " << fELoss*1.0e06 << " [keV] " << endl; + cout << "\n"; +} + + diff --git a/ecalt/barrel/SpdEcalTB2Point.h b/ecalt/barrel/SpdEcalTB2Point.h new file mode 100644 index 0000000000000000000000000000000000000000..f7f413a5521896ee8b08721fdc7d284fe49c2fb3 --- /dev/null +++ b/ecalt/barrel/SpdEcalTB2Point.h @@ -0,0 +1,82 @@ +// $Id$ +// Author: andre 2020/07/31 + +#ifndef __SPDECALTB2POINT_H__ +#define __SPDECALTB2POINT_H__ + +#include <TVector3.h> +#include "FairMCPoint.h" + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdEcalTB2GeoPoint // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdEcalTB2Point : public FairMCPoint { + +public: + + /** Constructor with arguments + *@param trackID Index of MCTrack + *@param detID Detector ID + *@param cellID Cell ID + *@param submodID SubModule ID + *@param pos Coordinates at entrance to active volume [cm] + *@param mom Momentum of track at entrance [GeV] + *@param tof Time since event start [ns] + *@param length Track length since creation [cm] + *@param ELoss Energy deposit [GeV] + *@param nodePath Node Path (TString) + **/ + + SpdEcalTB2Point(); + + SpdEcalTB2Point(Int_t fTrackID, Int_t fDetID, + Int_t fBasketID, Int_t fModuleZID, Int_t fModulePhiID, Int_t fCellID, Int_t fLayerID, + TString fMatID, + TVector3 pos, TVector3 mom, + Double_t tof, Double_t length, Double_t ELoss, + TString nodePath); + + SpdEcalTB2Point(const SpdEcalTB2Point& point) { *this = point; }; + + virtual ~SpdEcalTB2Point(); + + inline Int_t GetBasketID() const { return fBasketID; } + inline Int_t GetModuleZID() const { return fModuleZID; } + inline Int_t GetModulePhiID() const { return fModulePhiID; } + inline Int_t GetCellID() const { return fCellID; } + inline Int_t GetLayerID() const { return fLayerID; } + + inline TString GetMaterialID() const { return fMatID; } + + inline Double_t GetEloss() const { return fELoss; } //->FairMCPoint + inline Double_t GetTime() const { return fTime; } //->FairMCPoint + inline Double_t GetLength() const { return fLength; } //->FairMCPoint + + TVector3 GetPosition() const { return TVector3(fPx,fPy,fPz); } + TVector3 GetMomentum() const { return TVector3(fX,fY,fZ); } + + TString GetNodePath() const { return fNodePath; } + + virtual void Print(const Option_t* opt) const; + +private: + + Int_t fBasketID; + Int_t fModuleZID; + Int_t fModulePhiID; + Int_t fCellID; + Int_t fLayerID; + + TString fMatID; + + TString fNodePath; + + ClassDef(SpdEcalTB2Point,1) +}; + +#endif /* __SPDECALTB2POINT_H__ */ diff --git a/ecalt/ecps/SpdEcalTEC.cxx b/ecalt/ecps/SpdEcalTEC.cxx index f9119227222f3a1d92fd5c54bacfcfac5a54c905..ce9cad9fbbaf2260ad5b95051f295ad69b73f1bb 100644 --- a/ecalt/ecps/SpdEcalTEC.cxx +++ b/ecalt/ecps/SpdEcalTEC.cxx @@ -40,7 +40,7 @@ ClassImp(SpdEcalTEC) //_____________________________________________________________________________________ SpdEcalTEC::SpdEcalTEC(): - SpdDetector("Ecal endcaps (tor)", kSpdEcalTEC, kTRUE), + SpdDetector("Ecal endcaps (qsl)", kSpdEcalTEC, kTRUE), fTrackID(-1), fVolumeID1(-1),fVolumeID2(-1),fVolumeID3(-1), fPos(), diff --git a/ecalt/ecps/SpdEcalTEC2.cxx b/ecalt/ecps/SpdEcalTEC2.cxx new file mode 100644 index 0000000000000000000000000000000000000000..55ecbed765625bbc048e3129ede9f094a5bf9c56 --- /dev/null +++ b/ecalt/ecps/SpdEcalTEC2.cxx @@ -0,0 +1,552 @@ +// $Id$ +// Author: andre/artur 2020/07/31 + +#include "SpdEcalTEC2.h" + +#include "FairVolume.h" +#include "FairGeoVolume.h" +#include "FairGeoNode.h" +#include "FairRootManager.h" +#include "FairGeoLoader.h" +#include "FairGeoInterface.h" +#include "FairGeoLoader.h" +#include "FairGeoBuilder.h" +#include "FairGeoMedia.h" +#include "FairRun.h" +#include "FairRunSim.h" +#include "FairRuntimeDb.h" + +#include "TRefArray.h" +#include "TClonesArray.h" +#include "TParticle.h" +#include "TVirtualMC.h" +#include "TGeoManager.h" +#include "TGeoBBox.h" +#include "TGeoPgon.h" +#include "TGeoCompositeShape.h" +#include "TGeoTube.h" +#include "TGeoMaterial.h" +#include "TGeoMedium.h" +#include "TMatrixD.h" + +#include "SpdEcalTEC2.h" +#include "SpdEcalTEC2Point.h" +#include "SpdEcalTEC2GeoMapper.h" +#include "SpdCommonGeoMapper.h" +#include "SpdDetectorList.h" +#include "SpdStack.h" +#include "SpdParSet.h" +#include "SpdGeoFactory.h" + +#include <map> +#include <iostream> +#include <vector> + +using namespace std; + +using std::cout; +using std::endl; + +ClassImp(SpdEcalTEC2) + +//_____________________________________________________________________________________ +SpdEcalTEC2::SpdEcalTEC2(): + + SpdDetector("Ecal endcaps (tor)", kSpdEcalTEC, kTRUE), + fTrackID(-1), + fDetID(-1),fEndcapID(-1),fModuleID(-1), fCellID(-1), fLayerID(-1), fMatID(""), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fEnableWritingPointsScint(kTRUE), + fEnableWritingPointsAll(kFALSE), + fPointCollection(0), + fEndcap(0), + fModule(0), + fCell(0) +{ + SetParametersType("EcalTECParSet"); + + fNDataOut = 1; + fOutDataPointObject = "SpdEcalTEC2Point"; +} + +//_____________________________________________________________________________________ +SpdEcalTEC2::SpdEcalTEC2(const char* name, Bool_t active): + + SpdDetector(name, kSpdEcalTEC, active), + fTrackID(-1), + fDetID(-1),fEndcapID(-1),fModuleID(-1), fCellID(-1), fLayerID(-1), fMatID(""), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fEnableWritingPointsScint(kTRUE), + fEnableWritingPointsAll(kFALSE), + fPointCollection(0), + fEndcap(0), + fModule(0), + fCell(0) +{ + SetParametersType("EcalTECParSet"); + + fNDataOut = 1; + fOutDataPointObject = "SpdEcalTEC2Point"; +} + +//_____________________________________________________________________________________ +SpdEcalTEC2::~SpdEcalTEC2() +{ + if (fPointCollection) { + fPointCollection->Delete(); + delete fPointCollection; + fPointCollection = 0; + } +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2::Initialize() +{ + cout << "\n*******************************************************************************" << endl; + cout << "************************* SpdEcalTEC2::Initialize *****************************" << endl; + cout << "*******************************************************************************\n" << endl; + + // data collections + fPointCollection = new TClonesArray(fOutDataPointObject); + + // Initialize module and fill parameters + SpdDetector::Initialize(); + + // SpdParSet* pars = GetParameters(); + // if (pars) pars->printParams(); +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2::Reset() +{ + fPointCollection->Clear(); +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2::Register() +{ + if (!fGeoMapper) return; + + if (!fEnableWritingPointsScint) return; + + FairRootManager::Instance()->Register(fOutDataPointObject,"SpdEcalTEC2", + fPointCollection, kTRUE); +} + +//_____________________________________________________________________________________ +Bool_t SpdEcalTEC2::ProcessHits(FairVolume* vol) +{ + //cout << "<SpdEcalTEC2::ProcessHits> " << endl; + + //Set parameters at entrance of volume. Reset ELoss. + if (gMC->IsTrackEntering()) { + //cout << "track entering\n"; + fELoss = 0.; + fTime = gMC->TrackTime() * 1.e9; // ns -> s + fLength = gMC->TrackLength(); + gMC->TrackPosition(fPos); + gMC->TrackMomentum(fMom); + } + + // Sum energy loss for all steps in the active volume + fELoss += gMC->Edep(); + + // Create SpdEcalTEC2Point at exit of active volume + if ( gMC->IsTrackExiting() || + gMC->IsTrackStop() || + gMC->IsTrackDisappeared() ) + { + + if (!fSaveEmptyHits && fELoss == 0.) { return kFALSE; } + + fTrackID = gMC->GetStack()->GetCurrentTrackNumber(); + + fNodePath = gMC->CurrentVolPath(); + SpdGeopathParser parser; + parser.ParsePath(fNodePath); + + //cave: 1, endcap: 2, module:3, cell:4, layer:5, lead/scint:6 + fDetID = kSpdEcalTEC; + fEndcapID = parser.Num(2, true)*2 - 3; //-1: negative Z, +1: positive Z + fModuleID = parser.Num(3, true); + fCellID = parser.Num(4, true); + fLayerID = parser.Num(5, true); + fMatID = parser.Name(6, true); + + //cout << " <<< ENDCAP >>> " << fMatID << " " << gMC->CurrentVolPath() << endl; + + assert(fMatID == "EcalECLeadCell" || fMatID == "EcalECScintCell"); + + if (fEnableWritingPointsAll) AddHit(); + else if (fEnableWritingPointsScint && fMatID == "EcalECScintCell") AddHit(); + + SpdStack* stack = (SpdStack*)gMC->GetStack(); + stack->AddPoint(kSpdEcalTEC); + } + + return kTRUE; +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2::AddHit() +{ + static Bool_t addhit = (fOutDataPointObject == "SpdEcalTEC2Point") ? kTRUE : kFALSE; + + if (!addhit) return; + + TClonesArray& clref = *fPointCollection; + Int_t size = clref.GetEntriesFast(); + + //cout << "SpdEcalTEC2::AddHit: Adding hit: " << fTrackID << " " << fDetID << " " << fEndcapID << " " << fVolumeID3 << " " << + // fPos.X() << " " << fPos.Y() << " " << fPos.Z() << " " << + // fMom.Px() << " " << fMom.Py() << " " << fMom.Pz() << " " << + // fTime << " " << fLength << " " << fELoss << " path = " << fNodePath <<"\n"; + + new(clref[size]) SpdEcalTEC2Point(fTrackID,fDetID,fEndcapID,fModuleID, fCellID, fLayerID, fMatID, + TVector3(fPos.X(),fPos.Y(),fPos.Z()), + TVector3(fMom.Px(),fMom.Py(),fMom.Pz()), + fTime, fLength, fELoss, fNodePath); +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2::EndOfEvent() +{ + Reset(); +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2::FinishRun() +{ + //SpdDetector::FinishRun(); + FillNodesTableIn(GetParameters()); +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2::ConstructGeometry() +{ + fMasterVolume = SpdCommonGeoMapper::Instance()->GetMasterVolume(); + + if (!fMasterVolume) { + cout << "-E- <SpdIts::ConstructGeometry> No MASTER volume " << endl; + return; + } + + if (!GetMapper()) return; + + if (!fGeoMapper->InitGeometry()) return; + + //fGeoMapper->Print(""); + + Int_t geo_type = fGeoMapper->GetGeoType(); + + BuildGeometry(); + + fGeoMapper->LockGeometry(); + + cout << "\n*******************************************************************************" << endl; + cout << "********************** SpdEcalTEC2::ConstructGeometry *************************" << endl; + cout << "********************** GEOMETRY TYPE: " << geo_type + << " ***************************************" << endl; + cout << "*******************************************************************************\n" << endl; +} + +//________________________________________________________________________________ +void SpdEcalTEC2::BuildGeometry() +{ + BuildEndcap(); + + SpdEcalTEC2GeoMapper* mapper = dynamic_cast<SpdEcalTEC2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + Double_t zshift = mapper->GetEndcapMinDist() + 0.5*mapper->GetEndcapThickness(); + + fMasterVolume->AddNode(fEndcap, 1, new TGeoTranslation(0, 0,-zshift)); + fMasterVolume->AddNode(fEndcap, 2, new TGeoTranslation(0, 0, zshift)); +} + +//________________________________________________________________________________ +void SpdEcalTEC2::BuildEndcap() +{ + BuildModule(); + + SpdEcalTEC2GeoMapper* mapper = dynamic_cast<SpdEcalTEC2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + Double_t endcapThickness = mapper->GetEndcapThickness(); + Double_t endCapHoleRadius = mapper->GetEndcapSize() - mapper->GetEndcapWidth(); + Double_t layerEndcapSize = mapper->GetCellSize(); + Double_t cellClearance = mapper->GetCellClearance(); + Double_t moduleClearance = mapper->GetModuleClearance(); + Double_t endcapSize = mapper->GetEndcapSize(); + TString baseMedium = mapper->GetBaseMedium(); + + TGeoMedium* Air = FindMedium(baseMedium, ""); + + fEndcap = gGeoManager->MakePgon("Endcap", Air, 22.5, 360, 8, 2); + + TGeoPgon* pgonOuter = (TGeoPgon*)(fEndcap->GetShape()); + pgonOuter->DefineSection(0, -endcapThickness/2, endCapHoleRadius, endcapSize); + pgonOuter->DefineSection(1, endcapThickness/2, endCapHoleRadius, endcapSize); + + Double_t cellSize = 2*layerEndcapSize + cellClearance; + Double_t nCellsXY = 1; + Double_t totalXFilled = cellSize; + + while (totalXFilled < 2*endcapSize) { + totalXFilled += cellSize + moduleClearance; + nCellsXY += 1; + } + + nCellsXY -= 1; + totalXFilled -= (cellSize + moduleClearance); + + if (nCellsXY >= 1000) { + cout << "-E- <SpdEcalTEC2::ConstructGeometry_1> " + << "Number of modules >= 1000. Decrease cell size or remake the module naming scheme." << endl; + exit(1); + } + + Double_t gridLeftX = -totalXFilled/2; + Double_t gridBottomY = -totalXFilled/2; + + TGeoTranslation* currentModuleTrans; + + Double_t corner[3] = {0,0,0}; + + for (Int_t ix = 0; ix < nCellsXY; ++ix) { + for (Int_t iy = 0; iy < nCellsXY; ++iy) { + + corner[0] = gridLeftX + ix*(cellSize + moduleClearance); + corner[1] = gridBottomY + iy*(cellSize + moduleClearance); + + if (!fEndcap->Contains(corner)) continue; + corner[1] += cellSize; + if (!fEndcap->Contains(corner)) continue; + corner[0] += cellSize; + if (!fEndcap->Contains(corner)) continue; + corner[1] -= cellSize; + if (!fEndcap->Contains(corner)) continue; + corner[0] -= cellSize; + + currentModuleTrans = new TGeoTranslation(corner[0] + cellSize/2, corner[1] + cellSize/2, corner[2]); + + fEndcap->AddNode(fModule, (iy+1)*1000 + ix+1, currentModuleTrans); + } + } + + fEndcap->SetLineColor(kBlue); + fEndcap->SetFillColor(kBlue); + fEndcap->SetTransparency(50); +} + +//________________________________________________________________________________ +void SpdEcalTEC2::BuildModule() +{ + BuildCell(); + + SpdEcalTEC2GeoMapper* mapper = dynamic_cast<SpdEcalTEC2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + TString baseMedium = mapper->GetBaseMedium(); + TGeoMedium* Air = FindMedium(baseMedium, ""); + + Double_t halfsizeModule = mapper->GetCellSize() + 0.5*mapper->GetCellClearance(); + Double_t shift = 0.5*mapper->GetCellSize() + 0.5*mapper->GetCellClearance(); + + fModule = gGeoManager->MakeBox("Module", Air, halfsizeModule, halfsizeModule, 0.5*mapper->GetEndcapThickness()); + + fModule->AddNode(fCell, 1, new TGeoTranslation(-shift, shift, 0)); + fModule->AddNode(fCell, 2, new TGeoTranslation( shift, shift, 0)); + fModule->AddNode(fCell, 3, new TGeoTranslation(-shift, -shift, 0)); + fModule->AddNode(fCell, 4, new TGeoTranslation( shift, -shift, 0)); + + fModule->SetFillColor(kBlue); + fModule->SetLineColor(kBlue); + fModule->SetTransparency(50); +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2::BuildCell() +{ + SpdEcalTEC2GeoMapper* mapper = dynamic_cast<SpdEcalTEC2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + TString baseMedium = mapper->GetBaseMedium(); + TString absorberMedium = mapper->GetAbsorberMedium(); + TString scintMedium = mapper->GetScintMedium(); + Double_t layerEndcapSize = mapper->GetCellSize(); + Double_t endcapThickness = mapper->GetEndcapThickness(); + Double_t layer1SizeZ = mapper->GetLayer1SizeZ(); + Double_t layer2SizeZ = mapper->GetLayer2SizeZ(); + TGeoMedium* Air = FindMedium(baseMedium, ""); + TGeoMedium* Lead = FindMedium(absorberMedium, baseMedium); + TGeoMedium* Scint = FindMedium(scintMedium, baseMedium); + + // construct active volumes + TGeoVolume* mat1layer = gGeoManager->MakeBox("EcalECLeadCell", Lead, + layerEndcapSize/2, layerEndcapSize/2, layer1SizeZ/2); + TGeoVolume* mat2layer = gGeoManager->MakeBox("EcalECScintCell", Scint, + layerEndcapSize/2, layerEndcapSize/2, layer2SizeZ/2); + + if (fEnableWritingPointsScint) AddSensitiveVolume(mat2layer); // ATTENTION + if (fEnableWritingPointsAll) AddSensitiveVolume(mat1layer); // ATTENTION + + // construct layer + TGeoVolume* layer = gGeoManager->MakeBox("Layer", Air, layerEndcapSize/2, layerEndcapSize/2, (layer1SizeZ+layer2SizeZ)/2); + + layer->AddNode(mat1layer, 1, new TGeoTranslation(0, 0, -(layer1SizeZ+layer2SizeZ)/2 + layer1SizeZ/2)); + layer->AddNode(mat2layer, 1, new TGeoTranslation(0, 0, (layer1SizeZ+layer2SizeZ)/2 - layer2SizeZ/2)); + + // construct cell + fCell = gGeoManager->MakeBox("Cell", Lead, layerEndcapSize/2, layerEndcapSize/2, endcapThickness/2); + + Int_t nLayers = floor(endcapThickness/(layer1SizeZ + layer2SizeZ)); + Double_t currZcenter; + + for (Int_t ilayer = 0; ilayer < nLayers; ++ilayer) { + currZcenter = (layer1SizeZ + layer2SizeZ) * (-nLayers/2. + 0.5 + ilayer); + fCell->AddNode(layer, ilayer+1, new TGeoTranslation(0, 0, currZcenter)); + } + + layer->SetFillColor(kAzure+1); + layer->SetLineColor(kAzure+1); + layer->SetTransparency(50); + + mat1layer->SetFillColor(kBlue+4); + mat1layer->SetLineColor(kBlue+4); + mat1layer->SetTransparency(50); + + mat2layer->SetFillColor(kCyan); + mat2layer->SetLineColor(kCyan); + mat2layer->SetTransparency(50); + + fCell->SetFillColor(kAzure+1); + fCell->SetLineColor(kAzure+1); + fCell->SetTransparency(50); +} + +//_____________________________________________________________________________________ +SpdGeoMapper* SpdEcalTEC2::GetMapper() +{ + if (fGeoMapper) return fGeoMapper; + + SpdGeoFactory* factory = SpdGeoFactory::Instance(); + + // search for mapper + fGeoMapper = factory->SearchForMapper("SpdEcalTEC2GeoMapper"); + + // create default mapper + if (!fGeoMapper) fGeoMapper = factory->Mapper("SpdEcalTEC2GeoMapper"); + + return fGeoMapper; +} + +//_____________________________________________________________________________ +Bool_t SpdEcalTEC2::LoadParsFrom(SpdParSet* params) +{ + if (!params) return kFALSE; + + if (!SpdDetector::LoadParsFrom(params)) return kFALSE; + + TString mapper; + params->GetParameter("Mapper",mapper); + fGeoMapper = SpdGeoFactory::Instance()->Mapper(mapper); + if (fGeoMapper) fGeoMapper->LoadParametersFrom(params); + + fOutDataPointObject = "unknown"; + + if (fNDataOut < 1) return kTRUE; + + params->GetParameter("Detector/NOutData_1",fOutDataPointObject); + + return kTRUE; +} + +//_____________________________________________________________________________________ +TString SpdEcalTEC2::GetDataOut(Int_t n) const +{ + if (n < 0 || n >= fNDataOut) return "unknown"; + return fOutDataPointObject; +} + +//_____________________________________________________________________________________ +TClonesArray* SpdEcalTEC2::GetCollection(Int_t iColl) const +{ + return (iColl == 0) ? fPointCollection : 0; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +Double_t SpdEcalTEC2::GetCapacity() const +{ + // return (fEndcap) ? fEndcap->GetShape()->Capacity() : 0; + return 0; +} + +//_____________________________________________________________________________________ +Double_t SpdEcalTEC2::GetMass() const +{ + return (fEndcap) ? GetCapacity()*GetDensity() : 0; +} + +//_____________________________________________________________________________________ +Double_t SpdEcalTEC2::GetDensity() const +{ + return (fEndcap) ? fEndcap->GetMaterial()->GetDensity() : 0; +} + +//_____________________________________________________________________________ +void SpdEcalTEC2::Print(Option_t*) const +{ + SpdDetector::Print(""); + + if (!fGeoMapper) return; + + TString divider('-',150); + + cout << "\n"; + + fGeoMapper->Print(""); + + cout << "\n"; + cout <<"\tCapacity (total): " << GetCapacity()*1e-6 << " [m^3] " << endl; + cout <<"\tMass (total): " << GetMass()*1e-3 << " [kg] " << endl; + cout <<"\tDensity (averaged): " << GetDensity() << " [g/cm^3] " << endl; + cout << "\n"; + + cout << "\n" << divider.Data() << "\n"; + printf("%6s %4s %15s %14s %14s %14s \n\n","Type","N","Material","Dens [g/cm^3]","Volume [m^3]","Mass [kg]"); + + if (!fEndcap) { + cout << "\n"; + return; + } + + printf("%6d %4d %15s %14.6f %14.6f %14.6f \n", + 1, 1, fEndcap->GetMaterial()->GetName(), + GetDensity(), GetCapacity()*1e-6, GetMass()*1e-3); + printf("%6d %4d %15s %14.6f %14.6f %14.6f \n", + 1, 2, fEndcap->GetMaterial()->GetName(), + GetDensity(), GetCapacity()*1e-6, GetMass()*1e-3); + + cout << divider.Data() << "\n"; + + printf("%6s %35s %14.3e %14.3e \n","TOTAL:","",2*GetCapacity()*1e-6,2*GetMass()*1e-3); + + cout << divider.Data() << "\n"; + + cout << "\n"; + +} + diff --git a/ecalt/ecps/SpdEcalTEC2.h b/ecalt/ecps/SpdEcalTEC2.h new file mode 100644 index 0000000000000000000000000000000000000000..b6a20deab23b6fc78689f22fc8248b8bf54fc85e --- /dev/null +++ b/ecalt/ecps/SpdEcalTEC2.h @@ -0,0 +1,120 @@ +// $Id$ +// Author: andre/artur 2020/07/31 + +#ifndef __SPDECALTEC2_H__ +#define __SPDECALTEC2_H__ + +#include <TLorentzVector.h> +#include <TString.h> +#include "FairDetector.h" +#include "SpdDetector.h" +#include "TGeoManager.h" +#include "TMatrixD.h" +#include <vector> + +using std::vector; + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdEcalTEC2 // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdEcalTEC2Point; +class SpdEcalTEC2Hits; + +class FairVolume; +class TClonesArray; +class TGeoMedium; +class TParticle; + +class SpdEcalTEC2: public SpdDetector { + +public: + + SpdEcalTEC2(const char* Name, Bool_t Active); + SpdEcalTEC2(); + + virtual ~SpdEcalTEC2(); + + virtual void Initialize(); + virtual void Reset(); + virtual void Register(); + + virtual Bool_t ProcessHits(FairVolume* v = 0); + + virtual TString GetDataOut(Int_t n) const; + virtual TClonesArray* GetCollection(Int_t iColl) const; + + virtual Double_t GetCapacity() const; // cm^3 + virtual Double_t GetMass() const; // g + virtual Double_t GetDensity() const; // g/cm^3 + + virtual SpdGeoMapper* GetMapper(); + + virtual void ConstructGeometry(); + + virtual void EndOfEvent(); + virtual void FinishRun(); + + virtual Bool_t LoadParsFrom(SpdParSet* params); + + virtual void Print(Option_t*) const; + + void EnableWritingPointsScint(Bool_t enable = true) { fEnableWritingPointsScint = enable; } + void EnableWritingPointsAll(Bool_t enable = true) { fEnableWritingPointsScint = enable; + fEnableWritingPointsAll = enable; } + + TGeoVolume* GetEndcap() const { return fEndcap; } + TGeoVolume* GetModule() const { return fModule; } + TGeoVolume* GetCell() const { return fCell; } + +private: + + void AddHit(); + + /* Track information to be stored until the track leaves the active volume. */ + + Int_t fTrackID; //! track index + Int_t fDetID; //! detector ID + Int_t fEndcapID; //! endcap ID (+1 for +Z, -1 for -Z) + Int_t fModuleID; //! module ID + Int_t fCellID; //! cell ID + Int_t fLayerID; //! layer ID + TString fMatID; //! material name ("LEAD" etc. - if writing points in absorber is enabled or "SCINT" etc.) + TLorentzVector fPos; //! position at entrance + TLorentzVector fMom; //! momentum at entrance + Double32_t fTime; //! time + Double32_t fLength; //! length + Double32_t fELoss; //! energy loss + TString fNodePath; //! + + Bool_t fEnableWritingPointsScint; + Bool_t fEnableWritingPointsAll; + + /* containers for data */ + + TString fOutDataPointObject; //! + TClonesArray* fPointCollection; //! + + SpdEcalTEC2(const SpdEcalTEC2&); + SpdEcalTEC2& operator=(const SpdEcalTEC2&); + + /* GEOMETRY */ + + void BuildGeometry(); + + void BuildEndcap(); + void BuildModule(); + void BuildCell(); + + TGeoVolume* fEndcap; //! + TGeoVolume* fModule; //! + TGeoVolume* fCell; //! + + ClassDef(SpdEcalTEC2,1) +}; + +#endif /* __SPDECALTEC2_H__ */ diff --git a/ecalt/ecps/SpdEcalTEC2Point.cxx b/ecalt/ecps/SpdEcalTEC2Point.cxx new file mode 100644 index 0000000000000000000000000000000000000000..9ed66a0077a6db6607e62a046a83a07354b2cbae --- /dev/null +++ b/ecalt/ecps/SpdEcalTEC2Point.cxx @@ -0,0 +1,53 @@ +// $Id$ +// Author: andre 2020/07/31 + +#include "SpdEcalTEC2Point.h" + +#include <iostream> +using std::cout; +using std::endl; + +ClassImp(SpdEcalTEC2Point) + +//_____________________________________________________________________________________ +SpdEcalTEC2Point::SpdEcalTEC2Point():FairMCPoint(), +fEndcapID(0),fModuleID(0),fCellID(0),fLayerID(0),fMatID(""),fNodePath("") +{ + +} + +//_____________________________________________________________________________________ +SpdEcalTEC2Point::SpdEcalTEC2Point(Int_t trackID, Int_t detID, Int_t endcapID, Int_t moduleID, Int_t cellID, Int_t layerID, + TString matID, + TVector3 pos, TVector3 mom, Double_t tof, Double_t length, Double_t eLoss, + TString nodePath) +:FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), +fEndcapID(endcapID),fModuleID(moduleID),fCellID(cellID),fLayerID(layerID), +fMatID(matID),fNodePath(nodePath) +{ + +} + +//_____________________________________________________________________________________ +SpdEcalTEC2Point::~SpdEcalTEC2Point() +{ + +} + +//_____________________________________________________________________________________ +void SpdEcalTEC2Point::Print(const Option_t* opt) const +{ + cout << "<SpdEcalTEC2Point::Print> " << endl; + cout << "\n"; + cout << " EventID: " << fEventId << endl; + cout << " Track/DetectorID: " << fTrackID << "/" << fDetectorID << endl; + cout << " Endcap/Module: " << fEndcapID << "/" << fModuleID << endl; + cout << " Cell/Layer: " << fCellID << "/" << fLayerID << endl; + cout << " Material: " << fMatID << endl; + cout << " Node path: " << fNodePath << endl; + cout << " Position, Time: " << fX << ", " << fY << ", " << fZ << " [cm] " << fTime << " [ns] " << endl; + cout << " Momentum: " << fPx << ", " << fPy << ", " << fPz << " [GeV]" << endl; + cout << " Energy loss: " << fELoss*1.0e06 << " [keV] " << endl; + cout << "\n"; +} + diff --git a/ecalt/ecps/SpdEcalTEC2Point.h b/ecalt/ecps/SpdEcalTEC2Point.h new file mode 100644 index 0000000000000000000000000000000000000000..d4de049d223235e98bcdb33211d6cfad4a532af8 --- /dev/null +++ b/ecalt/ecps/SpdEcalTEC2Point.h @@ -0,0 +1,84 @@ +// $Id$ +// Author: andre 2020/07/31 + +#ifndef __SpdEcalTEC2ECPOINT_H__ +#define __SpdEcalTEC2ECPOINT_H__ + +#include <TVector3.h> +#include "FairMCPoint.h" + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdEcalTEC2GeoPoint // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdEcalTEC2Point : public FairMCPoint { + +public: + + /** Constructor with arguments + *@param trackID Index of MCTrack + *@param detID Detector ID + *@param endcapID Endcap ID + *@param moduleID Module ID + *@param cellID Cell ID + *@param layerID Layer ID + *@param matID Node material + *@param pos Coordinates at entrance to active volume [cm] + *@param mom Momentum of track at entrance [GeV] + *@param tof Time since event start [ns] + *@param length Track length since creation [cm] + *@param ELoss Energy deposit [GeV] + *@param nodePath Full node geopath + **/ + + SpdEcalTEC2Point(); + + SpdEcalTEC2Point(Int_t trackID, Int_t detID, Int_t endcapID, Int_t moduleID, Int_t cellID, Int_t layerID, + TString matID, + TVector3 pos, TVector3 mom, Double_t tof, Double_t length, Double_t ELoss, + TString nodePath); + + SpdEcalTEC2Point(const SpdEcalTEC2Point& point) { *this = point; }; + + virtual ~SpdEcalTEC2Point(); + + // Int_t FairMCPoint::GetDetectorID() const; + // Int_t FairMCPoint::GetTrackID() const; + + inline Int_t GetEndcapID() const { return fEndcapID; } + inline Int_t GetModuleID() const { return fModuleID; } + inline Int_t GetCellID() const { return fCellID; } + inline Int_t GetLayerID() const { return fLayerID; } + + inline TString GetMaterialID() const { return fMatID; } + + inline Double_t GetEloss() const { return fELoss; } //->FairMCPoint + inline Double_t GetTime() const { return fTime; } //->FairMCPoint + inline Double_t GetLength() const { return fLength; } //->FairMCPoint + + TVector3 GetPosition() const { return TVector3(fPx,fPy,fPz); } + TVector3 GetMomentum() const { return TVector3(fX,fY,fZ); } + + TString GetNodePath() const { return fNodePath; } + + virtual void Print(const Option_t* opt) const; + +private: + + Int_t fEndcapID; + Int_t fModuleID; + Int_t fCellID; + Int_t fLayerID; + + TString fMatID; + TString fNodePath; + + ClassDef(SpdEcalTEC2Point,1) + +}; + +#endif /* __SpdEcalTEC2ECPOINT_H__ */ diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 8c1318ed9fedccf5984c15bbcf36adc3693bbc5c..b6ac6f4e290e283de13bba90360213f91cc81100 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -7,3 +7,5 @@ ELSE() SET(GENFIT2_IS_DEFINED true CACHE BOOL "GENFIT2_IS_DEFINED" FORCE) ENDIF() +add_subdirectory (KFParticle) + diff --git a/external/GenFit2/core/src/MeasuredStateOnPlane.cc b/external/GenFit2/core/src/MeasuredStateOnPlane.cc index 794b5bd5aef7634864096440bd39750b9011963d..a5fa0dca10e88d748bd6318650a20e1025637abb 100644 --- a/external/GenFit2/core/src/MeasuredStateOnPlane.cc +++ b/external/GenFit2/core/src/MeasuredStateOnPlane.cc @@ -142,11 +142,17 @@ MeasuredStateOnPlane calcAverageState(const MeasuredStateOnPlane& forwardState, // averaging. TDecompChol d1(forwardState.getCov()); bool success = d1.Decompose(); + //printf("success (1): %d \n",success); TDecompChol d2(backwardState.getCov()); success &= d2.Decompose(); + //printf("success (2): %d \n",success); if (!success) { Exception e("KalmanFitterInfo::calcAverageState: ill-conditioned covariance matrix.", __LINE__,__FILE__); + //std::cout << "--------------------" << std::endl; + //backwardState.Print(); + //std::cout << "--------------------" << std::endl; + //d2.Print(); throw e; } diff --git a/external/KFParticle/CMakeLists.txt b/external/KFParticle/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..327d4c59a80543733e7270b8a6b1d30173d06998 --- /dev/null +++ b/external/KFParticle/CMakeLists.txt @@ -0,0 +1,56 @@ + +# +# Create a library called "KFParticle" +# + +set(INCLUDE_DIRECTORIES +${SYSTEM_INCLUDE_DIRECTORIES} +${BASE_INCLUDE_DIRECTORIES} +${ROOT_INCLUDE_DIR} +${CMAKE_SOURCE_DIR}/external/KFParticle +${CMAKE_SOURCE_DIR}/external/KFParticle/KFParticle +${CMAKE_SOURCE_DIR}/external/KFParticle/KFParticlePerformance +) + +include_directories( ${INCLUDE_DIRECTORIES}) + +set(LINK_DIRECTORIES +${ROOT_LIBRARY_DIR} +${FAIRROOT_LIBRARY_DIR} +) + +link_directories( ${LINK_DIRECTORIES}) + +set (SRCS + KFParticle/KFParticleTopoReconstructor.cxx + KFParticle/KFVertex.cxx + KFParticle/KFPTrack.cxx + KFParticle/KFPTrackVector.cxx + KFParticle/KFPVertex.cxx + KFParticle/KFParticlePVReconstructor.cxx + KFParticle/KFParticleDatabase.cxx + KFParticle/KFParticleBase.cxx + KFParticle/KFParticleBaseSIMD.cxx + KFParticle/KFParticle.cxx + KFParticle/KFParticleSIMD.cxx + KFParticle/KFParticleFinder.cxx + KFParticle/KFPEmcCluster.cxx + KFParticlePerformance/KFMCParticle.cxx + KFParticlePerformance/KFMCVertex.cxx + KFParticlePerformance/KFParticlePerformanceBase.cxx + KFParticlePerformance/KFTopoPerformance.cxx + KFParticlePerformance/KFPartEfficiencies.cxx +) + +ADD_DEFINITIONS(-DHomogeneousField) +#ADD_DEFINITIONS(-DNonhomogeneousField) + +set(LINKDEF KFParticleLinkDef.h) +set(LIBRARY_NAME KFParticle) + +set(DEPENDENCIES Vc) + +GENERATE_LIBRARY() + + + diff --git a/external/KFParticle/KFParticle/KFPEmcCluster.cxx b/external/KFParticle/KFParticle/KFPEmcCluster.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3798ce9d92c4302ea94c60bb10811af04752c2ba --- /dev/null +++ b/external/KFParticle/KFParticle/KFPEmcCluster.cxx @@ -0,0 +1,176 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFPEmcCluster.h" +#include <iostream> + +void KFPEmcCluster::SetParameter(const float_v& value, int iP, int iTr) +{ + /** Copies the SIMD vector "value" to the parameter vector KFPEmcCluster::fP[iP] + ** starting at the position "iTr". + ** \param[in] value - SIMD vector with the values to be stored + ** \param[in] iP - number of the parameter vector + ** \param[in] iTr - starting position in the parameter vector where the values should be stored + **/ + if( (iTr+float_vLen) < Size()) + reinterpret_cast<float_v&>(fP[iP][iTr]) = value; + else + { + const uint_v index(uint_v::IndexesFromZero()); + (reinterpret_cast<float_v&>(fP[iP][iTr])).gather(reinterpret_cast<const float*>(&value), index, simd_cast<float_m>(index<(Size() - iTr))); + } +} +void KFPEmcCluster::SetCovariance(const float_v& value, int iC, int iTr) +{ + /** Copies the SIMD vector "value" to the element of the covariance matrix vector KFPEmcCluster::fC[iC] + ** starting at the position "iTr". + ** \param[in] value - SIMD vector with the values to be stored + ** \param[in] iC - number of the element of the covariance matrix + ** \param[in] iTr - starting position in the parameter vector where the values should be stored + **/ + if( (iTr+float_vLen) < Size()) + reinterpret_cast<float_v&>(fC[iC][iTr]) = value; + else + { + const uint_v index(uint_v::IndexesFromZero()); + (reinterpret_cast<float_v&>(fC[iC][iTr])).gather(reinterpret_cast<const float*>(&value), index, simd_cast<float_m>(index<(Size() - iTr))); + } +} + +void KFPEmcCluster::Resize(const int n) +{ + /** Resizes all vectors in the class to a given value. + ** \param[in] n - new size of the vector + **/ + for(int i=0; i<4; i++) + fP[i].resize(n); + for(int i=0; i<10; i++) + fC[i].resize(n); + fId.resize(n); +} + +void KFPEmcCluster::Set(KFPEmcCluster& v, int vSize, int offset) +{ + /** Copies "vSize" clusters from the KFPEmcCluster "v" to the current object. + ** Tracks are put starting from the "offset" position. + ** \param[in] v - external KFPEmcCluster with input clusters to be copied + ** \param[in] vSize - number of clusters to be copied from "v" + ** \param[in] offset - offset position in the current object, starting from which input clusters will be stored + **/ + for(int iV=0; iV<vSize; iV++) + { + for(int i=0; i<4; i++) + fP[i][offset+iV] = v.fP[i][iV]; + for(int i=0; i<10; i++) + fC[i][offset+iV] = v.fC[i][iV]; + fId[offset+iV] = v.fId[iV]; + } +} + +void KFPEmcCluster::SetTracks(const KFPEmcCluster& track, const kfvector_uint& trackIndex, const int nIndexes) +{ + /** The current object is resised to "nIndexes", clusters with indices "trackIndex" are copied to the current object. + ** \param[in] track - input vector of clusters + ** \param[in] trackIndex - indices of clusters in a vector "track", which should be stored to the current object + ** \param[in] nIndexes - number of clusters to be copied, defines the new size of the current object + **/ + + if(nIndexes == 0) return; + + Resize(nIndexes); + + for(int iP=0; iP<4; iP++) + { + int iElement = 0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fP[iP][iElement]); + vec.gather(&(track.fP[iP][0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fP[iP][iElement]); + vec.gather(&(track.fP[iP][0]), index, simd_cast<float_m>(iElement+uint_v::IndexesFromZero()<nIndexes)); + + } + for(int iC=0; iC<10; iC++) + { + int iElement=0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fC[iC][iElement]); + vec.gather(&(track.fC[iC][0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fC[iC][iElement]); + vec.gather(&(track.fC[iC][0]), index, simd_cast<float_m>(iElement+uint_v::IndexesFromZero()<nIndexes)); + } + { + int iElement=0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fId[iElement]); + vec.gather(&(track.fId[0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fId[iElement]); + vec.gather(&(track.fId[0]), index, int_m(iElement+uint_v::IndexesFromZero()<nIndexes)); + } +} + +void KFPEmcCluster::PrintTrack(int n) +{ + /** Prints parameters of the cluster with index "n". + ** \param[in] n - index of cluster to be printed + **/ + for(int i=0; i<4; i++) + std::cout << fP[i][n] << " "; + std::cout << std::endl; + for(int i=0; i<10; i++) + std::cout << fC[i][n] << " "; + std::cout << std::endl; + + std::cout << fId[n] << std::endl; +} + +void KFPEmcCluster::PrintTracks() +{ + /** Prints all field of the current object. **/ + + std::cout << "NTracks " << Size() << std::endl; + if( Size()==0 ) return; + + std::cout << "Parameters: " << std::endl; + for(int iP=0; iP<4; iP++) + { + std::cout << " iP " << iP << ": "; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << Parameter(iP)[iTr]<< " "; + std::cout << std::endl; + } + + std::cout << "Cov matrix: " << std::endl; + for(int iC=0; iC<10; iC++) + { + std::cout << " iC " << iC << ": "; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << Covariance(iC)[iTr]<< " "; + std::cout << std::endl; + } + + std::cout << "Id: " << std::endl; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << Id()[iTr] << " "; + std::cout << std::endl; +} + \ No newline at end of file diff --git a/external/KFParticle/KFParticle/KFPEmcCluster.h b/external/KFParticle/KFParticle/KFPEmcCluster.h new file mode 100644 index 0000000000000000000000000000000000000000..329c7496239af085c3453024a4e0aea7cc03f016 --- /dev/null +++ b/external/KFParticle/KFParticle/KFPEmcCluster.h @@ -0,0 +1,123 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPEmcCluster_H +#define KFPEmcCluster_H + +#include "KFParticleDef.h" + +/** @class KFPEmcCluster + ** @brief A class to store vectors of input cluster from the electro-magnetic calorimeter. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** A cluster is described with the state vector { X, Y, Z, E } + ** and the corresponding covariance matrix. Also contains a unique id. + ** The data model implemented in the class is "Structure Of Arrays": + ** each parameter is stroed in a separate vector. Such data structure + ** allows fast vectorised access to the aligned data providing the + ** maximum possible speed for data reading, and at the same time easy + ** random access to the data members. + **/ + +class KFPEmcCluster +{ + public: + KFPEmcCluster():fP(), fC(), fId() { } + ~KFPEmcCluster() { } + + /**Returns size of the vectors. All data vectors have the same size. */ + int Size() const { return fP[0].size(); } + + void Resize(const int n); + void Set(KFPEmcCluster& v, int vSize, int offset); + void SetTracks(const KFPEmcCluster& track, const kfvector_uint& trackIndex, const int nIndexes); + + const kfvector_float& X() const { return fP[0]; } ///< Returns constant reference to the vector with X coordinates. + const kfvector_float& Y() const { return fP[1]; } ///< Returns constant reference to the vector with Y coordinates. + const kfvector_float& Z() const { return fP[2]; } ///< Returns constant reference to the vector with Z coordinates. + const kfvector_float& E() const { return fP[3]; } ///< Returns constant reference to the vector with energy of the cluster. + + const kfvector_float& Parameter(const int i) const { return fP[i]; } ///< Returns constant reference to the parameter vector with index "i". + const kfvector_float& Covariance(const int i) const { return fC[i]; } ///< Returns constant reference to the vector of the covariance matrix elements with index "i". + const kfvector_int& Id() const { return fId; } ///< Returns constant reference to the vector with unique id of the clusters. + + //modifiers + void SetParameter (float value, int iP, int iTr) { fP[iP][iTr] = value; } ///< Sets the "value" of the parameter "iP" of the cluster with index "iTr". + void SetCovariance(float value, int iC, int iTr) { fC[iC][iTr] = value; } ///< Sets the "value" of the element of covariance matrix "iC" of the cluster with index "iTr". + + void SetParameter (const float_v& value, int iP, int iTr); + void SetCovariance(const float_v& value, int iC, int iTr); + + void SetId (int value, int iTr) { fId[iTr] = value; } ///< Sets the "value" of the id of the cluster with index "iTr". + + void PrintTrack(int n); + void PrintTracks(); + + KFPEmcCluster(const KFPEmcCluster& clusters): fId() + { + /** Copy-constructor. Makes one-to-one copy.*/ + const int localSize = clusters.Size(); + + for(int i=0; i<4; i++) + { + fP[i].resize(localSize); + for(int n=0; n<localSize; n++) + fP[i][n] = clusters.fP[i][n]; + } + + for(int i=0; i<10; i++) + { + fC[i].resize(localSize); + for(int n=0; n<localSize; n++) + fC[i][n] = clusters.fC[i][n]; + } + + fId.resize(localSize); + for(int n=0; n<localSize; n++) + fId[n] = clusters.fId[n]; + } + + const KFPEmcCluster& operator = (const KFPEmcCluster& clusters) + { + /** Operator to copy one KFPEmcCluster object to another. Makes one-to-one copy.*/ + const int localSize = clusters.Size(); + + for(int i=0; i<4; i++) + { + fP[i].resize(localSize); + for(int n=0; n<localSize; n++) + fP[i][n] = clusters.fP[i][n]; + } + + for(int i=0; i<10; i++) + { + fC[i].resize(localSize); + for(int n=0; n<localSize; n++) + fC[i][n] = clusters.fC[i][n]; + } + + fId.resize(localSize); + for(int n=0; n<localSize; n++) + fId[n] = clusters.fId[n]; + + return *this; + } + + private: + kfvector_float fP[4]; ///< Coordinates of the cluster and energy: X, Y, Z, E. + kfvector_float fC[10]; ///< Covariance matrix of the parameters of the cluster. + + kfvector_int fId; ///< Vector with unique ids of the clusters. +}; + +#endif diff --git a/external/KFParticle/KFParticle/KFPInputData.h b/external/KFParticle/KFParticle/KFPInputData.h new file mode 100644 index 0000000000000000000000000000000000000000..3f01801be089d93acab9f53ec3d355b9c111da5f --- /dev/null +++ b/external/KFParticle/KFParticle/KFPInputData.h @@ -0,0 +1,370 @@ +//---------------------------------------------------------------------------- +// Structures with input data for KF Particle Finder +// . +// @author M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPINPUTDATA_H +#define KFPINPUTDATA_H + +#include "KFPTrackVector.h" +#include "KFParticle.h" + +#include <vector> +#include <string> +#include <fstream> + +/** @class KFPTrackIndex + ** @brief Helper structure to sort tracks in the KFPTrackVector object. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The structure is used in the KFParticleTopoReconstructor::SortTracks() function. + ** Tracks are sorted according to their pdg hypothesis: electrons, muons, pions, + ** tracks without pdg (-1), kaons, protons, deuterons, tritons, He3, He4. + ** Teh structure contains pdg hypothesis of the track and its index in the + ** KFPTrackVector object. + **/ + +struct KFPTrackIndex +{ + int fIndex; ///< index of the track in the KFPTrackVector object. + int fPdg; ///< PDG hypothesis of the track + + static bool Compare(const KFPTrackIndex& a, const KFPTrackIndex& b) + { + /** Static sorting function for comparison of the two input objects of class KFPTrackIndex. + ** Objects are sorted according to the PDG hypothesis: electrons, muons, pions, + ** tracks without pdg (-1), kaons, protons, deuterons, tritons, He3, He4. + ** Return "true" if a.fPdg < b.fPdg, otherwise returns "false". + ** \param[in] a - first object + ** \param[in] b - second object + **/ + int pdg1 = a.fPdg == -1 ? 250 : a.fPdg; + int pdg2 = b.fPdg == -1 ? 250 : b.fPdg; + + return (abs(pdg1) < abs(pdg2)); + } +}; + + +/** @class KFPInputData + ** @brief Class with the input data for KF Particle Finder: tracks, primary vertex and magnetic field. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is used to transfer the data between devices: CPU and Intel Xeon Phi. The memory is aligned + ** with the size of the SIMD vectors. + **/ + +class KFPInputData +{ + public: + + void *operator new(size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new(size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void operator delete(void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + void operator delete[](void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + + KFPInputData():fPV(0),fBz(0.f) {}; + ~KFPInputData() {}; + + bool ReadDataFromFile( std::string prefix ) + { + /** Reads the input data from the input file with the name defined by "prefix". + ** \param[in] prefix - string with the name of the input file + **/ + std::ifstream ifile(prefix.data()); + if ( !ifile.is_open() ) return 0; + int nSets; + ifile >> fBz; + ifile >> nSets; + for(int iSet=0; iSet<nSets; iSet++) + { + int nTracks = 0; + ifile >> nTracks; + fTracks[iSet].Resize(nTracks); + + for(int iP=0; iP<6; iP++) + { + float value; + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + { + ifile >> value; + fTracks[iSet].SetParameter(value, iP, iTr); + } + } + + for(int iC=0; iC<21; iC++) + { + float value; + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + { + ifile >> value; + fTracks[iSet].SetCovariance(value, iC, iTr); + } + } + + int tmpInt; + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + { + ifile >> tmpInt; + fTracks[iSet].SetId(tmpInt, iTr); + } + + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + { + ifile >> tmpInt; + fTracks[iSet].SetPDG(tmpInt, iTr); + } + + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + { + ifile >> tmpInt; + fTracks[iSet].SetQ(tmpInt, iTr); + } + + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + { + ifile >> tmpInt; + fTracks[iSet].SetPVIndex(tmpInt, iTr); + } + + ifile >> tmpInt; + fTracks[iSet].SetLastElectron(tmpInt); + ifile >> tmpInt; + fTracks[iSet].SetLastMuon (tmpInt); + ifile >> tmpInt; + fTracks[iSet].SetLastPion (tmpInt); + ifile >> tmpInt; + fTracks[iSet].SetLastKaon (tmpInt); + ifile >> tmpInt; + fTracks[iSet].SetLastProton (tmpInt); + } + + int nPV; + ifile>>nPV; + fPV.resize(nPV); + for(unsigned int iPV=0; iPV < fPV.size(); iPV++) + { + for(int iP=0; iP<3; iP++) + ifile >> fPV[iPV].Parameter(iP); + + for(int iC=0; iC<6; iC++) + ifile >> fPV[iPV].Covariance(iC); + } + + ifile.close(); + return 1; + } + + void SetDataToVector(int* data, int& dataSize) + { + /** Stores information to the memory under pointer "data". + ** \param[out] data - memory, where input information will be stored + ** \param[out] dataSize - size of the stored memory in "int" (or bloks of 4 bytes, or 32 bits) + **/ + dataSize = NInputSets + 1 + 1; //sizes of the track vectors and pv vector, and field + for(int iSet=0; iSet<NInputSets; iSet++) + dataSize += fTracks[iSet].DataSize(); + dataSize += fPV.size() * 9; + + for(int iSet=0; iSet<NInputSets; iSet++) + data[iSet] = fTracks[iSet].Size(); + data[NInputSets] = fPV.size(); + + float& field = reinterpret_cast<float&>(data[NInputSets+1]); + field = fBz; + + int offset = NInputSets+2; + + for(int iSet=0; iSet<NInputSets; iSet++) + fTracks[iSet].SetDataToVector(data, offset); + + for(int iP=0; iP<3; iP++) + { + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + { + float& tmpFloat = reinterpret_cast<float&>(data[offset + iPV]); + tmpFloat = fPV[iPV].Parameter(iP); + } + offset += fPV.size(); + } + + for(int iC=0; iC<6; iC++) + { + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + { + float& tmpFloat = reinterpret_cast<float&>(data[offset + iPV]); + tmpFloat = fPV[iPV].Covariance(iC); + } + offset += fPV.size(); + } + } + + void ReadDataFromVector(int* data) + { + /** Reads input data from the given memory. + ** \param[in] data - pointer to the memory with the input data + **/ + int offset = NInputSets+2; + for(int iSet=0; iSet<NInputSets; iSet++) + { + fTracks[iSet].Resize(data[iSet]); + fTracks[iSet].ReadDataFromVector(data, offset); + } + + float& field = reinterpret_cast<float&>(data[NInputSets+1]); + fBz = field; + + fPV.resize(data[NInputSets]); + + for(int iP=0; iP<3; iP++) + { + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + { + float& tmpFloat = reinterpret_cast<float&>(data[offset + iPV]); + fPV[iPV].Parameter(iP) = tmpFloat; + } + offset += fPV.size(); + } + + for(int iC=0; iC<6; iC++) + { + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + { + float& tmpFloat = reinterpret_cast<float&>(data[offset + iPV]); + fPV[iPV].Covariance(iC) = tmpFloat; + } + offset += fPV.size(); + } + } + + void Print() + { + /**Prints all fields of the current object.*/ + for(int iSet=0; iSet<NInputSets; iSet++) + fTracks[iSet].Print(); + std::cout << "N PV: " << fPV.size() << std::endl; + + std::cout << "X: "; + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + std::cout << fPV[iPV].X() <<" "; + std::cout << std::endl; + std::cout << "Y: "; + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + std::cout << fPV[iPV].Y() <<" "; + std::cout << std::endl; + std::cout << "Z: "; + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + std::cout << fPV[iPV].Z() <<" "; + std::cout << std::endl; + + std::cout << "Cov matrix: " << std::endl; + for(int iC=0; iC<6; iC++) + { + std::cout << " iC " << iC << ": "; + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + std::cout << fPV[iPV].Covariance(iC) <<" "; + std::cout << std::endl; + } + + std::cout << "Field: " << fBz << std::endl; + } + + KFPTrackVector* GetTracks() { return fTracks; } ///< Returns pointer to the array with track vectors. + float GetBz() const { return fBz; } ///< Returns value of the constant field Bz. + const std::vector<KFParticle>& GetPV() const { return fPV; } ///< Returns vector with primary vertices. + + const KFPInputData& operator = (const KFPInputData& data) + { + /** Copies input data from object "data" to the current object. Returns the current object. \param[in] data - input data*/ + for(int i=0; i<NInputSets; i++) + fTracks[i] = data.fTracks[i]; + fPV = data.fPV; + fBz = data.fBz; + + return *this; + } + KFPInputData(const KFPInputData& data):fPV(0),fBz(0.f) + { + /** Copies input data from object "data" to the current object. \param[in] data - input data */ + for(int i=0; i<NInputSets; i++) + fTracks[i] = data.fTracks[i]; + fPV = data.fPV; + fBz = data.fBz; + } + + protected: + /** Array of track vectors: \n + ** 0 - positive secondary tracks stored at the first point; \n + ** 1 - negative secondary tracks stored at the first point; \n + ** 2 - positive primary tracks stored at the first point; \n + ** 3 - positive primary tracks stored at the first point; \n + ** 4 - positive secondary tracks stored at the last point; \n + ** 5 - negative secondary tracks stored at the last point; \n + ** 6 - positive primary tracks stored at the last point; \n + ** 7 - positive primary tracks stored at the last point. + ** \see KFPTrackVector for documentation. + **/ + KFPTrackVector fTracks[NInputSets]__attribute__((aligned(sizeof(float_v)))); + std::vector<KFParticle> fPV; ///< Vector with primary vertices. + float fBz; ///< Constant homogenious one-component magnetic field Bz. +} __attribute__((aligned(sizeof(float_v)))); + +/** @class KFPInputDataArray + ** @brief Structure with the set of the input data for KF Particle Finder. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The structure contains pointer to array of KFPInputData objects. Copying of the + ** objects of this structure is disabled. + **/ + +struct KFPInputDataArray{ + KFPInputDataArray():fInput(0){}; + ~KFPInputDataArray() { if(fInput) delete [] fInput; } + + KFPInputData *fInput; ///< Pointer to the array of the input data objects. + + private: + const KFPInputDataArray& operator = (const KFPInputDataArray&); + KFPInputDataArray(const KFPInputDataArray&); +}; + + +/** @class KFPLinkedList + ** @brief Structure to creat a linked list of the input data. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The structure contains pointer to array of KFPInputData objects. Copying of the + ** objects of this structure is disabled. The list is used to create a queue for processing + ** at the device side (Intel Xeon Phi). + **/ + +struct KFPLinkedList +{ + void *operator new(size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new(size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void operator delete(void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + void operator delete[](void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + + KFPInputData data __attribute__((aligned(sizeof(float_v)))); ///< Input data for KF Particle Finder \see KFPInputData. + KFPLinkedList* next; ///< Link to the nex object in the linked list. +} __attribute__((aligned(sizeof(float_v)))); + +#endif diff --git a/external/KFParticle/KFParticle/KFPSimdAllocator.h b/external/KFParticle/KFParticle/KFPSimdAllocator.h new file mode 100644 index 0000000000000000000000000000000000000000..9baf6001fc29d51c67b5dedce5083edfa28a56f6 --- /dev/null +++ b/external/KFParticle/KFParticle/KFPSimdAllocator.h @@ -0,0 +1,109 @@ +//---------------------------------------------------------------------------- +// Allocator for SIMDised KF Particle +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPSimdAllocator_H +#define KFPSimdAllocator_H + +#include <Vc/Vc> + +/** @class KFPSimdAllocator + ** @brief Allocator which is needed to allocate memory in std::vector aligned by the size of SIMD vectors. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + **/ + +template <class T> +class KFPSimdAllocator { + public: + // type definitions + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + /** @class rebind + ** @brief Rebind allocator to type U of the SIMD allocator. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + **/ + template <class U> + struct rebind { + typedef KFPSimdAllocator<U> other; + }; + + /** Return address of "value". */ + pointer address (reference value) const { + return &value; + } + /** Return address of "value". */ + const_pointer address (const_reference value) const { + return &value; + } + + /* constructors and destructor + * - nothing to do because the allocator has no state + */ + KFPSimdAllocator() throw() { } + KFPSimdAllocator(const KFPSimdAllocator&) throw() { } + template <class U> + KFPSimdAllocator (const KFPSimdAllocator<U>&) throw() { } + ~KFPSimdAllocator() throw() { } + + /** Return maximum number of elements that can be allocated. */ + size_type max_size () const throw() { + return std::numeric_limits<std::size_t>::max() / sizeof(T); + } + + /** Allocate but don't initialize num elements of type T. */ + pointer allocate (size_type num, const void* = 0) { +// print message and allocate memory with global new + pointer ret = reinterpret_cast<pointer>( /*T::*/operator new(num*sizeof(T)) ); + return ret; + } + + /** Initialize elements of allocated storage "p" with an empty element. */ + void construct (pointer p) { + // initialize memory with placement new + new(p) T(); + } + + /** Initialize elements of allocated storage "p" with value "value". */ + void construct (pointer p, const T& value) { + new(p) T(value); + } + + /** Destroy elements of initialized storage "p". */ + void destroy (pointer p) { + // destroy objects by calling their destructor + p->~T(); + } + + /** Deallocate storage p of deleted elements. */ + void deallocate (pointer p, size_type num) { + // print message and deallocate memory with global delete + /*T::*/operator delete(static_cast<void*>(p), num*sizeof(T)); + + } + + void *operator new(size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new(size_t size) { return _mm_malloc(size, sizeof(Vc::float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(Vc::float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void operator delete(void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + void operator delete[](void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release +}; // KFPSimdAllocator + +#endif //KFPSimdAllocator diff --git a/external/KFParticle/KFParticle/KFPTrack.cxx b/external/KFParticle/KFParticle/KFPTrack.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8e636cdc9d8d599ee97b5ad47f88834de0ea86c1 --- /dev/null +++ b/external/KFParticle/KFParticle/KFPTrack.cxx @@ -0,0 +1,84 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFPTrack.h" + +#ifdef __ROOT__ +ClassImp(KFPTrack); +#endif + +void KFPTrack::RotateXY( float alpha ) +{ + /** Rotates the parameters of the track on an angle alpha in the XY plane. + ** Can be used in case of the transforamtion of the coordinate system. + ** The rotation matrix is: + ** \verbatim + { cos(A), -sin(A), 0, 0, 0, 0 } + { sin(A), cos(A), 0, 0, 0, 0 } + { 0, 0, 1, 0, 0, 0 } + { 0, 0, 0, cos(A), -sin(A), 0 } + { 0, 0, 0, sin(A), cos(A), 0 } + { 0, 0, 0, 0, 0, 1 } + \endverbatim + ** \param[in] alpha - rotation angle + **/ + const float cA = cos( alpha ); + const float sA = sin( alpha ); + + //float J[6][6] = { { cA, -sA, 0, 0, 0, 0 }, // X + // { sA, cA, 0, 0, 0, 0 }, // Y + // { 0, 0, 1, 0, 0, 0 }, // Z + // { 0, 0, 0, cA, -sA, 0 }, // Px + // { 0, 0, 0, sA, cA, 0 }, // Py + // { 0, 0, 0, 0, 0, 1 } }; // Pz + + const float x = GetX(), y = GetY(); + + SetX( -(x*sA + y*cA) ); + SetY( x*cA - y*sA ); + + const float px = GetPx(), py = GetPy(); + + SetPx( -(px*sA + py*cA) ); + SetPy( px*cA - py*sA ); + + float cov[21]; + for(int iC=0; iC<21; iC++) + cov[iC] = fC[iC]; + + fC[0] = cA*cA* cov[2] + 2* cA* cov[1]* sA + cov[0]*sA* sA; + + fC[1] = -(cA*cA * cov[1]) + cA* (-cov[0] + cov[2])* sA + cov[1]*sA* sA; + fC[2] = cA*cA* cov[0] - 2* cA* cov[1]* sA + cov[2]*sA* sA; + + fC[3] = -(cA* cov[4]) - cov[3]* sA; + fC[4] = cA* cov[3] - cov[4]* sA; + fC[5] = cov[5]; + + fC[6] = cA*cA* cov[11] + cA *(cov[10] + cov[7])* sA + cov[6]*sA* sA; + fC[7] = -(cA*cA * cov[10]) + cA* (cov[11] - cov[6])* sA + cov[7] *sA*sA; + fC[8] = -(cA *cov[12]) - cov[8] *sA; + fC[9] = cA*cA* cov[14] + 2 *cA* cov[13]* sA + cov[9]* sA*sA; + + fC[10] = -(cA*cA* cov[7]) + cA* (cov[11] - cov[6])* sA + cov[10]*sA* sA; + fC[11] = cA*cA* cov[6] - cA* (cov[10] + cov[7]) *sA + cov[11]*sA* sA; + fC[12] = cA* cov[8] - cov[12]* sA; + fC[13] = -(cA*cA* cov[13]) + cA* (cov[14] - cov[9])* sA + cov[13]* sA*sA; + fC[14] = cA*cA* cov[9] - 2* cA* cov[13]* sA + cov[14]* sA*sA; + + fC[15] = -(cA* cov[16]) - cov[15]* sA; + fC[16] = cA* cov[15] - cov[16]* sA; + fC[17] = cov[17]; + fC[18] = -(cA* cov[19]) - cov[18]* sA; + fC[19] = cA* cov[18] - cov[19]* sA; + fC[20] = cov[20]; + +} diff --git a/external/KFParticle/KFParticle/KFPTrack.h b/external/KFParticle/KFParticle/KFPTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..37f9bb1f1108c3b6ab644a119486c9ca9cec5070 --- /dev/null +++ b/external/KFParticle/KFParticle/KFPTrack.h @@ -0,0 +1,220 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPTrack_H +#define KFPTrack_H + +/** @class KFPTrack + ** @brief A scalar class for storage of the track in the cartesian parametrisation. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** A track is described with the state vector { X, Y, Z, Px, Py, Pz } + ** and the corresponding covariance matrix. Also contains charge of the + ** track, chi2 of the track fit, the corresponding number of degrees of freedom, + ** the unique Id of the track and the field approximation along the track trajectory. + **/ + +#include <cmath> +#include "TObject.h" +class KFPTrack +#ifdef __ROOT__ +: public TObject +#endif +{ + +public: + KFPTrack():fChi2(-1.f), fQ(0), fNDF(-1), fId(-1) { } + ~KFPTrack() { } + + int GetID() const { return fId; } ///< Returns Id of the track. + + bool GetXYZPxPyPz(float *p) const + { + /** Fills an array p with the parameters of the track. + ** \param[out] p - array where { X, Y, Z, Px, Py, Pz } are copied + **/ + for(int i=0; i<6; i++) + p[i] = fP[i]; + return 1; + } + bool GetCovarianceXYZPxPyPz(float cv[21]) const + { + /** Copies the covariance matrix of the track to the array of floats. + ** \param[out] cv[21] - the output array, where the covariance matrix is copied + **/ + for (int i=0; i<21; i++) + cv[i] = fC[i]; + return 1; + } + bool GetCovarianceXYZPxPyPz(double cv[21]) const + { + /** Copies the covariance matrix of the track to the array of doubles. + ** \param[out] cv[21] - the output array, where the covariance matrix is copied + **/ + for (int i=0; i<21; i++) + cv[i] = fC[i]; + return 1; + } + + /** Copies position of the track to the output array of floats. \param[out] position - the output array with the position of the track **/ + void GetXYZ(float *position) const {position[0] = fP[0]; position[1] = fP[1]; position[2] = fP[2];} + /** Copies 3 momentum components of the track to the output array of floats. \param[out] position - the output array with the momentum of the track **/ + void GetPxPyPz(float *position) const {position[0] = fP[3]; position[1] = fP[4]; position[2] = fP[5];} + /** Copies position of the track to the output array of floats. \param[out] position - the output array with the position of the track **/ + void XvYvZv(float *position) const {position[0] = fP[0]; position[1] = fP[1]; position[2] = fP[2];} + /** Copies 3 momentum components of the track to the output array of floats. \param[out] position - the output array with the momentum of the track **/ + void PxPyPz(float *position) const {position[0] = fP[3]; position[1] = fP[4]; position[2] = fP[5];} + /** Copies position of the track to the output array of doubles. \param[out] position - the output array with the position of the track **/ + void XvYvZv(double *position) const {position[0] = fP[0]; position[1] = fP[1]; position[2] = fP[2];} + /** Copies 3 momentum components of the track to the output array of doubles. \param[out] position - the output array with the momentum of the track **/ + void PxPyPz(double *position) const {position[0] = fP[3]; position[1] = fP[4]; position[2] = fP[5];} + + float GetX() const { return fP[0]; } ///< Returns X coordinate of the track. + float GetY() const { return fP[1]; } ///< Returns Y coordinate of the track. + float GetZ() const { return fP[2]; } ///< Returns Z coordinate of the track. + float GetPx() const { return fP[3]; } ///< Returns Px component of the momentum of the track. + float GetPy() const { return fP[4]; } ///< Returns Py component of the momentum of the track. + float GetPz() const { return fP[5]; } ///< Returns Pz component of the momentum of the track. + + float GetPt() const { return sqrt(fP[3]*fP[3]+fP[4]*fP[4]); } ///< Returns Pt - transverse momentum of the track. + float GetP() const { return sqrt(fP[3]*fP[3]+fP[4]*fP[4]+fP[5]*fP[5]); } ///< Returns P - momentum of the track. + + void GetCovarianceMatrix(float *covmatrix) + { + /** Copies the covariance matrix of the track to the array of floats. + ** \param[out] covmatrix[21] - the output array, where the covariance matrix is copied + **/ + for (int i=0; i<21; i++) + covmatrix[i] = fC[i]; + } + float GetParameter(int i) const { return fP[i]; } ///< Returns parameter "i" of the track. \param[in] i - index of the parameter to be returned + float GetCovariance(int i) const { return fC[i]; } ///< Returns element of the covariance matrix "i" of the track. \param[in] i - index of the element to be returned + + int Charge() const { return fQ; } ///< Returns charge of the track. + float GetChi2perNDF() const { return fChi2/fNDF; } ///< Returns Chi2/NDF of the track, NDF is a number of degrees of freedom. + float GetChi2() const { return fChi2; } ///< Returns Chi2 of the track. + int GetNDF() const { return fNDF; } ///< Returns number of degrees of freedom of the track. + + const float * GetTrack() const { return fP; } ///< Returns a pointer to the array of track parameters. + const float * GetCovMatrix() const { return fC; } ///< Returns a pointer to the array of the covariance matrix elements stored in a lower triangular form. + + void SetParameters(const float *position) + { + /** Sets parameters { X, Y, Z, Px, Py, Pz } of the track from the input array of floats. + ** \param[in] position - input array with the track parameters + **/ + for(int i=0; i<6; i++) + fP[i] = position[i]; + } + void SetParameters(double *position) + { + /** Sets parameters { X, Y, Z, Px, Py, Pz } of the track from the input array of doubles. + ** \param[in] position - input array with the track parameters + **/ + for(int i=0; i<6; i++) + fP[i] = position[i]; + } + void SetParameters(float x, float y, float z, float px, float py, float pz) + { + /** Sets parameters { X, Y, Z, Px, Py, Pz } of the track. + ** \param[in] x - X coordinate to be set + ** \param[in] y - Y coordinate to be set + ** \param[in] z - Z coordinate to be set + ** \param[in] Px - Px momentum component to be set + ** \param[in] Py - Py momentum component to be set + ** \param[in] Pz - Pz momentum component to be set + **/ + fP[0] = x; fP[1] = y; fP[2] = z; + fP[3] = px; fP[4] = py; fP[5] = pz; + } + void SetXYZ(float x, float y, float z) + { + /** Sets position { X, Y, Z } of the track. + ** \param[in] x - X coordinate to be set + ** \param[in] y - Y coordinate to be set + ** \param[in] z - Z coordinate to be set + **/ + fP[0] = x; fP[1] = y; fP[2] = z; + } + void SetPxPyPz(float px, float py, float pz) + { + /** Sets momentum { Px, Py, Pz } of the track. + ** \param[in] Px - Px momentum component to be set + ** \param[in] Py - Py momentum component to be set + ** \param[in] Pz - Pz momentum component to be set + **/ + fP[3] = px; fP[4] = py; fP[5] = pz; + } + void SetID(int id) {fId = id;} ///< Sets Id of the track. + + void SetX(float x) { fP[0] = x; } ///< Sets X coordinate of the track. + void SetY(float y) { fP[1] = y; } ///< Sets Y coordinate of the track. + void SetZ(float z) { fP[2] = z; } ///< Sets Z coordinate of the track. + void SetPx(float px) { fP[3] = px; } ///< Sets Px component of the track momentum. + void SetPy(float py) { fP[4] = py; } ///< Sets Py component of the track momentum. + void SetPz(float pz) { fP[5] = pz; } ///< Sets Pz component of the track momentum. + void SetCharge(int q) { fQ = q; } ///< Sets charge of the track. + void SetChi2(float chi) { fChi2 = chi; } ///< Sets a value of the track Chi2. + void SetNDF(int ndf) { fNDF = ndf; } ///< Sets a value of the number of degrees of freedom. + + void SetCovarianceMatrix(const float *C) + { + /** Sets the covariance matrix from the input array of floats. + ** \param[in] C[21] - array with the input elements of the covariance matrix stored in the lower triangular form + **/ + for (int i=0; i<21; i++) + fC[i] = C[i]; + } + void SetCovarianceMatrix(const double *C) + { + /** Sets the covariance matrix from the input array of doubles. + ** \param[in] C[21] - array with the input elements of the covariance matrix stored in the lower triangular form + **/ + for (int i=0; i<21; i++) + fC[i] = C[i]; + } + + /** Sets an element of the covariance matrix with index "i". \param[in] c - value to be set \param[in] i - index of the element */ + void SetCovariance(const int i, const float c) { fC[i]=c; } + + void RotateXY( float alpha ); // rotate on alpha in XY plane. Should be useful for CS change + + int Id() const { return fId; } ///< Returns Id of the track. + void SetId( int id ){ fId = id; } ///< Sets Id of the track. + +#ifdef NonhomogeneousField + const float* GetFieldCoeff() const { return fieldRegion; } ///< Returns array of the coefficients for field approximation. + /** Sets a field coefficient with index "i". \param[in] c - value to be set \param[in] i - index of the element */ + void SetFieldCoeff(float c, int i) { fieldRegion[i] = c; } +#endif + private: + + float fP[6]; ///< Parameters of the track: { X, Y, Z, Px, Py, Pz }. + float fC[21]; ///< Covariance matrix of the track parameters. Stored in the lower triangular form. + float fChi2; ///< Chi-square of the track fit. + char fQ; ///< Charge of the track. + short fNDF; ///< Number of degree of freedom of the fit. + int fId; ///< Id of the track. + +#ifdef NonhomogeneousField + /** \brief Approximation of the magnetic field along the track trajectory. + ** Each component (Bx, By, Bz) is approximated with the parabola depending on Z coordinate. Is defined in case of #ifdef NonhomogeneousField. + **/ + float fieldRegion[10]; +#endif +#ifdef __ROOT__ + ClassDef(KFPTrack,1) +#endif +}; + +#endif diff --git a/external/KFParticle/KFParticle/KFPTrackVector.cxx b/external/KFParticle/KFParticle/KFPTrackVector.cxx new file mode 100644 index 0000000000000000000000000000000000000000..24ff12365092410799313d151c5f387105a59b5c --- /dev/null +++ b/external/KFParticle/KFParticle/KFPTrackVector.cxx @@ -0,0 +1,412 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFPTrackVector.h" +#include <iostream> + +void KFPTrackVector::SetParameter(const float_v& value, int iP, int iTr) +{ + /** Copies the SIMD vector "value" to the parameter vector KFPTrackVector::fP[iP] + ** starting at the position "iTr". + ** \param[in] value - SIMD vector with the values to be stored + ** \param[in] iP - number of the parameter vector + ** \param[in] iTr - starting position in the parameter vector where the values should be stored + **/ +// gather caused errors at XeonPhi, temporarly replaced with the simple copying +// if( (iTr+float_vLen) < Size()) +// reinterpret_cast<float_v&>(fP[iP][iTr]) = value; +// else +// { +// const uint_v index(uint_v::IndexesFromZero()); +// (reinterpret_cast<float_v&>(fP[iP][iTr])).gather(reinterpret_cast<const float*>(&value), index, float_m(index<(Size() - iTr))); +// } + + if( (iTr+float_vLen) < Size()) + reinterpret_cast<float_v&>(fP[iP][iTr]) = value; + else + for(int i=0; i<float_v::Size; i++) + { + if(iTr + i >= Size()) continue; + fP[iP][iTr+i] = value[i]; + } +} +void KFPTrackVector::SetCovariance(const float_v& value, int iC, int iTr) +{ + /** Copies the SIMD vector "value" to the element of the covariance matrix vector KFPTrackVector::fC[iC] + ** starting at the position "iTr". + ** \param[in] value - SIMD vector with the values to be stored + ** \param[in] iC - number of the element of the covariance matrix + ** \param[in] iTr - starting position in the parameter vector where the values should be stored + **/ +// gather caused errors at XeonPhi, temporarly replaced with the simple copying +// if( (iTr+float_vLen) < Size()) +// reinterpret_cast<float_v&>(fC[iC][iTr]) = value; +// else +// { +// const uint_v index(uint_v::IndexesFromZero()); +// (reinterpret_cast<float_v&>(fC[iC][iTr])).gather(reinterpret_cast<const float*>(&value), index, float_m(index<(Size() - iTr))); +// } + + if( (iTr+float_vLen) < Size()) + reinterpret_cast<float_v&>(fC[iC][iTr]) = value; + else + for(int i=0; i<float_v::Size; i++) + { + if(iTr + i >= Size()) continue; + fC[iC][iTr+i] = value[i]; + } +} + + +void KFPTrackVector::Resize(const int n) +{ + /** Resizes all vectors in the class to a given value. + ** \param[in] n - new size of the vector + **/ + for(int i=0; i<6; i++) + fP[i].resize(n); + for(int i=0; i<21; i++) + fC[i].resize(n); +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField[i].resize(n); +#endif +// fChi2.resize(n); +// fNDF.resize(n); + fId.resize(n); + fPDG.resize(n); + fQ.resize(n); + fPVIndex.resize(n); + fNPixelHits.resize(n); +} + +void KFPTrackVector::Set(KFPTrackVector& v, int vSize, int offset) +{ + /** Copies "vSize" tracks from the KFPTrackVector "v" to the current object. + ** Tracks are put starting from the "offset" position. + ** \param[in] v - external KFPTrackVector with input tracks to be copied + ** \param[in] vSize - number of tracks to be copied from "v" + ** \param[in] offset - offset position in the current object, starting from which input tracks will be stored + **/ + for(int iV=0; iV<vSize; iV++) + { + for(int i=0; i<6; i++) + fP[i][offset+iV] = v.fP[i][iV]; + for(int i=0; i<21; i++) + fC[i][offset+iV] = v.fC[i][iV]; +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField[i][offset+iV] = v.fField[i][iV]; +#endif +// fChi2[offset+iV] = v.fChi2[iV]; +// fNDF[offset+iV] = v.fNDF[iV]; + fId[offset+iV] = v.fId[iV]; + fPDG[offset+iV] = v.fPDG[iV]; + fQ[offset+iV] = v.fQ[iV]; + fPVIndex[offset+iV] = v.fPVIndex[iV]; + fNPixelHits[offset+iV] = v.fNPixelHits[iV]; + } +} + +void KFPTrackVector::SetTracks(const KFPTrackVector& track, const kfvector_uint& trackIndex, const int nIndexes) +{ + /** The current object is resised to "nIndexes", tracks with indices "trackIndex" are copied to the current object. + ** \param[in] track - input vector of tracks + ** \param[in] trackIndex - indices of tracks in a vector "track", which should be stored to the current object + ** \param[in] nIndexes - number of tracks to be copied, defines the new size of the current object + **/ + if(nIndexes == 0) return; + + Resize(nIndexes); + + for(int iP=0; iP<6; iP++) + { + int iElement = 0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fP[iP][iElement]); + vec.gather(&(track.fP[iP][0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fP[iP][iElement]); + vec.gather(&(track.fP[iP][0]), index, simd_cast<float_m>(iElement+uint_v::IndexesFromZero()<nIndexes)); + + } + for(int iC=0; iC<21; iC++) + { + int iElement=0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fC[iC][iElement]); + vec.gather(&(track.fC[iC][0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fC[iC][iElement]); + vec.gather(&(track.fC[iC][0]), index, simd_cast<float_m>(iElement+uint_v::IndexesFromZero()<nIndexes)); + } +#ifdef NonhomogeneousField + for(int iP=0; iP<10; iP++) + { + int iElement = 0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fField[iP][iElement]); + vec.gather(&(track.fField[iP][0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + float_v& vec = reinterpret_cast<float_v&>(fField[iP][iElement]); + vec.gather(&(track.fField[iP][0]), index, simd_cast<float_m>(iElement+uint_v::IndexesFromZero()<nIndexes)); + } +#endif + { + int iElement=0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fId[iElement]); + vec.gather(&(track.fId[0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fId[iElement]); + vec.gather(&(track.fId[0]), index, int_m(iElement+uint_v::IndexesFromZero()<nIndexes)); + } + { + int iElement=0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fPDG[iElement]); + vec.gather(&(track.fPDG[0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fPDG[iElement]); + vec.gather(&(track.fPDG[0]), index, int_m(iElement+uint_v::IndexesFromZero()<nIndexes)); + } + { + int iElement=0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fQ[iElement]); + vec.gather(&(track.fQ[0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fQ[iElement]); + vec.gather(&(track.fQ[0]), index, int_m(iElement+uint_v::IndexesFromZero()<nIndexes)); + } + { + int iElement=0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fPVIndex[iElement]); + vec.gather(&(track.fPVIndex[0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fPVIndex[iElement]); + vec.gather(&(track.fPVIndex[0]), index, int_m(iElement+uint_v::IndexesFromZero()<nIndexes)); + } + { + int iElement=0; + for(iElement=0; iElement<nIndexes-float_vLen; iElement += float_vLen) + { + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fNPixelHits[iElement]); + vec.gather(&(track.fNPixelHits[0]), index); + } + const uint_v& index = reinterpret_cast<const uint_v&>(trackIndex[iElement]); + int_v& vec = reinterpret_cast<int_v&>(fNPixelHits[iElement]); + vec.gather(&(track.fNPixelHits[0]), index, int_m(iElement+uint_v::IndexesFromZero()<nIndexes)); + } +} + +void KFPTrackVector::GetTrack(KFPTrack& track, const int n) +{ + /** Copies track with index "n" for the current object to the KFPTrack object "track". + ** \param[out] track - KFPTrack object, where track with index "n" is copied + ** \param[in] n - index of the track to be copied + **/ + track.SetParameters(fP[0][n],fP[1][n],fP[2][n],fP[3][n],fP[4][n],fP[5][n]); + for(int i=0; i<21; i++) + track.SetCovariance(i,fC[i][n]); +// track.SetChi2(fChi2[n]); +// track.SetNDF(fNDF[n]); + track.SetId(fId[n]); + track.SetCharge(fQ[n]); + +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + track.SetFieldCoeff( fField[i][n], i); +#endif +} + +void KFPTrackVector::RotateXY( float_v alpha, int firstElement ) +{ + /** Rotates SIMD vector of tracks starting from the position "firstElement" onto the angles "alpha" in the XY plane. + ** Rotation matrix is: + \verbatim + { cos(A), -sin(A), 0, 0, 0, 0 } + { sin(A), cos(A), 0, 0, 0, 0 } + { 0, 0, 1, 0, 0, 0 } + { 0, 0, 0, cos(A), -sin(A), 0 } + { 0, 0, 0, sin(A), cos(A), 0 } + { 0, 0, 0, 0, 0, 1 } + \endverbatim + ** \param[in] alpha - rotation angles + ** \param[in] firstElement - track index, starting from which SIMD vector of tracks will be rotated + **/ + + const float_v cA = KFPMath::Cos( alpha ); + const float_v sA = KFPMath::Sin( alpha ); + + const float_v xInit = reinterpret_cast<const float_v&>(fP[0][firstElement]); + const float_v yInit = reinterpret_cast<const float_v&>(fP[1][firstElement]); + + float_v& x = reinterpret_cast<float_v&>(fP[0][firstElement]); + float_v& y = reinterpret_cast<float_v&>(fP[1][firstElement]); + + x = -(xInit*sA + yInit*cA); + y = xInit*cA - yInit*sA; + + const float_v pxInit = reinterpret_cast<const float_v&>(fP[3][firstElement]); + const float_v pyInit = reinterpret_cast<const float_v&>(fP[4][firstElement]); + + float_v& px = reinterpret_cast<float_v&>(fP[3][firstElement]); + float_v& py = reinterpret_cast<float_v&>(fP[4][firstElement]); + + px = -(pxInit*sA + pyInit*cA); + py = pxInit*cA - pyInit*sA; + + float_v cov[21]; + for(int iC=0; iC<21; iC++) + cov[iC] = reinterpret_cast<const float_v&>(fC[iC][firstElement]); + + reinterpret_cast<float_v&>(fC[0][firstElement]) = cA*cA* cov[2] + 2* cA* cov[1]* sA + cov[0]*sA* sA; + + reinterpret_cast<float_v&>(fC[1][firstElement]) = -(cA*cA * cov[1]) + cA* (-cov[0] + cov[2])* sA + cov[1]*sA* sA; + reinterpret_cast<float_v&>(fC[2][firstElement]) = cA*cA* cov[0] - 2* cA* cov[1]* sA + cov[2]*sA* sA; + + reinterpret_cast<float_v&>(fC[3][firstElement]) = -(cA* cov[4]) - cov[3]* sA; + reinterpret_cast<float_v&>(fC[4][firstElement]) = cA* cov[3] - cov[4]* sA; +// reinterpret_cast<float_v&>(fC[5][firstElement]) = cov[5]; + + reinterpret_cast<float_v&>(fC[6][firstElement]) = cA*cA* cov[11] + cA *(cov[10] + cov[7])* sA + cov[6]*sA* sA; + reinterpret_cast<float_v&>(fC[7][firstElement]) = -(cA*cA * cov[10]) + cA* (cov[11] - cov[6])* sA + cov[7] *sA*sA; + reinterpret_cast<float_v&>(fC[8][firstElement]) = -(cA *cov[12]) - cov[8] *sA; + reinterpret_cast<float_v&>(fC[9][firstElement]) = cA*cA* cov[14] + 2 *cA* cov[13]* sA + cov[9]* sA*sA; + + reinterpret_cast<float_v&>(fC[10][firstElement]) = -(cA*cA* cov[7]) + cA* (cov[11] - cov[6])* sA + cov[10]*sA* sA; + reinterpret_cast<float_v&>(fC[11][firstElement]) = cA*cA* cov[6] - cA* (cov[10] + cov[7]) *sA + cov[11]*sA* sA; + reinterpret_cast<float_v&>(fC[12][firstElement]) = cA* cov[8] - cov[12]* sA; + reinterpret_cast<float_v&>(fC[13][firstElement]) = -(cA*cA* cov[13]) + cA* (cov[14] - cov[9])* sA + cov[13]* sA*sA; + reinterpret_cast<float_v&>(fC[14][firstElement]) = cA*cA* cov[9] - 2* cA* cov[13]* sA + cov[14]* sA*sA; + + reinterpret_cast<float_v&>(fC[15][firstElement]) = -(cA* cov[16]) - cov[15]* sA; + reinterpret_cast<float_v&>(fC[16][firstElement]) = cA* cov[15] - cov[16]* sA; +// reinterpret_cast<float_v&>(fC[17][firstElement]) = cov[17]; + reinterpret_cast<float_v&>(fC[18][firstElement]) = -(cA* cov[19]) - cov[18]* sA; + reinterpret_cast<float_v&>(fC[19][firstElement]) = cA* cov[18] - cov[19]* sA; +// reinterpret_cast<float_v&>(fC[20][firstElement]) = cov[20]; +} // RotateXY + + +void KFPTrackVector::PrintTrack(int n) +{ + /** Prints parameters of the track with index "n". + ** \param[in] n - index of track to be printed + **/ + for(int i=0; i<6; i++) + std::cout << fP[i][n] << " "; + std::cout << std::endl; + + for(int i=0; i<21; i++) + std::cout << fC[i][n] << " "; + std::cout << std::endl; + + std::cout << fId[n] << " " << fPDG[n] << " " << fQ[n] << " " << fPVIndex[n] << " " << fNPixelHits[n] << std::endl; +} + +void KFPTrackVector::Print() +{ + /** Prints all field of the current object. **/ + + std::cout << "NTracks " << Size() << std::endl; + if( Size()==0 ) return; + + std::cout << "Parameters: " << std::endl; + for(int iP=0; iP<6; iP++) + { + std::cout << " iP " << iP << ": "; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << Parameter(iP)[iTr]<< " "; + std::cout << std::endl; + } + + std::cout << "Cov matrix: " << std::endl; + for(int iC=0; iC<21; iC++) + { + std::cout << " iC " << iC << ": "; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << Covariance(iC)[iTr]<< " "; + std::cout << std::endl; + } + + std::cout << "Id: " << std::endl; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << Id()[iTr] << " "; + std::cout << std::endl; + + std::cout << "Pdg: " << std::endl; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << PDG()[iTr] << " "; + std::cout << std::endl; + + std::cout << "Q: " << std::endl; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << Q()[iTr] << " "; + std::cout << std::endl; + + std::cout << "PV index: " << std::endl; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << PVIndex()[iTr] << " "; + std::cout << std::endl; + + std::cout << "fNPixelHits: " << std::endl; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << NPixelHits()[iTr] << " "; + std::cout << std::endl; + +#ifdef NonhomogeneousField + std::cout << "Field: " << std::endl; + for(int iF=0; iF<6; iF++) + { + std::cout << " iF " << iF << ": "; + for(int iTr=0; iTr<Size(); iTr++) + std::cout << FieldCoefficient(iF)[iTr]<< " "; + std::cout << std::endl; + } +#endif + + std::cout << "Last particle index: " << std::endl; + std::cout << LastElectron() << " " + << LastMuon() << " " + << LastPion() << " " + << LastKaon() << " " + << LastProton() << " " + << LastDeuteron() << " " + << LastTritium() << " " + << LastHe3() << " " + << LastHe4() << std::endl; +} + \ No newline at end of file diff --git a/external/KFParticle/KFParticle/KFPTrackVector.h b/external/KFParticle/KFParticle/KFPTrackVector.h new file mode 100644 index 0000000000000000000000000000000000000000..827b46ab456cd0db2b21316c4b4bdcc4462eca5b --- /dev/null +++ b/external/KFParticle/KFParticle/KFPTrackVector.h @@ -0,0 +1,396 @@ +//---------------------------------------------------------------------------- +// SIMDised vector approach for track representation +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPTrackVector_H +#define KFPTrackVector_H + +#include "KFPTrack.h" +#include "KFParticleDef.h" + +/** @class KFPTrackVector + ** @brief A class to store vectors of input tracks in the cartesian parametrisation. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** A track is described with the state vector { X, Y, Z, Px, Py, Pz } + ** and the corresponding covariance matrix. Also contains charge of the track, + ** unique Id, assigned PDG hypothesis, charge, index of the corresponding + ** primary vertex in case of primary track, number of hits from precise + ** detectors (like MVD in CBM, HFT in STAR, ITS in ALICE, etc.) + ** and the magnetic field approximation along the track trajectory + ** (in case of nonhomogeneous CBM-like field). \n + ** The data model implemented in the class is "Structure Of Arrays": + ** each parameter is stroed in a separate vector. Such data structure + ** allows fast vectorised access to the aligned data providing the + ** maximum possible speed for data reading, and at the same time easy + ** random access to the data members. Tracks are sorted by KFParticleTopoReconstructor::SortTracks(): + ** electrons, muons, pions, tracks without PID, kaons, protons, deuterons, tritons, He3, He4. + **/ + +class KFPTrackVector +{ + friend class KFParticleTopoReconstructor; + public: + KFPTrackVector():fId(), fPDG(), fQ(), fPVIndex(), fNPixelHits(), fNE(0), fNMu(0), fNPi(0), fNK(0), fNP(0), fND(0), fNT(0), fNHe3(0), fNHe4(0) { } + ~KFPTrackVector() { } + + /**Returns size of the vectors. All data vectors have the same size. */ + int Size() const { return fP[0].size(); } + int DataSize() const { + /**Returns size of the memory in floats (4 bytes or 32 bits) allocated by the current object. */ + const int& size = fP[0].size(); + + const int dataSize = size * 32 +#ifdef NonhomogeneousField + + size * 10 +#endif + + 9; + return dataSize; + } + + void Resize(const int n); + void Set(KFPTrackVector& v, int vSize, int offset); + void SetTracks(const KFPTrackVector& track, const kfvector_uint& trackIndex, const int nIndexes); + void GetTrack(KFPTrack& track, const int n); + + const kfvector_float& X() const { return fP[0]; } ///< Returns constant reference to the vector with X coordinates. + const kfvector_float& Y() const { return fP[1]; } ///< Returns constant reference to the vector with Y coordinates. + const kfvector_float& Z() const { return fP[2]; } ///< Returns constant reference to the vector with Z coordinates. + const kfvector_float& Px() const { return fP[3]; } ///< Returns constant reference to the vector with Px components of momentum. + const kfvector_float& Py() const { return fP[4]; } ///< Returns constant reference to the vector with Py components of momentum. + const kfvector_float& Pz() const { return fP[5]; } ///< Returns constant reference to the vector with Pz components of momentum. + + const kfvector_float& Parameter(const int i) const { return fP[i]; } ///< Returns constant reference to the track parameter vector with index "i". + const kfvector_float& Covariance(const int i) const { return fC[i]; } ///< Returns constant reference to the vector of the covariance matrix elements with index "i". +#ifdef NonhomogeneousField + const kfvector_float& FieldCoefficient(const int i) const { return fField[i]; } ///< Returns constant reference to the magnetic field coefficient with index "i". +#endif + + const kfvector_int& Id() const { return fId; } ///< Returns constant reference to the vector with track Id KFPTrackVector::fId. + const kfvector_int& PDG() const { return fPDG; } ///< Returns constant reference to the vector with assigned PDG hypothesis KFPTrackVector::fPDG. + const kfvector_int& Q() const { return fQ; } ///< Returns constant reference to the vector with charge KFPTrackVector::fQ. + const kfvector_int& PVIndex() const { return fPVIndex; } ///< Returns constant reference to the vector with indices of corresponding primary vertex KFPTrackVector::fPVIndex. + const kfvector_int& NPixelHits() const { return fNPixelHits; } ///< Returns constant reference to the vector with the number of precise measurements KFPTrackVector::fNPixelHits. + + float Pt(const int n) const { return sqrt(fP[3][n]*fP[3][n]+fP[4][n]*fP[4][n]); } ///< Returns transverse momentum of the track with index "n". + float P(const int n) const { return sqrt(fP[3][n]*fP[3][n]+fP[4][n]*fP[4][n]+fP[5][n]*fP[5][n]); } ///< Returns momentum of the track with index "n". + + //modifiers + void SetParameter (float value, int iP, int iTr) { fP[iP][iTr] = value; } ///< Sets the "value" of the parameter "iP" of the track with index "iTr". + void SetCovariance(float value, int iC, int iTr) { fC[iC][iTr] = value; } ///< Sets the "value" of the element of covariance matrix "iC" of the track with index "iTr". + + void SetParameter (const float_v& value, int iP, int iTr); + void SetCovariance(const float_v& value, int iC, int iTr); + +#ifdef NonhomogeneousField + void SetFieldCoefficient(float value, int iP, int iTr) { fField[iP][iTr] = value; } ///< Sets the "value" of the field coefficient "iP" of the track with index "iTr". +#endif + void SetId (int value, int iTr) { fId[iTr] = value; } ///< Sets Id of the track with index "iTr". + void SetPDG (int value, int iTr) { fPDG[iTr] = value; } ///< Sets PDG hypothesis of the track with index "iTr". + void SetQ (int value, int iTr) { fQ[iTr] = value; } ///< Sets charge of the track with index "iTr". + void SetPVIndex (int value, int iTr) { fPVIndex[iTr] = value; } ///< Sets index of the corresponding primary vertex of the track with index "iTr". + void SetNPixelHits (int value, int iTr) { fNPixelHits[iTr] = value; } ///< Sets number of precise measurement of the track with index "iTr". + void SetLastElectron(int n) { fNE = n; } ///< Sets index of the last electron. + void SetLastMuon (int n) { fNMu = n; } ///< Sets index of the last muon. + void SetLastPion (int n) { fNPi = n; } ///< Sets index of the last pion. + void SetLastKaon (int n) { fNK = n; } ///< Sets index of the last kaon. + void SetLastProton (int n) { fNP = n; } ///< Sets index of the last proton. + void SetLastDeuteron(int n) { fND = n; } ///< Sets index of the last deuteron. + void SetLastTritium (int n) { fNT = n; } ///< Sets index of the last triton. + void SetLastHe3 (int n) { fNHe3 = n; } ///< Sets index of the last He3. + void SetLastHe4 (int n) { fNHe4 = n; } ///< Sets index of the last He4. + + void RecalculateLastIndex() + { + /** Recalculate the last index of each track specie. Should be called after track sorting. */ + fNE = 0; fNMu = 0; fNPi = 0; fNK = 0; fNP = 0; fND = 0; fNT = 0; fNHe3 = 0; fNHe4 = 0; + for(int i=0; i<Size(); i++) + { + switch (abs(fPDG[i])) + { + case 11: fNE++; break; + case 13: fNMu++; break; + case 19: fNMu++; break; + case 211: fNPi++; break; + case 1: fNPi++; break; + case 3: fNPi++; break; + case 321: fNK++; break; + case 2212: fNP++; break; + case 1000010020: fND++; break; + case 1000010030: fNT++; break; + case 1000020030: fNHe3++; break; + case 1000020040: fNHe4++; break; + } + } + + fNMu += fNE; fNPi += fNMu; fNK += fNPi; fNP += fNK; + fND += fNP; fNT += fND; fNHe3 += fNT; fNHe4 += fNHe3; + } + + int FirstElectron() { return 0; } ///< Returns index of the first electron. + const int& LastElectron() const { return fNE; } ///< Returns index of the last electron. + int NElectrons() { return fNE; } ///< Returns number of electrons. + int FirstMuon() { return int(fNE/float_vLen)*float_vLen; } ///< Returns index of the first element of the SIMD vector with the first muon. + const int& LastMuon() const { return fNMu; } ///< Returns index of the last muon. + int NMuons() { return fNMu - fNE; } ///< Returns number of muons. + int FirstPion() { return int(fNMu/float_vLen)*float_vLen; } ///< Returns index of the first element of the SIMD vector with the first pion. + const int& LastPion() const { return fNPi; } ///< Returns index of the last pion. + int NPions() { return fNPi - fNMu; } ///< Returns number of pions. + int FirstKaon() { return int(fNPi/float_vLen)*float_vLen; } ///< Returns index of the first element of the SIMD vector with the first kaon. + const int& LastKaon() const { return fNK; } ///< Returns index of the last kaon. + int NKaons() { return fNK - fNPi; } ///< Returns number of kaons. + int FirstProton() { return int(fNK/float_vLen)*float_vLen; } ///< Returns index of the first element of the SIMD vector with the first proton. + const int& LastProton() const { return fNP; } ///< Returns index of the last proton. + int NProtons() { return fNP - fNK; } ///< Returns number of protons. + int FirstDeuteron() { return int(fNP/float_vLen)*float_vLen; } ///< Returns index of the first element of the SIMD vector with the first deuteron. + const int& LastDeuteron() const { return fND; } ///< Returns index of the last deuteron. + int NDeuterons() { return fND - fNP; } ///< Returns number of deuterons. + int FirstTritium() { return int(fND/float_vLen)*float_vLen; } ///< Returns index of the first element of the SIMD vector with the first triton. + const int& LastTritium() const { return fNT; } ///< Returns index of the last triton. + int NTritiums() { return fNT - fND; } ///< Returns number of tritons. + int FirstHe3() { return int(fNT/float_vLen)*float_vLen; } ///< Returns index of the first element of the SIMD vector with the first He3. + const int& LastHe3() const { return fNHe3; } ///< Returns index of the last He3. + int NHe3s() { return fNHe3 - fNT; } ///< Returns number of He3 tracks. + int FirstHe4() { return int(fNHe3/float_vLen)*float_vLen; } ///< Returns index of the first element of the SIMD vector with the first He4. + const int& LastHe4() const { return fNHe4; } ///< Returns index of the last He4. + int NHe4s() { return fNHe4 - fNHe3; } ///< Returns number of He4 tracks. + + void AddElectron() {fNE++;} ///< Increases by one index of the last electron. + void AddMuon() {fNMu++;} ///< Increases by one index of the last muon. + void AddPion() {fNPi++;} ///< Increases by one index of the last pion. + void AddKaon() {fNK++;} ///< Increases by one index of the last kaon. + void AddProton() {fNP++;} ///< Increases by one index of the last proton. + void AddDeuteron() {fND++;} ///< Increases by one index of the last deuteron. + void AddTririum() {fNT++;} ///< Increases by one index of the last triton. + void AddHe3() {fNHe3++;} ///< Increases by one index of the last He3. + void AddHe4() {fNHe4++;} ///< Increases by one index of the last He4. + + void RotateXY( float_v alpha, int firstElement ); + + void PrintTrack(int n); + void Print(); + + const KFPTrackVector& operator = (const KFPTrackVector& track) + { + /** Operator to copy one KFPTrackVector object to another. Makes one-to-one copy.*/ + const int localSize = track.Size(); + + for(int i=0; i<6; i++) + { + fP[i].resize(localSize); + for(int n=0; n<localSize; n++) + fP[i][n] = track.fP[i][n]; + } + + for(int i=0; i<21; i++) + { + fC[i].resize(localSize); + for(int n=0; n<localSize; n++) + fC[i][n] = track.fC[i][n]; + } + +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + { + fField[i].resize(localSize); + for(int n=0; n<localSize; n++) + fField[i][n] = track.fField[i][n]; + } +#endif + + fId.resize(localSize); + for(int n=0; n<localSize; n++) + fId[n] = track.fId[n]; + + fPDG.resize(localSize); + for(int n=0; n<localSize; n++) + fPDG[n] = track.fPDG[n]; + + fQ.resize(localSize); + for(int n=0; n<localSize; n++) + fQ[n] = track.fQ[n]; + + fPVIndex.resize(localSize); + for(int n=0; n<localSize; n++) + fPVIndex[n] = track.fPVIndex[n]; + + fNPixelHits.resize(localSize); + for(int n=0; n<localSize; n++) + fNPixelHits[n] = track.fNPixelHits[n]; + + fNE = track.fNE; + fNMu = track.fNMu; + fNPi = track.fNPi; + fNK = track.fNK; + fNP = track.fNP; + fND = track.fND; + fNT = track.fNT; + fNHe3 = track.fNHe3; + fNHe4 = track.fNHe4; + + return *this; + } + + void SetDataToVector(int* data, int& offset) + { + /** Copies entire vector to the provided memory starting form the position "offset". + ** The function is used in KFPInputData::SetDataToVector(). + ** \param[out] data - pointer to the memory where the track vectors should be copied; since all fields of + ** KFPTrackVector are of the same size (int or float) pointer can be safely casted to int* + ** \param[in,out] offset - starting position in "data" where vectors should be copied; after all vectors are + ** copied the offset is shifted on the size of the written object so the next KFPTrackVector object + ** can be copied to the "data" + **/ + for(int iP=0; iP<6; iP++) + { + memcpy( &(data[offset]), &(fP[iP][0]), Size()*sizeof(float)); + offset += Size(); + } + + for(int iC=0; iC<21; iC++) + { + memcpy( &(data[offset]), &(fC[iC][0]), Size()*sizeof(float)); + offset += Size(); + } + + memcpy( &(data[offset]), &(fId[0]), Size()*sizeof(float)); + offset += Size(); + + memcpy( &(data[offset]), &(fPDG[0]), Size()*sizeof(float)); + offset += Size(); + + memcpy( &(data[offset]), &(fQ[0]), Size()*sizeof(float)); + offset += Size(); + + memcpy( &(data[offset]), &(fPVIndex[0]), Size()*sizeof(float)); + offset += Size(); + + memcpy( &(data[offset]), &(fNPixelHits[0]), Size()*sizeof(float)); + offset += Size(); + +#ifdef NonhomogeneousField + for(int iF=0; iF<10; iF++) + { + memcpy( &(data[offset]), &(fField[iF][0]), Size()*sizeof(float)); + offset += Size(); + } +#endif + + data[offset] = fNE; offset++; + data[offset] = fNMu; offset++; + data[offset] = fNPi; offset++; + data[offset] = fNK; offset++; + data[offset] = fNP; offset++; + data[offset] = fND; offset++; + data[offset] = fNT; offset++; + data[offset] = fNHe3; offset++; + data[offset] = fNHe4; offset++; + } + + void ReadDataFromVector(int* data, int& offset) + { + /** Copies entire vector from the provided memory starting form the position "offset". + ** The function is used in KFPInputData::ReadDataFromVector(). + ** \param[in] data - pointer to the memory with the track vectors; since all fields of + ** KFPTrackVector are of the same size (int or float) pointer can be safely casted to int* + ** \param[in,out] offset - starting position of the memory to be copied; after all vectors are + ** copied the offset is shifted on the size of the read object so the next KFPTrackVector object + ** can be copied + **/ + for(int iP=0; iP<6; iP++) + { + memcpy( &(fP[iP][0]), &(data[offset]), Size()*sizeof(float)); + offset += Size(); + } + + for(int iC=0; iC<21; iC++) + { + memcpy( &(fC[iC][0]), &(data[offset]), Size()*sizeof(float)); + offset += Size(); + } + + memcpy( &(fId[0]), &(data[offset]), Size()*sizeof(float)); + offset += Size(); + + memcpy( &(fPDG[0]), &(data[offset]), Size()*sizeof(float)); + offset += Size(); + + memcpy( &(fQ[0]), &(data[offset]), Size()*sizeof(float)); + offset += Size(); + + memcpy( &(fPVIndex[0]), &(data[offset]), Size()*sizeof(float)); + offset += Size(); + + memcpy( &(fNPixelHits[0]), &(data[offset]), Size()*sizeof(float)); + offset += Size(); + +#ifdef NonhomogeneousField + for(int iF=0; iF<10; iF++) + { + memcpy( &(fField[iF][0]), &(data[offset]), Size()*sizeof(float)); + offset += Size(); + } +#endif + + fNE = data[offset]; offset++; + fNMu = data[offset]; offset++; + fNPi = data[offset]; offset++; + fNK = data[offset]; offset++; + fNP = data[offset]; offset++; + fND = data[offset]; offset++; + fNT = data[offset]; offset++; + fNHe3 = data[offset]; offset++; + fNHe4 = data[offset]; offset++; + } + + void *operator new(size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new(size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void operator delete(void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + void operator delete[](void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + + private: + kfvector_float fP[6]; ///< Vectors with parameters of the track : X, Y, Z, Px, Py, Pz. + kfvector_float fC[21]; ///< Vectors with covariance matrix of the track parameters stroed in a lower triangular form. + + kfvector_int fId; ///< Vector with the unique Id of tracks. + kfvector_int fPDG; ///< Vector with the PDG hypothesis. + kfvector_int fQ; ///< Vector with the charge of the tracks. + kfvector_int fPVIndex; ///< Vector with the index of the corresponding primary vertex. If track is considered secondary "-1" is stored. + kfvector_int fNPixelHits; ///< Vector with the number of hits from precise detectors (like MVD in CBM, HFT in STAR, ITS in ALICE, etc.) + + /** The coefficients of the field approximation of each field component along the track trajectory using parabolas: \n + ** cx0 = fField[0], cx1 = fField[1], cx2 = fField[2] - coefficients of the Bx approximation; \n + ** cy0 = fField[3], cy1 = fField[4], cy2 = fField[5] - coefficients of the By approximation; \n + ** cz0 = fField[6], cz1 = fField[7], cz2 = fField[8] - coefficients of the Bz approximation; \n + ** z0 = fField[9] - reference Z coordinate. \n + ** Bx(z) = cx0 + cx1*(z-z0) + cx2*(z-z0)^2 \n + ** By(z) = cy0 + cy1*(z-z0) + cy2*(z-z0)^2 \n + ** Bz(z) = cz0 + cz1*(z-z0) + cz2*(z-z0)^2 + **/ +#ifdef NonhomogeneousField + kfvector_float fField[10]; +#endif + + int fNE; ///< Index of the last electron. + int fNMu; ///< Index of the last muon. + int fNPi; ///< Index of the last pion (plus tracks without PID). + int fNK; ///< Index of the last kaon. + int fNP; ///< Index of the last proton. + int fND; ///< Index of the last deuteron. + int fNT; ///< Index of the last triton. + int fNHe3; ///< Index of the last He3. + int fNHe4; ///< Index of the last He4. +} __attribute__((aligned(sizeof(float_v)))); + +#endif diff --git a/external/KFParticle/KFParticle/KFPVertex.cxx b/external/KFParticle/KFParticle/KFPVertex.cxx new file mode 100644 index 0000000000000000000000000000000000000000..76815675afcb21d2e014e5a8aa79ec8848239ff6 --- /dev/null +++ b/external/KFParticle/KFParticle/KFPVertex.cxx @@ -0,0 +1,20 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFPVertex.h" + +KFPVertex::KFPVertex():fChi2(-1.f), fNContributors(0), fNDF(-1) +{ + for(int iP=0; iP<3; iP++) + fP[iP] = 0; + for(int iC=0; iC<6; iC++) + fC[iC] = 0; +} diff --git a/external/KFParticle/KFParticle/KFPVertex.h b/external/KFParticle/KFParticle/KFPVertex.h new file mode 100644 index 0000000000000000000000000000000000000000..b0ca45bb398a578c185575ae92adbde4ea1e45a0 --- /dev/null +++ b/external/KFParticle/KFParticle/KFPVertex.h @@ -0,0 +1,124 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPVertex_H +#define KFPVertex_H + +/** @class KFPVertex + ** @brief A scalar class for storage of the vertex in the cartesian parametrisation. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** A vertex is described with the state vector { X, Y, Z } + ** and the corresponding covariance matrix. Also contains chi2 of the fit, + ** corresponding number of degrees of freedom, + ** and number of tracks which were used to construct current vertex. + ** The class is used to provide an external vertex through the interfaces + ** to the KF Particle package. + **/ + +class KFPVertex +{ + public: + KFPVertex(); + ~KFPVertex() { } + +/* KFPVertex(const KFPVertex& vVert); + KFPVertex& operator=(const KFPVertex& vVert);*/ + + float GetX() const { return fP[0]; } ///< Returns X coordinate of the vertex. + float GetY() const { return fP[1]; } ///< Returns Y coordinate of the vertex. + float GetZ() const { return fP[2]; } ///< Returns Z coordinate of the vertex. + + /** Copies position of the vertex to the output array of floats. \param[out] position - the output array with the position of the vertex **/ + void GetXYZ(float *position) const {position[0] = fP[0]; position[1] = fP[1]; position[2] = fP[2];} + /** Copies position of the vertex to the output array of doubles. \param[out] position - the output array with the position of the vertex **/ + void GetXYZ(double *position) const {position[0] = fP[0]; position[1] = fP[1]; position[2] = fP[2];} + void GetCovarianceMatrix(float *covmatrix) const + { + /** Copies the covariance matrix of the vertex to the array of floats. + ** \param[out] covmatrix[6] - the output array, where the covariance matrix is copied + **/ + for (int i=0; i<6; i++) + covmatrix[i] = fC[i]; + } + void GetCovarianceMatrix(double *covmatrix) const + { + /** Copies the covariance matrix of the vertex to the array of doubles. + ** \param[out] covmatrix[6] - the output array, where the covariance matrix is copied + **/ + for (int i=0; i<6; i++) + covmatrix[i] = fC[i]; + } + + float GetChi2perNDF() const { return fChi2/fNDF; } ///< Returns Chi2/NDF of the vertex, NDF is a number of degrees of freedom. + float GetChi2() const { return fChi2; } ///< Returns Chi2 of the vertex fit. + int GetNDF() const { return fNDF; } ///< Returns number of degrees of freedom of the vertex. + int GetNContributors() const { return fNContributors; } ///< Returns number of tracks which were used for construction of the vertex + + float GetParameter(int i) const { return fP[i]; } ///< Returns parameter "i" of the vertex. \param[in] i - index of the parameter to be returned + float GetCovariance(int i) const { return fC[i]; } ///< Returns element of the covariance matrix "i" of the vertex. \param[in] i - index of the element to be returned + + /** Sets position { X, Y, Z } of the vertex from the input array of doubles. + ** \param[in] position - input array with the vertex parameters + **/ + void SetXYZ(float *position) { fP[0] = position[0]; fP[1] = position[1]; fP[2] = position[2]; } + /** Sets position { X, Y, Z } of the vertex. + ** \param[in] x - X coordinate to be set + ** \param[in] y - Y coordinate to be set + ** \param[in] z - Z coordinate to be set + **/ + void SetXYZ(float x, float y, float z) { fP[0] = x; fP[1] = y; fP[2] = z; } + void SetX(float x) { fP[0] = x; } ///< Sets X coordinate of the vertex + void SetY(float y) { fP[1] = y; } ///< Sets Y coordinate of the vertex + void SetZ(float z) { fP[2] = z; } ///< Sets Z coordinate of the vertex + void SetChi2(float chi) { fChi2 = chi; } ///< Sets Chi2 of the vertex + void SetNDF(int ndf) { fNDF = ndf; } ///< Sets number of degrees of freedom of the vertex + void SetNContributors(int nc) { fNContributors = nc; } ///< Sets number of tracks which were used for construction of the vertex + + void SetCovarianceMatrix(float *C) + { + /** Sets the covariance matrix from the input array of floats. + ** \param[in] C[6] - array with the input elements of the covariance matrix stored in the lower triangular form + **/ + for (int i=0; i<6; i++) + fC[i] = C[i]; + } + + void SetCovarianceMatrix(float C00,float C10,float C11,float C20,float C21,float C22) + { + /** Sets the covariance matrix from the input array of floats. + ** \param[in] C00 - Cxx + ** \param[in] C10 - Cxy = Cyx + ** \param[in] C11 - Cyy + ** \param[in] C20 - Cxz = Czx + ** \param[in] C21 - Cyz = Czy + ** \param[in] C22 - Czz + **/ + fC[0] = C00; + fC[1] = C10; + fC[2] = C11; + fC[3] = C20; + fC[4] = C21; + fC[5] = C22; + } + + private: + + float fP[3]; ///< Coordinates of the vertex. + float fC[6]; ///< Covariance matrix of the vertex parameters. + float fChi2; ///< Chi-square of the vertex fit. + int fNContributors; ///< Number of tracks, from which the vertex was built. + int fNDF; ///< Number of degrees of freedom of the vertex fit. +}; + +#endif diff --git a/external/KFParticle/KFParticle/KFParticle.cxx b/external/KFParticle/KFParticle/KFParticle.cxx new file mode 100644 index 0000000000000000000000000000000000000000..afe68599c2b34aafcd4ec732b90f6adb1bb316d2 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticle.cxx @@ -0,0 +1,492 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author S.Gorbunov, I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 13.05.07 +// +// Class to reconstruct and store the decayed particle parameters. +// The method is described in CBM-SOFT note 2007-003, +// ``Reconstruction of decayed particles based on the Kalman filter'', +// http://www.gsi.de/documents/DOC-2007-May-14-1.pdf +// +// This class is ALICE interface to general mathematics in KFParticleCore +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +#include "KFParticle.h" +#include "KFParticleDatabase.h" + +#include "KFPTrack.h" +#include "KFPVertex.h" + +#ifndef KFParticleStandalone +ClassImp(KFParticle); +#endif + + +#ifdef HomogeneousField +float KFParticle::fgBz = -5.; //* Bz compoment of the magnetic field +#endif + +KFParticle::KFParticle( const KFParticle &d1, const KFParticle &d2 ): KFParticleBase() +{ + /** Constructs a particle from two input daughter particles + ** \param[in] d1 - the first daughter particle + ** \param[in] d2 - the second daughter particle + **/ + KFParticle mother; + mother+= d1; + mother+= d2; + *this = mother; +} + +void KFParticle::Create( const float Param[], const float Cov[], Int_t Charge, float mass ) +{ + /** Constructor from a "cartesian" track, mass hypothesis should be provided + ** \param[in] Param[6] = { X, Y, Z, Px, Py, Pz } - position and momentum + ** \param[in] Cov[21] - lower-triangular part of the covariance matrix:@n + ** \verbatim + ( 0 . . . . . ) + ( 1 2 . . . . ) + Cov[21] = ( 3 4 5 . . . ) + ( 6 7 8 9 . . ) + ( 10 11 12 13 14 . ) + ( 15 16 17 18 19 20 ) + \endverbatim + ** \param[in] Charge - charge of the particle in elementary charge units + ** \param[in] mass - the mass hypothesis + **/ + float C[21]; + for( int i=0; i<21; i++ ) C[i] = Cov[i]; + + KFParticleBase::Initialize( Param, C, Charge, mass ); +} + +void KFParticle::Create( const Double_t Param[], const Double_t Cov[], Int_t Charge, float mass ) +{ + /** Constructor from a "cartesian" track, mass hypothesis should be provided + ** \param[in] Param[6] = { X, Y, Z, Px, Py, Pz } - position and momentum + ** \param[in] Cov[21] - lower-triangular part of the covariance matrix:@n + ** \verbatim + ( 0 . . . . . ) + ( 1 2 . . . . ) + Cov[21] = ( 3 4 5 . . . ) + ( 6 7 8 9 . . ) + ( 10 11 12 13 14 . ) + ( 15 16 17 18 19 20 ) + \endverbatim + ** \param[in] Charge - charge of the particle in elementary charge units + ** \param[in] mass - the mass hypothesis + **/ + float P[6]; + for(int i=0; i<6; i++ ) P[i] = Param[i]; + float C[21]; + for( int i=0; i<21; i++ ) C[i] = Cov[i]; + + KFParticleBase::Initialize( P, C, Charge, mass ); +} + +KFParticle::KFParticle( const KFPTrack &track, const int PID ): KFParticleBase() +{ + /** Constructor from a track in the KF Particle format, PID hypothesis should be provided + ** \param[in] track - KFPTrack containing 6 parameters: { X, Y, Z, Px, Py, Pz } and their errors + ** \param[in] PID - PID hypothesis, needed to assign mass to a particle and calculate the energy + **/ + + track.XvYvZv(fP); + track.PxPyPz(fP+3); + fQ = track.Charge(); + track.GetCovarianceXYZPxPyPz( fC ); + + float mass = KFParticleDatabase::Instance()->GetMass(PID); + + Create(fP,fC,fQ,mass); + fChi2 = track.GetChi2(); + fNDF = track.GetNDF(); + SetPDG(PID); +#ifdef NonhomogeneousField + for(int iF=0; iF<10; iF++) + SetFieldCoeff( track.GetFieldCoeff()[iF], iF); +#endif +} + +KFParticle::KFParticle( const KFPVertex &vertex ): KFParticleBase() +{ + /** Constructor from a vertex in the KF Particle format + ** \param[in] vertex - KFPVertex containing 3 parameters: { X, Y, Z } and their errors + **/ + + vertex.GetXYZ( fP ); + vertex.GetCovarianceMatrix( fC ); + fChi2 = vertex.GetChi2(); + fNDF = 2*vertex.GetNContributors() - 3; + fQ = 0; + fAtProductionVertex = 0; + fSFromDecay = 0; +} + +Bool_t KFParticle::GetDistanceFromVertexXY( const float vtx[], const float Cv[], float &val, float &err ) const +{ + /** Calculates the DCA distance from a vertex together with the error in the XY plane. + ** Returns "true" if calculation is failed, "false" if both value and the error are well defined. + ** \param[in] vtx[2] - { X, Y } coordinates of the vertex + ** \param[in] Cv[3] - lower-triangular part of the covariance matrix of the vertex + ** \param[out] val - the distance in the XY plane to the vertex + ** \param[out] err - the error of the calculated distance, takes into account errors of the particle and vertex + **/ + + Bool_t ret = 0; + + float mP[8]; + float mC[36]; + float dsdr[6] = {0.f}; + const float dS = GetDStoPoint(vtx, dsdr); + Transport( dS, dsdr, mP, mC ); + + float dx = mP[0] - vtx[0]; + float dy = mP[1] - vtx[1]; + float px = mP[3]; + float py = mP[4]; + float pt = sqrt(px*px + py*py); + float ex=0, ey=0; + if( pt<1.e-4 ){ + ret = 1; + pt = 1.; + val = 1.e4; + } else{ + ex = px/pt; + ey = py/pt; + val = dy*ex - dx*ey; + } + + float h0 = -ey; + float h1 = ex; + float h3 = (dy*ey + dx*ex)*ey/pt; + float h4 = -(dy*ey + dx*ex)*ex/pt; + + err = + h0*(h0*GetCovariance(0,0) + h1*GetCovariance(0,1) + h3*GetCovariance(0,3) + h4*GetCovariance(0,4) ) + + h1*(h0*GetCovariance(1,0) + h1*GetCovariance(1,1) + h3*GetCovariance(1,3) + h4*GetCovariance(1,4) ) + + h3*(h0*GetCovariance(3,0) + h1*GetCovariance(3,1) + h3*GetCovariance(3,3) + h4*GetCovariance(3,4) ) + + h4*(h0*GetCovariance(4,0) + h1*GetCovariance(4,1) + h3*GetCovariance(4,3) + h4*GetCovariance(4,4) ); + + if( Cv ){ + err+= h0*(h0*Cv[0] + h1*Cv[1] ) + h1*(h0*Cv[1] + h1*Cv[2] ); + } + + err = sqrt(fabs(err)); + + return ret; +} + +Bool_t KFParticle::GetDistanceFromVertexXY( const float vtx[], float &val, float &err ) const +{ + /** Calculates the DCA distance from a vertex together with the error in the XY plane. + ** Returns "true" if calculation is failed, "false" if both value and the error are well defined. + ** \param[in] vtx[2] - { X, Y } coordinates of the vertex + ** \param[out] val - the distance in the XY plane to the vertex + ** \param[out] err - the error of the calculated distance, takes into account errors of the particle only + **/ + return GetDistanceFromVertexXY( vtx, 0, val, err ); +} + + +Bool_t KFParticle::GetDistanceFromVertexXY( const KFParticle &Vtx, float &val, float &err ) const +{ + /** Calculates the DCA distance from a vertex in the KFParticle format together with the error in the XY plane. + ** Returns "true" if calculation is failed, "false" if both value and the error are well defined. + ** \param[in] Vtx - the vertex in the KFParticle format + ** \param[out] val - the distance in the XY plane to the vertex + ** \param[out] err - the error of the calculated distance, takes into account errors of the particle and vertex + **/ + + return GetDistanceFromVertexXY( Vtx.fP, Vtx.fC, val, err ); +} + +#ifdef HomogeneousField +Bool_t KFParticle::GetDistanceFromVertexXY( const KFPVertex &Vtx, float &val, float &err ) const +{ + /** Calculates the DCA distance from a vertex in the KFPVertex format together with the error in the XY plane. + ** Returns "true" if calculation is failed, "false" if both value and the error are well defined. + ** \param[in] Vtx - the vertex in the KFPVertex format + ** \param[out] val - the distance in the XY plane to the vertex + ** \param[out] err - the error of the calculated distance, takes into account errors of the particle and vertex + **/ + + return GetDistanceFromVertexXY( KFParticle(Vtx), val, err ); +} +#endif + +float KFParticle::GetDistanceFromVertexXY( const float vtx[] ) const +{ + /** Returns the DCA distance from a vertex in the XY plane. + ** \param[in] vtx[2] - { X, Y } coordinates of the vertex + **/ + + float val, err; + GetDistanceFromVertexXY( vtx, 0, val, err ); + return val; +} + +float KFParticle::GetDistanceFromVertexXY( const KFParticle &Vtx ) const +{ + /** Returns the DCA distance from a vertex in the KFParticle format in the XY plane. + ** \param[in] Vtx - the vertex in the KFParticle format + **/ + + return GetDistanceFromVertexXY( Vtx.fP ); +} + +#ifdef HomogeneousField +float KFParticle::GetDistanceFromVertexXY( const KFPVertex &Vtx ) const +{ + /** Returns the DCA distance from a vertex in the KFParticle format in the XY plane. + ** \param[in] Vtx - the vertex in the KFPVertex format + **/ + + return GetDistanceFromVertexXY( KFParticle(Vtx).fP ); +} +#endif + +float KFParticle::GetDistanceFromParticleXY( const KFParticle &p ) const +{ + /** Returns the DCA distance between the current and the second particles in the XY plane. + ** \param[in] p - the second particle + **/ + + float dsdr[4][6]; + float dS[2]; + GetDStoParticle( p, dS, dsdr ); + float mP[8], mC[36], mP1[8], mC1[36]; + Transport( dS[0], dsdr[0], mP, mC ); + p.Transport( dS[1], dsdr[3], mP1, mC1 ); + float dx = mP[0]-mP1[0]; + float dy = mP[1]-mP1[1]; + return sqrt(dx*dx+dy*dy); +} + +float KFParticle::GetDeviationFromParticleXY( const KFParticle &p ) const +{ + /** Returns sqrt(Chi2/ndf) deviation from other particle in the XY plane. + ** \param[in] p - the second particle + **/ + + float dsdr[4][6]; + float dS[2]; + GetDStoParticle( p, dS, dsdr ); + float mP[8], mC[36], mP1[8], mC1[36]; + Transport( dS[0], dsdr[0], mP, mC ); + p.Transport( dS[1], dsdr[3], mP1, mC1 ); + + float d[2]={ mP[0]-mP1[0], mP[1]-mP1[1] }; + + float sigmaS = .1+10.*sqrt( (d[0]*d[0]+d[1]*d[1] )/ + (mP1[3]*mP1[3]+mP1[4]*mP1[4] ) ); + + float h[2] = { mP1[3]*sigmaS, mP1[4]*sigmaS }; + + mC1[0] +=h[0]*h[0]; + mC1[1] +=h[1]*h[0]; + mC1[2] +=h[1]*h[1]; + + return GetDeviationFromVertexXY( mP1, mC1 )*sqrt(2./1.); +} + + +float KFParticle::GetDeviationFromVertexXY( const float vtx[], const float Cv[] ) const +{ + /** Returns sqrt(Chi2/ndf) deviation from the vertex in the XY plane. + ** \param[in] vtx[2] - { X, Y } coordinates of the vertex + ** \param[in] Cv[3] - lower-triangular part of the covariance matrix of the vertex + **/ + + float val, err; + Bool_t problem = GetDistanceFromVertexXY( vtx, Cv, val, err ); + if( problem || err<1.e-20 ) return 1.e4; + else return val/err; +} + + +float KFParticle::GetDeviationFromVertexXY( const KFParticle &Vtx ) const +{ + /** Returns sqrt(Chi2/ndf) deviation from the vertex in the KFParticle format in the XY plane. + ** \param[in] Vtx - the vertex in the KFParticle format + **/ + + return GetDeviationFromVertexXY( Vtx.fP, Vtx.fC ); +} + +#ifdef HomogeneousField +float KFParticle::GetDeviationFromVertexXY( const KFPVertex &Vtx ) const +{ + /** Returns sqrt(Chi2/ndf) deviation from the vertex in the KFPVertex format in the XY plane. + ** \param[in] Vtx - the vertex in the KFPVertex format + **/ + + KFParticle v(Vtx); + return GetDeviationFromVertexXY( v.fP, v.fC ); +} +#endif + +void KFParticle::GetParametersAtPoint(const float* point, const float* pointCov, float* m, float* mV) +{ + /** Transports particle to the DCA of the given point and stores obtained parameters and covariance matrix + ** \param[in] point[3] - the point to which particle is transported + ** \param[in] pointCov[6] - the covariance matrix of the point + ** \param[out] m[8] - the parameters of the particle at the DCA point + ** \param[out] mV[36] - the covariance matrix of the particle at the DCA point, accounts the covariance matrix of the point as well + **/ + + float dsdr[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + float dS = GetDStoPoint(point, dsdr); + float dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0, 0, 0}; + + float F[36], F1[36]; + for(int i2=0; i2<36; i2++){ + mV[i2] = 0.f; + F[i2] = 0.f; + F1[i2] = 0.f; + } + Transport(dS, dsdr, m, mV, dsdp, F, F1); + + float V1Tmp[36]; + for(int i=0; i<36; i++) + V1Tmp[i] = 0.f; + KFParticle::MultQSQt(F1, pointCov, V1Tmp, 6); + + for(int iC=0; iC<21; iC++) + mV[iC] += V1Tmp[iC]; +} + +float KFParticle::GetAngle ( const KFParticle &p ) const +{ + /** Returns the opening angle between the current and the second particle in 3D. + ** \param[in] p - the second particle + **/ + + float dsdr[4][6]; + float dS[2]; + GetDStoParticle( p, dS, dsdr ); + float mP[8], mC[36], mP1[8], mC1[36]; + Transport( dS[0], dsdr[0], mP, mC ); + p.Transport( dS[1], dsdr[3], mP1, mC1 ); + float n = sqrt( mP[3]*mP[3] + mP[4]*mP[4] + mP[5]*mP[5] ); + float n1= sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] + mP1[5]*mP1[5] ); + n*=n1; + float a = 0; + if( n>1.e-8 ) a = ( mP[3]*mP1[3] + mP[4]*mP1[4] + mP[5]*mP1[5] )/n; + if (fabs(a)<1.) a = acos(a); + else a = (a>=0) ?0 :3.14; + return a; +} + +float KFParticle::GetAngleXY( const KFParticle &p ) const +{ + /** Returns the opening angle between the current and the second particle in the XY plane. + ** \param[in] p - the second particle + **/ + + float dsdr[4][6]; + float dS[2]; + GetDStoParticle( p, dS, dsdr ); + float mP[8], mC[36], mP1[8], mC1[36]; + Transport( dS[0], dsdr[0], mP, mC ); + p.Transport( dS[1], dsdr[3], mP1, mC1 ); + float n = sqrt( mP[3]*mP[3] + mP[4]*mP[4] ); + float n1= sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] ); + n*=n1; + float a = 0; + if( n>1.e-8 ) a = ( mP[3]*mP1[3] + mP[4]*mP1[4] )/n; + if (fabs(a)<1.) a = acos(a); + else a = (a>=0) ?0 :3.14; + return a; +} + +float KFParticle::GetAngleRZ( const KFParticle &p ) const +{ + /** Returns the opening angle between the current and the second particle in the RZ plane, R = sqrt(X*X+Y*Y). + ** \param[in] p - the second particle + **/ + + float dsdr[4][6]; + float dS[2]; + GetDStoParticle( p, dS, dsdr ); + float mP[8], mC[36], mP1[8], mC1[36]; + Transport( dS[0], dsdr[0], mP, mC ); + p.Transport( dS[1], dsdr[3], mP1, mC1 ); + float nr = sqrt( mP[3]*mP[3] + mP[4]*mP[4] ); + float n1r= sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] ); + float n = sqrt( nr*nr + mP[5]*mP[5] ); + float n1= sqrt( n1r*n1r + mP1[5]*mP1[5] ); + n*=n1; + float a = 0; + if( n>1.e-8 ) a = ( nr*n1r +mP[5]*mP1[5])/n; + if (fabs(a)<1.) a = acos(a); + else a = (a>=0) ?0 :3.14; + return a; +} + +float KFParticle::GetPseudoProperDecayTime( const KFParticle &pV, const float& mass, float* timeErr2 ) const +{ + /** Returns the Pseudo Proper Time of the decay = (r*pt) / |pt| * M/|pt| + ** \param[in] pV - the creation point of the particle + ** \param[in] mass - the mass of the particle + ** \param[out] timeErr2 - error of the returned value, if null pointer is provided - is not calculated + **/ + + const float ipt2 = 1/( Px()*Px() + Py()*Py() ); + const float mipt2 = mass*ipt2; + const float dx = X() - pV.X(); + const float dy = Y() - pV.Y(); + + if ( timeErr2 ) { + // -- calculate error = sigma(f(r)) = f'Cf' + // r = {x,y,px,py,x_pV,y_pV} + // df/dr = { px*m/pt^2, + // py*m/pt^2, + // ( x - x_pV )*m*(1/pt^2 - 2(px/pt^2)^2), + // ( y - y_pV )*m*(1/pt^2 - 2(py/pt^2)^2), + // -px*m/pt^2, + // -py*m/pt^2 } + const float f0 = Px()*mipt2; + const float f1 = Py()*mipt2; + const float mipt2derivative = mipt2*(1-2*Px()*Px()*ipt2); + const float f2 = dx*mipt2derivative; + const float f3 = -dy*mipt2derivative; + const float f4 = -f0; + const float f5 = -f1; + + const float& mC00 = GetCovariance(0,0); + const float& mC10 = GetCovariance(0,1); + const float& mC11 = GetCovariance(1,1); + const float& mC20 = GetCovariance(3,0); + const float& mC21 = GetCovariance(3,1); + const float& mC22 = GetCovariance(3,3); + const float& mC30 = GetCovariance(4,0); + const float& mC31 = GetCovariance(4,1); + const float& mC32 = GetCovariance(4,3); + const float& mC33 = GetCovariance(4,4); + const float& mC44 = pV.GetCovariance(0,0); + const float& mC54 = pV.GetCovariance(1,0); + const float& mC55 = pV.GetCovariance(1,1); + + *timeErr2 = + f5*mC55*f5 + + f5*mC54*f4 + + f4*mC44*f4 + + f3*mC33*f3 + + f3*mC32*f2 + + f3*mC31*f1 + + f3*mC30*f0 + + f2*mC22*f2 + + f2*mC21*f1 + + f2*mC20*f0 + + f1*mC11*f1 + + f1*mC10*f0 + + f0*mC00*f0; + } + return ( dx*Px() + dy*Py() )*mipt2; +} diff --git a/external/KFParticle/KFParticle/KFParticle.h b/external/KFParticle/KFParticle/KFParticle.h new file mode 100644 index 0000000000000000000000000000000000000000..76b84f467b7cc74a4127ee2fc7028c6a81d2d8c0 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticle.h @@ -0,0 +1,1020 @@ +//--------------------------------------------------------------------------------- +// The KFParticle class +// . +// @author S.Gorbunov, I.Kisel +// @version 1.0 +// @since 13.05.07 +// +// Class to reconstruct and store the decayed particle parameters. +// The method is described in CBM-SOFT note 2007-003, +// ``Reconstruction of decayed particles based on the Kalman filter'', +// http://www.gsi.de/documents/DOC-2007-May-14-1.pdf +// +// This class is ALICE interface to general mathematics in KFParticleBase +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//_________________________________________________________________________________ + +//#define NonhomogeneousField +// #define HomogeneousField + +#ifndef KFPARTICLE_H +#define KFPARTICLE_H + +#include "KFParticleBase.h" +#include <cmath> + +class KFPTrack; +class KFPVertex; + +/** @class KFParticle + ** @brief The main scalar class of KF Particle package, describes particle objects. + ** @author S.Gorbunov, I.Kisel, M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The main scalar class of KF Particle pacakge, describes particle objects. + ** The particle is described with the state vector { X, Y, Z, Px, Py, Pz, E } + ** and the corresponding covariance matrix. + ** It contains functionality to create particle-object from track, to construct + ** short-lived particles from other tracks or particles. The mathematics is + ** based on the Kalman filter method. It also allows to subtract particles from + ** the already constructed object, + ** to transport particles, get parameters together with their errors, get distance + ** to other particles and vertices, get deviations from them in terms of errors, etc. + **/ + +class KFParticle :public KFParticleBase +{ + + public: + + //* + //* INITIALIZATION + //* + + //* Set magnetic field for all particles +#ifdef HomogeneousField + static void SetField( float Bz ); +#endif + //* Constructor (empty) + + KFParticle():KFParticleBase(){ ; } + + //* Destructor (empty) + + ~KFParticle(){ ; } + + //* Construction of mother particle by its 2-3-4 daughters + + KFParticle( const KFParticle &d1, const KFParticle &d2 ); + + KFParticle( const KFParticle &d1, const KFParticle &d2, + const KFParticle &d3 ); + + KFParticle( const KFParticle &d1, const KFParticle &d2, + const KFParticle &d3, const KFParticle &d4 ); + + //* Initialisation from "cartesian" coordinates ( X Y Z Px Py Pz ) + //* Parameters, covariance matrix, charge and PID hypothesis should be provided + + void Create( const float Param[], const float Cov[], Int_t Charge, float mass /*Int_t PID*/ ); + void Create( const Double_t Param[], const Double_t Cov[], Int_t Charge, float mass /*Int_t PID*/ ); + + //* Initialisation from ALICE track, PID hypothesis shoould be provided + + KFParticle( const KFPTrack &track, const int PID ); + + + //* Initialisation from VVertex + + KFParticle( const KFPVertex &vertex ); + + //* Initialise covariance matrix and set current parameters to 0.0 + + void Initialize(); + + //* + //* ACCESSORS + //* + + //* Simple accessors + + float GetX () const ; ///< Retruns X coordinate of the particle, fP[0]. + float GetY () const ; ///< Retruns Y coordinate of the particle, fP[1]. + float GetZ () const ; ///< Retruns Z coordinate of the particle, fP[2]. + float GetPx () const ; ///< Retruns X component of the momentum, fP[3]. + float GetPy () const ; ///< Retruns Y component of the momentum, fP[4]. + float GetPz () const ; ///< Retruns Z component of the momentum, fP[5]. + float GetE () const ; ///< Returns energy of the particle, fP[6]. + float GetS () const ; ///< Returns dS=l/p, l - decay length, fP[7], defined if production vertex is set. + char GetQ () const ; ///< Returns charge of the particle. + float GetChi2 () const ; ///< Returns Chi2 of the fit. + Int_t GetNDF () const ; ///< Returns number of decrease of freedom. + + Bool_t GetAtProductionVertex() const { return fAtProductionVertex; } ///< Returns a flag which shows if the particle is located at the production point + void SetAtProductionVertex(Bool_t b) { fAtProductionVertex = b; } ///< Set a flag that particle is at the production point + +#ifdef NonhomogeneousField + const float* GetFieldCoeff() const { return fieldRegion; } ///< Returns the field approximation for the current particle + void SetFieldCoeff(float c, int i) { fieldRegion[i] = c; } ///< Sets the field coefficient with index i. +#endif + + const float& X () const { return fP[0]; } ///< Retruns X coordinate of the particle, fP[0]. + const float& Y () const { return fP[1]; } ///< Retruns Y coordinate of the particle, fP[1]. + const float& Z () const { return fP[2]; } ///< Retruns Z coordinate of the particle, fP[2]. + const float& Px () const { return fP[3]; } ///< Retruns X component of the momentum, fP[3]. + const float& Py () const { return fP[4]; } ///< Retruns Y component of the momentum, fP[4]. + const float& Pz () const { return fP[5]; } ///< Retruns Z component of the momentum, fP[5]. + const float& E () const { return fP[6]; } ///< Returns energy of the particle, fP[6]. + const float& S () const { return fP[7]; } ///< Returns dS=l/p, l - decay length, fP[7], defined if production vertex is set. + const char& Q () const { return fQ; } ///< Returns charge of the particle. + const float& Chi2 () const { return fChi2; } ///< Returns Chi2 of the fit. + const Int_t& NDF () const { return fNDF; } ///< Returns number of decrease of freedom. + + float GetParameter ( int i ) const ; ///< Returns P[i] parameter. + float GetCovariance( int i ) const ; ///< Returns C[i] element of the covariance matrix in the lower triangular form. + float GetCovariance( int i, int j ) const ; ///< Returns C[i,j] element of the covariance matrix. + + //* Accessors with calculations, value returned w/o error flag + + float GetP () const; ///< Returns momentum + float GetPt () const; ///< Returns transverse momentum + float GetEta () const; ///< Returns pseudorapidity + float GetPhi () const; ///< Returns the azimuthal angle phi + float GetMomentum () const; ///< Returns momentum + float GetMass () const; ///< Returns mass + float GetDecayLength () const; ///< Returns decay length + float GetDecayLengthXY () const; ///< Returns decay length in XY + float GetLifeTime () const; ///< Returns life time ctau [cm] + float GetR () const; ///< Returns distance to the origin of the coordinate system {0,0,0} + + //* Accessors to estimated errors + + float GetErrX () const ; ///< Returns the error of X of current position + float GetErrY () const ; ///< Returns the error of Y of current position + float GetErrZ () const ; ///< Returns the error of Z of current position + float GetErrPx () const ; ///< Returns the error of X-compoment of the particle momentum + float GetErrPy () const ; ///< Returns the error of Y-compoment of the particle momentum + float GetErrPz () const ; ///< Returns the error of Z-compoment of the particle momentum + float GetErrE () const ; ///< Returns the error of energy + float GetErrS () const ; ///< Returns the error of decay length / momentum + float GetErrP () const ; ///< Returns the error of momentum + float GetErrPt () const ; ///< Returns the error of transverse momentum + float GetErrEta () const ; ///< Returns the error of pseudorapidity + float GetErrPhi () const ; ///< Returns the error of the azimuthal angle phi + float GetErrMomentum () const ; ///< Returns the error of momentum + float GetErrMass () const ; ///< Returns the error of mass + float GetErrDecayLength () const ; ///< Returns the error of decay length + float GetErrDecayLengthXY () const ; ///< Returns the error of decay length in XY + float GetErrLifeTime () const ; ///< Returns the error of life time + float GetErrR () const ; ///< Returns the error of distance to the origin of the coordinate system {0,0,0} + + //* Accessors with calculations( &value, &estimated sigma ) + //* error flag returned (0 means no error during calculations) + + int GetP ( float &P, float &SigmaP ) const ; //* momentum + int GetPt ( float &Pt, float &SigmaPt ) const ; //* transverse momentum + int GetEta ( float &Eta, float &SigmaEta ) const ; //* pseudorapidity + int GetPhi ( float &Phi, float &SigmaPhi ) const ; //* phi + int GetMomentum ( float &P, float &SigmaP ) const ; //* momentum + int GetMass ( float &M, float &SigmaM ) const ; //* mass + int GetDecayLength ( float &L, float &SigmaL ) const ; //* decay length + int GetDecayLengthXY ( float &L, float &SigmaL ) const ; //* decay length in XY + int GetLifeTime ( float &T, float &SigmaT ) const ; //* life time + int GetR ( float &R, float &SigmaR ) const ; //* R + float GetRapidity() const { return 0.5*log((fP[6] + fP[5])/(fP[6] - fP[5])); } ///< Returns rapidity of the particle + float GetTheta() const { return atan2(GetPt(),fP[5]); } ///< Returns the polar angle in RZ + + + //* + //* MODIFIERS + //* + + float & X () ; ///< Modifier of X coordinate of the particle, fP[0]. + float & Y () ; ///< Modifier of Y coordinate of the particle, fP[1]. + float & Z () ; ///< Modifier of Z coordinate of the particle, fP[2]. + float & Px () ; ///< Modifier of X component of the momentum, fP[3]. + float & Py () ; ///< Modifier of Y component of the momentum, fP[4]. + float & Pz () ; ///< Modifier of Z component of the momentum, fP[5]. + float & E () ; ///< Modifier of energy of the particle, fP[6]. + float & S () ; ///< Modifier of dS=l/p, l - decay length, fP[7], defined if production vertex is set. + char & Q () ; ///< Modifier of charge of the particle. + float & Chi2 () ; ///< Modifier of Chi2 of the fit. + Int_t & NDF () ; ///< Modifier of number of decrease of freedom. + + float & Parameter ( int i ) ; ///< Modifier of P[i] parameter. + float & Covariance( int i ) ; ///< Modifier of C[i] element of the covariance matrix in the lower triangular form. + float & Covariance( int i, int j ) ; ///< Modifier of C[i,j] element of the covariance matrix. + float * Parameters () ; ///< Returns pointer to the parameters fP + float * CovarianceMatrix() ; ///< Returns pointer to the covariance matrix fC + + //* + //* CONSTRUCTION OF THE PARTICLE BY ITS DAUGHTERS AND MOTHER + //* USING THE KALMAN FILTER METHOD + //* + + + //* Add daughter to the particle + + void AddDaughter( const KFParticle &Daughter ); + + //* Add daughter via += operator: ex.{ D0; D0+=Pion; D0+= Kaon; } + + void operator +=( const KFParticle &Daughter ); + + //* Everything in one go + + void Construct( const KFParticle *vDaughters[], int nDaughters, + const KFParticle *ProdVtx=0, float Mass=-1 ); + + //* + //* TRANSPORT + //* + //* ( main transportation parameter is S = SignedPath/Momentum ) + //* ( parameters of decay & production vertices are stored locally ) + //* + + //* Transport the particle close to xyz[] point + + void TransportToPoint( const float xyz[] ); + + //* Transport the particle close to VVertex +#ifdef HomogeneousField + void TransportToVertex( const KFPVertex &v ); +#endif + //* Transport the particle close to another particle p + void TransportToParticle( const KFParticle &p ); + + //* Get dS to a certain space point + float GetDStoPoint( const float xyz[3], float dsdr[6] ) const ; + + //* Get dS to other particle p (dSp for particle p also returned) + void GetDStoParticle( const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const ; + + + //* + //* OTHER UTILITIES + //* + + //* Calculate distance from another object [cm] in XY-plane + + Bool_t GetDistanceFromVertexXY( const float vtx[], float &val, float &err ) const ; + Bool_t GetDistanceFromVertexXY( const float vtx[], const float Cv[], float &val, float &err ) const ; + Bool_t GetDistanceFromVertexXY( const KFParticle &Vtx, float &val, float &err ) const ; +#ifdef HomogeneousField + Bool_t GetDistanceFromVertexXY( const KFPVertex &Vtx, float &val, float &err ) const ; +#endif + + float GetDistanceFromVertexXY( const float vtx[] ) const ; + float GetDistanceFromVertexXY( const KFParticle &Vtx ) const ; +#ifdef HomogeneousField + float GetDistanceFromVertexXY( const KFPVertex &Vtx ) const ; +#endif + float GetDistanceFromParticleXY( const KFParticle &p ) const ; + + //* Calculate sqrt(Chi2/ndf) deviation from another object in XY plane + //* ( v = [xyz]-vertex, Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix ) + + float GetDeviationFromVertexXY( const float v[], const float Cv[]=0 ) const ; + float GetDeviationFromVertexXY( const KFParticle &Vtx ) const ; +#ifdef HomogeneousField + float GetDeviationFromVertexXY( const KFPVertex &Vtx ) const ; +#endif + float GetDeviationFromParticleXY( const KFParticle &p ) const ; + + //* Get parameters at an arbitrary reconstructed point taking into account its errors + void GetParametersAtPoint(const float* point, const float* pointCov, float* m, float* mV); + + //* Calculate opennig angle between two particles + + float GetAngle ( const KFParticle &p ) const ; + float GetAngleXY( const KFParticle &p ) const ; + float GetAngleRZ( const KFParticle &p ) const ; + + float GetPseudoProperDecayTime( const KFParticle &primVertex, const float& mass, float* timeErr2 = 0 ) const; + + void GetFieldValue( const float xyz[], float B[] ) const ; + + void Transport( float dS, const float* dsdr, float P[], float C[], float* dsdr1=0, float* F=0, float* F1=0 ) const ; + + protected: + + //* + //* INTERNAL STUFF + //* + + //* Method to access ALICE field +#ifdef HomogeneousField + static float GetFieldAlice(); +#endif + + private: +#ifdef HomogeneousField + static float fgBz; ///< Bz compoment of the magnetic field (is defined in case of #ifdef HomogeneousField) +#endif +#ifdef NonhomogeneousField + /** \brief Approximation of the magnetic field along the track trajectory. + ** Each component (Bx, By, Bz) is approximated with the parabola depending on Z coordinate. Is defined in case of #ifdef NonhomogeneousField. + **/ + float fieldRegion[10]; +#endif + +#ifndef KFParticleStandalone + ClassDef( KFParticle, 3 ) +#endif +}; + + + +//--------------------------------------------------------------------- +// +// Inline implementation of the KFParticle methods +// +//--------------------------------------------------------------------- + +#ifdef HomogeneousField +inline void KFParticle::SetField( float Bz ) +{ + /** Sets the constant homogemeous one-component magnetic field Bz (is defined in case of #ifdef HomogeneousField). + ** \param[in] Bz - Z-component of the magnetic field + **/ + fgBz = Bz; +} +#endif + +inline KFParticle::KFParticle( const KFParticle &d1, + const KFParticle &d2, + const KFParticle &d3 ) +{ + /** Constructs a particle from three input daughter particles + ** \param[in] d1 - the first daughter particle + ** \param[in] d2 - the second daughter particle + ** \param[in] d3 - the third daughter particle + **/ + KFParticle mother; + mother+= d1; + mother+= d2; + mother+= d3; + *this = mother; +} + +inline KFParticle::KFParticle( const KFParticle &d1, + const KFParticle &d2, + const KFParticle &d3, + const KFParticle &d4 ) +{ + /** Constructs a particle from four input daughter particles + ** \param[in] d1 - the first daughter particle + ** \param[in] d2 - the second daughter particle + ** \param[in] d3 - the third daughter particle + ** \param[in] d4 - the fourth daughter particle + **/ + KFParticle mother; + mother+= d1; + mother+= d2; + mother+= d3; + mother+= d4; + *this = mother; +} + + +inline void KFParticle::Initialize() +{ + /** Calls KFParticleBase::Initialize()*/ + KFParticleBase::Initialize(); +} + +inline float KFParticle::GetX () const +{ + return KFParticleBase::GetX(); +} + +inline float KFParticle::GetY () const +{ + return KFParticleBase::GetY(); +} + +inline float KFParticle::GetZ () const +{ + return KFParticleBase::GetZ(); +} + +inline float KFParticle::GetPx () const +{ + return KFParticleBase::GetPx(); +} + +inline float KFParticle::GetPy () const +{ + return KFParticleBase::GetPy(); +} + +inline float KFParticle::GetPz () const +{ + return KFParticleBase::GetPz(); +} + +inline float KFParticle::GetE () const +{ + return KFParticleBase::GetE(); +} + +inline float KFParticle::GetS () const +{ + return KFParticleBase::GetS(); +} + +inline char KFParticle::GetQ () const +{ + return KFParticleBase::GetQ(); +} + +inline float KFParticle::GetChi2 () const +{ + return KFParticleBase::GetChi2(); +} + +inline Int_t KFParticle::GetNDF () const +{ + return KFParticleBase::GetNDF(); +} + +inline float KFParticle::GetParameter ( int i ) const +{ + return KFParticleBase::GetParameter(i); +} + +inline float KFParticle::GetCovariance( int i ) const +{ + return KFParticleBase::GetCovariance(i); +} + +inline float KFParticle::GetCovariance( int i, int j ) const +{ + return KFParticleBase::GetCovariance(i,j); +} + + +inline float KFParticle::GetP () const +{ + float par, err; + if( KFParticleBase::GetMomentum( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetPt () const +{ + float par, err; + if( KFParticleBase::GetPt( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetEta () const +{ + float par, err; + if( KFParticleBase::GetEta( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetPhi () const +{ + float par, err; + if( KFParticleBase::GetPhi( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetMomentum () const +{ + float par, err; + if( KFParticleBase::GetMomentum( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetMass () const +{ + float par, err; + if( KFParticleBase::GetMass( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetDecayLength () const +{ + float par, err; + if( KFParticleBase::GetDecayLength( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetDecayLengthXY () const +{ + float par, err; + if( KFParticleBase::GetDecayLengthXY( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetLifeTime () const +{ + float par, err; + if( KFParticleBase::GetLifeTime( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetR () const +{ + float par, err; + if( KFParticleBase::GetR( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetErrX () const +{ + return sqrt(fabs( GetCovariance(0,0) )); +} + +inline float KFParticle::GetErrY () const +{ + return sqrt(fabs( GetCovariance(1,1) )); +} + +inline float KFParticle::GetErrZ () const +{ + return sqrt(fabs( GetCovariance(2,2) )); +} + +inline float KFParticle::GetErrPx () const +{ + return sqrt(fabs( GetCovariance(3,3) )); +} + +inline float KFParticle::GetErrPy () const +{ + return sqrt(fabs( GetCovariance(4,4) )); +} + +inline float KFParticle::GetErrPz () const +{ + return sqrt(fabs( GetCovariance(5,5) )); +} + +inline float KFParticle::GetErrE () const +{ + return sqrt(fabs( GetCovariance(6,6) )); +} + +inline float KFParticle::GetErrS () const +{ + return sqrt(fabs( GetCovariance(7,7) )); +} + +inline float KFParticle::GetErrP () const +{ + float par, err; + if( KFParticleBase::GetMomentum( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrPt () const +{ + float par, err; + if( KFParticleBase::GetPt( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrEta () const +{ + float par, err; + if( KFParticleBase::GetEta( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrPhi () const +{ + float par, err; + if( KFParticleBase::GetPhi( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrMomentum () const +{ + float par, err; + if( KFParticleBase::GetMomentum( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrMass () const +{ + float par, err; + if( KFParticleBase::GetMass( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrDecayLength () const +{ + float par, err; + if( KFParticleBase::GetDecayLength( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrDecayLengthXY () const +{ + float par, err; + if( KFParticleBase::GetDecayLengthXY( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrLifeTime () const +{ + float par, err; + if( KFParticleBase::GetLifeTime( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrR () const +{ + float par, err; + if( KFParticleBase::GetR( par, err ) ) return 1.e10; + else return err; +} + + +inline int KFParticle::GetP( float &P, float &SigmaP ) const +{ + /** Calculates particle momentum and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] P - momentum of the particle + ** \param[out] SigmaP - its error + **/ + return KFParticleBase::GetMomentum( P, SigmaP ); +} + +inline int KFParticle::GetPt( float &Pt, float &SigmaPt ) const +{ + /** Calculates particle transverse momentum and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] Pt - transverse momentum of the particle + ** \param[out] SigmaPt - its error + **/ + return KFParticleBase::GetPt( Pt, SigmaPt ); +} + +inline int KFParticle::GetEta( float &Eta, float &SigmaEta ) const +{ + /** Calculates particle pseudorapidity and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] Eta - pseudorapidity of the particle + ** \param[out] SigmaEta - its error + **/ + return KFParticleBase::GetEta( Eta, SigmaEta ); +} + +inline int KFParticle::GetPhi( float &Phi, float &SigmaPhi ) const +{ + /** Calculates particle polar angle at the current point and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] Phi - polar angle of the particle + ** \param[out] SigmaPhi - its error + **/ + return KFParticleBase::GetPhi( Phi, SigmaPhi ); +} + +inline int KFParticle::GetMomentum( float &P, float &SigmaP ) const +{ + /** Calculates particle momentum and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] P - momentum of the particle + ** \param[out] SigmaP - its error + **/ + return KFParticleBase::GetMomentum( P, SigmaP ); +} + +inline int KFParticle::GetMass( float &M, float &SigmaM ) const +{ + /** Calculates the mass of the particle and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] M - mass of the particle + ** \param[out] SigmaM - its error + **/ + return KFParticleBase::GetMass( M, SigmaM ); +} + +inline int KFParticle::GetDecayLength( float &L, float &SigmaL ) const +{ + /** Calculates the decay length of the particle in the laboratory system and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] L - the decay length + ** \param[out] SigmaL - its error + **/ + return KFParticleBase::GetDecayLength( L, SigmaL ); +} + +inline int KFParticle::GetDecayLengthXY( float &L, float &SigmaL ) const +{ + /** Calculates the projection in the XY plane of the decay length of the particle in the laboratory + ** system and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] L - the decay length + ** \param[out] SigmaL - its error + **/ + return KFParticleBase::GetDecayLengthXY( L, SigmaL ); +} + +inline int KFParticle::GetLifeTime( float &T, float &SigmaT ) const +{ + /** Calculates the lifetime times speed of life (ctau) [cm] of the particle in the + ** center of mass frame and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] T - lifetime of the particle [cm] + ** \param[out] SigmaT - its error + **/ + return KFParticleBase::GetLifeTime( T, SigmaT ); +} + +inline int KFParticle::GetR( float &R, float &SigmaR ) const +{ + /** Calculates the distance to the point {0,0,0} and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] R - polar angle of the particle + ** \param[out] SigmaR - its error + **/ + return KFParticleBase::GetR( R, SigmaR ); +} + +inline float & KFParticle::X() +{ + return KFParticleBase::X(); +} + +inline float & KFParticle::Y() +{ + return KFParticleBase::Y(); +} + +inline float & KFParticle::Z() +{ + return KFParticleBase::Z(); +} + +inline float & KFParticle::Px() +{ + return KFParticleBase::Px(); +} + +inline float & KFParticle::Py() +{ + return KFParticleBase::Py(); +} + +inline float & KFParticle::Pz() +{ + return KFParticleBase::Pz(); +} + +inline float & KFParticle::E() +{ + return KFParticleBase::E(); +} + +inline float & KFParticle::S() +{ + return KFParticleBase::S(); +} + +inline char & KFParticle::Q() +{ + return KFParticleBase::Q(); +} + +inline float & KFParticle::Chi2() +{ + return KFParticleBase::Chi2(); +} + +inline Int_t & KFParticle::NDF() +{ + return KFParticleBase::NDF(); +} + +inline float & KFParticle::Parameter ( int i ) +{ + return KFParticleBase::Parameter(i); +} + +inline float & KFParticle::Covariance( int i ) +{ + return KFParticleBase::Covariance(i); +} + +inline float & KFParticle::Covariance( int i, int j ) +{ + return KFParticleBase::Covariance(i,j); +} + +inline float * KFParticle::Parameters () +{ + return fP; +} + +inline float * KFParticle::CovarianceMatrix() +{ + return fC; +} + + +inline void KFParticle::operator +=( const KFParticle &Daughter ) +{ + /** Operator to add daughter to the current particle. Calls AddDaughter() function. + ** \param[in] Daughter - the daughter particle + **/ +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + SetFieldCoeff(Daughter.GetFieldCoeff()[i], i); +#endif + KFParticleBase::operator +=( Daughter ); +} + + +inline void KFParticle::AddDaughter( const KFParticle &Daughter ) +{ + /** Adds daughter to the current particle. Depending on the selected construction method uses: \n + ** 1) Either simplifyed fast mathematics which consideres momentum and energy as + ** independent variables and thus ignores constraint on the fixed mass (fConstructMethod = 0). + ** In this case the mass of the daughter particle can be corrupted when the constructed vertex + ** is added as the measurement and the mass of the output short-lived particle can become + ** unphysical - smaller then the threshold. Implemented in the + ** AddDaughterWithEnergyFit() function \n + ** 2) Or slower but correct mathematics which requires that the masses of daughter particles + ** stays fixed in the construction process (fConstructMethod = 2). Implemented in the + ** AddDaughterWithEnergyFitMC() function. + ** \param[in] Daughter - the daughter particle + **/ +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + SetFieldCoeff(Daughter.GetFieldCoeff()[i], i); +#endif + KFParticleBase::AddDaughter( Daughter ); +} + +inline void KFParticle::Construct( const KFParticle *vDaughters[], int nDaughters, + const KFParticle *ProdVtx, float Mass ) +{ + /** Constructs a short-lived particle from a set of daughter particles:\n + ** 1) all parameters of the "this" objects are initialised;\n + ** 2) daughters are added one after another;\n + ** 3) if Parent pointer is not null, the production vertex is set to it;\n + ** 4) if Mass hypothesis >=0 the mass constraint is set. + ** \param[in] vDaughters - array of daughter particles + ** \param[in] nDaughters - number of daughter particles in the input array + ** \param[in] Parent - optional parrent particle + ** \param[in] Mass - optional mass hypothesis + **/ +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + SetFieldCoeff(vDaughters[0]->GetFieldCoeff()[i], i); +#endif + KFParticleBase::Construct( ( const KFParticleBase**)vDaughters, nDaughters, + ( const KFParticleBase*)ProdVtx, Mass ); +} + +inline void KFParticle::TransportToPoint( const float xyz[] ) +{ + /** Transports particle to the distance of closest approach to the point xyz. + ** \param[in] xyz[3] - point, where particle should be transported + **/ + float dsdr[6] = {0.f}; + float dS = GetDStoPoint(xyz, dsdr); + TransportToDS( dS, dsdr ); +} +#ifdef HomogeneousField +inline void KFParticle::TransportToVertex( const KFPVertex &v ) +{ + /** Transports particle to the distance of closest approach to the vertex v. + ** \param[in] v - vertex, where particle should be transported + **/ + TransportToPoint( KFParticle(v).fP ); +} +#endif +inline void KFParticle::TransportToParticle( const KFParticle &p ) +{ + /** Transports particle to the distance of closest approach to the particle p. + ** \param[in] p - particle, to which the current particle should be transported. + **/ + float dsdr[4][6]; + float dS[2]; + GetDStoParticle( p, dS, dsdr ); + TransportToDS( dS[0], dsdr[0] ); +} + +inline float KFParticle::GetDStoPoint( const float xyz[], float* dsdr ) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** If "HomogeneousField" is defined KFParticleBase::GetDStoPointBz() is called, + ** if "NonhomogeneousField" is defined - KFParticleBase::GetDStoPointCBM() + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + ** \param[in] param - optional parameter, is used in case if the parameters of the particle are rotated + ** to other coordinate system (see GetDStoPointBy() function), otherwise fP are used + **/ +#ifdef HomogeneousField + return KFParticleBase::GetDStoPointBz( GetFieldAlice(), xyz, dsdr ); +#endif +#ifdef NonhomogeneousField + return KFParticleBase::GetDStoPointCBM( xyz, dsdr ); +#endif + return 0.; +} + +#ifdef HomogeneousField +inline float KFParticle::GetFieldAlice() +{ + /** Returns value of the constant homogemeous one-component magnetic field Bz, (is defined in case of #ifdef HomogeneousField). */ + return fgBz; +} +#endif + +#ifdef HomogeneousField +inline void KFParticle::GetFieldValue( const float * /*xyz*/, float B[] ) const +{ + /** Calculates the Bx, By, Bz components at the point xyz using approximation of the + ** magnetic field along the particle trajectory. + ** \param[in] xyz[3] - X, Y, Z coordiantes of the point where the magnetic field should be calculated + ** \param[out] B[3] - value of X, Y, Z components of the calculated magnetic field at the given point + **/ + + B[0] = B[1] = 0; + B[2] = GetFieldAlice(); +} +#endif + +#ifdef NonhomogeneousField +inline void KFParticle::GetFieldValue( const float xyz[], float B[] ) const +{ + /** Calculates the Bx, By, Bz components at the point xyz using approximation of the + ** magnetic field along the particle trajectory. + ** \param[in] xyz[3] - X, Y, Z coordiantes of the point where the magnetic field should be calculated + ** \param[out] B[3] - value of X, Y, Z components of the calculated magnetic field at the given point + **/ + + const float dz = (xyz[2]-fieldRegion[9]); + const float dz2 = dz*dz; + + B[0] = fieldRegion[0] + fieldRegion[1]*dz + fieldRegion[2]*dz2; + B[1] = fieldRegion[3] + fieldRegion[4]*dz + fieldRegion[5]*dz2; + B[2] = fieldRegion[6] + fieldRegion[7]*dz + fieldRegion[8]*dz2; +} +#endif + +inline void KFParticle::GetDStoParticle( const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle \n + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. If "HomogeneousField" is defined KFParticleBase::GetDStoParticleBz() is called, + ** if "NonhomogeneousField" is defined - KFParticleBase::GetDStoParticleCBM() + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ +#ifdef HomogeneousField + KFParticleBase::GetDStoParticleBz( GetFieldAlice(), p, dS, dsdr ) ; +#endif +#ifdef NonhomogeneousField + KFParticleBase::GetDStoParticleCBM( p, dS, dsdr ) ; +#endif +} + +inline void KFParticle::Transport( float dS, const float* dsdr, float P[], float C[], float* dsdr1, float* F, float* F1 ) const +{ + /** Transports the parameters and their covariance matrix of the current particle + ** on a length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. If "HomogeneousField" is defined KFParticleBase::TransportBz() + ** is called, if "NonhomogeneousField" - KFParticleBase::TransportCBM(). + ** The obtained parameters and covariance matrix are stored to the arrays P and + ** C respectively. P and C can be set to the parameters fP and covariance matrix fC of the current particle. In this + ** case the particle parameters will be modified. Dependence of the transport parameter dS on the state vector of the + ** current particle is taken into account in the covariance matrix using partial derivatives dsdr = d(dS)/d(fP). If + ** a pointer to F is initialised the transport jacobian F = d(fP new)/d(fP old) is stored. + ** Since dS can depend on the state vector r1 of other particle or vertex, the corelation matrix + ** F1 = d(fP new)/d(r1) can be optionally calculated if a pointer F1 is provided. + * Parameters F and F1 should be either both initialised or both set to null pointer. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[in] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + ** \param[out] P[8] - array, where transported parameters should be stored + ** \param[out] C[36] - array, where transported covariance matrix (8x8) should be stored in the lower triangular form + ** \param[in] dsdr1[6] = ds/dr - partial derivatives of the parameter dS over the state vector of another particle + ** or vertex + ** \param[out] F[36] - optional parameter, transport jacobian, 6x6 matrix F = d(fP new)/d(fP old) + ** \param[out] F1[36] - optional parameter, corelation 6x6 matrix betweeen the current particle and particle or vertex + ** with the state vector r1, to which the current particle is being transported, F1 = d(fP new)/d(r1) + **/ +#ifdef HomogeneousField + KFParticleBase::TransportBz( GetFieldAlice(), dS, dsdr, P, C, dsdr1, F, F1 ); +#endif +#ifdef NonhomogeneousField + KFParticleBase::TransportCBM( dS, dsdr, P, C, dsdr1, F, F1 ); +#endif +} + +#endif diff --git a/external/KFParticle/KFParticle/KFParticleBase.cxx b/external/KFParticle/KFParticle/KFParticleBase.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f139c22ce935ec9e769954d09676e5963bfcbc80 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleBase.cxx @@ -0,0 +1,3455 @@ +//--------------------------------------------------------------------------------- +// Implementation of the KFParticleBase class +// . +// @author S.Gorbunov, I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 13.05.07 +// +// Class to reconstruct and store the decayed particle parameters. +// The method is described in CBM-SOFT note 2007-003, +// ``Reconstruction of decayed particles based on the Kalman filter'', +// http://www.gsi.de/documents/DOC-2007-May-14-1.pdf +// +// This class describes general mathematics which is used by KFParticle class +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//_________________________________________________________________________________ + + +#include "KFParticleBase.h" +#include <cmath> + +#ifndef KFParticleStandalone +ClassImp(KFParticleBase) +#endif + +#ifdef __ROOT__ +#include "TClass.h" +#include "TRSymMatrix.h" +#include "TRVector.h" +#include <iostream> + +KFParticleBase::KFParticleBase() :fChi2(0), fSFromDecay(0), SumDaughterMass(0), fMassHypo(-1), fNDF(-3), + fId(-1), fParentID(0), fIdTruth(0), fQuality(0), fIdParentMcVx(0), fAtProductionVertex(0), + fQ(0), fConstructMethod(0), fPDG(0), fDaughtersIds() +{ + static Bool_t first = kTRUE; + if (first) { + first = kFALSE; + KFParticleBase::Class()->IgnoreTObjectStreamer(); + } + //* Constructor + Clear(); +} + +void KFParticleBase::Clear(Option_t *option) { + Initialize(); + fIdTruth = 0; + fQuality = 0; + fIdParentMcVx = 0; + fParentID = 0; +} + +void KFParticleBase::Print(Option_t *opt) const { + std::cout << *this << std::endl; + if (opt && (opt[0] == 'a' || opt[0] == 'A')) { + TRVector P(8,fP); std::cout << "par. " << P << std::endl; + TRSymMatrix C(8,fC); std::cout << "cov. " << C << std::endl; + + } +} + +std::ostream& operator<<(std::ostream& os, const KFParticleBase& particle) { + static const Char_t *vn[14] = {"x","y","z","px","py","pz","E","S","M","t","p","Q","Chi2","NDF"}; + os << Form("p(%4i,%4i,%4i)",particle.Id(),particle.GetParentID(),particle.IdParentMcVx()); + for (Int_t i = 0; i < 8; i++) { + if (i == 6) continue; // E + if (i == 7 && particle.GetParameter(i) <= 0.0) continue; // S + if (particle.GetParameter(i) == 0. && particle.GetCovariance(i,i) == 0) continue; + if (particle.GetCovariance(i,i) > 0) + os << Form(" %s:%8.3f+/-%6.3f", vn[i], particle.GetParameter(i), TMath::Sqrt(particle.GetCovariance(i,i))); + else + os << Form(" %s:%8.3f", vn[i], particle.GetParameter(i)); + } + float Mtp[3] = {0.f, 0.f, 0.f}, MtpErr[3] = {0.f, 0.f, 0.f}; + particle.GetMass(Mtp[0], MtpErr[0]); if (MtpErr[0] < 1e-7 || MtpErr[0] > 1e10) MtpErr[0] = -13; + particle.GetLifeTime(Mtp[1], MtpErr[1]); if (MtpErr[1] <= 0 || MtpErr[1] > 1e10) MtpErr[1] = -13; + particle.GetMomentum(Mtp[2], MtpErr[2]); if (MtpErr[2] <= 0 || MtpErr[2] > 1e10) MtpErr[2] = -13; + for (Int_t i = 8; i < 11; i++) { + if (i == 9 && Mtp[i-8] <= 0.0) continue; // t + if (MtpErr[i-8] > 0 && MtpErr[i-8] < 9e2) os << Form(" %s:%8.3f+/-%7.3f", vn[i],Mtp[i-8],MtpErr[i-8]); + else os << Form(" %s:%8.3f", vn[i],Mtp[i-8]); + } + os << Form(" pdg:%5i Q:%2i chi2/NDF :%8.2f/%2i",particle.GetPDG(),particle.GetQ(),particle.GetChi2(),particle.GetNDF()); + if (particle.IdTruth()) os << Form(" IdT:%4i/%3i",particle.IdTruth(),particle.QaTruth()); + int nd = particle.NDaughters(); + if (nd > 1) { + os << " ND: " << nd << ":"; + if (nd > 3) nd = 3; + for (int d = 0; d < nd; d++) { + os << particle.DaughterIds()[d]; + if (d < nd-1) os << ","; + } + } + return os; +} +#endif + +#ifndef __ROOT__ +KFParticleBase::KFParticleBase() : fChi2(0), fSFromDecay(0), + SumDaughterMass(0), fMassHypo(-1), fNDF(-3), fId(-1), fAtProductionVertex(0), fQ(0), fConstructMethod(0), fPDG(0), fDaughtersIds() +{ + /** The default constructor, initialises the parameters by: \n + ** 1) all parameters are set to 0; \n + ** 2) all elements of the covariance matrix are set to 0 except Cxx=Cyy=Czz=100; \n + ** 3) Q = 0; \n + ** 4) chi2 is set to 0; \n + ** 5) NDF = -3, since 3 parameters should be fitted: X, Y, Z. + **/ + Initialize(); +} +#endif + +void KFParticleBase::Initialize( const float Param[], const float Cov[], Int_t Charge, float Mass ) +{ + /** Sets the parameters of the particle: + ** + ** \param[in] Param[6] = { X, Y, Z, Px, Py, Pz } - position and momentum + ** \param[in] Cov[21] - lower-triangular part of the covariance matrix:@n + ** \verbatim + ( 0 . . . . . ) + ( 1 2 . . . . ) + Cov[21] = ( 3 4 5 . . . ) + ( 6 7 8 9 . . ) + ( 10 11 12 13 14 . ) + ( 15 16 17 18 19 20 ) + \endverbatim + ** \param[in] Charge - charge of the particle in elementary charge units + ** \param[in] mass - the mass hypothesis + **/ + + + for( Int_t i=0; i<6 ; i++ ) fP[i] = Param[i]; + for( Int_t i=0; i<21; i++ ) fC[i] = Cov[i]; + + float energy = sqrt( Mass*Mass + fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]); + fP[6] = energy; + fP[7] = 0; + fQ = Charge; + fNDF = 0; + fChi2 = 0; + fAtProductionVertex = 0; + fSFromDecay = 0; + + float energyInv = 1./energy; + float + h0 = fP[3]*energyInv, + h1 = fP[4]*energyInv, + h2 = fP[5]*energyInv; + + fC[21] = h0*fC[ 6] + h1*fC[10] + h2*fC[15]; + fC[22] = h0*fC[ 7] + h1*fC[11] + h2*fC[16]; + fC[23] = h0*fC[ 8] + h1*fC[12] + h2*fC[17]; + fC[24] = h0*fC[ 9] + h1*fC[13] + h2*fC[18]; + fC[25] = h0*fC[13] + h1*fC[14] + h2*fC[19]; + fC[26] = h0*fC[18] + h1*fC[19] + h2*fC[20]; + fC[27] = ( h0*h0*fC[ 9] + h1*h1*fC[14] + h2*h2*fC[20] + + 2*(h0*h1*fC[13] + h0*h2*fC[18] + h1*h2*fC[19] ) ); + for( Int_t i=28; i<36; i++ ) fC[i] = 0; + fC[35] = 1.; + + SumDaughterMass = Mass; + fMassHypo = Mass; +} + +void KFParticleBase::Initialize() +{ + /** Initialises the parameters by default: \n + ** 1) all parameters are set to 0; \n + ** 2) all elements of the covariance matrix are set to 0 except Cxx=Cyy=Czz=100; \n + ** 3) Q = 0; \n + ** 4) chi2 is set to 0; \n + ** 5) NDF = -3, since 3 parameters should be fitted: X, Y, Z. + **/ + + for( Int_t i=0; i<8; i++) fP[i] = 0; + for(Int_t i=0;i<36;++i) fC[i]=0.; + fC[0] = fC[2] = fC[5] = 100.; + fC[35] = 1.; + fNDF = -3; + fChi2 = 0.; + fQ = 0; + fSFromDecay = 0; + fAtProductionVertex = 0; + SumDaughterMass = 0; + fMassHypo = -1; +} + +Int_t KFParticleBase::GetMomentum( float &p, float &error ) const +{ + /** Calculates particle momentum and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] p - momentum of the particle + ** \param[out] error - its error + **/ + + float x = fP[3]; + float y = fP[4]; + float z = fP[5]; + float x2 = x*x; + float y2 = y*y; + float z2 = z*z; + float p2 = x2+y2+z2; + p = sqrt(p2); + error = (x2*fC[9]+y2*fC[14]+z2*fC[20] + 2*(x*y*fC[13]+x*z*fC[18]+y*z*fC[19]) ); + if( error>1.e-16 && p>1.e-4 ){ + error = sqrt(error)/p; + return 0; + } + error = 1.e8; + return 1; +} + +Int_t KFParticleBase::GetPt( float &pt, float &error ) const +{ + /** Calculates particle transverse momentum and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] pt - transverse momentum of the particle + ** \param[out] error - its error + **/ + + float px = fP[3]; + float py = fP[4]; + float px2 = px*px; + float py2 = py*py; + float pt2 = px2+py2; + pt = sqrt(pt2); + error = (px2*fC[9] + py2*fC[14] + 2*px*py*fC[13] ); + if( error>0 && pt>1.e-4 ){ + error = sqrt(error)/pt; + return 0; + } + error = 1.e10; + return 1; +} + +Int_t KFParticleBase::GetEta( float &eta, float &error ) const +{ + /** Calculates particle pseudorapidity and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] eta - pseudorapidity of the particle + ** \param[out] error - its error + **/ + + float px = fP[3]; + float py = fP[4]; + float pz = fP[5]; + float pt2 = px*px + py*py; + float p2 = pt2 + pz*pz; + float p = sqrt(p2); + float a = p + pz; + float b = p - pz; + eta = 1.e10; + if( b > 1.e-8 ){ + float c = a/b; + if( c>1.e-8 ) eta = 0.5*log(c); + } + float h3 = -px*pz; + float h4 = -py*pz; + float pt4 = pt2*pt2; + float p2pt4 = p2*pt4; + error = (h3*h3*fC[9] + h4*h4*fC[14] + pt4*fC[20] + 2*( h3*(h4*fC[13] + fC[18]*pt2) + pt2*h4*fC[19] ) ); + + if( error>0 && p2pt4>1.e-10 ){ + error = sqrt(error/p2pt4); + return 0; + } + + error = 1.e10; + return 1; +} + +Int_t KFParticleBase::GetPhi( float &phi, float &error ) const +{ + /** Calculates particle polar angle at the current point and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] phi - polar angle of the particle + ** \param[out] error - its error + **/ + + float px = fP[3]; + float py = fP[4]; + float px2 = px*px; + float py2 = py*py; + float pt2 = px2 + py2; + phi = atan2(py,px); + error = (py2*fC[9] + px2*fC[14] - 2*px*py*fC[13] ); + if( error>0 && pt2>1.e-4 ){ + error = sqrt(error)/pt2; + return 0; + } + error = 1.e10; + return 1; +} + +Int_t KFParticleBase::GetR( float &r, float &error ) const +{ + /** Calculates the distance to the point {0,0,0} and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] r - polar angle of the particle + ** \param[out] error - its error + **/ + + float x = fP[0]; + float y = fP[1]; + float x2 = x*x; + float y2 = y*y; + r = sqrt(x2 + y2); + error = (x2*fC[0] + y2*fC[2] - 2*x*y*fC[1] ); + if( error>0 && r>1.e-4 ){ + error = sqrt(error)/r; + return 0; + } + error = 1.e10; + return 1; +} + +Int_t KFParticleBase::GetMass( float &m, float &error ) const +{ + /** Calculates the mass of the particle and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] m - mass of the particle + ** \param[out] error - its error + **/ + + // s = sigma^2 of m2/2 + + float s = ( fP[3]*fP[3]*fC[9] + fP[4]*fP[4]*fC[14] + fP[5]*fP[5]*fC[20] + + fP[6]*fP[6]*fC[27] + + 2*( + fP[3]*fP[4]*fC[13] + fP[5]*(fP[3]*fC[18] + fP[4]*fC[19]) + - fP[6]*( fP[3]*fC[24] + fP[4]*fC[25] + fP[5]*fC[26] ) ) + ); + + float m2 = (fP[6]*fP[6] - fP[3]*fP[3] - fP[4]*fP[4] - fP[5]*fP[5]); + + if(m2<0.) + { + error = 1.e3; + m = -sqrt(-m2); + return 1; + } + + m = sqrt(m2); + if( m>1.e-6 ){ + if( s >= 0 ) { + error = sqrt(s)/m; + return 0; + } + } + else { + error = 0.; + return 0; + } + error = 1.e3; + + return 1; +} + + +Int_t KFParticleBase::GetDecayLength( float &l, float &error ) const +{ + /** Calculates the decay length of the particle in the laboratory system and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] l - the decay length + ** \param[out] error - its error + **/ + + float x = fP[3]; + float y = fP[4]; + float z = fP[5]; + float t = fP[7]; + float x2 = x*x; + float y2 = y*y; + float z2 = z*z; + float p2 = x2+y2+z2; + l = t*sqrt(p2); + if( p2>1.e-4){ + error = p2*fC[35] + t*t/p2*(x2*fC[9]+y2*fC[14]+z2*fC[20] + + 2*(x*y*fC[13]+x*z*fC[18]+y*z*fC[19]) ) + + 2*t*(x*fC[31]+y*fC[32]+z*fC[33]); + error = sqrt(fabs(error)); + return 0; + } + error = 1.e20; + return 1; +} + +Int_t KFParticleBase::GetDecayLengthXY( float &l, float &error ) const +{ + /** Calculates the projection in the XY plane of the decay length of the particle in the laboratory + ** system and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] l - the decay length + ** \param[out] error - its error + **/ + + float x = fP[3]; + float y = fP[4]; + float t = fP[7]; + float x2 = x*x; + float y2 = y*y; + float pt2 = x2+y2; + l = t*sqrt(pt2); + if( pt2>1.e-4){ + error = pt2*fC[35] + t*t/pt2*(x2*fC[9]+y2*fC[14] + 2*x*y*fC[13] ) + + 2*t*(x*fC[31]+y*fC[32]); + error = sqrt(fabs(error)); + return 0; + } + error = 1.e20; + return 1; +} + + +Int_t KFParticleBase::GetLifeTime( float &ctau, float &error ) const +{ + /** Calculates the lifetime times speed of life (ctau) [cm] of the particle in the + ** center of mass frame and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] ctau - lifetime of the particle [cm] + ** \param[out] error - its error + **/ + + float m, dm; + GetMass( m, dm ); + float cTM = (-fP[3]*fC[31] - fP[4]*fC[32] - fP[5]*fC[33] + fP[6]*fC[34]); + ctau = fP[7]*m; + error = m*m*fC[35] + 2*fP[7]*cTM + fP[7]*fP[7]*dm*dm; + if( error > 0 ){ + error = sqrt( error ); + return 0; + } + error = 1.e20; + return 1; +} + + +void KFParticleBase::operator +=( const KFParticleBase &Daughter ) +{ + /** Operator to add daughter to the current particle. Calls AddDaughter() function. + ** \param[in] Daughter - the daughter particle + **/ + + AddDaughter( Daughter ); +} + +bool KFParticleBase::GetMeasurement( const KFParticleBase& daughter, float m[], float V[], float D[3][3] ) +{ + /** Obtains the measurements from the current particle and the daughter to be added for the Kalman filter + ** mathematics. If these are two first daughters they are transported to the point of the closest approach, + ** if the third or higher daughter is added it is transported to the DCA point of the already constructed + ** vertex. The correlations are taken into account in the covariance matrices of both measurements, + ** the correlation matrix of two measurements is also calculated. Parameters of the current particle are + ** modified by this function, the daughter is not changed, its parameters are stored to the output arrays + ** after modifications. + ** \param[in] daughter - the daughter particle to be added, stays unchanged + ** \param[out] m[8] - the output parameters of the daughter particle at the DCA point + ** \param[out] V[36] - the output covariance matrix of the daughter parameters, takes into account the correlation + ** \param[out] D[3][3] - the correlation matrix between the current and daughter particles + **/ + + if(fNDF == -1) + { + float ds[2] = {0.f,0.f}; + float dsdr[4][6]; + float F1[36], F2[36], F3[36], F4[36]; + for(int i1=0; i1<36; i1++) + { + F1[i1] = 0; + F2[i1] = 0; + F3[i1] = 0; + F4[i1] = 0; + } + GetDStoParticle( daughter, ds, dsdr ); + + if( fabs(ds[0]*fP[5]) > 1000.f || fabs(ds[1]*daughter.fP[5]) > 1000.f) + return 0; + + float V0Tmp[36] = {0.}; + float V1Tmp[36] = {0.}; + + float C[36]; + for(int iC=0; iC<36; iC++) + C[iC] = fC[iC]; + + Transport(ds[0], dsdr[0], fP, fC, dsdr[1], F1, F2); + daughter.Transport(ds[1], dsdr[3], m, V, dsdr[2], F4, F3); + + MultQSQt(F2, daughter.fC, V0Tmp, 6); + MultQSQt(F3, C, V1Tmp, 6); + + for(int iC=0; iC<21; iC++) + { + fC[iC] += V0Tmp[iC]; + V[iC] += V1Tmp[iC]; + } + + float C1F1T[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + C1F1T[i][j] = 0; + for(int k=0; k<6; k++) + { + C1F1T[i][j] += C[IJ(i,k)] * F1[j*6+k]; + } + } + float F3C1F1T[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + F3C1F1T[i][j] = 0; + for(int k=0; k<6; k++) + { + F3C1F1T[i][j] += F3[i*6+k] * C1F1T[k][j]; + } + } + float C2F2T[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + C2F2T[i][j] = 0; + for(int k=0; k<6; k++) + { + C2F2T[i][j] += daughter.fC[IJ(i,k)] * F2[j*6+k]; + } + } + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + D[i][j] = F3C1F1T[i][j]; + for(int k=0; k<6; k++) + { + D[i][j] += F4[i*6+k] * C2F2T[k][j]; + } + } + } + else + { + float dsdr[6]; + float dS = daughter.GetDStoPoint(fP, dsdr); + + float dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0, 0, 0}; + + float F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0; + F1[i2] = 0; + } + daughter.Transport(dS, dsdr, m, V, dsdp, F, F1); + +// float V1Tmp[36] = {0.}; +// MultQSQt(F1, fC, V1Tmp, 6); + +// for(int iC=0; iC<21; iC++) +// V[iC] += V1Tmp[iC]; + + float VFT[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<6; j++) + { + VFT[i][j] = 0; + for(int k=0; k<3; k++) + { + VFT[i][j] += fC[IJ(i,k)] * F1[j*6+k]; + } + } + + float FVFT[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + FVFT[i][j] = 0; + for(int k=0; k<3; k++) + { + FVFT[i][j] += F1[i*6+k] * VFT[k][j]; + } + } + + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + D[i][j] = 0; + for(int k=0; k<3; k++) + { + D[i][j] += fC[IJ(j,k)] * F1[i*6+k]; + } + } + + V[0] += FVFT[0][0]; + V[1] += FVFT[1][0]; + V[2] += FVFT[1][1]; + V[3] += FVFT[2][0]; + V[4] += FVFT[2][1]; + V[5] += FVFT[2][2]; + +// if(fNDF > 100) +// { +// float dx = fP[0] - m[0]; +// float dy = fP[1] - m[1]; +// float dz = fP[2] - m[2]; +// float sigmaS = 3.f*sqrt( (dx*dx + dy*dy + dz*dz) / (m[3]*m[3] + m[4]*m[4] + m[5]*m[5]) ); +// +// float h[3] = { m[3]*sigmaS, m[4]*sigmaS, m[5]*sigmaS }; +// V[0]+= h[0]*h[0]; +// V[1]+= h[1]*h[0]; +// V[2]+= h[1]*h[1]; +// V[3]+= h[2]*h[0]; +// V[4]+= h[2]*h[1]; +// V[5]+= h[2]*h[2]; +// } + } + + return 1; +} + +void KFParticleBase::AddDaughter( const KFParticleBase &Daughter ) +{ + /** Adds daughter to the current particle. Depending on the selected construction method uses: \n + ** 1) Either simplifyed fast mathematics which consideres momentum and energy as + ** independent variables and thus ignores constraint on the fixed mass (fConstructMethod = 0). + ** In this case the mass of the daughter particle can be corrupted when the constructed vertex + ** is added as the measurement and the mass of the output short-lived particle can become + ** unphysical - smaller then the threshold. Implemented in the + ** AddDaughterWithEnergyFit() function \n + ** 2) Or slower but correct mathematics which requires that the masses of daughter particles + ** stays fixed in the construction process (fConstructMethod = 2). Implemented in the + ** AddDaughterWithEnergyFitMC() function. + ** \param[in] Daughter - the daughter particle + **/ + + if( fNDF<-1 ){ // first daughter -> just copy + fNDF = -1; + fQ = Daughter.GetQ(); + for( Int_t i=0; i<7; i++) fP[i] = Daughter.fP[i]; + for( Int_t i=0; i<28; i++) fC[i] = Daughter.fC[i]; + fSFromDecay = 0; + fMassHypo = Daughter.fMassHypo; + SumDaughterMass = Daughter.SumDaughterMass; + return; + } + + if(static_cast<int>(fConstructMethod) == 0) + AddDaughterWithEnergyFit(Daughter); + else if(static_cast<int>(fConstructMethod) == 2) + AddDaughterWithEnergyFitMC(Daughter); + + SumDaughterMass += Daughter.SumDaughterMass; + fMassHypo = -1; +} + +void KFParticleBase::AddDaughterWithEnergyFit( const KFParticleBase &Daughter ) +{ + /** Adds daughter to the current particle. Uses simplifyed fast mathematics which consideres momentum + ** and energy as independent variables and thus ignores constraint on the fixed mass. + ** In this case the mass of the daughter particle can be corrupted when the constructed vertex + ** is added as the measurement and the mass of the output short-lived particle can become + ** unphysical - smaller then the threshold. + ** \param[in] Daughter - the daughter particle + **/ + + Int_t maxIter = 1; + + for( Int_t iter=0; iter<maxIter; iter++ ){ + + float m[8], mV[36]; + + float D[3][3]; + if(! GetMeasurement(Daughter, m, mV, D) ) + return; + + float mS[6]= { fC[0]+mV[0], + fC[1]+mV[1], fC[2]+mV[2], + fC[3]+mV[3], fC[4]+mV[4], fC[5]+mV[5] }; + + InvertCholetsky3(mS); + + //* Residual (measured - estimated) + + float zeta[3] = { m[0]-fP[0], m[1]-fP[1], m[2]-fP[2] }; + + float dChi2 = (mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]; + if (dChi2 > 1e9) return; +// if(fNDF > 100 && dChi2 > 9) return; + + float K[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + K[i][j] = 0; + for(int k=0; k<3; k++) + K[i][j] += fC[IJ(i,k)] * mS[IJ(k,j)]; + } + + //* CHt = CH' - D' + float mCHt0[7], mCHt1[7], mCHt2[7]; + + mCHt0[0]=fC[ 0] ; mCHt1[0]=fC[ 1] ; mCHt2[0]=fC[ 3] ; + mCHt0[1]=fC[ 1] ; mCHt1[1]=fC[ 2] ; mCHt2[1]=fC[ 4] ; + mCHt0[2]=fC[ 3] ; mCHt1[2]=fC[ 4] ; mCHt2[2]=fC[ 5] ; + mCHt0[3]=fC[ 6]-mV[ 6]; mCHt1[3]=fC[ 7]-mV[ 7]; mCHt2[3]=fC[ 8]-mV[ 8]; + mCHt0[4]=fC[10]-mV[10]; mCHt1[4]=fC[11]-mV[11]; mCHt2[4]=fC[12]-mV[12]; + mCHt0[5]=fC[15]-mV[15]; mCHt1[5]=fC[16]-mV[16]; mCHt2[5]=fC[17]-mV[17]; + mCHt0[6]=fC[21]-mV[21]; mCHt1[6]=fC[22]-mV[22]; mCHt2[6]=fC[23]-mV[23]; + + //* Kalman gain K = mCH'*S + + float k0[7], k1[7], k2[7]; + + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + //* Add the daughter momentum to the particle momentum + + fP[ 3] += m[ 3]; + fP[ 4] += m[ 4]; + fP[ 5] += m[ 5]; + fP[ 6] += m[ 6]; + + fC[ 9] += mV[ 9]; + fC[13] += mV[13]; + fC[14] += mV[14]; + fC[18] += mV[18]; + fC[19] += mV[19]; + fC[20] += mV[20]; + fC[24] += mV[24]; + fC[25] += mV[25]; + fC[26] += mV[26]; + fC[27] += mV[27]; + + + //* New estimation of the vertex position r += K*zeta + + for(Int_t i=0;i<7;++i) + fP[i] = fP[i] + k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + //* New covariance matrix C -= K*(mCH')' + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + fC[k] = fC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + float K2[3][3]; + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + K2[i][j] = -K[j][i]; + K2[i][i] += 1; + } + + float A[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + A[i][j] = 0; + for(int k=0; k<3; k++) + { + A[i][j] += D[i][k] * K2[k][j]; + } + } + + double M[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + M[i][j] = 0; + for(int k=0; k<3; k++) + { + M[i][j] += K[i][k] * A[k][j]; + } + } + + fC[0] += 2*M[0][0]; + fC[1] += M[0][1] + M[1][0]; + fC[2] += 2*M[1][1]; + fC[3] += M[0][2] + M[2][0]; + fC[4] += M[1][2] + M[2][1]; + fC[5] += 2*M[2][2]; + + //* Calculate Chi^2 + + fNDF += 2; + fQ += Daughter.GetQ(); + fSFromDecay = 0; + fChi2 += dChi2; + + } +} + +void KFParticleBase::SubtractDaughter( const KFParticleBase &Daughter ) +{ + /** Subtracts a daughter particle from the mother particle. The mathematics is + ** similar to AddDaughterWithEnergyFit() but momentum is subtracted. + ** \param[in] Daughter - the daughter particle + **/ + + float m[8], mV[36]; + + float D[3][3]; + if(! GetMeasurement(Daughter, m, mV, D) ) + return; + + float mS[6]= { fC[0]+mV[0], + fC[1]+mV[1], fC[2]+mV[2], + fC[3]+mV[3], fC[4]+mV[4], fC[5]+mV[5] }; + + InvertCholetsky3(mS); + + //* Residual (measured - estimated) + + float zeta[3] = { m[0]-fP[0], m[1]-fP[1], m[2]-fP[2] }; + + float dChi2 = (mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]; + + float K[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + K[i][j] = 0; + for(int k=0; k<3; k++) + K[i][j] += fC[IJ(i,k)] * mS[IJ(k,j)]; + } + + //* CHt = CH' - D' + float mCHt0[7], mCHt1[7], mCHt2[7]; + + mCHt0[0]=fC[ 0] ; mCHt1[0]=fC[ 1] ; mCHt2[0]=fC[ 3] ; + mCHt0[1]=fC[ 1] ; mCHt1[1]=fC[ 2] ; mCHt2[1]=fC[ 4] ; + mCHt0[2]=fC[ 3] ; mCHt1[2]=fC[ 4] ; mCHt2[2]=fC[ 5] ; + mCHt0[3]=fC[ 6]+mV[ 6]; mCHt1[3]=fC[ 7]+mV[ 7]; mCHt2[3]=fC[ 8]+mV[ 8]; + mCHt0[4]=fC[10]+mV[10]; mCHt1[4]=fC[11]+mV[11]; mCHt2[4]=fC[12]+mV[12]; + mCHt0[5]=fC[15]+mV[15]; mCHt1[5]=fC[16]+mV[16]; mCHt2[5]=fC[17]+mV[17]; + mCHt0[6]=fC[21]+mV[21]; mCHt1[6]=fC[22]+mV[22]; mCHt2[6]=fC[23]+mV[23]; + + //* Kalman gain K = mCH'*S + + float k0[7], k1[7], k2[7]; + + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + //* Add the daughter momentum to the particle momentum + + fP[ 3] -= m[ 3]; + fP[ 4] -= m[ 4]; + fP[ 5] -= m[ 5]; + fP[ 6] -= m[ 6]; + + fC[ 9] += mV[ 9]; + fC[13] += mV[13]; + fC[14] += mV[14]; + fC[18] += mV[18]; + fC[19] += mV[19]; + fC[20] += mV[20]; + fC[24] += mV[24]; + fC[25] += mV[25]; + fC[26] += mV[26]; + fC[27] += mV[27]; + + + //* New estimation of the vertex position r += K*zeta + + for(Int_t i=0;i<7;++i) + fP[i] = fP[i] + k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + //* New covariance matrix C -= K*(mCH')' + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + fC[k] = fC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + float K2[3][3]; + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + K2[i][j] = -K[j][i]; + K2[i][i] += 1; + } + + float A[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + A[i][j] = 0; + for(int k=0; k<3; k++) + { + A[i][j] += D[i][k] * K2[k][j]; + } + } + + double M[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + M[i][j] = 0; + for(int k=0; k<3; k++) + { + M[i][j] += K[i][k] * A[k][j]; + } + } + + fC[0] += 2*M[0][0]; + fC[1] += M[0][1] + M[1][0]; + fC[2] += 2*M[1][1]; + fC[3] += M[0][2] + M[2][0]; + fC[4] += M[1][2] + M[2][1]; + fC[5] += 2*M[2][2]; + + //* Calculate Chi^2 + + fNDF += 2; + fQ += Daughter.GetQ(); + fSFromDecay = 0; + fChi2 += dChi2; +} + + +void KFParticleBase::AddDaughterWithEnergyFitMC( const KFParticleBase &Daughter ) +{ + /** Adds daughter to the current particle. Uses slower but correct mathematics + ** which requires that the masses of daughter particles + ** stays fixed in the construction process. + ** \param[in] Daughter - the daughter particle + **/ + + Int_t maxIter = 1; + + for( Int_t iter=0; iter<maxIter; iter++ ){ + + float m[8], mV[36]; + + float D[3][3]; + GetMeasurement(Daughter, m, mV, D); + + float mS[6]= { fC[0]+mV[0], + fC[1]+mV[1], fC[2]+mV[2], + fC[3]+mV[3], fC[4]+mV[4], fC[5]+mV[5] }; + InvertCholetsky3(mS); + //* Residual (measured - estimated) + + float zeta[3] = { m[0]-fP[0], m[1]-fP[1], m[2]-fP[2] }; + + float K[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + K[i][j] = 0; + for(int k=0; k<3; k++) + K[i][j] += fC[IJ(i,k)] * mS[IJ(k,j)]; + } + + + //* CHt = CH' + + float mCHt0[7], mCHt1[7], mCHt2[7]; + + mCHt0[0]=fC[ 0] ; mCHt1[0]=fC[ 1] ; mCHt2[0]=fC[ 3] ; + mCHt0[1]=fC[ 1] ; mCHt1[1]=fC[ 2] ; mCHt2[1]=fC[ 4] ; + mCHt0[2]=fC[ 3] ; mCHt1[2]=fC[ 4] ; mCHt2[2]=fC[ 5] ; + mCHt0[3]=fC[ 6] ; mCHt1[3]=fC[ 7] ; mCHt2[3]=fC[ 8] ; + mCHt0[4]=fC[10] ; mCHt1[4]=fC[11] ; mCHt2[4]=fC[12] ; + mCHt0[5]=fC[15] ; mCHt1[5]=fC[16] ; mCHt2[5]=fC[17] ; + mCHt0[6]=fC[21] ; mCHt1[6]=fC[22] ; mCHt2[6]=fC[23] ; + + //* Kalman gain K = mCH'*S + + float k0[7], k1[7], k2[7]; + + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + // last itearation -> update the particle + + //* VHt = VH' + + float mVHt0[7], mVHt1[7], mVHt2[7]; + + mVHt0[0]=mV[ 0] ; mVHt1[0]=mV[ 1] ; mVHt2[0]=mV[ 3] ; + mVHt0[1]=mV[ 1] ; mVHt1[1]=mV[ 2] ; mVHt2[1]=mV[ 4] ; + mVHt0[2]=mV[ 3] ; mVHt1[2]=mV[ 4] ; mVHt2[2]=mV[ 5] ; + mVHt0[3]=mV[ 6] ; mVHt1[3]=mV[ 7] ; mVHt2[3]=mV[ 8] ; + mVHt0[4]=mV[10] ; mVHt1[4]=mV[11] ; mVHt2[4]=mV[12] ; + mVHt0[5]=mV[15] ; mVHt1[5]=mV[16] ; mVHt2[5]=mV[17] ; + mVHt0[6]=mV[21] ; mVHt1[6]=mV[22] ; mVHt2[6]=mV[23] ; + + //* Kalman gain Km = mCH'*S + + float km0[7], km1[7], km2[7]; + + for(Int_t i=0;i<7;++i){ + km0[i] = mVHt0[i]*mS[0] + mVHt1[i]*mS[1] + mVHt2[i]*mS[3]; + km1[i] = mVHt0[i]*mS[1] + mVHt1[i]*mS[2] + mVHt2[i]*mS[4]; + km2[i] = mVHt0[i]*mS[3] + mVHt1[i]*mS[4] + mVHt2[i]*mS[5]; + } + + for(Int_t i=0;i<7;++i) + fP[i] = fP[i] + k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + for(Int_t i=0;i<7;++i) + m[i] = m[i] - km0[i]*zeta[0] - km1[i]*zeta[1] - km2[i]*zeta[2]; + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + fC[k] = fC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + mV[k] = mV[k] - (km0[i]*mVHt0[j] + km1[i]*mVHt1[j] + km2[i]*mVHt2[j] ); + } + } + + float mDf[7][7]; + + for(Int_t i=0;i<7;++i){ + for(Int_t j=0;j<7;++j){ + mDf[i][j] = (km0[i]*mCHt0[j] + km1[i]*mCHt1[j] + km2[i]*mCHt2[j] ); + } + } + + float mJ1[7][7], mJ2[7][7]; + for(Int_t iPar1=0; iPar1<7; iPar1++) + { + for(Int_t iPar2=0; iPar2<7; iPar2++) + { + mJ1[iPar1][iPar2] = 0; + mJ2[iPar1][iPar2] = 0; + } + } + + float mMassParticle = fP[6]*fP[6] - (fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]); + float mMassDaughter = m[6]*m[6] - (m[3]*m[3] + m[4]*m[4] + m[5]*m[5]); + if(mMassParticle > 0) mMassParticle = sqrt(mMassParticle); + if(mMassDaughter > 0) mMassDaughter = sqrt(mMassDaughter); + + if( fMassHypo > -0.5) + SetMassConstraint(fP,fC,mJ1,fMassHypo); + else if((mMassParticle < SumDaughterMass) || (fP[6]<0) ) + SetMassConstraint(fP,fC,mJ1,SumDaughterMass); + + if(Daughter.fMassHypo > -0.5) + SetMassConstraint(m,mV,mJ2,Daughter.fMassHypo); + else if((mMassDaughter < Daughter.SumDaughterMass) || (m[6] < 0) ) + SetMassConstraint(m,mV,mJ2,Daughter.SumDaughterMass); + + float mDJ[7][7]; + + for(Int_t i=0; i<7; i++) { + for(Int_t j=0; j<7; j++) { + mDJ[i][j] = 0; + for(Int_t k=0; k<7; k++) { + mDJ[i][j] += mDf[i][k]*mJ1[j][k]; + } + } + } + + for(Int_t i=0; i<7; ++i){ + for(Int_t j=0; j<7; ++j){ + mDf[i][j]=0; + for(Int_t l=0; l<7; l++){ + mDf[i][j] += mJ2[i][l]*mDJ[l][j]; + } + } + } + + //* Add the daughter momentum to the particle momentum + + fP[ 3] += m[ 3]; + fP[ 4] += m[ 4]; + fP[ 5] += m[ 5]; + fP[ 6] += m[ 6]; + + fC[ 9] += mV[ 9]; + fC[13] += mV[13]; + fC[14] += mV[14]; + fC[18] += mV[18]; + fC[19] += mV[19]; + fC[20] += mV[20]; + fC[24] += mV[24]; + fC[25] += mV[25]; + fC[26] += mV[26]; + fC[27] += mV[27]; + + fC[6 ] += mDf[3][0]; fC[7 ] += mDf[3][1]; fC[8 ] += mDf[3][2]; + fC[10] += mDf[4][0]; fC[11] += mDf[4][1]; fC[12] += mDf[4][2]; + fC[15] += mDf[5][0]; fC[16] += mDf[5][1]; fC[17] += mDf[5][2]; + fC[21] += mDf[6][0]; fC[22] += mDf[6][1]; fC[23] += mDf[6][2]; + + fC[9 ] += mDf[3][3] + mDf[3][3]; + fC[13] += mDf[4][3] + mDf[3][4]; fC[14] += mDf[4][4] + mDf[4][4]; + fC[18] += mDf[5][3] + mDf[3][5]; fC[19] += mDf[5][4] + mDf[4][5]; fC[20] += mDf[5][5] + mDf[5][5]; + fC[24] += mDf[6][3] + mDf[3][6]; fC[25] += mDf[6][4] + mDf[4][6]; fC[26] += mDf[6][5] + mDf[5][6]; fC[27] += mDf[6][6] + mDf[6][6]; + + + float K2[3][3]; + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + K2[i][j] = -K[j][i]; + K2[i][i] += 1; + } + + float A[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + A[i][j] = 0; + for(int k=0; k<3; k++) + { + A[i][j] += D[i][k] * K2[k][j]; + } + } + + double M[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + M[i][j] = 0; + for(int k=0; k<3; k++) + { + M[i][j] += K[i][k] * A[k][j]; + } + } + + fC[0] += 2*M[0][0]; + fC[1] += M[0][1] + M[1][0]; + fC[2] += 2*M[1][1]; + fC[3] += M[0][2] + M[2][0]; + fC[4] += M[1][2] + M[2][1]; + fC[5] += 2*M[2][2]; + + //* Calculate Chi^2 + + fNDF += 2; + fQ += Daughter.GetQ(); + fSFromDecay = 0; + fChi2 += (mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]; + } +} + +void KFParticleBase::SetProductionVertex( const KFParticleBase &Vtx ) +{ + /** Adds a vertex as a point-like measurement to the current particle. + ** The eights parameter of the state vector is filled with the decay + ** length to the momentum ratio (s = l/p). The corresponding covariances + ** are calculated as well. The parameters of the particle are stored + ** at the position of the production vertex. + ** \param[in] Vtx - the assumed producation vertex + **/ + + const float *m = Vtx.fP, *mV = Vtx.fC; + + float decayPoint[3] = {fP[0], fP[1], fP[2]}; + float decayPointCov[6] = { fC[0], fC[1], fC[2], fC[3], fC[4], fC[5] }; + + float D[6][6]; + for(int iD1=0; iD1<6; iD1++) + for(int iD2=0; iD2<6; iD2++) + D[iD1][iD2] = 0.f; + + Bool_t noS = ( fC[35]<=0 ); // no decay length allowed + + if( noS ){ + TransportToDecayVertex(); + fP[7] = 0; + fC[28] = fC[29] = fC[30] = fC[31] = fC[32] = fC[33] = fC[34] = fC[35] = 0; + } + else + { + float dsdr[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + float dS = GetDStoPoint(Vtx.fP, dsdr); + + float dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0, 0, 0}; + + float F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0; + F1[i2] = 0; + } + Transport( dS, dsdr, fP, fC, dsdp, F, F1 ); + + float CTmp[36] = {0.}; + MultQSQt(F1, mV, CTmp, 6); + + for(int iC=0; iC<6; iC++) + fC[iC] += CTmp[iC]; + + for(int i=0; i<6; i++) + for(int j=0; j<3; j++) + { + D[i][j] = 0; + for(int k=0; k<3; k++) + { + D[i][j] += mV[IJ(j,k)] * F1[i*6+k]; + } + } + } + + float mS[6] = { fC[0] + mV[0], + fC[1] + mV[1], fC[2] + mV[2], + fC[3] + mV[3], fC[4] + mV[4], fC[5] + mV[5] }; + InvertCholetsky3(mS); + + float res[3] = { m[0] - X(), m[1] - Y(), m[2] - Z() }; + + float K[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + K[i][j] = 0; + for(int k=0; k<3; k++) + K[i][j] += fC[IJ(i,k)] * mS[IJ(k,j)]; + } + + float mCHt0[7], mCHt1[7], mCHt2[7]; + mCHt0[0]=fC[ 0]; mCHt1[0]=fC[ 1]; mCHt2[0]=fC[ 3]; + mCHt0[1]=fC[ 1]; mCHt1[1]=fC[ 2]; mCHt2[1]=fC[ 4]; + mCHt0[2]=fC[ 3]; mCHt1[2]=fC[ 4]; mCHt2[2]=fC[ 5]; + mCHt0[3]=fC[ 6]; mCHt1[3]=fC[ 7]; mCHt2[3]=fC[ 8]; + mCHt0[4]=fC[10]; mCHt1[4]=fC[11]; mCHt2[4]=fC[12]; + mCHt0[5]=fC[15]; mCHt1[5]=fC[16]; mCHt2[5]=fC[17]; + mCHt0[6]=fC[21]; mCHt1[6]=fC[22]; mCHt2[6]=fC[23]; + + float k0[7], k1[7], k2[7]; + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + for(Int_t i=0;i<7;++i) + fP[i] = fP[i] + k0[i]*res[0] + k1[i]*res[1] + k2[i]*res[2]; + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + fC[k] = fC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + float K2[3][3]; + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + K2[i][j] = -K[j][i]; + K2[i][i] += 1; + } + + float A[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + A[i][j] = 0; + for(int k=0; k<3; k++) + { + A[i][j] += D[k][i] * K2[k][j]; + } + } + + double M[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + M[i][j] = 0; + for(int k=0; k<3; k++) + { + M[i][j] += K[i][k] * A[k][j]; + } + } + + fC[0] += 2*M[0][0]; + fC[1] += M[0][1] + M[1][0]; + fC[2] += 2*M[1][1]; + fC[3] += M[0][2] + M[2][0]; + fC[4] += M[1][2] + M[2][1]; + fC[5] += 2*M[2][2]; + + fChi2 += (mS[0]*res[0] + mS[1]*res[1] + mS[3]*res[2])*res[0] + + (mS[1]*res[0] + mS[2]*res[1] + mS[4]*res[2])*res[1] + + (mS[3]*res[0] + mS[4]*res[1] + mS[5]*res[2])*res[2]; + fNDF += 2; + + if( noS ){ + fP[7] = 0; + fC[28] = fC[29] = fC[30] = fC[31] = fC[32] = fC[33] = fC[34] = fC[35] = 0; + fSFromDecay = 0; + } + else + { + float dsdr[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + fP[7] = GetDStoPoint(decayPoint, dsdr); + + float dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0, 0, 0}; + + float F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0; + F1[i2] = 0; + } + float tmpP[8], tmpC[36]; + Transport( fP[7], dsdr, tmpP, tmpC, dsdp, F, F1 ); + + fC[35] = 0; + for(int iDsDr=0; iDsDr<6; iDsDr++) + { + float dsdrC = 0, dsdpV = 0; + + for(int k=0; k<6; k++) + dsdrC += dsdr[k] * fC[IJ(k,iDsDr)]; // (-dsdr[k])*fC[k,j] + + fC[iDsDr+28] = dsdrC; + fC[35] += dsdrC*dsdr[iDsDr] ; + if(iDsDr < 3) + { + for(int k=0; k<3; k++) + dsdpV -= dsdr[k] * decayPointCov[IJ(k,iDsDr)]; // + fC[35] -= dsdpV*dsdr[iDsDr]; + } + } + fSFromDecay = -fP[7]; + } + + fAtProductionVertex = 1; +} + +void KFParticleBase::SetMassConstraint( float *mP, float *mC, float mJ[7][7], float mass ) +{ + /** Sets the exact nonlinear mass constraint on the state vector mP with the covariance matrix mC. + ** \param[in,out] mP - the state vector to be modified + ** \param[in,out] mC - the corresponding covariance matrix + ** \param[in,out] mJ - the Jacobian between initial and modified parameters + ** \param[in] mass - the mass to be set on the state vector mP + **/ + + //* Set nonlinear mass constraint (Mass) on the state vector mP with a covariance matrix mC. + + const float energy2 = mP[6]*mP[6], p2 = mP[3]*mP[3]+mP[4]*mP[4]+mP[5]*mP[5], mass2 = mass*mass; + + const float a = energy2 - p2 + 2.*mass2; + const float b = -2.*(energy2 + p2); + const float c = energy2 - p2 - mass2; + + float lambda = 0; + if(fabs(b) > 1.e-10) lambda = -c / b; + + float d = 4.*energy2*p2 - mass2*(energy2-p2-2.*mass2); + if(d>=0 && fabs(a) > 1.e-10) lambda = (energy2 + p2 - sqrt(d))/a; + + if(mP[6] < 0) //If energy < 0 we need a lambda < 0 + lambda = -1000000.; //Empirical, a better solution should be found + + Int_t iIter=0; + for(iIter=0; iIter<100; iIter++) + { + float lambda2 = lambda*lambda; + float lambda4 = lambda2*lambda2; + + float lambda0 = lambda; + + float f = -mass2 * lambda4 + a*lambda2 + b*lambda + c; + float df = -4.*mass2 * lambda2*lambda + 2.*a*lambda + b; + if(fabs(df) < 1.e-10) break; + lambda -= f/df; + if(fabs(lambda0 - lambda) < 1.e-8) break; + } + + const float lpi = 1./(1. + lambda); + const float lmi = 1./(1. - lambda); + const float lp2i = lpi*lpi; + const float lm2i = lmi*lmi; + + float lambda2 = lambda*lambda; + + float dfl = -4.*mass2 * lambda2*lambda + 2.*a*lambda + b; + float dfx[7] = {0};//,0,0,0}; + dfx[0] = -2.*(1. + lambda)*(1. + lambda)*mP[3]; + dfx[1] = -2.*(1. + lambda)*(1. + lambda)*mP[4]; + dfx[2] = -2.*(1. + lambda)*(1. + lambda)*mP[5]; + dfx[3] = 2.*(1. - lambda)*(1. - lambda)*mP[6]; + float dlx[4] = {1,1,1,1}; + if(fabs(dfl) > 1.e-10 ) + { + for(int i=0; i<4; i++) + dlx[i] = -dfx[i] / dfl; + } + + float dxx[4] = {mP[3]*lm2i, mP[4]*lm2i, mP[5]*lm2i, -mP[6]*lp2i}; + + for(Int_t i=0; i<7; i++) + for(Int_t j=0; j<7; j++) + mJ[i][j]=0; + mJ[0][0] = 1.; + mJ[1][1] = 1.; + mJ[2][2] = 1.; + + for(Int_t i=3; i<7; i++) + for(Int_t j=3; j<7; j++) + mJ[i][j] = dlx[j-3]*dxx[i-3]; + + for(Int_t i=3; i<6; i++) + mJ[i][i] += lmi; + mJ[6][6] += lpi; + + float mCJ[7][7]; + + for(Int_t i=0; i<7; i++) { + for(Int_t j=0; j<7; j++) { + mCJ[i][j] = 0; + for(Int_t k=0; k<7; k++) { + mCJ[i][j] += mC[IJ(i,k)]*mJ[j][k]; + } + } + } + + for(Int_t i=0; i<7; ++i){ + for(Int_t j=0; j<=i; ++j){ + mC[IJ(i,j)]=0; + for(Int_t l=0; l<7; l++){ + mC[IJ(i,j)] += mJ[i][l]*mCJ[l][j]; + } + } + } + + mP[3] *= lmi; + mP[4] *= lmi; + mP[5] *= lmi; + mP[6] *= lpi; +} + +void KFParticleBase::SetNonlinearMassConstraint( float mass ) +{ + /** Sets the exact nonlinear mass constraint on the current particle. + ** \param[in] mass - the mass to be set on the particle + **/ + + const float& px = fP[3]; + const float& py = fP[4]; + const float& pz = fP[5]; + const float& energy = fP[6]; + + const float residual = (energy*energy - px*px - py*py - pz*pz) - mass*mass; + const float dm2 = float(4.f) * ( fC[9]*px*px + fC[14]*py*py + fC[20]*pz*pz + fC[27]*energy*energy + + float(2.f) * ( (fC[13]*py + fC[18]*pz - fC[24]*energy)*px + (fC[19]*pz - fC[25]*energy)*py - fC[26]*pz*energy) ); + const float dChi2 = residual*residual / dm2; + fChi2 += dChi2; + fNDF += 1; + + float mJ[7][7]; + SetMassConstraint( fP, fC, mJ, mass ); + fMassHypo = mass; + SumDaughterMass = mass; +} + +void KFParticleBase::SetMassConstraint( float Mass, float SigmaMass ) +{ + /** Sets linearised mass constraint on the current particle. The constraint can be set with + ** an uncertainty. + ** \param[in] Mass - the mass to be set on the state vector mP + ** \param[in] SigmaMass - uncertainty of the constraint + **/ + + fMassHypo = Mass; + SumDaughterMass = Mass; + + float m2 = Mass*Mass; // measurement, weighted by Mass + float s2 = m2*SigmaMass*SigmaMass; // sigma^2 + + float p2 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + float e0 = sqrt(m2+p2); + + float mH[8]; + mH[0] = mH[1] = mH[2] = 0.; + mH[3] = -2*fP[3]; + mH[4] = -2*fP[4]; + mH[5] = -2*fP[5]; + mH[6] = 2*fP[6];//e0; + mH[7] = 0; + + float zeta = e0*e0 - e0*fP[6]; + zeta = m2 - (fP[6]*fP[6]-p2); + + float mCHt[8], s2_est=0; + for( Int_t i=0; i<8; ++i ){ + mCHt[i] = 0.0; + for (Int_t j=0;j<8;++j) mCHt[i] += Cij(i,j)*mH[j]; + s2_est += mH[i]*mCHt[i]; + } + + if( s2_est<1.e-20 ) return; // calculated mass error is already 0, + // the particle can not be constrained on mass + + float w2 = 1./( s2 + s2_est ); + fChi2 += zeta*zeta*w2; + fNDF += 1; + for( Int_t i=0, ii=0; i<8; ++i ){ + float ki = mCHt[i]*w2; + fP[i]+= ki*zeta; + for(Int_t j=0;j<=i;++j) fC[ii++] -= ki*mCHt[j]; + } +} + + +void KFParticleBase::SetNoDecayLength() +{ + /** Sets constraint on the zero decay length. When the production point is set + ** the measurement from this particle is created at the decay point. + **/ + + TransportToDecayVertex(); + + float h[8]; + h[0] = h[1] = h[2] = h[3] = h[4] = h[5] = h[6] = 0; + h[7] = 1; + + float zeta = 0 - fP[7]; + for(Int_t i=0;i<8;++i) zeta -= h[i]*(fP[i]-fP[i]); + + float s = fC[35]; + if( s>1.e-20 ){ + s = 1./s; + fChi2 += zeta*zeta*s; + fNDF += 1; + for( Int_t i=0, ii=0; i<7; ++i ){ + float ki = fC[28+i]*s; + fP[i]+= ki*zeta; + for(Int_t j=0;j<=i;++j) fC[ii++] -= ki*fC[28+j]; + } + } + fP[7] = 0; + fC[28] = fC[29] = fC[30] = fC[31] = fC[32] = fC[33] = fC[34] = fC[35] = 0; +} + + +void KFParticleBase::Construct( const KFParticleBase* vDaughters[], Int_t nDaughters, + const KFParticleBase *Parent, float Mass ) +{ + /** Constructs a short-lived particle from a set of daughter particles:\n + ** 1) all parameters of the "this" objects are initialised;\n + ** 2) daughters are added one after another;\n + ** 3) if Parent pointer is not null, the production vertex is set to it;\n + ** 4) if Mass hypothesis >=0 the mass constraint is set. + ** \param[in] vDaughters - array of daughter particles + ** \param[in] nDaughters - number of daughter particles in the input array + ** \param[in] Parent - optional parrent particle + ** \param[in] Mass - optional mass hypothesis + **/ + + const int maxIter = 1; + for( Int_t iter=0; iter<maxIter; iter++ ){ + fAtProductionVertex = 0; + fSFromDecay = 0; + SumDaughterMass = 0; + + for(Int_t i=0;i<36;++i) fC[i]=0.; + fC[35] = 1.; + + fNDF = -3; + fChi2 = 0.; + fQ = 0; + + for( Int_t itr =0; itr<nDaughters; itr++ ){ + AddDaughter( *vDaughters[itr] ); + } + } + + if( Mass>=0 ) SetMassConstraint( Mass ); + if( Parent ) SetProductionVertex( *Parent ); +} + +void KFParticleBase::TransportToDecayVertex() +{ + /** Transports the particle to its decay vertex */ + float dsdr[6] = {0.f}; + if( fSFromDecay != 0 ) TransportToDS( -fSFromDecay, dsdr ); + fAtProductionVertex = 0; +} + +void KFParticleBase::TransportToProductionVertex() +{ + /** Transports the particle to its production vertex */ + float dsdr[6] = {0.f}; + if( fSFromDecay != -fP[7] ) TransportToDS( -fSFromDecay-fP[7], dsdr ); + fAtProductionVertex = 1; +} + + +void KFParticleBase::TransportToDS( float dS, const float* dsdr ) +{ + /** Transport the particle on a certain distane. The distance is defined by the dS=l/p parameter, where \n + ** 1) l - signed distance;\n + ** 2) p - momentum of the particle. \n + ** \param[in] dS = l/p - distance normalised to the momentum of the particle to be transported on + ** \param[in] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + **/ + + Transport( dS, dsdr, fP, fC ); + fSFromDecay+= dS; +} + + +float KFParticleBase::GetDStoPointLine( const float xyz[3], float dsdr[6] ) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** assuming the straigth line trajectory. Is used for particles with charge 0 or in case of zero magnetic field. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** \param[in] xyz[3] - point where particle should be transported + ** \param[out] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + **/ + + float p2 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + if( p2<1.e-4 ) p2 = 1; + + const float& a = fP[3]*(xyz[0]-fP[0]) + fP[4]*(xyz[1]-fP[1]) + fP[5]*(xyz[2]-fP[2]); + dsdr[0] = -fP[3]/p2; + dsdr[1] = -fP[4]/p2; + dsdr[2] = -fP[5]/p2; + dsdr[3] = ((xyz[0]-fP[0])*p2 - 2.f* fP[3]*a)/(p2*p2); + dsdr[4] = ((xyz[1]-fP[1])*p2 - 2.f* fP[4]*a)/(p2*p2); + dsdr[5] = ((xyz[2]-fP[2])*p2 - 2.f* fP[5]*a)/(p2*p2); + + return a/p2; +} + + +float KFParticleBase::GetDStoPointBz( float B, const float xyz[3], float dsdr[6], const float* param) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field Bz. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** \param[in] B - magnetic field Bz + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + ** \param[in] param - optional parameter, is used in case if the parameters of the particle are rotated + ** to other coordinate system (see GetDStoPointBy() function), otherwise fP are used + **/ + + if(!param) + param = fP; + + const float& x = param[0]; + const float& y = param[1]; + const float& z = param[2]; + const float& px = param[3]; + const float& py = param[4]; + const float& pz = param[5]; + + const float kCLight = 0.000299792458f; + float bq = B*fQ*kCLight; + float pt2 = px*px + py*py; + float p2 = pt2 + pz*pz; + + float dx = xyz[0] - x; + float dy = xyz[1] - y; + float dz = xyz[2] - z; + float a = dx*px+dy*py; + float dS(0.f); + + float abq = bq*a; + + const float LocalSmall = 1.e-8f; + bool mask = ( fabs(bq)<LocalSmall ); + if(mask && p2>1.e-4f) + { + dS = (a + dz*pz)/p2; + + dsdr[0] = -px/p2; + dsdr[1] = -py/p2; + dsdr[2] = -pz/p2; + dsdr[3] = (dx*p2 - 2.f* px *(a + dz *pz))/(p2*p2); + dsdr[4] = (dy*p2 - 2.f* py *(a + dz *pz))/(p2*p2); + dsdr[5] = (dz*p2 - 2.f* pz *(a + dz *pz))/(p2*p2); + } + if(mask) + { + return dS; + } + + dS = atan2( abq, pt2 + bq*(dy*px -dx*py) )/bq; + + float bs= bq*dS; + + float s = sin(bs), c = cos(bs); + + if(fabs(bq) < LocalSmall) + bq = LocalSmall; + float bbq = bq*(dx*py - dy*px) - pt2; + + dsdr[0] = (px*bbq - py*abq)/(abq*abq + bbq*bbq); + dsdr[1] = (px*abq + py*bbq)/(abq*abq + bbq*bbq); + dsdr[2] = 0; + dsdr[3] = -(dx*bbq + dy*abq + 2.f*px*a)/(abq*abq + bbq*bbq); + dsdr[4] = (dx*abq - dy*bbq - 2.f*py*a)/(abq*abq + bbq*bbq); + dsdr[5] = 0; + + float sz(0.f); + float cCoeff = (bbq*c - abq*s) - pz*pz ; + if(fabs(cCoeff) > 1.e-8f) + sz = (dS*pz - dz)*pz / cCoeff; + + float dcdr[6] = {0.f}; + dcdr[0] = -bq*py*c - bbq*s*bq*dsdr[0] + px*bq*s - abq*c*bq*dsdr[0]; + dcdr[1] = bq*px*c - bbq*s*bq*dsdr[1] + py*bq*s - abq*c*bq*dsdr[1]; + dcdr[3] = (-bq*dy-2*px)*c - bbq*s*bq*dsdr[3] - dx*bq*s - abq*c*bq*dsdr[3]; + dcdr[4] = ( bq*dx-2*py)*c - bbq*s*bq*dsdr[4] - dy*bq*s - abq*c*bq*dsdr[4]; + dcdr[5] = -2*pz; + + for(int iP=0; iP<6; iP++) + dsdr[iP] += pz*pz/cCoeff*dsdr[iP] - sz/cCoeff*dcdr[iP]; + dsdr[2] += pz/cCoeff; + dsdr[5] += (2.f*pz*dS - dz)/cCoeff; + + dS += sz; + + bs= bq*dS; + s = sin(bs), c = cos(bs); + + float sB, cB; + const float kOvSqr6 = 1.f/sqrt(float(6.f)); + + if(LocalSmall < fabs(bs)) + { + sB = s/bq; + cB = (1.f-c)/bq; + } + else + { + sB = (1.f-bs*kOvSqr6)*(1.f+bs*kOvSqr6)*dS; + cB = .5f*sB*bs; + } + + float p[5]; + p[0] = x + sB*px + cB*py; + p[1] = y - cB*px + sB*py; + p[2] = z + dS*pz; + p[3] = c*px + s*py; + p[4] = -s*px + c*py; + + dx = xyz[0] - p[0]; + dy = xyz[1] - p[1]; + dz = xyz[2] - p[2]; + a = dx*p[3]+dy*p[4] + dz*pz; + abq = bq*a; + + dS += atan2( abq, p2 + bq*(dy*p[3] -dx*p[4]) )/bq; + + return dS; +} + +float KFParticleBase::GetDStoPointBy( float By, const float xyz[3], float dsdr[6] ) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field By. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** The particle parameters are transformed to the coordinate system, where the main component of the magnetic field + ** By is directed along the Z axis: x->x, y->-z, z->y, and the function GetDStoPointBz() is called. Derivatives dsdr are transformed back + ** to the coordinate system of the particle. + ** \param[in] By - magnetic field By + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + **/ + + const float param[6] = { fP[0], -fP[2], fP[1], fP[3], -fP[5], fP[4] }; + const float point[3] = { xyz[0], -xyz[2], xyz[1] }; + + float dsdrBz[6] = {0.f}; + + const float dS = GetDStoPointBz(By, point, dsdrBz, param); + dsdr[0] = dsdrBz[0]; + dsdr[1] = dsdrBz[2]; + dsdr[2] = -dsdrBz[1]; + dsdr[3] = dsdrBz[3]; + dsdr[4] = dsdrBz[5]; + dsdr[5] = -dsdrBz[4]; + + return dS; +} + +float KFParticleBase::GetDStoPointB( const float* B, const float xyz[3], float dsdr[6] ) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field B. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** The particle parameters are transformed to the coordinate system, where the magnetic field B + ** is directed along the Z axis and the function GetDStoPointBz() is called. Derivatives dsdr are transformed back + ** to the coordinate system of the particle. + ** \param[in] B[3] - three components of the magnetic field at the current position of the particle + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + **/ + + const float& Bx = B[0]; + const float& By = B[1]; + const float& Bz = B[2]; + + const float& Bxz = sqrt(Bx*Bx + Bz*Bz); + const float& Br = sqrt(Bx*Bx + By*By + Bz*Bz); + + float cosA = 1; + float sinA = 0; + if(fabs(Bxz) > 1.e-8f) + { + cosA = Bz/Bxz; + sinA = Bx/Bxz; + } + + const float& sinP = By/Br; + const float& cosP = Bxz/Br; + + const float param[6] = { cosA*fP[0] - sinA*fP[2], + -sinA*sinP*fP[0] + cosP*fP[1] - cosA*sinP*fP[2], + cosP*sinA*fP[0] + sinP*fP[1] + cosA*cosP*fP[2], + cosA*fP[3] - sinA*fP[5], + -sinA*sinP*fP[3] + cosP*fP[4] - cosA*sinP*fP[5], + cosP*sinA*fP[3] + sinP*fP[4] + cosA*cosP*fP[5]}; + const float point[3] = { cosA*xyz[0] - sinA*xyz[2], + -sinA*sinP*xyz[0] + cosP*xyz[1] - cosA*sinP*xyz[2], + cosP*sinA*xyz[0] + sinP*xyz[1] + cosA*cosP*xyz[2] }; + + float dsdrBz[6] = {0.f}; + + const float dS = GetDStoPointBz(Br, point, dsdrBz, param); + dsdr[0] = dsdrBz[0]*cosA - dsdrBz[1]*sinA*sinP + dsdrBz[2]*sinA*cosP; + dsdr[1] = dsdrBz[1]*cosP + dsdrBz[2]*sinP; + dsdr[2] = -dsdrBz[0]*sinA - dsdrBz[1]*cosA*sinP + dsdrBz[2]*cosA*cosP; + dsdr[3] = dsdrBz[3]*cosA - dsdrBz[4]*sinA*sinP + dsdrBz[5]*sinA*cosP; + dsdr[4] = dsdrBz[4]*cosP + dsdrBz[5]*sinP; + dsdr[5] = -dsdrBz[3]*sinA - dsdrBz[4]*cosA*sinP + dsdrBz[5]*cosA*cosP; + + return dS; +} + +float KFParticleBase::GetDStoPointCBM( const float xyz[3], float dsdr[6] ) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** in case of the CBM-like nonhomogeneous magnetic field. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** For this the y-component of the magnetic field at the current position of the particle is obtained and + ** the GetDStoPointBy() is called. + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + **/ + + float dS = 0; + float fld[3]; + GetFieldValue( fP, fld ); + dS = GetDStoPointBy( fld[1], xyz, dsdr ); + + return dS; +} + +void KFParticleBase::GetDStoParticleBz( float Bz, const KFParticleBase &p, float dS[2], float dsdr[4][6], const float* param1, const float* param2 ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field Bz. dS[0] is the transport parameter for the current particle, + ** dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle (if the pointer is not provided it is initialised with fP) and + ** param2 are parameters of the second particle "p" (if the pointer is not provided it is initialised with p.fP). Parameters + ** param1 and param2 should be either provided both or both set to null pointers. + ** \param[in] Bz - magnetic field Bz + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + ** \param[in] param1 - optional parameter, is used in case if the parameters of the current particles are rotated + ** to other coordinate system (see GetDStoParticleBy() function), otherwise fP are used + ** \param[in] param2 - optional parameter, is used in case if the parameters of the second particles are rotated + ** to other coordinate system (see GetDStoParticleBy() function), otherwise p.fP are used + **/ + + if(!param1) + { + param1 = fP; + param2 = p.fP; + } + + //* Get dS to another particle for Bz field + const float kOvSqr6 = 1.f/sqrt(float(6.f)); + const float kCLight = 0.000299792458f; + + //in XY plane + //first root + const float& bq1 = Bz*fQ*kCLight; + const float& bq2 = Bz*p.fQ*kCLight; + + const bool& isStraight1 = fabs(bq1) < 1.e-8f; + const bool& isStraight2 = fabs(bq2) < 1.e-8f; + + if( isStraight1 && isStraight2 ) + { + GetDStoParticleLine(p, dS, dsdr); + return; + } + + const float& px1 = param1[3]; + const float& py1 = param1[4]; + const float& pz1 = param1[5]; + + const float& px2 = param2[3]; + const float& py2 = param2[4]; + const float& pz2 = param2[5]; + + const float& pt12 = px1*px1 + py1*py1; + const float& pt22 = px2*px2 + py2*py2; + + const float& x01 = param1[0]; + const float& y01 = param1[1]; + const float& z01 = param1[2]; + + const float& x02 = param2[0]; + const float& y02 = param2[1]; + const float& z02 = param2[2]; + + float dS1[2] = {0.f}, dS2[2]={0.f}; + + const float& dx0 = (x01 - x02); + const float& dy0 = (y01 - y02); + const float& dr02 = dx0*dx0 + dy0*dy0; + const float& drp1 = dx0*px1 + dy0*py1; + const float& dxyp1 = dx0*py1 - dy0*px1; + const float& drp2 = dx0*px2 + dy0*py2; + const float& dxyp2 = dx0*py2 - dy0*px2; + const float& p1p2 = px1*px2 + py1*py2; + const float& dp1p2 = px1*py2 - px2*py1; + + const float& k11 = (bq2*drp1 - dp1p2); + const float& k21 = (bq1*(bq2*dxyp1 - p1p2) + bq2*pt12); + const float& k12 = ((bq1*drp2 - dp1p2)); + const float& k22 = (bq2*(bq1*dxyp2 + p1p2) - bq1*pt22); + + const float& kp = (dxyp1*bq2 - dxyp2*bq1 - p1p2); + const float& kd = dr02/2.f*bq1*bq2 + kp; + const float& c1 = -(bq1*kd + pt12*bq2); + const float& c2 = bq2*kd + pt22*bq1; + + float d1 = pt12*pt22 - kd*kd; + if(d1<0.f) + d1 = float(0.f); + d1 = sqrt( d1 ); + float d2 = pt12*pt22 - kd*kd; + if(d2<0.f) + d2 = float(0.f); + d2 = sqrt( d2 ); + + // find two points of closest approach in XY plane + + float dS1dR1[2][6]; + float dS2dR2[2][6]; + + float dS1dR2[2][6]; + float dS2dR1[2][6]; + + float dk11dr1[6] = {bq2*px1, bq2*py1, 0, bq2*dx0 - py2, bq2*dy0 + px2, 0}; + float dk11dr2[6] = {-bq2*px1, -bq2*py1, 0, py1, -px1, 0}; + float dk12dr1[6] = {bq1*px2, bq1*py2, 0, -py2, px2, 0}; + float dk12dr2[6] = {-bq1*px2, -bq1*py2, 0, bq1*dx0 + py1, bq1*dy0 - px1, 0}; + float dk21dr1[6] = {bq1*bq2*py1, -bq1*bq2*px1, 0, 2*bq2*px1 + bq1*(-(bq2*dy0) - px2), 2*bq2*py1 + bq1*(bq2*dx0 - py2), 0}; + float dk21dr2[6] = {-(bq1*bq2*py1), bq1*bq2*px1, 0, -(bq1*px1), -(bq1*py1), 0}; + float dk22dr1[6] = {bq1*bq2*py2, -(bq1*bq2*px2), 0, bq2*px2, bq2*py2, 0}; + float dk22dr2[6] = {-(bq1*bq2*py2), bq1*bq2*px2, 0, bq2*(-(bq1*dy0) + px1) - 2*bq1*px2, bq2*(bq1*dx0 + py1) - 2*bq1*py2, 0}; + + float dkddr1[6] = {bq1*bq2*dx0 + bq2*py1 - bq1*py2, bq1*bq2*dy0 - bq2*px1 + bq1*px2, 0, -bq2*dy0 - px2, bq2*dx0 - py2, 0}; + float dkddr2[6] = {-bq1*bq2*dx0 - bq2*py1 + bq1*py2, -bq1*bq2*dy0 + bq2*px1 - bq1*px2, 0, bq1*dy0 - px1, -bq1*dx0 - py1, 0}; + + float dc1dr1[6] = {-(bq1*(bq1*bq2*dx0 + bq2*py1 - bq1*py2)), -(bq1*(bq1*bq2*dy0 - bq2*px1 + bq1*px2)), 0, -2*bq2*px1 - bq1*(-(bq2*dy0) - px2), -2*bq2*py1 - bq1*(bq2*dx0 - py2), 0}; + float dc1dr2[6] = {-(bq1*(-(bq1*bq2*dx0) - bq2*py1 + bq1*py2)), -(bq1*(-(bq1*bq2*dy0) + bq2*px1 - bq1*px2)), 0, -(bq1*(bq1*dy0 - px1)), -(bq1*(-(bq1*dx0) - py1)), 0}; + + float dc2dr1[6] = {bq2*(bq1*bq2*dx0 + bq2*py1 - bq1*py2), bq2*(bq1*bq2*dy0 - bq2*px1 + bq1*px2), 0, bq2*(-(bq2*dy0) - px2), bq2*(bq2*dx0 - py2), 0}; + float dc2dr2[6] = {bq2*(-(bq1*bq2*dx0) - bq2*py1 + bq1*py2), bq2*(-(bq1*bq2*dy0) + bq2*px1 - bq1*px2), 0, bq2*(bq1*dy0 - px1) + 2*bq1*px2, bq2*(-(bq1*dx0) - py1) + 2*bq1*py2, 0}; + + float dd1dr1[6] = {0,0,0,0,0,0}; + float dd1dr2[6] = {0,0,0,0,0,0}; + if(d1>0) + { + for(int i=0; i<6; i++) + { + dd1dr1[i] = -kd/d1*dkddr1[i]; + dd1dr2[i] = -kd/d1*dkddr2[i]; + } + dd1dr1[3] += px1/d1*pt22; dd1dr1[4] += py1/d1*pt22; + dd1dr2[3] += px2/d1*pt12; dd1dr2[4] += py2/d1*pt12; + } + + if(!isStraight1) + { + dS1[0] = atan2( bq1*(k11*c1 + k21*d1), (bq1*k11*d1*bq1 - k21*c1) )/bq1; + dS1[1] = atan2( bq1*(k11*c1 - k21*d1), (-bq1*k11*d1*bq1 - k21*c1) )/bq1; + + float a = bq1*(k11*c1 + k21*d1); + float b = bq1*k11*d1*bq1 - k21*c1; + for(int iP=0; iP<6; iP++) + { + if(( b*b + a*a ) > 0) + { + const float dadr1 = bq1*( dk11dr1[iP]*c1 + k11*dc1dr1[iP] + dk21dr1[iP]*d1 + k21*dd1dr1[iP] ); + const float dadr2 = bq1*( dk11dr2[iP]*c1 + k11*dc1dr2[iP] + dk21dr2[iP]*d1 + k21*dd1dr2[iP] ); + const float dbdr1 = bq1*bq1*( dk11dr1[iP]*d1 + k11*dd1dr1[iP] ) - ( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float dbdr2 = bq1*bq1*( dk11dr2[iP]*d1 + k11*dd1dr2[iP] ) - ( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[0][iP] = 1/bq1 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ); + dS1dR2[0][iP] = 1/bq1 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ); + } + else + { + dS1dR1[0][iP] = 0; + dS1dR2[0][iP] = 0; + } + } + + a = bq1*(k11*c1 - k21*d1); + b = -bq1*k11*d1*bq1 - k21*c1; + for(int iP=0; iP<6; iP++) + { + if(( b*b + a*a ) > 0) + { + const float dadr1 = bq1*( dk11dr1[iP]*c1 + k11*dc1dr1[iP] - (dk21dr1[iP]*d1 + k21*dd1dr1[iP]) ); + const float dadr2 = bq1*( dk11dr2[iP]*c1 + k11*dc1dr2[iP] - (dk21dr2[iP]*d1 + k21*dd1dr2[iP]) ); + const float dbdr1 = -bq1*bq1*( dk11dr1[iP]*d1 + k11*dd1dr1[iP] ) - ( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float dbdr2 = -bq1*bq1*( dk11dr2[iP]*d1 + k11*dd1dr2[iP] ) - ( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[1][iP] = 1/bq1 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ); + dS1dR2[1][iP] = 1/bq1 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ); + } + else + { + dS1dR1[1][iP] = 0; + dS1dR2[1][iP] = 0; + } + } + } + if(!isStraight2) + { + dS2[0] = atan2( (bq2*k12*c2 + k22*d2*bq2), (bq2*k12*d2*bq2 - k22*c2) )/bq2; + dS2[1] = atan2( (bq2*k12*c2 - k22*d2*bq2), (-bq2*k12*d2*bq2 - k22*c2) )/bq2; + + float a = bq2*(k12*c2 + k22*d2); + float b = bq2*k12*d2*bq2 - k22*c2; + for(int iP=0; iP<6; iP++) + { + if(( b*b + a*a ) > 0) + { + const float dadr1 = bq2*( dk12dr1[iP]*c2 + k12*dc2dr1[iP] + dk22dr1[iP]*d1 + k22*dd1dr1[iP] ); + const float dadr2 = bq2*( dk12dr2[iP]*c2 + k12*dc2dr2[iP] + dk22dr2[iP]*d1 + k22*dd1dr2[iP] ); + const float dbdr1 = bq2*bq2*( dk12dr1[iP]*d1 + k12*dd1dr1[iP] ) - (dk22dr1[iP]*c2 + k22*dc2dr1[iP]); + const float dbdr2 = bq2*bq2*( dk12dr2[iP]*d1 + k12*dd1dr2[iP] ) - (dk22dr2[iP]*c2 + k22*dc2dr2[iP]); + + dS2dR1[0][iP] = 1/bq2 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ); + dS2dR2[0][iP] = 1/bq2 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ); + } + else + { + dS2dR1[0][iP] = 0; + dS2dR2[0][iP] = 0; + } + } + + a = bq2*(k12*c2 - k22*d2); + b = -bq2*k12*d2*bq2 - k22*c2; + for(int iP=0; iP<6; iP++) + { + if(( b*b + a*a ) > 0) + { + const float dadr1 = bq2*( dk12dr1[iP]*c2 + k12*dc2dr1[iP] - (dk22dr1[iP]*d1 + k22*dd1dr1[iP]) ); + const float dadr2 = bq2*( dk12dr2[iP]*c2 + k12*dc2dr2[iP] - (dk22dr2[iP]*d1 + k22*dd1dr2[iP]) ); + const float dbdr1 = -bq2*bq2*( dk12dr1[iP]*d1 + k12*dd1dr1[iP] ) - (dk22dr1[iP]*c2 + k22*dc2dr1[iP]); + const float dbdr2 = -bq2*bq2*( dk12dr2[iP]*d1 + k12*dd1dr2[iP] ) - (dk22dr2[iP]*c2 + k22*dc2dr2[iP]); + + dS2dR1[1][iP] = 1/bq2 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ); + dS2dR2[1][iP] = 1/bq2 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ); + } + else + { + dS2dR1[1][iP] = 0; + dS2dR2[1][iP] = 0; + } + } + } + if(isStraight1 && (pt12>0.f) ) + { + dS1[0] = (k11*c1 + k21*d1)/(- k21*c1); + dS1[1] = (k11*c1 - k21*d1)/(- k21*c1); + + float a = k11*c1 + k21*d1; + float b = -k21*c1; + + for(int iP=0; iP<6; iP++) + { + if(b*b > 0) + { + const float dadr1 = ( dk11dr1[iP]*c1 + k11*dc1dr1[iP] + dk21dr1[iP]*d1 + k21*dd1dr1[iP] ); + const float dadr2 = ( dk11dr2[iP]*c1 + k11*dc1dr2[iP] + dk21dr2[iP]*d1 + k21*dd1dr2[iP] ); + const float dbdr1 = -( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float dbdr2 = -( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[0][iP] = dadr1/b - dbdr1*a/(b*b) ; + dS1dR2[0][iP] = dadr2/b - dbdr2*a/(b*b) ; + } + else + { + dS1dR1[0][iP] = 0; + dS1dR2[0][iP] = 0; + } + } + + a = k11*c1 - k21*d1; + for(int iP=0; iP<6; iP++) + { + if(b*b > 0) + { + const float dadr1 = ( dk11dr1[iP]*c1 + k11*dc1dr1[iP] - dk21dr1[iP]*d1 - k21*dd1dr1[iP] ); + const float dadr2 = ( dk11dr2[iP]*c1 + k11*dc1dr2[iP] - dk21dr2[iP]*d1 - k21*dd1dr2[iP] ); + const float dbdr1 = -( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float dbdr2 = -( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[1][iP] = dadr1/b - dbdr1*a/(b*b) ; + dS1dR2[1][iP] = dadr2/b - dbdr2*a/(b*b) ; + } + else + { + dS1dR1[1][iP] = 0; + dS1dR2[1][iP] = 0; + } + } + } + if(isStraight2 && (pt22>0.f) ) + { + dS2[0] = (k12*c2 + k22*d2)/(- k22*c2); + dS2[1] = (k12*c2 - k22*d2)/(- k22*c2); + + float a = k12*c2 + k22*d1; + float b = -k22*c2; + + for(int iP=0; iP<6; iP++) + { + if(b*b > 0) + { + const float dadr1 = ( dk12dr1[iP]*c2 + k12*dc2dr1[iP] + dk22dr1[iP]*d1 + k22*dd1dr1[iP] ); + const float dadr2 = ( dk12dr2[iP]*c2 + k12*dc2dr2[iP] + dk22dr2[iP]*d1 + k22*dd1dr2[iP] ); + const float dbdr1 = -( dk22dr1[iP]*c2 + k22*dc2dr1[iP] ); + const float dbdr2 = -( dk22dr2[iP]*c2 + k22*dc2dr2[iP] ); + + dS2dR1[0][iP] = dadr1/b - dbdr1*a/(b*b) ; + dS2dR2[0][iP] = dadr2/b - dbdr2*a/(b*b) ; + } + else + { + dS2dR1[0][iP] = 0; + dS2dR2[0][iP] = 0; + } + } + + a = k12*c2 - k22*d1; + for(int iP=0; iP<6; iP++) + { + if(b*b > 0) + { + const float dadr1 = ( dk12dr1[iP]*c2 + k12*dc2dr1[iP] - dk22dr1[iP]*d1 - k22*dd1dr1[iP] ); + const float dadr2 = ( dk12dr2[iP]*c2 + k12*dc2dr2[iP] - dk22dr2[iP]*d1 - k22*dd1dr2[iP] ); + const float dbdr1 = -( dk22dr1[iP]*c2 + k22*dc2dr1[iP] ); + const float dbdr2 = -( dk22dr2[iP]*c2 + k22*dc2dr2[iP] ); + + dS2dR1[1][iP] = dadr1/b - dbdr1*a/(b*b) ; + dS2dR2[1][iP] = dadr2/b - dbdr2*a/(b*b) ; + } + else + { + dS2dR1[1][iP] = 0; + dS2dR2[1][iP] = 0; + } + } + } + + //select a point which is close to the primary vertex (with the smallest r) + + float dr2[2]; + for(int iP = 0; iP<2; iP++) + { + const float& bs1 = bq1*dS1[iP]; + const float& bs2 = bq2*dS2[iP]; + float sss = sin(bs1), ccc = cos(bs1); + + const bool& bs1Big = fabs(bs1) > 1.e-8f; + const bool& bs2Big = fabs(bs2) > 1.e-8f; + + float sB(0.f), cB(0.f); + if(bs1Big) + { + sB = sss/bq1; + cB = (1.f-ccc)/bq1; + } + else + { + sB = ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS1[iP]); + cB = .5f*sB*bs1; + } + + const float& x1 = param1[0] + sB*px1 + cB*py1; + const float& y1 = param1[1] - cB*px1 + sB*py1; + const float& z1 = param1[2] + dS1[iP]*param1[5]; + + sss = sin(bs2), ccc = cos(bs2); + + if(bs2Big) + { + sB = sss/bq2; + cB = (1.f-ccc)/bq2; + } + else + { + sB = ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS2[iP]); + cB = .5f*sB*bs2; + } + + const float& x2 = param2[0] + sB*px2 + cB*py2; + const float& y2 = param2[1] - cB*px2 + sB*py2; + const float& z2 = param2[2] + dS2[iP]*param2[5]; + + float dx = (x1-x2); + float dy = (y1-y2); + float dz = (z1-z2); + + dr2[iP] = dx*dx + dy*dy + dz*dz; + } + + const bool isFirstRoot = dr2[0] < dr2[1]; + if(isFirstRoot) + { + dS[0] = dS1[0]; + dS[1] = dS2[0]; + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP] = dS1dR1[0][iP]; + dsdr[1][iP] = dS1dR2[0][iP]; + dsdr[2][iP] = dS2dR1[0][iP]; + dsdr[3][iP] = dS2dR2[0][iP]; + } + } + else + { + dS[0] = dS1[1]; + dS[1] = dS2[1]; + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP] = dS1dR1[1][iP]; + dsdr[1][iP] = dS1dR2[1][iP]; + dsdr[2][iP] = dS2dR1[1][iP]; + dsdr[3][iP] = dS2dR2[1][iP]; + } + } + + //find correct parts of helices + int n1(0); + int n2(0); + float dzMin = fabs( (z01-z02) + dS[0]*pz1 - dS[1]*pz2 ); + const float pi2(6.283185307f); + + //TODO optimise for loops for neutral particles + const float& i1Float = -bq1/pi2*(z01/pz1+dS[0]); + for(int di1=-1; di1<=1; di1++) + { + int i1(0); + if(!isStraight1) + i1 = int(i1Float) + di1; + + const float& i2Float = ( ((z01-z02) + (dS[0]+pi2*i1/bq1)*pz1)/pz2 - dS[1]) * bq2/pi2; + for(int di2 = -1; di2<=1; di2++) + { + int i2(0); + if(!isStraight2) + i2 = int(i2Float) + di2; + + const float& z1 = z01 + (dS[0]+pi2*i1/bq1)*pz1; + const float& z2 = z02 + (dS[1]+pi2*i2/bq2)*pz2; + const float& dz = fabs( z1-z2 ); + + if(dz < dzMin) + { + n1 = i1; + n2 = i2; + dzMin = dz; + } + } + } + + if(!isStraight1) + dS[0] += float(n1)*pi2/bq1; + if(!isStraight2) + dS[1] += float(n2)*pi2/bq2; + + //Line correction + { + const float& bs1 = bq1*dS[0]; + const float& bs2 = bq2*dS[1]; + float sss = sin(bs1), ccc = cos(bs1); + + const bool& bs1Big = fabs(bs1) > 1.e-8f; + const bool& bs2Big = fabs(bs2) > 1.e-8f; + + float sB(0.f), cB(0.f); + if(bs1Big) + { + sB = sss/bq1; + cB = (1.f-ccc)/bq1; + } + else + { + sB = ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS[0]); + cB = .5f*sB*bs1; + } + + const float& x1 = x01 + sB*px1 + cB*py1; + const float& y1 = y01 - cB*px1 + sB*py1; + const float& z1 = z01 + dS[0]*pz1; + const float& ppx1 = ccc*px1 + sss*py1; + const float& ppy1 = -sss*px1 + ccc*py1; + const float& ppz1 = pz1; + + float sss1 = sin(bs2), ccc1 = cos(bs2); + + float sB1(0.f), cB1(0.f); + if(bs2Big) + { + sB1 = sss1/bq2; + cB1 = (1.f-ccc1)/bq2; + } + else + { + sB1 = ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS[1]); + cB1 = .5f*sB1*bs2; + } + + const float& x2 = x02 + sB1*px2 + cB1*py2; + const float& y2 = y02 - cB1*px2 + sB1*py2; + const float& z2 = z02 + dS[1]*pz2; + const float& ppx2 = ccc1*px2 + sss1*py2; + const float& ppy2 = -sss1*px2 + ccc1*py2; + const float& ppz2 = pz2; + + const float& p12 = ppx1*ppx1 + ppy1*ppy1 + ppz1*ppz1; + const float& p22 = ppx2*ppx2 + ppy2*ppy2 + ppz2*ppz2; + const float& lp1p2 = ppx1*ppx2 + ppy1*ppy2 + ppz1*ppz2; + + const float& dx = (x2 - x1); + const float& dy = (y2 - y1); + const float& dz = (z2 - z1); + + const float& ldrp1 = ppx1*dx + ppy1*dy + ppz1*dz; + const float& ldrp2 = ppx2*dx + ppy2*dy + ppz2*dz; + + float detp = lp1p2*lp1p2 - p12*p22; + if( fabs(detp)<1.e-4 ) detp = 1; //TODO correct!!! + + //dsdr calculation + const float a1 = ldrp2*lp1p2 - ldrp1*p22; + const float a2 = ldrp2*p12 - ldrp1*lp1p2; + const float lp1p2_ds0 = bq1*( ppx2*ppy1 - ppy2*ppx1); + const float lp1p2_ds1 = bq2*( ppx1*ppy2 - ppy1*ppx2); + const float ldrp1_ds0 = -p12 + bq1*(ppy1*dx - ppx1*dy); + const float ldrp1_ds1 = lp1p2; + const float ldrp2_ds0 = -lp1p2; + const float ldrp2_ds1 = p22 + bq2*(ppy2*dx - ppx2*dy); + const float detp_ds0 = 2*lp1p2*lp1p2_ds0; + const float detp_ds1 = 2*lp1p2*lp1p2_ds1; + const float a1_ds0 = ldrp2_ds0*lp1p2 + ldrp2*lp1p2_ds0 - ldrp1_ds0*p22; + const float a1_ds1 = ldrp2_ds1*lp1p2 + ldrp2*lp1p2_ds1 - ldrp1_ds1*p22; + const float a2_ds0 = ldrp2_ds0*p12 - ldrp1_ds0*lp1p2 - ldrp1*lp1p2_ds0; + const float a2_ds1 = ldrp2_ds1*p12 - ldrp1_ds1*lp1p2 - ldrp1*lp1p2_ds1; + + const float dsl1ds0 = a1_ds0/detp - a1*detp_ds0/(detp*detp); + const float dsl1ds1 = a1_ds1/detp - a1*detp_ds1/(detp*detp); + const float dsl2ds0 = a2_ds0/detp - a2*detp_ds0/(detp*detp); + const float dsl2ds1 = a2_ds1/detp - a2*detp_ds1/(detp*detp); + + float dsldr[4][6]; + for(int iP=0; iP<6; iP++) + { + dsldr[0][iP] = dsl1ds0*dsdr[0][iP] + dsl1ds1*dsdr[2][iP]; + dsldr[1][iP] = dsl1ds0*dsdr[1][iP] + dsl1ds1*dsdr[3][iP]; + dsldr[2][iP] = dsl2ds0*dsdr[0][iP] + dsl2ds1*dsdr[2][iP]; + dsldr[3][iP] = dsl2ds0*dsdr[1][iP] + dsl2ds1*dsdr[3][iP]; + } + + for(int iDS=0; iDS<4; iDS++) + for(int iP=0; iP<6; iP++) + dsdr[iDS][iP] += dsldr[iDS][iP]; + + const float lp1p2_dr0[6] = {0, 0, 0, ccc*ppx2 - ppy2*sss, ccc*ppy2 + ppx2*sss, pz2}; + const float lp1p2_dr1[6] = {0, 0, 0, ccc1*ppx1 - ppy1*sss1, ccc1*ppy1 + ppx1*sss1, pz1}; + const float ldrp1_dr0[6] = {-ppx1, -ppy1, -pz1, cB*ppy1 - ppx1*sB + ccc*dx - sss*dy, -cB*ppx1-ppy1*sB + sss*dx + ccc*dy, -dS[0]*pz1 + dz}; + const float ldrp1_dr1[6] = { ppx1, ppy1, pz1, -cB1*ppy1 + ppx1*sB1, cB1*ppx1 + ppy1*sB1, dS[1]*pz1}; + const float ldrp2_dr0[6] = {-ppx2, -ppy2, -pz2, cB*ppy2 - ppx2*sB, -cB*ppx2-ppy2*sB, -dS[0]*pz2}; + const float ldrp2_dr1[6] = {ppx2, ppy2, pz2, -cB1*ppy2 + ppx2*sB1 + ccc1*dx- sss1*dy, cB1*ppx2 + ppy2*sB1 + sss1*dx + ccc1*dy, dz + dS[1]*pz2}; + const float p12_dr0[6] = {0, 0, 0, 2*px1, 2*py1, 2*pz1}; + const float p22_dr1[6] = {0, 0, 0, 2*px2, 2*py2, 2*pz2}; + float a1_dr0[6], a1_dr1[6], a2_dr0[6], a2_dr1[6], detp_dr0[6], detp_dr1[6]; + for(int iP=0; iP<6; iP++) + { + a1_dr0[iP] = ldrp2_dr0[iP]*lp1p2 + ldrp2*lp1p2_dr0[iP] - ldrp1_dr0[iP]*p22; + a1_dr1[iP] = ldrp2_dr1[iP]*lp1p2 + ldrp2*lp1p2_dr1[iP] - ldrp1_dr1[iP]*p22 - ldrp1*p22_dr1[iP]; + a2_dr0[iP] = ldrp2_dr0[iP]*p12 + ldrp2*p12_dr0[iP] - ldrp1_dr0[iP]*lp1p2 - ldrp1*lp1p2_dr0[iP]; + a2_dr1[iP] = ldrp2_dr1[iP]*p12 - ldrp1_dr1[iP]*lp1p2 - ldrp1*lp1p2_dr1[iP]; + detp_dr0[iP] = 2*lp1p2*lp1p2_dr0[iP] - p12_dr0[iP]*p22; + detp_dr1[iP] = 2*lp1p2*lp1p2_dr1[iP] - p12*p22_dr1[iP]; + + dsdr[0][iP] += a1_dr0[iP]/detp - a1*detp_dr0[iP]/(detp*detp); + dsdr[1][iP] += a1_dr1[iP]/detp - a1*detp_dr1[iP]/(detp*detp); + dsdr[2][iP] += a2_dr0[iP]/detp - a2*detp_dr0[iP]/(detp*detp); + dsdr[3][iP] += a2_dr1[iP]/detp - a2*detp_dr1[iP]/(detp*detp); + } + + dS[0] += (ldrp2*lp1p2 - ldrp1*p22) /detp; + dS[1] += (ldrp2*p12 - ldrp1*lp1p2)/detp; + } +} + +void KFParticleBase::GetDStoParticleBy( float B, const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field By. dS[0] is the transport parameter for the current particle, + ** dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. + ** The particle parameters are transformed to the coordinate system, where the main component of the magnetic field + ** By is directed along the Z axis: x->x, y->-z, z->y, and the function GetDStoPointBz() is called. Derivatives dsdr are transformed back + ** to the coordinate system of the particle. + ** \param[in] B - magnetic field By + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ + + const float param1[6] = { fP[0], -fP[2], fP[1], fP[3], -fP[5], fP[4] }; + const float param2[6] = { p.fP[0], -p.fP[2], p.fP[1], p.fP[3], -p.fP[5], p.fP[4] }; + + float dsdrBz[4][6]; + for(int i1=0; i1<4; i1++) + for(int i2=0; i2<6; i2++) + dsdrBz[i1][i2] = 0; + + GetDStoParticleBz(B, p, dS, dsdrBz, param1, param2); + + for(int iDs=0; iDs<4; iDs++) + { + dsdr[iDs][0] = dsdrBz[iDs][0]; + dsdr[iDs][1] = dsdrBz[iDs][2]; + dsdr[iDs][2] = -dsdrBz[iDs][1]; + dsdr[iDs][3] = dsdrBz[iDs][3]; + dsdr[iDs][4] = dsdrBz[iDs][5]; + dsdr[iDs][5] = -dsdrBz[iDs][4]; + } +} + +void KFParticleBase::GetDStoParticleLine( const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the straight line trajectory. Is used for particles with charge 0 or in case of zero magnetic field. + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ + + float p12 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + float p22 = p.fP[3]*p.fP[3] + p.fP[4]*p.fP[4] + p.fP[5]*p.fP[5]; + float p1p2 = fP[3]*p.fP[3] + fP[4]*p.fP[4] + fP[5]*p.fP[5]; + + float drp1 = fP[3]*(p.fP[0]-fP[0]) + fP[4]*(p.fP[1]-fP[1]) + fP[5]*(p.fP[2]-fP[2]); + float drp2 = p.fP[3]*(p.fP[0]-fP[0]) + p.fP[4]*(p.fP[1]-fP[1]) + p.fP[5]*(p.fP[2]-fP[2]); + + float detp = p1p2*p1p2 - p12*p22; + if( fabs(detp)<1.e-4 ) detp = 1; //TODO correct!!! + + dS[0] = (drp2*p1p2 - drp1*p22) /detp; + dS[1] = (drp2*p12 - drp1*p1p2)/detp; + + const float x01 = fP[0]; + const float y01 = fP[1]; + const float z01 = fP[2]; + const float px1 = fP[3]; + const float py1 = fP[4]; + const float pz1 = fP[5]; + + const float x02 = p.fP[0]; + const float y02 = p.fP[1]; + const float z02 = p.fP[2]; + const float px2 = p.fP[3]; + const float py2 = p.fP[4]; + const float pz2 = p.fP[5]; + + const float drp1_dr1[6] = {-px1, -py1, -pz1, -x01 + x02, -y01 + y02, -z01 + z02}; + const float drp1_dr2[6] = {px1, py1, pz1, 0, 0, 0}; + const float drp2_dr1[6] = {-px2, -py2, -pz2, 0, 0, 0}; + const float drp2_dr2[6] = {px2, py2, pz2, -x01 + x02, -y01 + y02, -z01 + z02}; + const float dp1p2_dr1[6] = {0, 0, 0, px2, py2, pz2}; + const float dp1p2_dr2[6] = {0, 0, 0, px1, py1, pz1}; + const float dp12_dr1[6] = {0, 0, 0, 2*px1, 2*py1, 2*pz1}; + const float dp12_dr2[6] = {0, 0, 0, 0, 0, 0}; + const float dp22_dr1[6] = {0, 0, 0, 0, 0, 0}; + const float dp22_dr2[6] = {0, 0, 0, 2*px2, 2*py2, 2*pz2}; + const float ddetp_dr1[6] = {0, 0, 0, -2*p22*px1 + 2*p1p2*px2, -2*p22*py1 + 2*p1p2*py2, -2*p22*pz1 + 2*p1p2*pz2}; + const float ddetp_dr2[6] = {0, 0, 0, 2*p1p2*px1 - 2*p12*px2, 2*p1p2*py1 - 2*p12*py2, 2*p1p2*pz1 - 2*p12*pz2}; + + + float da1_dr1[6], da1_dr2[6], da2_dr1[6], da2_dr2[6]; + + const float a1 = drp2*p1p2 - drp1*p22; + const float a2 = drp2*p12 - drp1*p1p2; + for(int i=0; i<6; i++) + { + da1_dr1[i] = drp2_dr1[i]*p1p2 + drp2*dp1p2_dr1[i] - drp1_dr1[i]*p22 - drp1*dp22_dr1[i]; + da1_dr2[i] = drp2_dr2[i]*p1p2 + drp2*dp1p2_dr2[i] - drp1_dr2[i]*p22 - drp1*dp22_dr2[i]; + + da2_dr1[i] = drp2_dr1[i]*p12 + drp2*dp12_dr1[i] - drp1_dr1[i]*p1p2 - drp1*dp1p2_dr1[i]; + da2_dr2[i] = drp2_dr2[i]*p12 + drp2*dp12_dr2[i] - drp1_dr2[i]*p1p2 - drp1*dp1p2_dr2[i]; + + dsdr[0][i] = da1_dr1[i]/detp - a1/(detp*detp)*ddetp_dr1[i]; + dsdr[1][i] = da1_dr2[i]/detp - a1/(detp*detp)*ddetp_dr2[i]; + + dsdr[2][i] = da2_dr1[i]/detp - a2/(detp*detp)*ddetp_dr1[i]; + dsdr[3][i] = da2_dr2[i]/detp - a2/(detp*detp)*ddetp_dr2[i]; + } +} + +void KFParticleBase::GetDStoParticleCBM( const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** in case of the CBM-like nonhomogeneous magnetic field. + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. + ** For this the y-component of the magnetic field at the position of the current particle is obtained and + ** the GetDStoParticleBy() is called. It is assumed that particles are already close to each other and that the difference + ** in magnetic field approximation between two particles can be neglected. If the charge of both particles + ** is zero or if the magnetic field is zero the function GetDStoParticleLine() is called. + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ + + float fld[3]; + GetFieldValue( fP, fld ); + + const float& bq1 = fld[1]*fQ; + const float& bq2 = fld[1]*p.fQ; + const bool& isStraight1 = fabs(bq1) < 1.e-8f; + const bool& isStraight2 = fabs(bq2) < 1.e-8f; + + if( isStraight1 && isStraight2 ) + GetDStoParticleLine(p, dS, dsdr); + else + GetDStoParticleBy(fld[1], p, dS, dsdr); +} + +void KFParticleBase::TransportCBM( float dS, const float* dsdr, float P[], float C[], float* dsdr1, float* F, float* F1) const +{ + /** Transports the parameters and their covariance matrix of the current particle assuming CBM-like nonhomogeneous + ** magnetic field on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters and covariance matrix are stored to the arrays P and + ** C respectively. P and C can be set to the parameters fP and covariance matrix fC of the current particle. In this + ** case the particle parameters will be modified. Dependence of the transport parameter dS on the state vector of the + ** current particle is taken into account in the covariance matrix using partial derivatives dsdr = d(dS)/d(fP). If + ** a pointer to F is initialised the transport jacobian F = d(fP new)/d(fP old) is stored. + ** Since dS can depend on the state vector r1 of other particle or vertex, the corelation matrix + ** F1 = d(fP new)/d(r1) can be optionally calculated if a pointer F1 is provided. + * Parameters F and F1 should be either both initialised or both set to null pointer. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[in] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + ** \param[out] P[8] - array, where transported parameters should be stored + ** \param[out] C[36] - array, where transported covariance matrix (8x8) should be stored in the lower triangular form + ** \param[in] dsdr1[6] = ds/dr - partial derivatives of the parameter dS over the state vector of another particle + ** or vertex + ** \param[out] F[36] - optional parameter, transport jacobian, 6x6 matrix F = d(fP new)/d(fP old) + ** \param[out] F1[36] - optional parameter, corelation 6x6 matrix betweeen the current particle and particle or vertex + ** with the state vector r1, to which the current particle is being transported, F1 = d(fP new)/d(r1) + **/ + + if( fQ==0 ){ + TransportLine( dS, dsdr, P, C, dsdr1, F, F1 ); + return; + } + + if( fabs(dS*fP[5]) > 1000.f ) dS = 0; + + const float kCLight = 0.000299792458; + + float c = fQ*kCLight; + + // construct coefficients + + float + px = fP[3], + py = fP[4], + pz = fP[5]; + + float sx=0, sy=0, sz=0, syy=0, syz=0, syyy=0, ssx=0, ssy=0, ssz=0, ssyy=0, ssyz=0, ssyyy=0; + + { // get field integrals + + float fld[3][3]; + float p0[3], p1[3], p2[3]; + + // line track approximation + + p0[0] = fP[0]; + p0[1] = fP[1]; + p0[2] = fP[2]; + + p2[0] = fP[0] + px*dS; + p2[1] = fP[1] + py*dS; + p2[2] = fP[2] + pz*dS; + + p1[0] = 0.5*(p0[0]+p2[0]); + p1[1] = 0.5*(p0[1]+p2[1]); + p1[2] = 0.5*(p0[2]+p2[2]); + + // first order track approximation + { + GetFieldValue( p0, fld[0] ); + GetFieldValue( p1, fld[1] ); + GetFieldValue( p2, fld[2] ); + + float ssy1 = ( 7*fld[0][1] + 6*fld[1][1]-fld[2][1] )*c*dS*dS/96.; + float ssy2 = ( fld[0][1] + 2*fld[1][1] )*c*dS*dS/6.; + + p1[0] -= ssy1*pz; + p1[2] += ssy1*px; + p2[0] -= ssy2*pz; + p2[2] += ssy2*px; + } + + GetFieldValue( p0, fld[0] ); + GetFieldValue( p1, fld[1] ); + GetFieldValue( p2, fld[2] ); + + sx = c*( fld[0][0] + 4*fld[1][0] + fld[2][0] )*dS/6.; + sy = c*( fld[0][1] + 4*fld[1][1] + fld[2][1] )*dS/6.; + sz = c*( fld[0][2] + 4*fld[1][2] + fld[2][2] )*dS/6.; + + ssx = c*( fld[0][0] + 2*fld[1][0])*dS*dS/6.; + ssy = c*( fld[0][1] + 2*fld[1][1])*dS*dS/6.; + ssz = c*( fld[0][2] + 2*fld[1][2])*dS*dS/6.; + + float c2[3][3] = { { 5, -4, -1},{ 44, 80, -4},{ 11, 44, 5} }; // /=360. + float cc2[3][3] = { { 38, 8, -4},{ 148, 208, -20},{ 3, 36, 3} }; // /=2520. + for(Int_t n=0; n<3; n++) + for(Int_t m=0; m<3; m++) + { + syz += c2[n][m]*fld[n][1]*fld[m][2]; + ssyz += cc2[n][m]*fld[n][1]*fld[m][2]; + } + + syz *= c*c*dS*dS/360.; + ssyz *= c*c*dS*dS*dS/2520.; + + syy = c*( fld[0][1] + 4*fld[1][1] + fld[2][1] )*dS; + syyy = syy*syy*syy / 1296; + syy = syy*syy/72; + + ssyy = ( fld[0][1]*( 38*fld[0][1] + 156*fld[1][1] - fld[2][1] )+ + fld[1][1]*( 208*fld[1][1] +16*fld[2][1] )+ + fld[2][1]*( 3*fld[2][1] ) + )*dS*dS*dS*c*c/2520.; + ssyyy = + ( + fld[0][1]*( fld[0][1]*( 85*fld[0][1] + 526*fld[1][1] - 7*fld[2][1] )+ + fld[1][1]*( 1376*fld[1][1] +84*fld[2][1] )+ + fld[2][1]*( 19*fld[2][1] ) )+ + fld[1][1]*( fld[1][1]*( 1376*fld[1][1] +256*fld[2][1] )+ + fld[2][1]*( 62*fld[2][1] ) )+ + fld[2][1]*fld[2][1] *( 3*fld[2][1] ) + )*dS*dS*dS*dS*c*c*c/90720.; + + } + + float mJ[8][8]; + for( Int_t i=0; i<8; i++ ) for( Int_t j=0; j<8; j++) mJ[i][j]=0; + + mJ[0][0]=1; mJ[0][1]=0; mJ[0][2]=0; mJ[0][3]=dS-ssyy; mJ[0][4]=ssx; mJ[0][5]=ssyyy-ssy; + mJ[1][0]=0; mJ[1][1]=1; mJ[1][2]=0; mJ[1][3]=-ssz; mJ[1][4]=dS; mJ[1][5]=ssx+ssyz; + mJ[2][0]=0; mJ[2][1]=0; mJ[2][2]=1; mJ[2][3]=ssy-ssyyy; mJ[2][4]=-ssx; mJ[2][5]=dS-ssyy; + + mJ[3][0]=0; mJ[3][1]=0; mJ[3][2]=0; mJ[3][3]=1-syy; mJ[3][4]=sx; mJ[3][5]=syyy-sy; + mJ[4][0]=0; mJ[4][1]=0; mJ[4][2]=0; mJ[4][3]=-sz; mJ[4][4]=1; mJ[4][5]=sx+syz; + mJ[5][0]=0; mJ[5][1]=0; mJ[5][2]=0; mJ[5][3]=sy-syyy; mJ[5][4]=-sx; mJ[5][5]=1-syy; + mJ[6][6] = mJ[7][7] = 1; + + P[0] = fP[0] + mJ[0][3]*px + mJ[0][4]*py + mJ[0][5]*pz; + P[1] = fP[1] + mJ[1][3]*px + mJ[1][4]*py + mJ[1][5]*pz; + P[2] = fP[2] + mJ[2][3]*px + mJ[2][4]*py + mJ[2][5]*pz; + P[3] = mJ[3][3]*px + mJ[3][4]*py + mJ[3][5]*pz; + P[4] = mJ[4][3]*px + mJ[4][4]*py + mJ[4][5]*pz; + P[5] = mJ[5][3]*px + mJ[5][4]*py + mJ[5][5]*pz; + P[6] = fP[6]; + P[7] = fP[7]; + + float mJds[6][6]; + for( Int_t i=0; i<6; i++ ) for( Int_t j=0; j<6; j++) mJds[i][j]=0; + + if(fabs(dS)>0) + { + mJds[0][3]= 1 - 3*ssyy/dS; mJds[0][4]= 2*ssx/dS; mJds[0][5]= (4.f*ssyyy-2*ssy)/dS; + mJds[1][3]= -2.f*ssz/dS; mJds[1][4]= 1; mJds[1][5]= (2.f*ssx + 3.*ssyz)/dS; + mJds[2][3]= (2.f*ssy-4.f*ssyyy)/dS; mJds[2][4]=-2*ssx/dS; mJds[2][5]= 1 - 3.f*ssyy/dS; + + mJds[3][3]= -2.f*syy/dS; mJds[3][4]= sx/dS; mJds[3][5]= 3.f*syyy/dS - sy/dS; + mJds[4][3]= -sz/dS; mJds[4][4]=0; mJds[4][5] = sx/dS + 2.f*syz/dS; + mJds[5][3]= sy/dS - 3.f*syyy/dS; mJds[5][4]=-sx/dS; mJds[5][5]= -2.f*syy/dS; + } + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + mJ[i1][i2] += mJds[i1][3]*px*dsdr[i2] + mJds[i1][4]*py*dsdr[i2] + mJds[i1][5]*pz*dsdr[i2]; + + MultQSQt( mJ[0], fC, C, 8); + + if(F) + { + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + F[i*6+j] = mJ[i][j]; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + F1[i1*6 + i2] = mJds[i1][3]*px*dsdr1[i2] + mJds[i1][4]*py*dsdr1[i2] + mJds[i1][5]*pz*dsdr1[i2]; + } +} + + +void KFParticleBase::TransportBz( float Bz, float dS, const float* dsdr, float P[], float C[], float* dsdr1, float* F, float* F1 ) const +{ + /** Transports the parameters and their covariance matrix of the current particle assuming constant homogeneous + ** magnetic field Bz on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters and covariance matrix are stored to the arrays P and + ** C respectively. P and C can be set to the parameters fP and covariance matrix fC of the current particle. In this + ** case the particle parameters will be modified. Dependence of the transport parameter dS on the state vector of the + ** current particle is taken into account in the covariance matrix using partial derivatives dsdr = d(dS)/d(fP). If + ** a pointer to F is initialised the transport jacobian F = d(fP new)/d(fP old) is stored. + ** Since dS can depend on the state vector r1 of other particle or vertex, the corelation matrix + ** F1 = d(fP new)/d(r1) can be optionally calculated if a pointer F1 is provided. + * Parameters F and F1 should be either both initialised or both set to null pointer. + ** \param[in] Bz - z-component of the constant homogeneous magnetic field Bz + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[in] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + ** \param[out] P[8] - array, where transported parameters should be stored + ** \param[out] C[36] - array, where transported covariance matrix (8x8) should be stored in the lower triangular form + ** \param[in] dsdr1[6] = ds/dr - partial derivatives of the parameter dS over the state vector of another particle + ** or vertex + ** \param[out] F[36] - optional parameter, transport jacobian, 6x6 matrix F = d(fP new)/d(fP old) + ** \param[out] F1[36] - optional parameter, corelation 6x6 matrix betweeen the current particle and particle or vertex + ** with the state vector r1, to which the current particle is being transported, F1 = d(fP new)/d(r1) + **/ + + const float kCLight = 0.000299792458; + Bz = Bz*fQ*kCLight; + float bs= Bz*dS; + float s = sin(bs), c = cos(bs); + float sB, cB; + if( fabs(bs)>1.e-10){ + sB= s/Bz; + cB= (1-c)/Bz; + }else{ + const float kOvSqr6 = 1./sqrt(6.); + sB = (1.-bs*kOvSqr6)*(1.+bs*kOvSqr6)*dS; + cB = .5*sB*bs; + } + + float px = fP[3]; + float py = fP[4]; + float pz = fP[5]; + + P[0] = fP[0] + sB*px + cB*py; + P[1] = fP[1] - cB*px + sB*py; + P[2] = fP[2] + dS*pz; + P[3] = c*px + s*py; + P[4] = -s*px + c*py; + P[5] = fP[5]; + P[6] = fP[6]; + P[7] = fP[7]; + + float mJ[8][8]; + for( Int_t i=0; i<8; i++ ) for( Int_t j=0; j<8; j++) mJ[i][j]=0; + + for(int i=0; i<8; i++) mJ[i][i]=1; + mJ[0][3] = sB; mJ[0][4] = cB; + mJ[1][3] = -cB; mJ[1][4] = sB; + mJ[2][5] = dS; + mJ[3][3] = c; mJ[3][4] = s; + mJ[4][3] = -s; mJ[4][4] = c; + + + float mJds[6][6]; + for( Int_t i=0; i<6; i++ ) for( Int_t j=0; j<6; j++) mJds[i][j]=0; + mJds[0][3] = c; mJds[0][4] = s; + mJds[1][3] = -s; mJds[1][4] = c; + mJds[2][5] = 1; + mJds[3][3] = -Bz*s; mJds[3][4] = Bz*c; + mJds[4][3] = -Bz*c; mJds[4][4] = -Bz*s; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + mJ[i1][i2] += mJds[i1][3]*px*dsdr[i2] + mJds[i1][4]*py*dsdr[i2] + mJds[i1][5]*pz*dsdr[i2]; + + MultQSQt( mJ[0], fC, C, 8); + + if(F) + { + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + F[i*6+j] = mJ[i][j]; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + F1[i1*6 + i2] = mJds[i1][3]*px*dsdr1[i2] + mJds[i1][4]*py*dsdr1[i2] + mJds[i1][5]*pz*dsdr1[i2]; + } +} + + +float KFParticleBase::GetDistanceFromVertex( const KFParticleBase &Vtx ) const +{ + /** Returns the DCA distance from vertex in the KFParticle format in 3D. + ** \param[in] Vtx - the vertex in the KFParticle format + **/ + + return GetDistanceFromVertex( Vtx.fP ); +} + +float KFParticleBase::GetDistanceFromVertex( const float vtx[] ) const +{ + /** Returns the DCA distance from vertex in 3D. + ** \param[in] vtx[3] - the vertex coordinates {X, Y, Z} + **/ + + float mP[8], mC[36]; + + float dsdr[6] = {0.f}; + const float dS = GetDStoPoint(vtx, dsdr); + + Transport( dS, dsdr, mP, mC ); + float d[3]={ vtx[0]-mP[0], vtx[1]-mP[1], vtx[2]-mP[2]}; + return sqrt( d[0]*d[0]+d[1]*d[1]+d[2]*d[2] ); +} + +float KFParticleBase::GetDistanceFromParticle( const KFParticleBase &p ) + const +{ + /** Returns the DCA distance from another particle p. + ** \param[in] p - the second particle + **/ + + float dsdr[4][6]; + float dS[2]; + GetDStoParticle( p, dS, dsdr ); + float mP[8], mC[36], mP1[8], mC1[36]; + Transport( dS[0], dsdr[0], mP, mC ); + p.Transport( dS[1], dsdr[3], mP1, mC1 ); + float dx = mP[0]-mP1[0]; + float dy = mP[1]-mP1[1]; + float dz = mP[2]-mP1[2]; + return sqrt(dx*dx+dy*dy+dz*dz); +} + +float KFParticleBase::GetDeviationFromVertex( const KFParticleBase &Vtx ) const +{ + /** Returns Chi2 deviation of the current particle from the vertex in the KFParticle format in 3D. + ** \param[in] Vtx - the vertex in KFPartcile format + **/ + + return GetDeviationFromVertex( Vtx.fP, Vtx.fC ); +} + + +float KFParticleBase::GetDeviationFromVertex( const float v[], const float Cv[] ) const +{ + /** Returns Chi2 deviation of the current particle from the vertex v with the covariance matrix Cv in 3D. + ** \param[in] v[3] - coordinates of the vertex {X, Y, Z} + ** \param[in] Cv[6] - covariance matrix of the vertex {Cxx, Cxy, Cyy, Cxz, Czy, Czz} + **/ + + float mP[8]; + float mC[36]; + float dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + const float dS = GetDStoPoint(v, dsdr); + float dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0, 0, 0}; + float F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0; + F1[i2] = 0; + } + Transport( dS, dsdr, mP, mC, dsdp, F, F1 ); + + if(Cv) + { + float VFT[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<6; j++) + { + VFT[i][j] = 0; + for(int k=0; k<3; k++) + { + VFT[i][j] += Cv[IJ(i,k)] * F1[j*6+k]; + } + } + + float FVFT[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + FVFT[i][j] = 0; + for(int k=0; k<3; k++) + { + FVFT[i][j] += F1[i*6+k] * VFT[k][j]; + } + } + mC[0] += FVFT[0][0] + Cv[0]; + mC[1] += FVFT[1][0] + Cv[1]; + mC[2] += FVFT[1][1] + Cv[2]; + mC[3] += FVFT[2][0] + Cv[3]; + mC[4] += FVFT[2][1] + Cv[4]; + mC[5] += FVFT[2][2] + Cv[5]; + } + + InvertCholetsky3(mC); + + float d[3]={ v[0]-mP[0], v[1]-mP[1], v[2]-mP[2]}; + + return ( ( mC[0]*d[0] + mC[1]*d[1] + mC[3]*d[2])*d[0] + +(mC[1]*d[0] + mC[2]*d[1] + mC[4]*d[2])*d[1] + +(mC[3]*d[0] + mC[4]*d[1] + mC[5]*d[2])*d[2] ); +} + + +float KFParticleBase::GetDeviationFromParticle( const KFParticleBase &p ) const +{ + /** Returns Chi2 deviation of the current particle from another particle in 3D. + ** \param[in] p - the second particle + **/ + + float ds[2] = {0.f,0.f}; + float dsdr[4][6]; + float F1[36], F2[36], F3[36], F4[36]; + for(int i1=0; i1<36; i1++) + { + F1[i1] = 0; + F2[i1] = 0; + F3[i1] = 0; + F4[i1] = 0; + } + GetDStoParticle( p, ds, dsdr ); + + float V0Tmp[36] = {0.}; + float V1Tmp[36] = {0.}; + + + float mP1[8], mC1[36]; + float mP2[8], mC2[36]; + + Transport(ds[0], dsdr[0], mP1, mC1, dsdr[1], F1, F2); + p.Transport(ds[1], dsdr[3], mP2, mC2, dsdr[2], F4, F3); + + MultQSQt(F2, p.fC, V0Tmp, 6); + MultQSQt(F3, fC, V1Tmp, 6); + + for(int iC=0; iC<6; iC++) + mC1[iC] += V0Tmp[iC] + mC2[iC] + V1Tmp[iC]; + + float d[3]={ mP2[0]-mP1[0], mP2[1]-mP1[1], mP2[2]-mP1[2]}; + + return ( ( mC1[0]*d[0] + mC1[1]*d[1] + mC1[3]*d[2])*d[0] + +(mC1[1]*d[0] + mC1[2]*d[1] + mC1[4]*d[2])*d[1] + +(mC1[3]*d[0] + mC1[4]*d[1] + mC1[5]*d[2])*d[2] ); +} + + + +void KFParticleBase::SubtractFromVertex( KFParticleBase &Vtx ) const +{ + /** Subtract the current particle from vertex Vtx using the Kalman filter mathematics. + ** \param[in] Vtx - vertex from which particle should be subtracted + **/ + + float m[8]; + float mCm[36]; + float D[3][3]; + Vtx.GetMeasurement( *this, m, mCm, D ); + //* + + float mS[6] = { mCm[0] - Vtx.fC[0] + (D[0][0] + D[0][0]), + mCm[1] - Vtx.fC[1] + (D[1][0] + D[0][1]), mCm[2] - Vtx.fC[2] + (D[1][1] + D[1][1]), + mCm[3] - Vtx.fC[3] + (D[2][0] + D[0][2]), mCm[4] - Vtx.fC[4] + (D[1][2] + D[2][1]), mCm[5] - Vtx.fC[5] + (D[2][2] + D[2][2]) }; + InvertCholetsky3(mS); + + //* Residual (measured - estimated) + + float zeta[3] = { m[0]-Vtx.fP[0], m[1]-Vtx.fP[1], m[2]-Vtx.fP[2] }; + + //* mCHt = mCH' - D' + + float mCHt0[3], mCHt1[3], mCHt2[3]; + + mCHt0[0]=Vtx.fC[ 0] ; mCHt1[0]=Vtx.fC[ 1] ; mCHt2[0]=Vtx.fC[ 3] ; + mCHt0[1]=Vtx.fC[ 1] ; mCHt1[1]=Vtx.fC[ 2] ; mCHt2[1]=Vtx.fC[ 4] ; + mCHt0[2]=Vtx.fC[ 3] ; mCHt1[2]=Vtx.fC[ 4] ; mCHt2[2]=Vtx.fC[ 5] ; + + //* Kalman gain K = mCH'*S + + float k0[3], k1[3], k2[3]; + + for(Int_t i=0;i<3;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + //* New estimation of the vertex position r += K*zeta + + float dChi2 = ((mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]); + + for(Int_t i=0;i<3;++i) + Vtx.fP[i] -= k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + //* New covariance matrix C -= K*(mCH')' + + for(Int_t i=0, k=0;i<3;++i){ + for(Int_t j=0;j<=i;++j,++k) + Vtx.fC[k] += k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j]; + } + + //* Calculate Chi^2 + + Vtx.fNDF -= 2; + Vtx.fChi2 -= dChi2; +} + +void KFParticleBase::SubtractFromParticle( KFParticleBase &Vtx ) const +{ + /** Subtract the current particle from another particle Vtx using the Kalman filter mathematics. + ** The function is depricated and is kept for compatibility reasons. Should be replaced with SubtractDaughter(). + ** \param[in] Vtx - particle from which the current particle should be subtracted + **/ + + float m[8]; + float mV[36]; + + float D[3][3]; + Vtx.GetMeasurement( *this, m, mV, D ); + + float mS[6] = { mV[0] - Vtx.fC[0] + (D[0][0] + D[0][0]), + mV[1] - Vtx.fC[1] + (D[1][0] + D[0][1]), mV[2] - Vtx.fC[2] + (D[1][1] + D[1][1]), + mV[3] - Vtx.fC[3] + (D[2][0] + D[0][2]), mV[4] - Vtx.fC[4] + (D[1][2] + D[2][1]), mV[5] - Vtx.fC[5] + (D[2][2] + D[2][2]) }; + InvertCholetsky3(mS); + + //* Residual (measured - estimated) + + float zeta[3] = { m[0]-Vtx.fP[0], m[1]-Vtx.fP[1], m[2]-Vtx.fP[2] }; + + //* CHt = CH' - D' + + float mCHt0[7], mCHt1[7], mCHt2[7]; + + mCHt0[0]=mV[ 0] ; mCHt1[0]=mV[ 1] ; mCHt2[0]=mV[ 3] ; + mCHt0[1]=mV[ 1] ; mCHt1[1]=mV[ 2] ; mCHt2[1]=mV[ 4] ; + mCHt0[2]=mV[ 3] ; mCHt1[2]=mV[ 4] ; mCHt2[2]=mV[ 5] ; + mCHt0[3]=Vtx.fC[ 6]-mV[ 6]; mCHt1[3]=Vtx.fC[ 7]-mV[ 7]; mCHt2[3]=Vtx.fC[ 8]-mV[ 8]; + mCHt0[4]=Vtx.fC[10]-mV[10]; mCHt1[4]=Vtx.fC[11]-mV[11]; mCHt2[4]=Vtx.fC[12]-mV[12]; + mCHt0[5]=Vtx.fC[15]-mV[15]; mCHt1[5]=Vtx.fC[16]-mV[16]; mCHt2[5]=Vtx.fC[17]-mV[17]; + mCHt0[6]=Vtx.fC[21]-mV[21]; mCHt1[6]=Vtx.fC[22]-mV[22]; mCHt2[6]=Vtx.fC[23]-mV[23]; + + //* Kalman gain K = mCH'*S + + float k0[7], k1[7], k2[7]; + + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + //* Add the daughter momentum to the particle momentum + + Vtx.fP[ 3] -= m[ 3]; + Vtx.fP[ 4] -= m[ 4]; + Vtx.fP[ 5] -= m[ 5]; + Vtx.fP[ 6] -= m[ 6]; + + Vtx.fC[ 9] -= mV[ 9]; + Vtx.fC[13] -= mV[13]; + Vtx.fC[14] -= mV[14]; + Vtx.fC[18] -= mV[18]; + Vtx.fC[19] -= mV[19]; + Vtx.fC[20] -= mV[20]; + Vtx.fC[24] -= mV[24]; + Vtx.fC[25] -= mV[25]; + Vtx.fC[26] -= mV[26]; + Vtx.fC[27] -= mV[27]; + + //* New estimation of the vertex position r += K*zeta + + for(Int_t i=0;i<3;++i) + Vtx.fP[i] = m[i] - (k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]); + for(Int_t i=3;i<7;++i) + Vtx.fP[i] = Vtx.fP[i] - (k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]); + + //* New covariance matrix C -= K*(mCH')' + + float ffC[28] = {-mV[ 0], + -mV[ 1], -mV[ 2], + -mV[ 3], -mV[ 4], -mV[ 5], + mV[ 6], mV[ 7], mV[ 8], Vtx.fC[ 9], + mV[10], mV[11], mV[12], Vtx.fC[13], Vtx.fC[14], + mV[15], mV[16], mV[17], Vtx.fC[18], Vtx.fC[19], Vtx.fC[20], + mV[21], mV[22], mV[23], Vtx.fC[24], Vtx.fC[25], Vtx.fC[26], Vtx.fC[27] }; + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + Vtx.fC[k] = ffC[k] + (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + //* Calculate Chi^2 + Vtx.fNDF -= 2; + Vtx.fQ -= GetQ(); + Vtx.fSFromDecay = 0; + Vtx.fChi2 -= ((mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]); +} + +void KFParticleBase::TransportLine( float dS, const float* dsdr, float P[], float C[], float* dsdr1, float* F, float* F1 ) const +{ + /** Transports the parameters and their covariance matrix of the current particle assuming the straight line trajectory + ** on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters and covariance matrix are stored to the arrays P and + ** C respectively. P and C can be set to the parameters fP and covariance matrix fC of the current particle. In this + ** case the particle parameters will be modified. Dependence of the transport parameter dS on the state vector of the + ** current particle is taken into account in the covariance matrix using partial derivatives dsdr = d(dS)/d(fP). If + ** a pointer to F is initialised the transport jacobian F = d(fP new)/d(fP old) is stored. + ** Since dS can depend on the state vector r1 of other particle or vertex, the corelation matrix + ** F1 = d(fP new)/d(r1) can be optionally calculated if a pointer F1 is provided. + * Parameters F and F1 should be either both initialised or both set to null pointer. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[in] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + ** \param[out] P[8] - array, where transported parameters should be stored + ** \param[out] C[36] - array, where transported covariance matrix (8x8) should be stored in the lower triangular form + ** \param[in] dsdr1[6] = ds/dr - partial derivatives of the parameter dS over the state vector of another particle + ** or vertex + ** \param[out] F[36] - optional parameter, transport jacobian, 6x6 matrix F = d(fP new)/d(fP old) + ** \param[out] F1[36] - optional parameter, corelation 6x6 matrix betweeen the current particle and particle or vertex + ** with the state vector r1, to which the current particle is being transported, F1 = d(fP new)/d(r1) + **/ + + float mJ[8][8]; + for( Int_t i=0; i<8; i++ ) for( Int_t j=0; j<8; j++) mJ[i][j]=0; + + mJ[0][0]=1; mJ[0][1]=0; mJ[0][2]=0; mJ[0][3]=dS; mJ[0][4]=0; mJ[0][5]=0; + mJ[1][0]=0; mJ[1][1]=1; mJ[1][2]=0; mJ[1][3]=0; mJ[1][4]=dS; mJ[1][5]=0; + mJ[2][0]=0; mJ[2][1]=0; mJ[2][2]=1; mJ[2][3]=0; mJ[2][4]=0; mJ[2][5]=dS; + + mJ[3][0]=0; mJ[3][1]=0; mJ[3][2]=0; mJ[3][3]=1; mJ[3][4]=0; mJ[3][5]=0; + mJ[4][0]=0; mJ[4][1]=0; mJ[4][2]=0; mJ[4][3]=0; mJ[4][4]=1; mJ[4][5]=0; + mJ[5][0]=0; mJ[5][1]=0; mJ[5][2]=0; mJ[5][3]=0; mJ[5][4]=0; mJ[5][5]=1; + mJ[6][6] = mJ[7][7] = 1; + + float px = fP[3], py = fP[4], pz = fP[5]; + + P[0] = fP[0] + dS*fP[3]; + P[1] = fP[1] + dS*fP[4]; + P[2] = fP[2] + dS*fP[5]; + P[3] = fP[3]; + P[4] = fP[4]; + P[5] = fP[5]; + P[6] = fP[6]; + P[7] = fP[7]; + + float mJds[6][6]; + for( Int_t i=0; i<6; i++ ) for( Int_t j=0; j<6; j++) mJds[i][j]=0; + + mJds[0][3]= 1; + mJds[1][4]= 1; + mJds[2][5]= 1; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + mJ[i1][i2] += mJds[i1][3]*px*dsdr[i2] + mJds[i1][4]*py*dsdr[i2] + mJds[i1][5]*pz*dsdr[i2]; + MultQSQt( mJ[0], fC, C, 8); + + if(F) + { + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + F[i*6+j] = mJ[i][j]; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + F1[i1*6 + i2] = mJds[i1][3]*px*dsdr1[i2] + mJds[i1][4]*py*dsdr1[i2] + mJds[i1][5]*pz*dsdr1[i2]; + } +} + +void KFParticleBase::GetArmenterosPodolanski(KFParticleBase& positive, KFParticleBase& negative, float QtAlfa[2] ) +{ + /** Calculates parameters for the Armenteros-Podolanski plot for two particles. + ** Example how to use:\n + ** KFParticle PosParticle(...) \n + ** KFParticle NegParticle(...) \n + ** Gamma.ConstructGamma(PosParticle, NegParticle); \n + ** float VertexGamma[3] = {Gamma.GetX(), Gamma.GetY(), Gamma.GetZ()}; \n + ** PosParticle.TransportToPoint(VertexGamma); \n + ** NegParticle.TransportToPoint(VertexGamma); \n + ** float armenterosQtAlfa[2] = {0.}; \n + ** KFParticle::GetArmenterosPodolanski(PosParticle, NegParticle, armenterosQtAlfa ); \n + ** \param[in] positive - first particle, positive or neutral + ** \param[in] negative - second particle, negative or neutral + ** \param[out] QtAlfa[2] - parameters for the Armenteros-Podolanski plot: QtAlfa[0] = qt - projection of the + ** momenta of the particles on the transverse direction with respect to the total momentum, same for both particles; + ** QtAlfa[1] = (Pl+ - Pl-)/(Pl+ + Pl-) - combination of the longitudinal components. + **/ + + float alpha = 0., qt = 0.; + float spx = positive.GetPx() + negative.GetPx(); + float spy = positive.GetPy() + negative.GetPy(); + float spz = positive.GetPz() + negative.GetPz(); + float sp = sqrt(spx*spx + spy*spy + spz*spz); + if( sp == 0.0) return; + float pn, pln, plp; + + pn = sqrt(negative.GetPx()*negative.GetPx() + negative.GetPy()*negative.GetPy() + negative.GetPz()*negative.GetPz()); +// pp = sqrt(positive.GetPx()*positive.GetPx() + positive.GetPy()*positive.GetPy() + positive.GetPz()*positive.GetPz()); + pln = (negative.GetPx()*spx+negative.GetPy()*spy+negative.GetPz()*spz)/sp; + plp = (positive.GetPx()*spx+positive.GetPy()*spy+positive.GetPz()*spz)/sp; + + if( pn == 0.0) return; + float ptm = (1.-((pln/pn)*(pln/pn))); + qt= (ptm>=0.)? pn*sqrt(ptm) :0; + alpha = (plp-pln)/(plp+pln); + + QtAlfa[0] = qt; + QtAlfa[1] = alpha; +} + +void KFParticleBase::RotateXY(float angle, float Vtx[3]) +{ + /** Rotates the KFParticle object around OZ axis, OZ axis is set by the vertex position. + ** \param[in] angle - angle of rotation in XY plane in [rad] + ** \param[in] Vtx[3] - position of the vertex in [cm] + **/ + + // Before rotation the center of the coordinat system should be moved to the vertex position; move back after rotation + X() = X() - Vtx[0]; + Y() = Y() - Vtx[1]; + Z() = Z() - Vtx[2]; + + // Rotate the kf particle + float c = cos(angle); + float s = sin(angle); + + float mA[8][ 8]; + for( Int_t i=0; i<8; i++ ){ + for( Int_t j=0; j<8; j++){ + mA[i][j] = 0; + } + } + for( int i=0; i<8; i++ ){ + mA[i][i] = 1; + } + mA[0][0] = c; mA[0][1] = s; + mA[1][0] = -s; mA[1][1] = c; + mA[3][3] = c; mA[3][4] = s; + mA[4][3] = -s; mA[4][4] = c; + + float mAC[8][8]; + float mAp[8]; + + for( Int_t i=0; i<8; i++ ){ + mAp[i] = 0; + for( Int_t k=0; k<8; k++){ + mAp[i]+=mA[i][k] * fP[k]; + } + } + + for( Int_t i=0; i<8; i++){ + fP[i] = mAp[i]; + } + + for( Int_t i=0; i<8; i++ ){ + for( Int_t j=0; j<8; j++ ){ + mAC[i][j] = 0; + for( Int_t k=0; k<8; k++ ){ + mAC[i][j]+= mA[i][k] * GetCovariance(k,j); + } + } + } + + for( Int_t i=0; i<8; i++ ){ + for( Int_t j=0; j<=i; j++ ){ + float xx = 0; + for( Int_t k=0; k<8; k++){ + xx+= mAC[i][k]*mA[j][k]; + } + Covariance(i,j) = xx; + } + } + + X() = GetX() + Vtx[0]; + Y() = GetY() + Vtx[1]; + Z() = GetZ() + Vtx[2]; +} + +void KFParticleBase::InvertCholetsky3(float a[6]) +{ + /** Inverts symmetric 3x3 matrix a using modified Choletsky decomposition. The result is stored to the same matrix a. + ** \param[in,out] a - 3x3 symmetric matrix + **/ + + float d[3], uud, u[3][3]; + for(int i=0; i<3; i++) + { + d[i]=0; + for(int j=0; j<3; j++) + u[i][j]=0; + } + + for(int i=0; i<3 ; i++) + { + uud=0; + for(int j=0; j<i; j++) + uud += u[j][i]*u[j][i]*d[j]; + uud = a[i*(i+3)/2] - uud; + + if(fabs(uud)<1.e-12f) uud = 1.e-12f; + + d[i] = uud/fabs(uud); + u[i][i] = sqrt(fabs(uud)); + + for(int j=i+1; j<3; j++) + { + uud = 0; + for(int k=0; k<i; k++) + uud += u[k][i]*u[k][j]*d[k]; + uud = a[j*(j+1)/2+i] - uud; + u[i][j] = d[i]/u[i][i]*uud; + } + } + + float u1[3]; + + for(int i=0; i<3; i++) + { + u1[i] = u[i][i]; + u[i][i] = 1/u[i][i]; + } + for(int i=0; i<2; i++) + { + u[i][i+1] = - u[i][i+1]*u[i][i]*u[i+1][i+1]; + } + for(int i=0; i<1; i++) + { + u[i][i+2] = u[i][i+1]*u1[i+1]*u[i+1][i+2]-u[i][i+2]*u[i][i]*u[i+2][i+2]; + } + + for(int i=0; i<3; i++) + a[i+3] = u[i][2]*u[2][2]*d[2]; + for(int i=0; i<2; i++) + a[i+1] = u[i][1]*u[1][1]*d[1] + u[i][2]*u[1][2]*d[2]; + a[0] = u[0][0]*u[0][0]*d[0] + u[0][1]*u[0][1]*d[1] + u[0][2]*u[0][2]*d[2]; +} + +void KFParticleBase::MultQSQt( const float Q[], const float S[], float SOut[], const int kN ) +{ + /** Matrix multiplication SOut = Q*S*Q^T, where Q - square matrix, S - symmetric matrix. + ** \param[in] Q - square matrix + ** \param[in] S - input symmetric matrix + ** \param[out] SOut - output symmetric matrix + ** \param[in] kN - dimensionality of the matrices + **/ + + float* mA = new float[kN*kN]; + + for( Int_t i=0, ij=0; i<kN; i++ ){ + for( Int_t j=0; j<kN; j++, ++ij ){ + mA[ij] = 0 ; + for( Int_t k=0; k<kN; ++k ) mA[ij]+= S[( k<=i ) ? i*(i+1)/2+k :k*(k+1)/2+i] * Q[ j*kN+k]; + } + } + + for( Int_t i=0; i<kN; i++ ){ + for( Int_t j=0; j<=i; j++ ){ + Int_t ij = ( j<=i ) ? i*(i+1)/2+j :j*(j+1)/2+i; + SOut[ij] = 0 ; + for( Int_t k=0; k<kN; k++ ) SOut[ij] += Q[ i*kN+k ] * mA[ k*kN+j ]; + } + } + + if(mA) delete [] mA; +} + +// 72-charachters line to define the printer border +//3456789012345678901234567890123456789012345678901234567890123456789012 + diff --git a/external/KFParticle/KFParticle/KFParticleBase.h b/external/KFParticle/KFParticle/KFParticleBase.h new file mode 100644 index 0000000000000000000000000000000000000000..c233cee36b157d45e54090a724a2aaa81143d5b8 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleBase.h @@ -0,0 +1,297 @@ +//--------------------------------------------------------------------------------- +// The KFParticleBase class +// . +// @author S.Gorbunov, I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 13.05.07 +// +// Class to reconstruct and store the decayed particle parameters. +// The method is described in CBM-SOFT note 2007-003, +// ``Reconstruction of decayed particles based on the Kalman filter'', +// http://www.gsi.de/documents/DOC-2007-May-14-1.pdf +// +// This class describes general mathematics which is used by KFParticle class +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//_________________________________________________________________________________ + + +#ifndef KFPARTICLEBASE_H +#define KFPARTICLEBASE_H + +#ifdef __ROOT__ //for the STAR experiment +#define HomogeneousField +#endif + +#ifdef HLTCA_STANDALONE +#include "RootTypesDef.h" +#else +#include "TObject.h" +#endif + +#include <vector> + +/** @class KFParticleBase + ** @brief The base of KFParticle class, describes particle objects. + ** @author S.Gorbunov, I.Kisel, M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** Contains the main mathematics of the KF Particle . Will be merged with the KFParticle class. + **/ + +class KFParticleBase :public TObject { + + public: + + /** + ** Abstract methods are defined in the KFParticle class + **/ + + /** Virtual method to access the magnetic field**/ + virtual void GetFieldValue(const float xyz[], float B[]) const = 0; + + /** Virtual method to get extrapolation parameter dS=l/p to . Is defined in KFParticle.**/ + virtual float GetDStoPoint( const float xyz[3], float dsdr[6] ) const = 0; + + float GetDStoPointLine( const float xyz[3], float dsdr[6] ) const; + float GetDStoPointBz( float B, const float xyz[3], float dsdr[6], const float* param=0) const; + float GetDStoPointBy( float By, const float xyz[3], float dsdr[6] ) const; + float GetDStoPointB( const float* B, const float xyz[3], float dsdr[6] ) const; + float GetDStoPointCBM( const float xyz[3], float dsdr[6] ) const; + + /** Virtual method to get extrapolation parameter dS=l/p to another particle. Is defined in KFParticle.**/ + virtual void GetDStoParticle( const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const = 0; + + void GetDStoParticleLine( const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const ; + void GetDStoParticleBz( float Bz, const KFParticleBase &p, float dS[2], float dsdr[4][6], const float* param1=0, const float* param2=0 ) const ; + void GetDStoParticleBy( float B, const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const ; + void GetDStoParticleCBM( const KFParticleBase &p, float dS[2], float dsdr[4][6] ) const ; + + /** Virtual method to transport a particle on a certain distance along the trajectory. Is defined in KFParticle.**/ + virtual void Transport( float dS, const float dsdr[6], float P[], float C[], float* dsdr1=0, float* F=0, float* F1=0 ) const = 0; + + + KFParticleBase(); + virtual ~KFParticleBase() { ; } ///< The default destructor. + + void Initialize( const float Param[], const float Cov[], Int_t Charge, float Mass ); + void Initialize(); + + void SetConstructMethod(Int_t m) {fConstructMethod = m;} ///< Defines the construction method for the current particle (see description of fConstructMethod). + void SetMassHypo(float m) { fMassHypo = m;} ///< Sets the mass hypothesis to the particle, is used when fConstructMethod = 2. + const float& GetMassHypo() const { return fMassHypo; } ///< Returns the mass hypothesis. + const float& GetSumDaughterMass() const {return SumDaughterMass;} ///< Returns the sum of masses of the daughters. + + //* + //* ACCESSORS + //* + + //* Simple accessors + + float GetX () const { return fP[0]; } ///< Retruns X coordinate of the particle, fP[0]. + float GetY () const { return fP[1]; } ///< Retruns Y coordinate of the particle, fP[1]. + float GetZ () const { return fP[2]; } ///< Retruns Z coordinate of the particle, fP[2]. + float GetPx () const { return fP[3]; } ///< Retruns X component of the momentum, fP[3]. + float GetPy () const { return fP[4]; } ///< Retruns Y component of the momentum, fP[4]. + float GetPz () const { return fP[5]; } ///< Retruns Z component of the momentum, fP[5]. + float GetE () const { return fP[6]; } ///< Returns energy of the particle, fP[6]. + float GetS () const { return fP[7]; } ///< Returns dS=l/p, l - decay length, fP[7], defined if production vertex is set. + char GetQ () const { return fQ; } ///< Returns charge of the particle. + float GetChi2 () const { return fChi2; } ///< Returns Chi2 of the fit. + Int_t GetNDF () const { return fNDF; } ///< Returns number of decrease of freedom. + + const float& X () const { return fP[0]; } ///< Retruns X coordinate of the particle, fP[0]. + const float& Y () const { return fP[1]; } ///< Retruns Y coordinate of the particle, fP[1]. + const float& Z () const { return fP[2]; } ///< Retruns Z coordinate of the particle, fP[2]. + const float& Px () const { return fP[3]; } ///< Retruns X component of the momentum, fP[3]. + const float& Py () const { return fP[4]; } ///< Retruns Y component of the momentum, fP[4]. + const float& Pz () const { return fP[5]; } ///< Retruns Z component of the momentum, fP[5]. + const float& E () const { return fP[6]; } ///< Returns energy of the particle, fP[6]. + const float& S () const { return fP[7]; } ///< Returns dS=l/p, l - decay length, fP[7], defined if production vertex is set. + const char& Q () const { return fQ; } ///< Returns charge of the particle. + const float& Chi2 () const { return fChi2; } ///< Returns Chi2 of the fit. + const Int_t& NDF () const { return fNDF; } ///< Returns number of decrease of freedom. + + float GetParameter ( Int_t i ) const { return fP[i]; } ///< Returns P[i] parameter. + float GetCovariance( Int_t i ) const { return fC[i]; } ///< Returns C[i] element of the covariance matrix in the lower triangular form. + float GetCovariance( Int_t i, Int_t j ) const { return fC[IJ(i,j)]; } ///< Returns C[i,j] element of the covariance matrix. + + //* Accessors with calculations( &value, &estimated sigma ) + //* error flag returned (0 means no error during calculations) + + Int_t GetMomentum ( float &p, float &error ) const ; + Int_t GetPt ( float &pt, float &error ) const ; + Int_t GetEta ( float &eta, float &error ) const ; + Int_t GetPhi ( float &phi, float &error ) const ; + Int_t GetMass ( float &m, float &error ) const ; + Int_t GetDecayLength ( float &l, float &error ) const ; + Int_t GetDecayLengthXY ( float &l, float &error ) const ; + Int_t GetLifeTime ( float &ctau,float &error ) const ; + Int_t GetR ( float &r, float &error ) const ; + + //* + //* MODIFIERS + //* + + float & X () { return fP[0]; } ///< Modifier of X coordinate of the particle, fP[0]. + float & Y () { return fP[1]; } ///< Modifier of Y coordinate of the particle, fP[1]. + float & Z () { return fP[2]; } ///< Modifier of Z coordinate of the particle, fP[2]. + float & Px () { return fP[3]; } ///< Modifier of X component of the momentum, fP[3]. + float & Py () { return fP[4]; } ///< Modifier of Y component of the momentum, fP[4]. + float & Pz () { return fP[5]; } ///< Modifier of Z component of the momentum, fP[5]. + float & E () { return fP[6]; } ///< Modifier of energy of the particle, fP[6]. + float & S () { return fP[7]; } ///< Modifier of dS=l/p, l - decay length, fP[7], defined if production vertex is set. + char & Q () { return fQ; } ///< Modifier of charge of the particle. + float & Chi2 () { return fChi2; } ///< Modifier of Chi2 of the fit. + Int_t & NDF () { return fNDF; } ///< Modifier of number of decrease of freedom. + + float & Parameter ( Int_t i ) { return fP[i]; } ///< Modifier of P[i] parameter. + float & Covariance( Int_t i ) { return fC[i]; } ///< Modifier of C[i] element of the covariance matrix in the lower triangular form. + float & Covariance( Int_t i, Int_t j ) { return fC[IJ(i,j)]; } ///< Modifier of C[i,j] element of the covariance matrix. + + + //* + //* CONSTRUCTION OF THE PARTICLE BY ITS DAUGHTERS AND MOTHER + //* USING THE KALMAN FILTER METHOD + //* + + + //* Simple way to add daughter ex. D0+= Pion; + + void operator +=( const KFParticleBase &Daughter ); + + //* Add daughter track to the particle + + void AddDaughter( const KFParticleBase &Daughter ); + void SubtractDaughter( const KFParticleBase &Daughter ); + + void AddDaughterWithEnergyFit( const KFParticleBase &Daughter ); + void AddDaughterWithEnergyFitMC( const KFParticleBase &Daughter ); + + //* Set production vertex + + void SetProductionVertex( const KFParticleBase &Vtx ); + + //* Set mass constraint + + void SetNonlinearMassConstraint( float Mass ); + void SetMassConstraint( float Mass, float SigmaMass = 0 ); + + //* Set no decay length for resonances + + void SetNoDecayLength(); + + + //* Everything in one go + + void Construct( const KFParticleBase *vDaughters[], Int_t nDaughters, const KFParticleBase *ProdVtx=0, float Mass=-1 ); + + //Transport functions + void TransportToDecayVertex(); + void TransportToProductionVertex(); + void TransportToDS( float dS, const float* dsdr ); + void TransportBz( float Bz, float dS, const float* dsdr, float P[], float C[], float* dsdr1=0, float* F=0, float* F1=0 ) const; + void TransportCBM( float dS, const float* dsdr, float P[], float C[], float* dsdr1=0, float* F=0, float* F1=0 ) const; + + //* + //* OTHER UTILITIES + //* + + //* Calculate distance from another object [cm] + + float GetDistanceFromVertex( const float vtx[] ) const; + float GetDistanceFromVertex( const KFParticleBase &Vtx ) const; + float GetDistanceFromParticle( const KFParticleBase &p ) const; + + //* Calculate sqrt(Chi2/ndf) deviation from vertex + //* v = [xyz], Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix + + float GetDeviationFromVertex( const float v[], const float Cv[]=0 ) const; + float GetDeviationFromVertex( const KFParticleBase &Vtx ) const; + float GetDeviationFromParticle( const KFParticleBase &p ) const; + + void SubtractFromVertex( KFParticleBase &Vtx ) const; + void SubtractFromParticle( KFParticleBase &Vtx ) const; + + static void GetArmenterosPodolanski(KFParticleBase& positive, KFParticleBase& negative, float QtAlfa[2] ); + void RotateXY(float angle, float Vtx[3]); + + int Id() const { return fId; } ///< Returns Id of the particle. + int NDaughters() const { return fDaughtersIds.size(); } ///< Returns number of daughter particles. + const std::vector<int>& DaughterIds() const { return fDaughtersIds; } ///< Returns the vector with the indices of daughter particles. + void CleanDaughtersId() { fDaughtersIds.clear(); } ///< Cleans the vector with the indices of daughter particles. + + void SetId( int id ) { fId = id; } ///< Sets the Id of the particle. After the construction of a particle should be set by user. + void AddDaughterId( int id ) { fDaughtersIds.push_back(id); } ///< Adds index of the daughter particle. + + void SetPDG ( int pdg ) { fPDG = pdg; } ///< Sets the PDG hypothesis. + int GetPDG () const { return fPDG; } ///< Returns the PDG hypothesis. + +#ifdef __ROOT__ //for the STAR experiment + virtual void Print(Option_t *opt="") const; + Int_t IdTruth() const { return fIdTruth;} + Int_t QaTruth() const { return fQuality; } + Int_t IdParentMcVx() const {return fIdParentMcVx;} + Int_t IdParentVx() const {return IdParentMcVx();} + void SetParentID(Int_t id=0) {fParentID = id;} + Int_t GetParentID() const {return fParentID;} + void SetIdParentMcVx(Int_t id) {fIdParentMcVx = id;} + void SetIdTruth(Int_t idtru,Int_t qatru=0) {fIdTruth = (UShort_t) idtru; fQuality = (UShort_t) qatru;} + virtual void Clear(Option_t * /*option*/ =""); +#endif + + static void InvertCholetsky3(float a[6]); + static void MultQSQt( const float Q[], const float S[], float SOut[], const int kN ); + + protected: + /** Converts a pair of indices {i,j} of the covariance matrix to one index corresponding to the triangular form. */ + static Int_t IJ( Int_t i, Int_t j ){ + return ( j<=i ) ? i*(i+1)/2+j :j*(j+1)/2+i; + } + /** Return an element of the covariance matrix with {i,j} indices. */ + float & Cij( Int_t i, Int_t j ){ return fC[IJ(i,j)]; } + void TransportLine( float S, const float* dsdr, float P[], float C[], float* dsdr1, float* F, float* F1 ) const ; + bool GetMeasurement( const KFParticleBase& daughter, float m[], float V[], float D[3][3] ) ; + void SetMassConstraint( float *mP, float *mC, float mJ[7][7], float mass ); + + float fP[8]; ///< Particle parameters { X, Y, Z, Px, Py, Pz, E, S[=DecayLength/P]}. + float fC[36]; ///< Low-triangle covariance matrix of fP. + float fChi2; ///< Chi^2. + float fSFromDecay; ///< Distance from the decay vertex to the current position. + float SumDaughterMass; ///< Sum of the daughter particles masses. Needed to set the constraint on the minimum mass during particle construction. + float fMassHypo; ///< The mass hypothesis, used for the constraints during particle construction. + Int_t fNDF; ///< Number of degrees of freedom. + int fId; ///< Id of the particle. +#ifdef __ROOT__ //for the STAR experiment + Short_t fParentID; ///< Id of the parent particle. + Short_t fIdTruth; ///< MC track id. + Short_t fQuality; ///< quality of this information (percentage of hits coming from the above MC track). + Short_t fIdParentMcVx; ///< for track and McTrack for vertex. +#endif + Bool_t fAtProductionVertex; ///< Flag shows if particle is at the production point. + char fQ; ///< The charge of the particle in the units of the elementary charge. + + /** \brief Determines the method for the particle construction. \n + ** 0 - Energy considered as an independent veriable, fitted independently from momentum, without any constraints on mass \n + ** 2 - Energy considered as an independent variable, fitted independently from momentum, with constraints on mass of daughter particle + **/ + char fConstructMethod; + int fPDG; ///< The PDG hypothesis assigned to the particle. + + /** \brief A vector with ids of the daughter particles: \n + ** 1) if particle is created from a track - the index of the track, in this case the size of the vector is always equal to one; \n + ** 2) if particle is constructed from other particles - indices of these particles in the same array. + **/ + std::vector<int> fDaughtersIds; + +#ifndef KFParticleStandalone + ClassDef( KFParticleBase, 2 ) +#endif +}; + +#ifdef __ROOT__ //for the STAR experiment +std::ostream& operator<<(std::ostream& os, KFParticleBase const & particle); +#endif + +#endif diff --git a/external/KFParticle/KFParticle/KFParticleBaseSIMD.cxx b/external/KFParticle/KFParticle/KFParticleBaseSIMD.cxx new file mode 100644 index 0000000000000000000000000000000000000000..87ee17e019283570e311bc59bf399c02b8af0101 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleBaseSIMD.cxx @@ -0,0 +1,4121 @@ +//--------------------------------------------------------------------------------- +// Implementation of the KFParticleBaseSIMD class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 13.05.07 +// +// Class to reconstruct and store the decayed particle parameters. +// The method is described in CBM-SOFT note 2007-003, +// ``Reconstruction of decayed particles based on the Kalman filter'', +// http://www.gsi.de/documents/DOC-2007-May-14-1.pdf +// +// This class describes general mathematics which is used by KFParticle class +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//_________________________________________________________________________________ + + +#include "KFParticleBaseSIMD.h" +#include <iostream> + +static const float_v small = 1.e-20f; + +KFParticleBaseSIMD::KFParticleBaseSIMD() :fQ(0), fNDF(-3), fChi2(0.f), fSFromDecay(0.f), + SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fAtProductionVertex(0), fPDG(0), fConstructMethod(0), fDaughterIds() +{ + /** The default constructor, initialises the parameters by: \n + ** 1) all parameters are set to 0; \n + ** 2) all elements of the covariance matrix are set to 0 except Cxx=Cyy=Czz=100; \n + ** 3) Q = 0; \n + ** 4) chi2 is set to 0; \n + ** 5) NDF = -3, since 3 parameters should be fitted: X, Y, Z. + **/ + Initialize(); +} + +void KFParticleBaseSIMD::Initialize( const float_v Param[], const float_v Cov[], int_v Charge, float_v Mass ) +{ + /** Sets the parameters of the particle: + ** \param[in] Param[6] = { X, Y, Z, Px, Py, Pz } - position and momentum + ** \param[in] Cov[21] - lower-triangular part of the covariance matrix:@n + ** \verbatim + ( 0 . . . . . ) + ( 1 2 . . . . ) + Cov[21] = ( 3 4 5 . . . ) + ( 6 7 8 9 . . ) + ( 10 11 12 13 14 . ) + ( 15 16 17 18 19 20 ) + \endverbatim + ** \param[in] Charge - charge of the particle in elementary charge units + ** \param[in] mass - the mass hypothesis + **/ + + for( Int_t i=0; i<6 ; i++ ) fP[i] = Param[i]; + for( Int_t i=0; i<21; i++ ) fC[i] = Cov[i]; + + float_v energy = sqrt( Mass*Mass + fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]); + fP[6] = energy; + fP[7] = 0; + fQ = Charge; + fNDF = 0; + fChi2 = 0; + fAtProductionVertex = 0; + fSFromDecay = 0; + + float_v energyInv = 1.f/energy; + float_v + h0 = fP[3]*energyInv, + h1 = fP[4]*energyInv, + h2 = fP[5]*energyInv; + + fC[21] = h0*fC[ 6] + h1*fC[10] + h2*fC[15]; + fC[22] = h0*fC[ 7] + h1*fC[11] + h2*fC[16]; + fC[23] = h0*fC[ 8] + h1*fC[12] + h2*fC[17]; + fC[24] = h0*fC[ 9] + h1*fC[13] + h2*fC[18]; + fC[25] = h0*fC[13] + h1*fC[14] + h2*fC[19]; + fC[26] = h0*fC[18] + h1*fC[19] + h2*fC[20]; + fC[27] = ( h0*h0*fC[ 9] + h1*h1*fC[14] + h2*h2*fC[20] + + 2*(h0*h1*fC[13] + h0*h2*fC[18] + h1*h2*fC[19] ) ); + for( Int_t i=28; i<36; i++ ) fC[i] = 0.f; + fC[35] = 1.f; + + SumDaughterMass = Mass; + fMassHypo = Mass; +} + +void KFParticleBaseSIMD::Initialize() +{ + /** Initialises the parameters by default: \n + ** 1) all parameters are set to 0; \n + ** 2) all elements of the covariance matrix are set to 0 except Cxx=Cyy=Czz=100; \n + ** 3) Q = 0; \n + ** 4) chi2 is set to 0; \n + ** 5) NDF = -3, since 3 parameters should be fitted: X, Y, Z. + **/ + + for( Int_t i=0; i<8; i++) fP[i] = 0.f; + for(Int_t i=0;i<36;++i) fC[i]=0.f; + fC[0] = fC[2] = fC[5] = 100.f; + fC[35] = 1.f; + fNDF = -3; + fChi2 = 0.f; + fQ = 0; + fSFromDecay = 0.f; + fAtProductionVertex = 0; + SumDaughterMass = 0.f; + fMassHypo = -1; +} + +float_m KFParticleBaseSIMD::GetMomentum( float_v &p, float_v &error ) const +{ + /** Calculates particle momentum and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** \param[out] p - momentum of the particle + ** \param[out] error - its error + **/ + + float_v x = fP[3]; + float_v y = fP[4]; + float_v z = fP[5]; + float_v x2 = x*x; + float_v y2 = y*y; + float_v z2 = z*z; + float_v p2 = x2+y2+z2; + p = sqrt(p2); + error = (x2*fC[9]+y2*fC[14]+z2*fC[20] + 2*(x*y*fC[13]+x*z*fC[18]+y*z*fC[19]) ); + const float_v LocalSmall = 1.e-4f; + float_m mask = (0.f < error) && (LocalSmall < abs(p)); + error(!mask) = 1.e20f; + error = sqrt(error); + return (!mask); +} + +float_m KFParticleBaseSIMD::GetPt( float_v &pt, float_v &error ) const +{ + /** Calculates particle transverse momentum and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** \param[out] pt - transverse momentum of the particle + ** \param[out] error - its error + **/ + + float_v px = fP[3]; + float_v py = fP[4]; + float_v px2 = px*px; + float_v py2 = py*py; + float_v pt2 = px2+py2; + pt = sqrt(pt2); + error = (px2*fC[9] + py2*fC[14] + 2*px*py*fC[13] ); + const float_v LocalSmall = 1.e-4f; + float_m mask = ( (0.f < error) && (LocalSmall < abs(pt))); + error(!mask) = 1.e20f; + error = sqrt(error); + return (!mask); +} + +float_m KFParticleBaseSIMD::GetEta( float_v &eta, float_v &error ) const +{ + /** Calculates particle pseudorapidity and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** \param[out] eta - pseudorapidity of the particle + ** \param[out] error - its error + **/ + + const float_v BIG = 1.e8f; + const float_v LocalSmall = 1.e-8f; + + float_v px = fP[3]; + float_v py = fP[4]; + float_v pz = fP[5]; + float_v pt2 = px*px + py*py; + float_v p2 = pt2 + pz*pz; + float_v p = sqrt(p2); + float_v a = p + pz; + float_v b = p - pz; + eta = BIG; + float_v c = 0.f; + c(b > LocalSmall) = (a/b); + float_v logc = 0.5f*KFPMath::Log(c); + eta(LocalSmall<abs(c)) = logc; + + float_v h3 = -px*pz; + float_v h4 = -py*pz; + float_v pt4 = pt2*pt2; + float_v p2pt4 = p2*pt4; + error = (h3*h3*fC[9] + h4*h4*fC[14] + pt4*fC[20] + 2*( h3*(h4*fC[13] + fC[18]*pt2) + pt2*h4*fC[19] ) ); + + float_m mask = ((LocalSmall < abs(p2pt4)) && (0.f < error)); + error(mask) = sqrt(error/p2pt4); + error(!mask) = BIG; + + return (!mask); +} + +float_m KFParticleBaseSIMD::GetPhi( float_v &phi, float_v &error ) const +{ + /** Calculates particle polar angle at the current point and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** \param[out] phi - polar angle of the particle + ** \param[out] error - its error + **/ + + float_v px = fP[3]; + float_v py = fP[4]; + float_v px2 = px*px; + float_v py2 = py*py; + float_v pt2 = px2 + py2; + phi = KFPMath::ATan2(py,px); + error = (py2*fC[9] + px2*fC[14] - float_v(2.f)*px*py*fC[13] ); + + float_m mask = (0.f < error) && (1.e-4f < pt2); + error(mask) = sqrt(error)/pt2; + error(!mask) = 1.e10f; + return !mask; +} + +float_m KFParticleBaseSIMD::GetR( float_v &r, float_v &error ) const +{ + /** Calculates the distance to the point {0,0,0} and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** \param[out] r - polar angle of the particle + ** \param[out] error - its error + **/ + + float_v x = fP[0]; + float_v y = fP[1]; + float_v x2 = x*x; + float_v y2 = y*y; + r = sqrt(x2 + y2); + error = (x2*fC[0] + y2*fC[2] - float_v(2.f)*x*y*fC[1] ); + + float_m mask = (0.f < error) && (1.e-4f < r); + error(mask) = sqrt(error)/r; + error(!mask ) = 1.e10f; + return !mask; +} + +float_m KFParticleBaseSIMD::GetMass( float_v &m, float_v &error ) const +{ + /** Calculates the mass of the particle and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** \param[out] m - mass of the particle + ** \param[out] error - its error + **/ + + const float_v BIG = 1.e8f; + const float_v LocalSmall = 1.e-8f; + + float_v s = ( fP[3]*fP[3]*fC[9] + fP[4]*fP[4]*fC[14] + fP[5]*fP[5]*fC[20] + + fP[6]*fP[6]*fC[27] + + float_v(2.f)*( + fP[3]*fP[4]*fC[13] + fP[5]*(fP[3]*fC[18] + fP[4]*fC[19]) + - fP[6]*( fP[3]*fC[24] + fP[4]*fC[25] + fP[5]*fC[26] ) ) + ); + + float_v m2 = (fP[6]*fP[6] - fP[3]*fP[3] - fP[4]*fP[4] - fP[5]*fP[5]); + + float_m mask = 0.f <= m2; + m(mask) = sqrt(m2); + m(!mask) = -sqrt(-m2); + + mask = (mask && (0.f <= s) && (LocalSmall < m)); + error(mask) = sqrt(s)/m; + error(!mask) = BIG; + + return !mask; +} + + +float_m KFParticleBaseSIMD::GetDecayLength( float_v &l, float_v &error ) const +{ + /** Calculates the decay length of the particle in the laboratory system and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] l - the decay length + ** \param[out] error - its error + **/ + + const float_v BIG = 1.e20f; + + float_v x = fP[3]; + float_v y = fP[4]; + float_v z = fP[5]; + float_v t = fP[7]; + float_v x2 = x*x; + float_v y2 = y*y; + float_v z2 = z*z; + float_v p2 = x2+y2+z2; + l = t*sqrt(p2); + + error = p2*fC[35] + t*t/p2*(x2*fC[9]+y2*fC[14]+z2*fC[20] + + float_v(2.f)*(x*y*fC[13]+x*z*fC[18]+y*z*fC[19]) ) + + float_v(2.f)*t*(x*fC[31]+y*fC[32]+z*fC[33]); + + float_m mask = ((1.e-4f) < p2); + error(mask) = sqrt(abs(error)); + error(!mask) = BIG; + return !mask; +} + +float_m KFParticleBaseSIMD::GetDecayLengthXY( float_v &l, float_v &error ) const +{ + /** Calculates the projection in the XY plane of the decay length of the particle in the laboratory + ** system and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] l - the decay length + ** \param[out] error - its error + **/ + + const float_v BIG = 1.e8f; + float_v x = fP[3]; + float_v y = fP[4]; + float_v t = fP[7]; + float_v x2 = x*x; + float_v y2 = y*y; + float_v pt2 = x2+y2; + l = t*sqrt(pt2); + + error = pt2*fC[35] + t*t/pt2*(x2*fC[9]+y2*fC[14] + 2*x*y*fC[13] ) + + float_v(2.f)*t*(x*fC[31]+y*fC[32]); + float_m mask = ((1.e-4f) < pt2); + error(mask) = sqrt(abs(error)); + error(!mask) = BIG; + return !mask; +} + + +float_m KFParticleBaseSIMD::GetLifeTime( float_v &tauC, float_v &error ) const +{ + /** Calculates the lifetime times speed of life (ctau) [cm] of the particle in the + ** center of mass frame and its error. If they are well defined the corresponding element of the + ** return mask is set to 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] ctau - lifetime of the particle [cm] + ** \param[out] error - its error + **/ + + const float_v BIG = 1.e20f; + + float_v m, dm; + GetMass( m, dm ); + float_v cTM = (-fP[3]*fC[31] - fP[4]*fC[32] - fP[5]*fC[33] + fP[6]*fC[34]); + tauC = fP[7]*m; + error = m*m*fC[35] + 2*fP[7]*cTM + fP[7]*fP[7]*dm*dm; + float_m mask = (0.f < error); + error(mask) = sqrt(error); + error(!mask) = BIG; + return !mask; +} + + +void KFParticleBaseSIMD::operator +=( const KFParticleBaseSIMD &Daughter ) +{ + /** Operator to add daughter to the current particle. Calls AddDaughter() function. + ** \param[in] Daughter - the daughter particle + **/ + + AddDaughter( Daughter ); +} + +void KFParticleBaseSIMD::GetMeasurement( const KFParticleBaseSIMD& daughter, float_v m[], float_v V[], float_v D[3][3] ) +{ + /** Obtains the measurements from the current particle and the daughter to be added for the Kalman filter + ** mathematics. If these are two first daughters they are transported to the point of the closest approach, + ** if the third or higher daughter is added it is transported to the DCA point of the already constructed + ** vertex. The correlations are taken into account in the covariance matrices of both measurements, + ** the correlation matrix of two measurements is also calculated. Parameters of the current particle are + ** modified by this function, the daughter is not changed, its parameters are stored to the output arrays + ** after modifications. + ** \param[in] daughter - the daughter particle to be added, stays unchanged + ** \param[out] m[8] - the output parameters of the daughter particle at the DCA point + ** \param[out] V[36] - the output covariance matrix of the daughter parameters, takes into account the correlation + ** \param[out] D[3][3] - the correlation matrix between the current and daughter particles + **/ + + if(fNDF[0] == -1) + { + float_v ds[2] = {0.f,0.f}; + float_v dsdr[4][6]; + float_v F1[36], F2[36], F3[36], F4[36]; + for(int i1=0; i1<36; i1++) + { + F1[i1] = 0; + F2[i1] = 0; + F3[i1] = 0; + F4[i1] = 0; + } + GetDStoParticle( daughter, ds, dsdr ); + + float_v V0Tmp[36] ; + float_v V1Tmp[36] ; + + float_v C[36]; + for(int iC=0; iC<36; iC++) + C[iC] = fC[iC]; + + Transport(ds[0], dsdr[0], fP, fC, dsdr[1], F1, F2); + daughter.Transport(ds[1], dsdr[3], m, V, dsdr[2], F4, F3); + + MultQSQt(F2, daughter.fC, V0Tmp, 6); + MultQSQt(F3, C, V1Tmp, 6); + + for(int iC=0; iC<21; iC++) + { + fC[iC] += V0Tmp[iC]; + V[iC] += V1Tmp[iC]; + } + + float_v C1F1T[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + C1F1T[i][j] = 0; + for(int k=0; k<6; k++) + { + C1F1T[i][j] += C[IJ(i,k)] * F1[j*6+k]; + } + } + float_v F3C1F1T[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + F3C1F1T[i][j] = 0; + for(int k=0; k<6; k++) + { + F3C1F1T[i][j] += F3[i*6+k] * C1F1T[k][j]; + } + } + float_v C2F2T[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + C2F2T[i][j] = 0; + for(int k=0; k<6; k++) + { + C2F2T[i][j] += daughter.fC[IJ(i,k)] * F2[j*6+k]; + } + } + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + D[i][j] = F3C1F1T[i][j]; + for(int k=0; k<6; k++) + { + D[i][j] += F4[i*6+k] * C2F2T[k][j]; + } + } + } + else + { + float_v dsdr[6]; + float_v dS = daughter.GetDStoPoint(fP, dsdr); + + float_v dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f}; + + float_v F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0; + F1[i2] = 0; + } + daughter.Transport(dS, dsdr, m, V, dsdp, F, F1); + +// float_v V1Tmp[36] = {0.}; +// MultQSQt(F1, fC, V1Tmp, 6); + +// for(int iC=0; iC<21; iC++) +// V[iC] += V1Tmp[iC]; + + float_v VFT[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<6; j++) + { + VFT[i][j] = 0; + for(int k=0; k<3; k++) + { + VFT[i][j] += fC[IJ(i,k)] * F1[j*6+k]; + } + } + + float_v FVFT[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + FVFT[i][j] = 0; + for(int k=0; k<3; k++) + { + FVFT[i][j] += F1[i*6+k] * VFT[k][j]; + } + } + + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + D[i][j] = 0; + for(int k=0; k<3; k++) + { + D[i][j] += fC[IJ(j,k)] * F1[i*6+k]; + } + } + + V[0] += FVFT[0][0]; + V[1] += FVFT[1][0]; + V[2] += FVFT[1][1]; + V[3] += FVFT[2][0]; + V[4] += FVFT[2][1]; + V[5] += FVFT[2][2]; + } +} + +void KFParticleBaseSIMD::AddDaughter( const KFParticleBaseSIMD &Daughter ) +{ + /** Adds daughter to the current particle. Depending on the selected construction method uses: \n + ** 1) Either simplifyed fast mathematics which consideres momentum and energy as + ** independent variables and thus ignores constraint on the fixed mass (fConstructMethod = 0). + ** In this case the mass of the daughter particle can be corrupted when the constructed vertex + ** is added as the measurement and the mass of the output short-lived particle can become + ** unphysical - smaller then the threshold. Implemented in the + ** AddDaughterWithEnergyFit() function \n + ** 2) Or slower but correct mathematics which requires that the masses of daughter particles + ** stays fixed in the construction process (fConstructMethod = 2). Implemented in the + ** AddDaughterWithEnergyFitMC() function. + ** \param[in] Daughter - the daughter particle + **/ + + AddDaughterId( Daughter.Id() ); + + if( int(fNDF[0])<-1 ){ // first daughter -> just copy + fNDF = -1; + fQ = Daughter.GetQ(); + for( Int_t i=0; i<7; i++ ) fP[i] = Daughter.fP[i]; + for( Int_t i=0; i<28; i++ ) fC[i] = Daughter.fC[i]; + fSFromDecay = 0; + fMassHypo = Daughter.fMassHypo; + SumDaughterMass = Daughter.SumDaughterMass; + return; + } + + if(fConstructMethod == 0) + AddDaughterWithEnergyFit(Daughter); + else if(fConstructMethod == 2) + AddDaughterWithEnergyFitMC(Daughter); + + SumDaughterMass += Daughter.SumDaughterMass; + fMassHypo = -1.f; +} + +void KFParticleBaseSIMD::AddDaughterWithEnergyFit( const KFParticleBaseSIMD &Daughter ) +{ + /** Adds daughter to the current particle. Uses simplifyed fast mathematics which consideres momentum + ** and energy as independent variables and thus ignores constraint on the fixed mass. + ** In this case the mass of the daughter particle can be corrupted when the constructed vertex + ** is added as the measurement and the mass of the output short-lived particle can become + ** unphysical - smaller then the threshold. + ** \param[in] Daughter - the daughter particle + **/ + + Int_t maxIter = 1; + + for( Int_t iter=0; iter<maxIter; iter++ ){ + + float_v m[8], mV[36]; + + float_v D[3][3]; + GetMeasurement(Daughter, m, mV, D); + + float_v mS[6]= { fC[0]+mV[0], + fC[1]+mV[1], fC[2]+mV[2], + fC[3]+mV[3], fC[4]+mV[4], fC[5]+mV[5] }; + InvertCholetsky3(mS); + //* Residual (measured - estimated) + + float_v zeta[3] = { m[0]-fP[0], m[1]-fP[1], m[2]-fP[2] }; + + float_v K[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + K[i][j] = 0; + for(int k=0; k<3; k++) + K[i][j] += fC[IJ(i,k)] * mS[IJ(k,j)]; + } + + //* CHt = CH' - D' + float_v mCHt0[7], mCHt1[7], mCHt2[7]; + + mCHt0[0]=fC[ 0] ; mCHt1[0]=fC[ 1] ; mCHt2[0]=fC[ 3] ; + mCHt0[1]=fC[ 1] ; mCHt1[1]=fC[ 2] ; mCHt2[1]=fC[ 4] ; + mCHt0[2]=fC[ 3] ; mCHt1[2]=fC[ 4] ; mCHt2[2]=fC[ 5] ; + mCHt0[3]=fC[ 6]-mV[ 6]; mCHt1[3]=fC[ 7]-mV[ 7]; mCHt2[3]=fC[ 8]-mV[ 8]; + mCHt0[4]=fC[10]-mV[10]; mCHt1[4]=fC[11]-mV[11]; mCHt2[4]=fC[12]-mV[12]; + mCHt0[5]=fC[15]-mV[15]; mCHt1[5]=fC[16]-mV[16]; mCHt2[5]=fC[17]-mV[17]; + mCHt0[6]=fC[21]-mV[21]; mCHt1[6]=fC[22]-mV[22]; mCHt2[6]=fC[23]-mV[23]; + + //* Kalman gain K = mCH'*S + + float_v k0[7], k1[7], k2[7]; + + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + //* Add the daughter momentum to the particle momentum + + fP[ 3] += m[ 3]; + fP[ 4] += m[ 4]; + fP[ 5] += m[ 5]; + fP[ 6] += m[ 6]; + + fC[ 9] += mV[ 9]; + fC[13] += mV[13]; + fC[14] += mV[14]; + fC[18] += mV[18]; + fC[19] += mV[19]; + fC[20] += mV[20]; + fC[24] += mV[24]; + fC[25] += mV[25]; + fC[26] += mV[26]; + fC[27] += mV[27]; + + + //* New estimation of the vertex position r += K*zeta + + for(Int_t i=0;i<7;++i) + fP[i] = fP[i] + k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + //* New covariance matrix C -= K*(mCH')' + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + fC[k] = fC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + float_v K2[3][3]; + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + K2[i][j] = -K[j][i]; + K2[i][i] += 1; + } + + float_v A[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + A[i][j] = 0; + for(int k=0; k<3; k++) + { + A[i][j] += D[i][k] * K2[k][j]; + } + } + + float_v M[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + M[i][j] = 0; + for(int k=0; k<3; k++) + { + M[i][j] += K[i][k] * A[k][j]; + } + } + + fC[0] += 2.f*M[0][0]; + fC[1] += M[0][1] + M[1][0]; + fC[2] += 2.f*M[1][1]; + fC[3] += M[0][2] + M[2][0]; + fC[4] += M[1][2] + M[2][1]; + fC[5] += 2.f*M[2][2]; + + //* Calculate Chi^2 + + fNDF += 2; + fQ += Daughter.GetQ(); + fSFromDecay = 0; + fChi2 += (mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]; + } +} + +void KFParticleBaseSIMD::AddDaughterWithEnergyFitMC( const KFParticleBaseSIMD &Daughter ) +{ + /** Adds daughter to the current particle. Uses slower but correct mathematics + ** which requires that the masses of daughter particles + ** stays fixed in the construction process. + ** \param[in] Daughter - the daughter particle + **/ + + Int_t maxIter = 1; + + for( Int_t iter=0; iter<maxIter; iter++ ){ + + float_v m[8], mV[36]; + + float_v D[3][3]; + GetMeasurement(Daughter, m, mV, D); + + float_v mS[6]= { fC[0]+mV[0], + fC[1]+mV[1], fC[2]+mV[2], + fC[3]+mV[3], fC[4]+mV[4], fC[5]+mV[5] }; + InvertCholetsky3(mS); + //* Residual (measured - estimated) + + float_v zeta[3] = { m[0]-fP[0], m[1]-fP[1], m[2]-fP[2] }; + + float_v K[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + K[i][j] = 0; + for(int k=0; k<3; k++) + K[i][j] += fC[IJ(i,k)] * mS[IJ(k,j)]; + } + + + //* CHt = CH' + + float_v mCHt0[7], mCHt1[7], mCHt2[7]; + + mCHt0[0]=fC[ 0] ; mCHt1[0]=fC[ 1] ; mCHt2[0]=fC[ 3] ; + mCHt0[1]=fC[ 1] ; mCHt1[1]=fC[ 2] ; mCHt2[1]=fC[ 4] ; + mCHt0[2]=fC[ 3] ; mCHt1[2]=fC[ 4] ; mCHt2[2]=fC[ 5] ; + mCHt0[3]=fC[ 6] ; mCHt1[3]=fC[ 7] ; mCHt2[3]=fC[ 8] ; + mCHt0[4]=fC[10] ; mCHt1[4]=fC[11] ; mCHt2[4]=fC[12] ; + mCHt0[5]=fC[15] ; mCHt1[5]=fC[16] ; mCHt2[5]=fC[17] ; + mCHt0[6]=fC[21] ; mCHt1[6]=fC[22] ; mCHt2[6]=fC[23] ; + + //* Kalman gain K = mCH'*S + + float_v k0[7], k1[7], k2[7]; + + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + // last itearation -> update the particle + + //* VHt = VH' + + float_v mVHt0[7], mVHt1[7], mVHt2[7]; + + mVHt0[0]=mV[ 0] ; mVHt1[0]=mV[ 1] ; mVHt2[0]=mV[ 3] ; + mVHt0[1]=mV[ 1] ; mVHt1[1]=mV[ 2] ; mVHt2[1]=mV[ 4] ; + mVHt0[2]=mV[ 3] ; mVHt1[2]=mV[ 4] ; mVHt2[2]=mV[ 5] ; + mVHt0[3]=mV[ 6] ; mVHt1[3]=mV[ 7] ; mVHt2[3]=mV[ 8] ; + mVHt0[4]=mV[10] ; mVHt1[4]=mV[11] ; mVHt2[4]=mV[12] ; + mVHt0[5]=mV[15] ; mVHt1[5]=mV[16] ; mVHt2[5]=mV[17] ; + mVHt0[6]=mV[21] ; mVHt1[6]=mV[22] ; mVHt2[6]=mV[23] ; + + //* Kalman gain Km = mCH'*S + + float_v km0[7], km1[7], km2[7]; + + for(Int_t i=0;i<7;++i){ + km0[i] = mVHt0[i]*mS[0] + mVHt1[i]*mS[1] + mVHt2[i]*mS[3]; + km1[i] = mVHt0[i]*mS[1] + mVHt1[i]*mS[2] + mVHt2[i]*mS[4]; + km2[i] = mVHt0[i]*mS[3] + mVHt1[i]*mS[4] + mVHt2[i]*mS[5]; + } + + for(Int_t i=0;i<7;++i) + fP[i] = fP[i] + k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + for(Int_t i=0;i<7;++i) + m[i] = m[i] - km0[i]*zeta[0] - km1[i]*zeta[1] - km2[i]*zeta[2]; + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + fC[k] = fC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + mV[k] = mV[k] - (km0[i]*mVHt0[j] + km1[i]*mVHt1[j] + km2[i]*mVHt2[j] ); + } + } + + float_v mDf[7][7]; + + for(Int_t i=0;i<7;++i){ + for(Int_t j=0;j<7;++j){ + mDf[i][j] = (km0[i]*mCHt0[j] + km1[i]*mCHt1[j] + km2[i]*mCHt2[j] ); + } + } + + float_v mJ1[7][7], mJ2[7][7]; + for(Int_t iPar1=0; iPar1<7; iPar1++) + { + for(Int_t iPar2=0; iPar2<7; iPar2++) + { + mJ1[iPar1][iPar2] = 0; + mJ2[iPar1][iPar2] = 0; + } + } + + float_v mMassParticle = fP[6]*fP[6] - (fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]); + float_v mMassDaughter = m[6]*m[6] - (m[3]*m[3] + m[4]*m[4] + m[5]*m[5]); + mMassParticle(mMassParticle > 0.f) = sqrt(mMassParticle); + mMassParticle(mMassParticle <= 0.f) = 0.f; + mMassDaughter(mMassDaughter > 0.f) = sqrt(mMassDaughter); + mMassDaughter(mMassDaughter <= 0.f) = 0.f; + + float_m mask1 = fMassHypo > -0.5f; + float_m mask2 = (!mask1) && ( (mMassParticle < SumDaughterMass) || (fP[6]<0.f)) ; + SetMassConstraint(fP,fC,mJ1,fMassHypo, mask1); + SetMassConstraint(fP,fC,mJ1,SumDaughterMass, mask2); + + float_m mask3 = Daughter.fMassHypo > -0.5f; + float_m mask4 = ( (!mask3) && ( (mMassDaughter<Daughter.SumDaughterMass) || (m[6]<0.f)) ); + SetMassConstraint(m,mV,mJ2,Daughter.fMassHypo, mask3); + SetMassConstraint(m,mV,mJ2,Daughter.SumDaughterMass, mask4); + + float_v mDJ[7][7]; + + for(Int_t i=0; i<7; i++) { + for(Int_t j=0; j<7; j++) { + mDJ[i][j] = 0; + for(Int_t k=0; k<7; k++) { + mDJ[i][j] += mDf[i][k]*mJ1[j][k]; + } + } + } + + for(Int_t i=0; i<7; ++i){ + for(Int_t j=0; j<7; ++j){ + mDf[i][j]=0; + for(Int_t l=0; l<7; l++){ + mDf[i][j] += mJ2[i][l]*mDJ[l][j]; + } + } + } + + //* Add the daughter momentum to the particle momentum + + fP[ 3] += m[ 3]; + fP[ 4] += m[ 4]; + fP[ 5] += m[ 5]; + fP[ 6] += m[ 6]; + + fC[ 9] += mV[ 9]; + fC[13] += mV[13]; + fC[14] += mV[14]; + fC[18] += mV[18]; + fC[19] += mV[19]; + fC[20] += mV[20]; + fC[24] += mV[24]; + fC[25] += mV[25]; + fC[26] += mV[26]; + fC[27] += mV[27]; + + fC[6 ] += mDf[3][0]; fC[7 ] += mDf[3][1]; fC[8 ] += mDf[3][2]; + fC[10] += mDf[4][0]; fC[11] += mDf[4][1]; fC[12] += mDf[4][2]; + fC[15] += mDf[5][0]; fC[16] += mDf[5][1]; fC[17] += mDf[5][2]; + fC[21] += mDf[6][0]; fC[22] += mDf[6][1]; fC[23] += mDf[6][2]; + + fC[9 ] += mDf[3][3] + mDf[3][3]; + fC[13] += mDf[4][3] + mDf[3][4]; fC[14] += mDf[4][4] + mDf[4][4]; + fC[18] += mDf[5][3] + mDf[3][5]; fC[19] += mDf[5][4] + mDf[4][5]; fC[20] += mDf[5][5] + mDf[5][5]; + fC[24] += mDf[6][3] + mDf[3][6]; fC[25] += mDf[6][4] + mDf[4][6]; fC[26] += mDf[6][5] + mDf[5][6]; fC[27] += mDf[6][6] + mDf[6][6]; + + + float_v K2[3][3]; + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + K2[i][j] = -K[j][i]; + K2[i][i] += 1; + } + + float_v A[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + A[i][j] = 0.f; + for(int k=0; k<3; k++) + { + A[i][j] += D[i][k] * K2[k][j]; + } + } + + float_v M[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + M[i][j] = 0.f; + for(int k=0; k<3; k++) + { + M[i][j] += K[i][k] * A[k][j]; + } + } + + fC[0] += 2*M[0][0]; + fC[1] += M[0][1] + M[1][0]; + fC[2] += 2*M[1][1]; + fC[3] += M[0][2] + M[2][0]; + fC[4] += M[1][2] + M[2][1]; + fC[5] += 2*M[2][2]; + + //* Calculate Chi^2 + + fNDF += 2; + fQ += Daughter.GetQ(); + fSFromDecay = 0; + fChi2 += (mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]; + } +} + +void KFParticleBaseSIMD::SubtractDaughter( const KFParticleBaseSIMD &Daughter ) +{ + /** Subtracts a daughter particle from the mother particle. The mathematics is + ** similar to AddDaughterWithEnergyFit() but momentum is subtracted. + ** \param[in] Daughter - the daughter particle + **/ + + AddDaughterId( Daughter.Id() ); + + float_v m[8], mV[36]; + + float_v D[3][3]; + GetMeasurement(Daughter, m, mV, D); + + float_v mS[6]= { fC[0]+mV[0], + fC[1]+mV[1], fC[2]+mV[2], + fC[3]+mV[3], fC[4]+mV[4], fC[5]+mV[5] }; + InvertCholetsky3(mS); + //* Residual (measured - estimated) + + float_v zeta[3] = { m[0]-fP[0], m[1]-fP[1], m[2]-fP[2] }; + + float_v K[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + K[i][j] = 0; + for(int k=0; k<3; k++) + K[i][j] += fC[IJ(i,k)] * mS[IJ(k,j)]; + } + + //* CHt = CH' - D' + float_v mCHt0[7], mCHt1[7], mCHt2[7]; + + mCHt0[0]=fC[ 0] ; mCHt1[0]=fC[ 1] ; mCHt2[0]=fC[ 3] ; + mCHt0[1]=fC[ 1] ; mCHt1[1]=fC[ 2] ; mCHt2[1]=fC[ 4] ; + mCHt0[2]=fC[ 3] ; mCHt1[2]=fC[ 4] ; mCHt2[2]=fC[ 5] ; + mCHt0[3]=fC[ 6]+mV[ 6]; mCHt1[3]=fC[ 7]+mV[ 7]; mCHt2[3]=fC[ 8]+mV[ 8]; + mCHt0[4]=fC[10]+mV[10]; mCHt1[4]=fC[11]+mV[11]; mCHt2[4]=fC[12]+mV[12]; + mCHt0[5]=fC[15]+mV[15]; mCHt1[5]=fC[16]+mV[16]; mCHt2[5]=fC[17]+mV[17]; + mCHt0[6]=fC[21]+mV[21]; mCHt1[6]=fC[22]+mV[22]; mCHt2[6]=fC[23]+mV[23]; + + //* Kalman gain K = mCH'*S + + float_v k0[7], k1[7], k2[7]; + + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + //* Add the daughter momentum to the particle momentum + + fP[ 3] -= m[ 3]; + fP[ 4] -= m[ 4]; + fP[ 5] -= m[ 5]; + fP[ 6] -= m[ 6]; + + fC[ 9] += mV[ 9]; + fC[13] += mV[13]; + fC[14] += mV[14]; + fC[18] += mV[18]; + fC[19] += mV[19]; + fC[20] += mV[20]; + fC[24] += mV[24]; + fC[25] += mV[25]; + fC[26] += mV[26]; + fC[27] += mV[27]; + + + //* New estimation of the vertex position r += K*zeta + + for(Int_t i=0;i<7;++i) + fP[i] = fP[i] + k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + //* New covariance matrix C -= K*(mCH')' + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + fC[k] = fC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + float_v K2[3][3]; + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + K2[i][j] = -K[j][i]; + K2[i][i] += 1; + } + + float_v A[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + A[i][j] = 0; + for(int k=0; k<3; k++) + { + A[i][j] += D[i][k] * K2[k][j]; + } + } + + float_v M[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + M[i][j] = 0; + for(int k=0; k<3; k++) + { + M[i][j] += K[i][k] * A[k][j]; + } + } + + fC[0] += 2.f*M[0][0]; + fC[1] += M[0][1] + M[1][0]; + fC[2] += 2.f*M[1][1]; + fC[3] += M[0][2] + M[2][0]; + fC[4] += M[1][2] + M[2][1]; + fC[5] += 2.f*M[2][2]; + + //* Calculate Chi^2 + + fNDF += 2; + fQ -= Daughter.GetQ(); + fSFromDecay = 0; + fChi2 += (mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]; +} + +void KFParticleBaseSIMD::SetProductionVertex( const KFParticleBaseSIMD &Vtx ) +{ + /** Adds a vertex as a point-like measurement to the current particle. + ** The eights parameter of the state vector is filled with the decay + ** length to the momentum ratio (s = l/p). The corresponding covariances + ** are calculated as well. The parameters of the particle are stored + ** at the position of the production vertex. + ** \param[in] Vtx - the assumed producation vertex + **/ + + const float_v *m = Vtx.fP, *mV = Vtx.fC; + + float_v decayPoint[3] = {fP[0], fP[1], fP[2]}; + float_v decayPointCov[6] = { fC[0], fC[1], fC[2], fC[3], fC[4], fC[5] }; + + float_v D[6][6]; + for(int iD1=0; iD1<6; iD1++) + for(int iD2=0; iD2<6; iD2++) + D[iD1][iD2] = 0.f; + + Bool_t noS = ( fC[35][0]<=0.f ); // no decay length allowed + + if( noS ){ + TransportToDecayVertex(); + fP[7] = 0.f; + fC[28] = fC[29] = fC[30] = fC[31] = fC[32] = fC[33] = fC[34] = fC[35] = 0.f; + } + else + { + float_v dsdr[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + float_v dS = GetDStoPoint(Vtx.fP, dsdr); + + float_v dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f }; + + float_v F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0.f; + F1[i2] = 0.f; + } + Transport( dS, dsdr, fP, fC, dsdp, F, F1 ); + + float_v CTmp[36]; + MultQSQt(F1, mV, CTmp, 6); + + for(int iC=0; iC<21; iC++) + fC[iC] += CTmp[iC]; + + for(int i=0; i<6; i++) + for(int j=0; j<3; j++) + { + D[i][j] = 0; + for(int k=0; k<3; k++) + { + D[i][j] += mV[IJ(j,k)] * F1[i*6+k]; + } + } + } + + float_v mS[6] = { fC[0] + mV[0], + fC[1] + mV[1], fC[2] + mV[2], + fC[3] + mV[3], fC[4] + mV[4], fC[5] + mV[5] }; + InvertCholetsky3(mS); + + float_v res[3] = { m[0] - X(), m[1] - Y(), m[2] - Z() }; + + float_v K[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + K[i][j] = 0; + for(int k=0; k<3; k++) + K[i][j] += fC[IJ(i,k)] * mS[IJ(k,j)]; + } + + float_v mCHt0[7], mCHt1[7], mCHt2[7]; + mCHt0[0]=fC[ 0]; mCHt1[0]=fC[ 1]; mCHt2[0]=fC[ 3]; + mCHt0[1]=fC[ 1]; mCHt1[1]=fC[ 2]; mCHt2[1]=fC[ 4]; + mCHt0[2]=fC[ 3]; mCHt1[2]=fC[ 4]; mCHt2[2]=fC[ 5]; + mCHt0[3]=fC[ 6]; mCHt1[3]=fC[ 7]; mCHt2[3]=fC[ 8]; + mCHt0[4]=fC[10]; mCHt1[4]=fC[11]; mCHt2[4]=fC[12]; + mCHt0[5]=fC[15]; mCHt1[5]=fC[16]; mCHt2[5]=fC[17]; + mCHt0[6]=fC[21]; mCHt1[6]=fC[22]; mCHt2[6]=fC[23]; + + float_v k0[7], k1[7], k2[7]; + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + for(Int_t i=0;i<7;++i) + fP[i] = fP[i] + k0[i]*res[0] + k1[i]*res[1] + k2[i]*res[2]; + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + fC[k] = fC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + float_v K2[3][3]; + for(int i=0; i<3; i++) + { + for(int j=0; j<3; j++) + K2[i][j] = -K[j][i]; + K2[i][i] += 1; + } + + float_v A[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + A[i][j] = 0; + for(int k=0; k<3; k++) + { + A[i][j] += D[k][i] * K2[k][j]; + } + } + + float_v M[3][3]; + for(int i=0; i<3; i++) + for(int j=0; j<3; j++) + { + M[i][j] = 0; + for(int k=0; k<3; k++) + { + M[i][j] += K[i][k] * A[k][j]; + } + } + + fC[0] += 2*M[0][0]; + fC[1] += M[0][1] + M[1][0]; + fC[2] += 2*M[1][1]; + fC[3] += M[0][2] + M[2][0]; + fC[4] += M[1][2] + M[2][1]; + fC[5] += 2*M[2][2]; + + fChi2 += (mS[0]*res[0] + mS[1]*res[1] + mS[3]*res[2])*res[0] + + (mS[1]*res[0] + mS[2]*res[1] + mS[4]*res[2])*res[1] + + (mS[3]*res[0] + mS[4]*res[1] + mS[5]*res[2])*res[2]; + fNDF += 2; + + if( noS ){ + fP[7] = 0; + fC[28] = fC[29] = fC[30] = fC[31] = fC[32] = fC[33] = fC[34] = fC[35] = 0.f; + fSFromDecay = 0; + } + else + { + float_v dsdr[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + fP[7] = GetDStoPoint(decayPoint, dsdr); + + float_v dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f}; + + float_v F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0.f; + F1[i2] = 0.f; + } + float_v tmpP[8], tmpC[36]; + Transport( fP[7], dsdr, tmpP, tmpC, dsdp, F, F1 ); + + fC[35] = 0.f; + for(int iDsDr=0; iDsDr<6; iDsDr++) + { + float_v dsdrC = 0.f, dsdpV = 0.f; + + for(int k=0; k<6; k++) + dsdrC += dsdr[k] * fC[IJ(k,iDsDr)]; // (-dsdr[k])*fC[k,j] + + fC[iDsDr+28] = dsdrC; + fC[35] += dsdrC*dsdr[iDsDr] ; + if(iDsDr < 3) + { + for(int k=0; k<3; k++) + dsdpV -= dsdr[k] * decayPointCov[IJ(k,iDsDr)]; // + fC[35] -= dsdpV*dsdr[iDsDr]; + } + } + fSFromDecay = -fP[7]; + } + + fAtProductionVertex = 1; +} + +void KFParticleBaseSIMD::SetMassConstraint( float_v *mP, float_v *mC, float_v mJ[7][7], float_v mass, float_m mask ) +{ + /** Sets the exact nonlinear mass constraint on the state vector mP with the covariance matrix mC. + ** \param[in,out] mP - the state vector to be modified + ** \param[in,out] mC - the corresponding covariance matrix + ** \param[in,out] mJ - the Jacobian between initial and modified parameters + ** \param[in] mass - the mass to be set on the state vector mP + ** \param[in] mask - mask defines entries of the SIMD vector, for which the constraint should be applied + **/ + + const float_v energy2 = mP[6]*mP[6], p2 = mP[3]*mP[3]+mP[4]*mP[4]+mP[5]*mP[5], mass2 = mass*mass; + + const float_v a = energy2 - p2 + 2.f*mass2; + const float_v b = -2.f*(energy2 + p2); + const float_v c = energy2 - p2 - mass2; + + float_v lambda(Vc::Zero); + lambda(abs(b) > float_v(1.e-10f)) = -c/b ; + + float_v d = 4.f*energy2*p2 - mass2*(energy2-p2-2.f*mass2); + float_m qMask = (d >= 0.f) && (abs(a) > (1.e-10f)) ; + lambda(qMask) = (energy2 + p2 - sqrt(d))/a; + + lambda(mP[6]<0.f) = -1000000.f; + + Int_t iIter=0; + for(iIter=0; iIter<100; iIter++) + { + float_v lambda2 = lambda*lambda; + float_v lambda4 = lambda2*lambda2; + +// float_v lambda0 = lambda; + + float_v f = -mass2 * lambda4 + a*lambda2 + b*lambda + c; + float_v df = -4.f*mass2 * lambda2*lambda + 2.f*a*lambda + b; + lambda(abs(df) > float_v(1.e-10f)) -= f/df; +// if(TMath::Abs(lambda0 - lambda) < 1.e-8) break; + } + + const float_v lpi = 1.f/(1.f + lambda); + const float_v lmi = 1.f/(1.f - lambda); + const float_v lp2i = lpi*lpi; + const float_v lm2i = lmi*lmi; + + float_v lambda2 = lambda*lambda; + + float_v dfl = -4.f*mass2 * lambda2*lambda + 2.f*a*lambda + b; + float_v dfx[4] = {0.f,0.f,0.f,0.f}; + dfx[0] = -2.f*(1.f + lambda)*(1.f + lambda)*mP[3]; + dfx[1] = -2.f*(1.f + lambda)*(1.f + lambda)*mP[4]; + dfx[2] = -2.f*(1.f + lambda)*(1.f + lambda)*mP[5]; + dfx[3] = 2.f*(1.f - lambda)*(1.f - lambda)*mP[6]; + float_v dlx[4] = {1.f,1.f,1.f,1.f}; + + for(int i=0; i<4; i++) + dlx[i](abs(dfl) > float_v(1.e-10f)) = -dfx[i] / dfl; + + float_v dxx[4] = {mP[3]*lm2i, mP[4]*lm2i, mP[5]*lm2i, -mP[6]*lp2i}; + + for(Int_t i=0; i<7; i++) + for(Int_t j=0; j<7; j++) + mJ[i][j]=0; + mJ[0][0] = 1.; + mJ[1][1] = 1.; + mJ[2][2] = 1.; + + for(Int_t i=3; i<7; i++) + for(Int_t j=3; j<7; j++) + mJ[i][j] = dlx[j-3]*dxx[i-3]; + + for(Int_t i=3; i<6; i++) + mJ[i][i] += lmi; + mJ[6][6] += lpi; + + float_v mCJ[7][7]; + + for(Int_t i=0; i<7; i++) { + for(Int_t j=0; j<7; j++) { + mCJ[i][j] = 0; + for(Int_t k=0; k<7; k++) { + mCJ[i][j] += mC[IJ(i,k)]*mJ[j][k]; + } + } + } + + for(Int_t i=0; i<7; ++i){ + for(Int_t j=0; j<=i; ++j){ + mC[IJ(i,j)](mask) = 0.f; + for(Int_t l=0; l<7; l++){ + mC[IJ(i,j)](mask) += mJ[i][l]*mCJ[l][j]; + } + } + } + + mP[3](mask) *= lmi; + mP[4](mask) *= lmi; + mP[5](mask) *= lmi; + mP[6](mask) *= lpi; +} + +void KFParticleBaseSIMD::SetNonlinearMassConstraint( float_v mass ) +{ + /** Sets the exact nonlinear mass constraint on the current particle. + ** \param[in] mass - the mass to be set on the particle + **/ + + const float_v& px = fP[3]; + const float_v& py = fP[4]; + const float_v& pz = fP[5]; + const float_v& energy = fP[6]; + + const float_v residual = (energy*energy - px*px - py*py - pz*pz) - mass*mass; + const float_v dm2 = float_v(4.f) * ( fC[9]*px*px + fC[14]*py*py + fC[20]*pz*pz + fC[27]*energy*energy + + float_v(2.f) * ( (fC[13]*py + fC[18]*pz - fC[24]*energy)*px + (fC[19]*pz - fC[25]*energy)*py - fC[26]*pz*energy) ); + const float_v dChi2 = residual*residual / dm2; + fChi2 += dChi2; + fNDF += 1; + + float_v mJ[7][7]; + SetMassConstraint( fP, fC, mJ, mass, float_m(true) ); + fMassHypo = mass; + SumDaughterMass = mass; +} + +void KFParticleBaseSIMD::SetMassConstraint( float_v Mass, float_v SigmaMass ) +{ + /** Sets linearised mass constraint on the current particle. The constraint can be set with + ** an uncertainty. + ** \param[in] Mass - the mass to be set on the state vector mP + ** \param[in] SigmaMass - uncertainty of the constraint + **/ + + fMassHypo = Mass; + SumDaughterMass = Mass; + + float_v m2 = Mass*Mass; // measurement, weighted by Mass + float_v s2 = m2*SigmaMass*SigmaMass; // sigma^2 + + float_v p2 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + float_v e0 = sqrt(m2+p2); + + float_v mH[8]; + mH[0] = mH[1] = mH[2] = 0.f; + mH[3] = -2.f*fP[3]; + mH[4] = -2.f*fP[4]; + mH[5] = -2.f*fP[5]; + mH[6] = 2.f*fP[6];//e0; + mH[7] = 0.f; + + float_v zeta = e0*e0 - e0*fP[6]; + zeta = m2 - (fP[6]*fP[6]-p2); + + float_v mCHt[8], s2_est=0.f; + for( Int_t i=0; i<8; ++i ){ + mCHt[i] = 0.0f; + for (Int_t j=0;j<8;++j) mCHt[i] += Cij(i,j)*mH[j]; + s2_est += mH[i]*mCHt[i]; + } + +//TODO add protection +// if( s2_est<1.e-20 ) return; // calculated mass error is already 0, + // the particle can not be constrained on mass + + float_v w2 = 1.f/( s2 + s2_est ); + fChi2 += zeta*zeta*w2; + fNDF += 1; + for( Int_t i=0, ii=0; i<8; ++i ){ + float_v ki = mCHt[i]*w2; + fP[i]+= ki*zeta; + for(Int_t j=0;j<=i;++j) fC[ii++] -= ki*mCHt[j]; + } +} + + +void KFParticleBaseSIMD::SetNoDecayLength() +{ + /** Sets constraint on the zero decay length. When the production point is set + ** the measurement from this particle is created at the decay point. + **/ + + TransportToDecayVertex(); + + float_v h[8]; + h[0] = h[1] = h[2] = h[3] = h[4] = h[5] = h[6] = 0.f; + h[7] = 1.f; + + float_v zeta = 0.f - fP[7]; + for(Int_t i=0;i<8;++i) zeta -= h[i]*(fP[i]-fP[i]); + + float_v s = fC[35]; +// if( s>1.e-20 ) //TODO add protection + { + s = 1.f/s; + fChi2 += zeta*zeta*s; + fNDF += 1; + for( Int_t i=0, ii=0; i<7; ++i ){ + float_v ki = fC[28+i]*s; + fP[i]+= ki*zeta; + for(Int_t j=0;j<=i;++j) fC[ii++] -= ki*fC[28+j]; + } + } + fP[7] = 0.f; + fC[28] = fC[29] = fC[30] = fC[31] = fC[32] = fC[33] = fC[34] = fC[35] = 0.f; +} + +void KFParticleBaseSIMD::Construct( const KFParticleBaseSIMD* vDaughters[], Int_t nDaughters, + const KFParticleBaseSIMD *Parent, Float_t Mass ) +{ + /** Constructs a short-lived particle from a set of daughter particles:\n + ** 1) all parameters of the "this" objects are initialised;\n + ** 2) daughters are added one after another;\n + ** 3) if Parent pointer is not null, the production vertex is set to it;\n + ** 4) if Mass hypothesis >=0 the mass constraint is set. + ** \param[in] vDaughters - array of daughter particles + ** \param[in] nDaughters - number of daughter particles in the input array + ** \param[in] Parent - optional parrent particle + ** \param[in] Mass - optional mass hypothesis + **/ + + const int maxIter = 1; + for( Int_t iter=0; iter<maxIter; iter++ ){ + + CleanDaughtersId(); + SetNDaughters(nDaughters); + + fAtProductionVertex = 0; + fSFromDecay = float_v(Vc::Zero); + SumDaughterMass = float_v(Vc::Zero); + + for(Int_t i=0;i<36;++i) fC[i]=0.; + fC[35] = 1.; + + fNDF = -3; + fChi2 = 0.; + fQ = 0; + + for( Int_t itr =0; itr<nDaughters; itr++ ){ + AddDaughter( *vDaughters[itr] ); + } + } + + if( Mass>=0 ) SetMassConstraint( Mass ); + if( Parent ) SetProductionVertex( *Parent ); +} + +void KFParticleBaseSIMD::TransportToDecayVertex() +{ + /** Transports the particle to its decay vertex */ + float_v dsdr[6] = {float_v(Vc::Zero),float_v(Vc::Zero),float_v(Vc::Zero),float_v(Vc::Zero),float_v(Vc::Zero),float_v(Vc::Zero)}; + if( !( (abs(fSFromDecay) < float_v(1.e-6f)).isFull() ) ) TransportToDS( -fSFromDecay, dsdr ); + fAtProductionVertex = 0; +} + +void KFParticleBaseSIMD::TransportToProductionVertex() +{ + /** Transports the particle to its production vertex */ + float_v dsdr[6] = {float_v(Vc::Zero),float_v(Vc::Zero),float_v(Vc::Zero),float_v(Vc::Zero),float_v(Vc::Zero),float_v(Vc::Zero)}; + if( !( (abs(fSFromDecay + fP[7]) < float_v(1.e-6f)).isFull() ) ) TransportToDS( -fSFromDecay-fP[7], dsdr ); + fAtProductionVertex = 1; +} + + +void KFParticleBaseSIMD::TransportToDS( float_v dS, const float_v* dsdr ) +{ + /** Transport the particle on a certain distane. The distance is defined by the dS=l/p parameter, where \n + ** 1) l - signed distance;\n + ** 2) p - momentum of the particle. \n + ** \param[in] dS = l/p - distance normalised to the momentum of the particle to be transported on + ** \param[in] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + **/ + + Transport( dS, dsdr, fP, fC ); + fSFromDecay+= dS; +} + +void KFParticleBaseSIMD::TransportToDSLine( float_v dS, const float_v* dsdr ) +{ + /** Transport the particle on a certain distane assuming the linear trajectory. + ** The distance is defined by the dS=l/p parameter, where \n + ** 1) l - signed distance;\n + ** 2) p - momentum of the particle. \n + ** \param[in] dS = l/p - distance normalised to the momentum of the particle to be transported on + ** \param[in] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + **/ + + TransportLine( dS, dsdr, fP, fC ); + fSFromDecay+= dS; +} + +void KFParticleBaseSIMD::GetDistanceToVertexLine( const KFParticleBaseSIMD &Vertex, float_v &l, float_v &dl, float_m *isParticleFromVertex ) const +{ + /** Calculates the distance between the particle position and the vertex together with the error. + ** Errors of both particle and vertex are taken into account. Also optionally checks if partcile + ** is pointing flying from the vertex, not in the direction to the vertex if the pointer to the + ** mask isParticleFromVertex is provided. + ** \param[in] Vertex - vertex to which the distance should be calculated + ** \param[out] l - distance between the current position of the particle and a vertex + ** \param[out] dl - the error of the calculated distance + ** \param[out] isParticleFromVertex - mask which shows if particle is flying in the direction from the vertex + **/ + + float_v c[6] = {Vertex.fC[0]+fC[0], Vertex.fC[1]+fC[1], Vertex.fC[2]+fC[2], + Vertex.fC[3]+fC[3], Vertex.fC[4]+fC[4], Vertex.fC[5]+fC[5]}; + + float_v dx = (Vertex.fP[0]-fP[0]); + float_v dy = (Vertex.fP[1]-fP[1]); + float_v dz = (Vertex.fP[2]-fP[2]); + + l = sqrt( dx*dx + dy*dy + dz*dz ); + dl = c[0]*dx*dx + c[2]*dy*dy + c[5]*dz*dz + 2*(c[1]*dx*dy + c[3]*dx*dz + c[4]*dy*dz); + + l(abs(l) < 1.e-8f) = 1.e-8f; + float_m ok = float_v(Vc::Zero)<=dl; + dl(!ok) = 1.e8f; + dl(ok) = sqrt( dl )/l; + + if(isParticleFromVertex) + { + *isParticleFromVertex = ok && ( l<float_v(3.f*dl) ); + float_v cosV = dx*fP[3] + dy*fP[4] + dz*fP[5]; +// float_v dCos = dy*dy*fC[14] + dz*dz*fC[20] + dx*dx*fC[9] + 2*dz*fC[15]*fP[3] + c[0]* fP[3]*fP[3] + +// 2*dz*fC[16]* fP[4] + 2 *c[1] *fP[3] *fP[4] + c[2] *fP[4]*fP[4] + 2 *dz *fC[17]* fP[5] + +// 2*c[3] *fP[3]* fP[5] + 2 *c[4] *fP[4] *fP[5] + c[5]*fP[5] *fP[5] + +// 2*dy *(dz *fC[19] + fC[10] *fP[3] + fC[11]* fP[4] + fC[12]* fP[5]) + +// 2*dx *(dy *fC[13] + dz *fC[18] + fC[6]* fP[3] + fC[7]* fP[4] + fC[8]* fP[5]); +// ok = float_v(float_v(0)<dCos); +// dCos = float_v(ok & ( dCos )); +// dCos = sqrt(dCos); + *isParticleFromVertex = (*isParticleFromVertex) || (!(*isParticleFromVertex) && (cosV<0.f) ) ; + } +} + +float_v KFParticleBaseSIMD::GetDStoPointLine( const float_v xyz[3], float_v dsdr[6] ) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** assuming the straigth line trajectory. Is used for particles with charge 0 or in case of zero magnetic field. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** \param[in] xyz[3] - point where particle should be transported + ** \param[out] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + **/ + + float_v p2 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + p2( p2 < float_v(1.e-4f) ) = float_v(1.f); + + const float_v& a = fP[3]*(xyz[0]-fP[0]) + fP[4]*(xyz[1]-fP[1]) + fP[5]*(xyz[2]-fP[2]); + dsdr[0] = -fP[3]/p2; + dsdr[1] = -fP[4]/p2; + dsdr[2] = -fP[5]/p2; + dsdr[3] = ((xyz[0]-fP[0])*p2 - 2.f* fP[3]*a)/(p2*p2); + dsdr[4] = ((xyz[1]-fP[1])*p2 - 2.f* fP[4]*a)/(p2*p2); + dsdr[5] = ((xyz[2]-fP[2])*p2 - 2.f* fP[5]*a)/(p2*p2); + + return a/p2; +} + +float_v KFParticleBaseSIMD::GetDStoPointBz( float_v B, const float_v xyz[3], float_v dsdr[6], const float_v* param) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field Bz. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** \param[in] B - magnetic field Bz + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + ** \param[in] param - optional parameter, is used in case if the parameters of the particle are rotated + ** to other coordinate system (see GetDStoPointBy() function), otherwise fP are used + **/ + + if(!param) + param = fP; + //* Get dS to a certain space point for Bz field + + const float_v& x = param[0]; + const float_v& y = param[1]; + const float_v& z = param[2]; + const float_v& px = param[3]; + const float_v& py = param[4]; + const float_v& pz = param[5]; + + const float_v kCLight = 0.000299792458f; + float_v bq = B*simd_cast<float_v>(fQ)*kCLight; + float_v pt2 = param[3]*param[3] + param[4]*param[4]; + float_v p2 = pt2 + param[5]*param[5]; + + float_v dx = xyz[0] - param[0]; + float_v dy = xyz[1] - param[1]; + float_v dz = xyz[2] - param[2]; + float_v a = dx*param[3]+dy*param[4]; + float_v dS(Vc::Zero); + + float_v abq = bq*a; + + const float_v LocalSmall = 1.e-8f; + float_m mask = ( abs(bq)<LocalSmall ); + if( !( (!mask).isFull() ) ) + { + dS(mask && float_m(p2>1.e-4f)) = (a + dz*pz)/p2; + + dsdr[0](mask && float_m(p2>1.e-4f)) = -px/p2; + dsdr[1](mask && float_m(p2>1.e-4f)) = -py/p2; + dsdr[2](mask && float_m(p2>1.e-4f)) = -pz/p2; + dsdr[3](mask && float_m(p2>1.e-4f)) = (dx*p2 - 2.f* px *(a + dz *pz))/(p2*p2); + dsdr[4](mask && float_m(p2>1.e-4f)) = (dy*p2 - 2.f* py *(a + dz *pz))/(p2*p2); + dsdr[5](mask && float_m(p2>1.e-4f)) = (dz*p2 - 2.f* pz *(a + dz *pz))/(p2*p2); + + if(mask.isFull()) + return dS; + } + + dS(!mask) = KFPMath::ATan2( abq, pt2 + bq*(dy*px -dx*py) )/bq; + + float_v bs= bq*dS; + + float_v s = sin(bs), c = cos(bs); + + bq(abs(bq) < LocalSmall) = LocalSmall; + float_v bbq = bq*(dx*py - dy*px) - pt2; + + dsdr[0](!mask) = (px*bbq - py*abq)/(abq*abq + bbq*bbq); + dsdr[1](!mask) = (px*abq + py*bbq)/(abq*abq + bbq*bbq); + dsdr[2](!mask) = 0; + dsdr[3](!mask) = -(dx*bbq + dy*abq + 2.f*px*a)/(abq*abq + bbq*bbq); + dsdr[4](!mask) = (dx*abq - dy*bbq - 2.f*py*a)/(abq*abq + bbq*bbq); + dsdr[5](!mask) = 0; + + float_v sz(Vc::Zero); + float_v cCoeff = (bbq*c - abq*s) - pz*pz ; + sz(abs(cCoeff) > 1.e-8f) = (dS*pz - dz)*pz / cCoeff; + + float_v dcdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + dcdr[0] = -bq*py*c - bbq*s*bq*dsdr[0] + px*bq*s - abq*c*bq*dsdr[0]; + dcdr[1] = bq*px*c - bbq*s*bq*dsdr[1] + py*bq*s - abq*c*bq*dsdr[1]; + dcdr[3] = (-bq*dy-2*px)*c - bbq*s*bq*dsdr[3] - dx*bq*s - abq*c*bq*dsdr[3]; + dcdr[4] = ( bq*dx-2*py)*c - bbq*s*bq*dsdr[4] - dy*bq*s - abq*c*bq*dsdr[4]; + dcdr[5] = -2*pz; + + for(int iP=0; iP<6; iP++) + dsdr[iP](!mask) += pz*pz/cCoeff*dsdr[iP] - sz/cCoeff*dcdr[iP]; + + dsdr[2](!mask) += pz/cCoeff; + dsdr[5](!mask) += (2.f*pz*dS - dz)/cCoeff; + + dS(!mask) += sz; + + bs= bq*dS; + s = sin(bs); + c = cos(bs); + + float_v sB, cB; + const float_v kOvSqr6 = 1.f/sqrt(float_v(6.f)); + + sB(LocalSmall < abs(bs)) = s/bq; + sB(LocalSmall >= abs(bs)) = (1.f-bs*kOvSqr6)*(1.f+bs*kOvSqr6)*dS; + cB(LocalSmall < abs(bs)) = (1.f-c)/bq; + cB(LocalSmall >= abs(bs)) = .5f*sB*bs; + + float_v p[5]; + p[0] = x + sB*px + cB*py; + p[1] = y - cB*px + sB*py; + p[2] = z + dS*pz; + p[3] = c*px + s*py; + p[4] = -s*px + c*py; + + dx = xyz[0] - p[0]; + dy = xyz[1] - p[1]; + dz = xyz[2] - p[2]; + a = dx*p[3]+dy*p[4] + dz*pz; + + abq = bq*a; + + dS(!mask) += KFPMath::ATan2( abq, p2 + bq*(dy*p[3] -dx*p[4]) )/bq; + + return dS; +} + +float_v KFParticleBaseSIMD::GetDStoPointBy( float_v By, const float_v xyz[3], float_v dsdr[6] ) + const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field By. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** The particle parameters are transformed to the coordinate system, where the main component of the magnetic field + ** By is directed along the Z axis: x->x, y->-z, z->y, and the function GetDStoPointBz() is called. Derivatives dsdr are transformed back + ** to the coordinate system of the particle. + ** \param[in] By - magnetic field By + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + **/ + + const float_v param[6] = { fP[0], -fP[2], fP[1], fP[3], -fP[5], fP[4] }; + const float_v point[3] = { xyz[0], -xyz[2], xyz[1] }; + + float_v dsdrBz[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + + const float_v dS = GetDStoPointBz(By, point, dsdrBz, param); + dsdr[0] = dsdrBz[0]; + dsdr[1] = dsdrBz[2]; + dsdr[2] = -dsdrBz[1]; + dsdr[3] = dsdrBz[3]; + dsdr[4] = dsdrBz[5]; + dsdr[5] = -dsdrBz[4]; + + return dS; +} + +float_v KFParticleBaseSIMD::GetDStoPointCBM( const float_v xyz[3], float_v dsdr[6] ) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** in case of the CBM-like nonhomogeneous magnetic field. + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** For this the y-component of the magnetic field at the current position of the particle is obtained and + ** the GetDStoPointBy() is called. + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + **/ + + float_v dS(Vc::Zero); + + float_v fld[3]; + GetFieldValue( fP, fld ); + dS = GetDStoPointBy( fld[1],xyz, dsdr ); + + dS(abs(dS)>1.E3f) = 0.f; + + return dS; +} + +void KFParticleBaseSIMD::GetDStoParticleBz( float_v B, const KFParticleBaseSIMD &p, + float_v dS[2], float_v dsdr[4][6], const float_v* param1, const float_v* param2 ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field Bz. dS[0] is the transport parameter for the current particle, + ** dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle (if the pointer is not provided it is initialised with fP) and + ** param2 are parameters of the second particle "p" (if the pointer is not provided it is initialised with p.fP). Parameters + ** param1 and param2 should be either provided both or both set to null pointers. + ** \param[in] B - magnetic field Bz + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + ** \param[in] param1 - optional parameter, is used in case if the parameters of the current particles are rotated + ** to other coordinate system (see GetDStoParticleBy() function), otherwise fP are used + ** \param[in] param2 - optional parameter, is used in case if the parameters of the second particles are rotated + ** to other coordinate system (see GetDStoParticleBy() function), otherwise p.fP are used + **/ + + if(!param1) + { + param1 = fP; + param2 = p.fP; + } + + //* Get dS to another particle for Bz field + const float_v kOvSqr6 = 1.f/sqrt(float_v(6.f)); + const float_v kCLight = 0.000299792458f; + + //in XY plane + //first root + const float_v& bq1 = B*simd_cast<float_v>(fQ)*kCLight; + const float_v& bq2 = B*simd_cast<float_v>(p.fQ)*kCLight; + + const float_m& isStraight1 = abs(bq1) < float_v(1.e-8f); + const float_m& isStraight2 = abs(bq2) < float_v(1.e-8f); + + if( isStraight1.isFull() && isStraight2.isFull() ) + { + GetDStoParticleLine(p, dS, dsdr); + return; + } + + const float_v& px1 = param1[3]; + const float_v& py1 = param1[4]; + const float_v& pz1 = param1[5]; + + const float_v& px2 = param2[3]; + const float_v& py2 = param2[4]; + const float_v& pz2 = param2[5]; + + const float_v& pt12 = px1*px1 + py1*py1; + const float_v& pt22 = px2*px2 + py2*py2; + + const float_v& x01 = param1[0]; + const float_v& y01 = param1[1]; + const float_v& z01 = param1[2]; + + const float_v& x02 = param2[0]; + const float_v& y02 = param2[1]; + const float_v& z02 = param2[2]; + + float_v dS1[2] = {0.f, 0.f}, dS2[2]={0.f, 0.f}; + + const float_v& dx0 = (x01 - x02); + const float_v& dy0 = (y01 - y02); + const float_v& dr02 = dx0*dx0 + dy0*dy0; + const float_v& drp1 = dx0*px1 + dy0*py1; + const float_v& dxyp1 = dx0*py1 - dy0*px1; + const float_v& drp2 = dx0*px2 + dy0*py2; + const float_v& dxyp2 = dx0*py2 - dy0*px2; + const float_v& p1p2 = px1*px2 + py1*py2; + const float_v& dp1p2 = px1*py2 - px2*py1; + + const float_v& k11 = (bq2*drp1 - dp1p2); + const float_v& k21 = (bq1*(bq2*dxyp1 - p1p2) + bq2*pt12); + const float_v& k12 = ((bq1*drp2 - dp1p2)); + const float_v& k22 = (bq2*(bq1*dxyp2 + p1p2) - bq1*pt22); + + const float_v& kp = (dxyp1*bq2 - dxyp2*bq1 - p1p2); + const float_v& kd = dr02/2.f*bq1*bq2 + kp; + const float_v& c1 = -(bq1*kd + pt12*bq2); + const float_v& c2 = bq2*kd + pt22*bq1; + + float_v d1 = pt12*pt22 - kd*kd; + d1(d1 < float_v(Vc::Zero)) = float_v(Vc::Zero); + d1 = sqrt( d1 ); + float_v d2 = pt12*pt22 - kd*kd; + d2(d2 < float_v(Vc::Zero)) = float_v(Vc::Zero); + d2 = sqrt( d2 ); + + float_v dS1dR1[2][6]; + float_v dS2dR2[2][6]; + + float_v dS1dR2[2][6]; + float_v dS2dR1[2][6]; + + float_v dk11dr1[6] = {bq2*px1, bq2*py1, 0.f, bq2*dx0 - py2, bq2*dy0 + px2, 0.f}; + float_v dk11dr2[6] = {-bq2*px1, -bq2*py1, 0.f, py1, -px1, 0.f}; + float_v dk12dr1[6] = {bq1*px2, bq1*py2, 0.f, -py2, px2, 0.f}; + float_v dk12dr2[6] = {-bq1*px2, -bq1*py2, 0.f, bq1*dx0 + py1, bq1*dy0 - px1, 0.f}; + float_v dk21dr1[6] = {bq1*bq2*py1, -bq1*bq2*px1, 0.f, 2.f*bq2*px1 + bq1*(-(bq2*dy0) - px2), 2.f*bq2*py1 + bq1*(bq2*dx0 - py2), 0.f}; + float_v dk21dr2[6] = {-(bq1*bq2*py1), bq1*bq2*px1, 0.f, -(bq1*px1), -(bq1*py1), 0.f}; + float_v dk22dr1[6] = {bq1*bq2*py2, -(bq1*bq2*px2), 0.f, bq2*px2, bq2*py2, 0.f}; + float_v dk22dr2[6] = {-(bq1*bq2*py2), bq1*bq2*px2, 0.f, bq2*(-(bq1*dy0) + px1) - 2.f*bq1*px2, bq2*(bq1*dx0 + py1) - 2.f*bq1*py2, 0.f}; + + float_v dkddr1[6] = {bq1*bq2*dx0 + bq2*py1 - bq1*py2, bq1*bq2*dy0 - bq2*px1 + bq1*px2, 0.f, -bq2*dy0 - px2, bq2*dx0 - py2, 0.f}; + float_v dkddr2[6] = {-bq1*bq2*dx0 - bq2*py1 + bq1*py2, -bq1*bq2*dy0 + bq2*px1 - bq1*px2, 0.f, bq1*dy0 - px1, -bq1*dx0 - py1, 0.f}; + + float_v dc1dr1[6] = {-(bq1*(bq1*bq2*dx0 + bq2*py1 - bq1*py2)), -(bq1*(bq1*bq2*dy0 - bq2*px1 + bq1*px2)), 0.f, -2.f*bq2*px1 - bq1*(-(bq2*dy0) - px2), -2.f*bq2*py1 - bq1*(bq2*dx0 - py2), 0.f}; + float_v dc1dr2[6] = {-(bq1*(-(bq1*bq2*dx0) - bq2*py1 + bq1*py2)), -(bq1*(-(bq1*bq2*dy0) + bq2*px1 - bq1*px2)), 0.f, -(bq1*(bq1*dy0 - px1)), -(bq1*(-(bq1*dx0) - py1)), 0.f}; + + float_v dc2dr1[6] = {bq2*(bq1*bq2*dx0 + bq2*py1 - bq1*py2), bq2*(bq1*bq2*dy0 - bq2*px1 + bq1*px2), 0.f, bq2*(-(bq2*dy0) - px2), bq2*(bq2*dx0 - py2), 0.f}; + float_v dc2dr2[6] = {bq2*(-(bq1*bq2*dx0) - bq2*py1 + bq1*py2), bq2*(-(bq1*bq2*dy0) + bq2*px1 - bq1*px2), 0.f, bq2*(bq1*dy0 - px1) + 2.f*bq1*px2, bq2*(-(bq1*dx0) - py1) + 2.f*bq1*py2, 0.f}; + + float_v dd1dr1[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + float_v dd1dr2[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + { + for(int i=0; i<6; i++) + { + dd1dr1[i](d1>0.f) = -kd/d1*dkddr1[i]; + dd1dr2[i](d1>0.f) = -kd/d1*dkddr2[i]; + } + dd1dr1[3](d1>0.f) += px1/d1*pt22; dd1dr1[4](d1>0.f) += py1/d1*pt22; + dd1dr2[3](d1>0.f) += px2/d1*pt12; dd1dr2[4](d1>0.f) += py2/d1*pt12; + } + + // find two points of closest approach in XY plane + if( ! ( (!isStraight1).isEmpty() ) ) + { + dS1[0](!isStraight1) = KFPMath::ATan2( (bq1*k11*c1 + k21*d1*bq1), (bq1*k11*d1*bq1 - k21*c1) )/bq1; + dS1[1](!isStraight1) = KFPMath::ATan2( (bq1*k11*c1 - k21*d1*bq1), (-bq1*k11*d1*bq1 - k21*c1) )/bq1; + + float_v a = bq1*(k11*c1 + k21*d1); + float_v b = bq1*k11*d1*bq1 - k21*c1; + for(int iP=0; iP<6; iP++) + { + const float_v dadr1 = bq1*( dk11dr1[iP]*c1 + k11*dc1dr1[iP] + dk21dr1[iP]*d1 + k21*dd1dr1[iP] ); + const float_v dadr2 = bq1*( dk11dr2[iP]*c1 + k11*dc1dr2[iP] + dk21dr2[iP]*d1 + k21*dd1dr2[iP] ); + const float_v dbdr1 = bq1*bq1*( dk11dr1[iP]*d1 + k11*dd1dr1[iP] ) - ( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float_v dbdr2 = bq1*bq1*( dk11dr2[iP]*d1 + k11*dd1dr2[iP] ) - ( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[0][iP](!isStraight1) = 1/bq1 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ); + dS1dR2[0][iP](!isStraight1) = 1/bq1 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ); + } + + a = bq1*(k11*c1 - k21*d1); + b = -bq1*k11*d1*bq1 - k21*c1; + for(int iP=0; iP<6; iP++) + { + const float_v dadr1 = bq1*( dk11dr1[iP]*c1 + k11*dc1dr1[iP] - (dk21dr1[iP]*d1 + k21*dd1dr1[iP]) ); + const float_v dadr2 = bq1*( dk11dr2[iP]*c1 + k11*dc1dr2[iP] - (dk21dr2[iP]*d1 + k21*dd1dr2[iP]) ); + const float_v dbdr1 = -bq1*bq1*( dk11dr1[iP]*d1 + k11*dd1dr1[iP] ) - ( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float_v dbdr2 = -bq1*bq1*( dk11dr2[iP]*d1 + k11*dd1dr2[iP] ) - ( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[1][iP](!isStraight1) = 1/bq1 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ); + dS1dR2[1][iP](!isStraight1) = 1/bq1 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ); + } + } + if( ! ( (!isStraight2).isEmpty() ) ) + { + dS2[0](!isStraight2) = KFPMath::ATan2( (bq2*k12*c2 + k22*d2*bq2), (bq2*k12*d2*bq2 - k22*c2) )/bq2; + dS2[1](!isStraight2) = KFPMath::ATan2( (bq2*k12*c2 - k22*d2*bq2), (-bq2*k12*d2*bq2 - k22*c2) )/bq2; + + float_v a = bq2*(k12*c2 + k22*d2); + float_v b = bq2*k12*d2*bq2 - k22*c2; + for(int iP=0; iP<6; iP++) + { + const float_v dadr1 = bq2*( dk12dr1[iP]*c2 + k12*dc2dr1[iP] + dk22dr1[iP]*d1 + k22*dd1dr1[iP] ); + const float_v dadr2 = bq2*( dk12dr2[iP]*c2 + k12*dc2dr2[iP] + dk22dr2[iP]*d1 + k22*dd1dr2[iP] ); + const float_v dbdr1 = bq2*bq2*( dk12dr1[iP]*d1 + k12*dd1dr1[iP] ) - (dk22dr1[iP]*c2 + k22*dc2dr1[iP]); + const float_v dbdr2 = bq2*bq2*( dk12dr2[iP]*d1 + k12*dd1dr2[iP] ) - (dk22dr2[iP]*c2 + k22*dc2dr2[iP]); + + dS2dR1[0][iP](!isStraight2) = 1/bq2 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ); + dS2dR2[0][iP](!isStraight2) = 1/bq2 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ); + } + + a = bq2*(k12*c2 - k22*d2); + b = -bq2*k12*d2*bq2 - k22*c2; + for(int iP=0; iP<6; iP++) + { + const float_v dadr1 = bq2*( dk12dr1[iP]*c2 + k12*dc2dr1[iP] - (dk22dr1[iP]*d1 + k22*dd1dr1[iP]) ); + const float_v dadr2 = bq2*( dk12dr2[iP]*c2 + k12*dc2dr2[iP] - (dk22dr2[iP]*d1 + k22*dd1dr2[iP]) ); + const float_v dbdr1 = -bq2*bq2*( dk12dr1[iP]*d1 + k12*dd1dr1[iP] ) - (dk22dr1[iP]*c2 + k22*dc2dr1[iP]); + const float_v dbdr2 = -bq2*bq2*( dk12dr2[iP]*d1 + k12*dd1dr2[iP] ) - (dk22dr2[iP]*c2 + k22*dc2dr2[iP]); + + dS2dR1[1][iP](!isStraight2) = 1/bq2 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ); + dS2dR2[1][iP](!isStraight2) = 1/bq2 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ); + } + } + if( ! ( isStraight1.isEmpty() ) ) + { + dS1[0](isStraight1 && (pt12>float_v(Vc::Zero)) ) = (k11*c1 + k21*d1)/(- k21*c1); + dS1[1](isStraight1 && (pt12>float_v(Vc::Zero)) ) = (k11*c1 - k21*d1)/(- k21*c1); + + float_v a = k11*c1 + k21*d1; + float_v b = -k21*c1; + + for(int iP=0; iP<6; iP++) + { + const float_v dadr1 = ( dk11dr1[iP]*c1 + k11*dc1dr1[iP] + dk21dr1[iP]*d1 + k21*dd1dr1[iP] ); + const float_v dadr2 = ( dk11dr2[iP]*c1 + k11*dc1dr2[iP] + dk21dr2[iP]*d1 + k21*dd1dr2[iP] ); + const float_v dbdr1 = -( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float_v dbdr2 = -( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[0][iP](isStraight1 && (pt12>float_v(Vc::Zero)) ) = dadr1/b - dbdr1*a/(b*b) ; + dS1dR2[0][iP](isStraight1 && (pt12>float_v(Vc::Zero)) ) = dadr2/b - dbdr2*a/(b*b) ; + } + + a = k11*c1 - k21*d1; + for(int iP=0; iP<6; iP++) + { + const float_v dadr1 = ( dk11dr1[iP]*c1 + k11*dc1dr1[iP] - dk21dr1[iP]*d1 - k21*dd1dr1[iP] ); + const float_v dadr2 = ( dk11dr2[iP]*c1 + k11*dc1dr2[iP] - dk21dr2[iP]*d1 - k21*dd1dr2[iP] ); + const float_v dbdr1 = -( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float_v dbdr2 = -( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[1][iP](isStraight1 && (pt12>float_v(Vc::Zero)) ) = dadr1/b - dbdr1*a/(b*b) ; + dS1dR2[1][iP](isStraight1 && (pt12>float_v(Vc::Zero)) ) = dadr2/b - dbdr2*a/(b*b) ; + } + } + if( ! ( isStraight2.isEmpty() ) ) + { + dS2[0](isStraight2 && (pt22>float_v(Vc::Zero)) ) = (k12*c2 + k22*d2)/(- k22*c2); + dS2[1](isStraight2 && (pt22>float_v(Vc::Zero)) ) = (k12*c2 - k22*d2)/(- k22*c2); + + float_v a = k12*c2 + k22*d1; + float_v b = -k22*c2; + + for(int iP=0; iP<6; iP++) + { + const float_v dadr1 = ( dk12dr1[iP]*c2 + k12*dc2dr1[iP] + dk22dr1[iP]*d1 + k22*dd1dr1[iP] ); + const float_v dadr2 = ( dk12dr2[iP]*c2 + k12*dc2dr2[iP] + dk22dr2[iP]*d1 + k22*dd1dr2[iP] ); + const float_v dbdr1 = -( dk22dr1[iP]*c2 + k22*dc2dr1[iP] ); + const float_v dbdr2 = -( dk22dr2[iP]*c2 + k22*dc2dr2[iP] ); + + dS2dR1[0][iP](isStraight2 && (pt22>float_v(Vc::Zero)) ) = dadr1/b - dbdr1*a/(b*b) ; + dS2dR2[0][iP](isStraight2 && (pt22>float_v(Vc::Zero)) ) = dadr2/b - dbdr2*a/(b*b) ; + } + + a = k12*c2 - k22*d1; + for(int iP=0; iP<6; iP++) + { + const float_v dadr1 = ( dk12dr1[iP]*c2 + k12*dc2dr1[iP] - dk22dr1[iP]*d1 - k22*dd1dr1[iP] ); + const float_v dadr2 = ( dk12dr2[iP]*c2 + k12*dc2dr2[iP] - dk22dr2[iP]*d1 - k22*dd1dr2[iP] ); + const float_v dbdr1 = -( dk22dr1[iP]*c2 + k22*dc2dr1[iP] ); + const float_v dbdr2 = -( dk22dr2[iP]*c2 + k22*dc2dr2[iP] ); + + dS2dR1[1][iP](isStraight2 && (pt22>float_v(Vc::Zero)) ) = dadr1/b - dbdr1*a/(b*b) ; + dS2dR2[1][iP](isStraight2 && (pt22>float_v(Vc::Zero)) ) = dadr2/b - dbdr2*a/(b*b) ; + } + } + + //select a point which is close to the primary vertex (with the smallest r) + + float_v dr2[2]; + for(int iP = 0; iP<2; iP++) + { + const float_v& bs1 = bq1*dS1[iP]; + const float_v& bs2 = bq2*dS2[iP]; + float_v sss = sin(bs1), ccc = cos(bs1); + + const float_m& bs1Big = abs(bs1) > 1.e-8f; + const float_m& bs2Big = abs(bs2) > 1.e-8f; + + float_v sB(Vc::Zero), cB(Vc::Zero); + sB(bs1Big) = sss/bq1; + sB(!bs1Big) = ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS1[iP]); + cB(bs1Big) = (1.f-ccc)/bq1; + cB(!bs1Big) = .5f*sB*bs1; + + const float_v& x1 = param1[0] + sB*px1 + cB*py1; + const float_v& y1 = param1[1] - cB*px1 + sB*py1; + const float_v& z1 = param1[2] + dS1[iP]*param1[5]; + + sss = sin(bs2); ccc = cos(bs2); + + sB(bs2Big) = sss/bq2; + sB(!bs2Big) = ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS2[iP]); + cB(bs2Big) = (1.f-ccc)/bq2; + cB(!bs2Big) = .5f*sB*bs2; + + const float_v& x2 = param2[0] + sB*px2 + cB*py2; + const float_v& y2 = param2[1] - cB*px2 + sB*py2; + const float_v& z2 = param2[2] + dS2[iP]*param2[5]; + + float_v dx = (x1-x2); + float_v dy = (y1-y2); + float_v dz = (z1-z2); + + dr2[iP] = dx*dx + dy*dy + dz*dz; + } + + float_v pointParam[2][8]; + float_v pointCov[2][36]; + + float_v dsdrM1[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + for(int iP=0; iP<6; iP++) + dsdrM1[iP] = (dS1dR1[0][iP] + dS1dR1[1][iP])/2.f; + Transport((dS1[0] + dS1[1]) / 2.f, dsdrM1, pointParam[0], pointCov[0]); + float_v dsdrM2[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + for(int iP=0; iP<6; iP++) + dsdrM2[iP] = (dS2dR2[0][iP] + dS2dR2[1][iP])/2.f; + p.Transport((dS2[0] + dS2[1]) / 2.f, dsdrM2, pointParam[1], pointCov[1]); + + const float_v drPoint[3] = { pointParam[0][0] - pointParam[1][0], pointParam[0][1] - pointParam[1][1], pointParam[0][2] - pointParam[1][2] } ; + const float_v covPoint[6] = { pointCov[0][0] + pointCov[1][0], + pointCov[0][1] + pointCov[1][1], + pointCov[0][2] + pointCov[1][2], + pointCov[0][3] + pointCov[1][3], + pointCov[0][4] + pointCov[1][4], + pointCov[0][5] + pointCov[1][5] }; + float_v dr2Points = drPoint[0]*drPoint[0] + drPoint[1]*drPoint[1] + drPoint[2]*drPoint[2]; + float_v dr2PointCov = drPoint[0]*drPoint[0]*covPoint[0] + drPoint[1]*drPoint[1]*covPoint[2] + drPoint[2]*drPoint[2]*covPoint[5] + + 2.f*( drPoint[0]*drPoint[1]*covPoint[1] + drPoint[0]*drPoint[2]*covPoint[3] + drPoint[1]*drPoint[2]*covPoint[4] ); + const float_m isMiddlePoint = (dr2Points*dr2Points < 25.f*dr2PointCov);// && (abs(fPDG)==int_v(11)) && (abs(p.fPDG)==int_v(11)); + const float_m isFirstRoot = (dr2[0] < dr2[1]) & (!isMiddlePoint); + + // if(!(isFirstRoot.isEmpty())) + { + dS[0](isFirstRoot) = dS1[0]; + dS[1](isFirstRoot) = dS2[0]; + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP](isFirstRoot) = dS1dR1[0][iP]; + dsdr[1][iP](isFirstRoot) = dS1dR2[0][iP]; + dsdr[2][iP](isFirstRoot) = dS2dR1[0][iP]; + dsdr[3][iP](isFirstRoot) = dS2dR2[0][iP]; + } + } + // if( !( (!isFirstRoot).isEmpty() ) ) + { + dS[0](!isFirstRoot) = dS1[1]; + dS[1](!isFirstRoot) = dS2[1]; + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP](!isFirstRoot) = dS1dR1[1][iP]; + dsdr[1][iP](!isFirstRoot) = dS1dR2[1][iP]; + dsdr[2][iP](!isFirstRoot) = dS2dR1[1][iP]; + dsdr[3][iP](!isFirstRoot) = dS2dR2[1][iP]; + } + } + // if(!(isMiddlePoint.isEmpty())) + { + dS[0](isMiddlePoint) = (dS1[0] + dS1[1]) / 2.f; + dS[1](isMiddlePoint) = (dS2[0] + dS2[1]) / 2.f; + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP](isMiddlePoint) = (dS1dR1[1][iP] + dS1dR1[0][iP])/2.f; + dsdr[1][iP](isMiddlePoint) = (dS1dR2[1][iP] + dS1dR2[0][iP])/2.f; + dsdr[2][iP](isMiddlePoint) = (dS2dR1[1][iP] + dS2dR1[0][iP])/2.f; + dsdr[3][iP](isMiddlePoint) = (dS2dR2[1][iP] + dS2dR2[0][iP])/2.f; + } + } + + //find correct parts of helices + int_v n1(Vc::Zero); + int_v n2(Vc::Zero); +// float_v dzMin = abs( (z01-z02) + dS[0]*pz1 - dS[1]*pz2 ); + const float_v pi2(6.283185307f); + +// //TODO optimise for loops for neutral particles +// const float_v& i1Float = -bq1/pi2*(z01/pz1+dS[0]); +// for(int di1=-1; di1<=1; di1++) +// { +// int_v i1(Vc::Zero); +// i1(int_m(!isStraight1)) = int_v(i1Float) + di1; +// +// const float_v& i2Float = ( ((z01-z02) + (dS[0]+pi2*i1/bq1)*pz1)/pz2 - dS[1]) * bq2/pi2; +// for(int di2 = -1; di2<=1; di2++) +// { +// int_v i2(Vc::Zero); +// i2(int_m(!isStraight2)) = int_v(i2Float) + di2; +// +// const float_v& z1 = z01 + (dS[0]+pi2*i1/bq1)*pz1; +// const float_v& z2 = z02 + (dS[1]+pi2*i2/bq2)*pz2; +// const float_v& dz = abs( z1-z2 ); +// +// n1(int_m(dz < dzMin)) = i1; +// n2(int_m(dz < dzMin)) = i2; +// dzMin(dz < dzMin) = dz; +// } +// } +// +// dS[0](!isStraight1) += float_v(n1)*pi2/bq1; +// dS[1](!isStraight2) += float_v(n2)*pi2/bq2; + + //add a correction on z-coordinate +#if 0 + { + const float_v& bs1 = bq1*dS[0]; + const float_v& bs2 = bq2*dS[1]; + + float_v sss = KFPMath::Sin(bs1), ccc = KFPMath::Cos(bs1); + const float_v& xr1 = sss*px1 - ccc*py1; + const float_v& yr1 = ccc*px1 + sss*py1; + + float_v sss1 = KFPMath::Sin(bs2), ccc1 = KFPMath::Cos(bs2); + const float_v& xr2 = sss1*px2 - ccc1*py2; + const float_v& yr2 = ccc1*px2 + sss1*py2; + + const float_v& br = xr1*xr2 + yr1*yr2; + const float_v& dx0mod = dx0*bq1*bq2 + py1*bq2 - py2*bq1; + const float_v& dy0mod = dy0*bq1*bq2 - px1*bq2 + px2*bq1; + const float_v& ar1 = dx0mod*xr1 + dy0mod*yr1; + const float_v& ar2 = dx0mod*xr2 + dy0mod*yr2; + const float_v& cz = (z01 - z02) + dS[0]*pz1 - dS[1]*pz2; + + float_v kz11 = - ar1 + bq1*br + bq2*pz1*pz1; + float_v kz12 = -bq2*(br+pz1*pz2); + float_v kz21 = bq1*(br+pz1*pz2); + float_v kz22 = - ar2 - bq2*br - bq1*pz2*pz2; + + kz11(isStraight2) = pz1*pz1 + (px1*px1+py1*py1)*ccc + bq1*( (px2*dS[1] - dx0)*xr1 + (py2*dS[1] - dy0)*yr1 ); + kz12(isStraight2) = -(br + pz1*pz2); + kz21(isStraight1) = (br + pz1*pz2); + kz22(isStraight1) = -pz2*pz2 - (px2*px2+py2*py2)*ccc1 - bq2*( (px1*dS[0] + dx0)*xr2 + (py1*dS[0] + dy0)*yr2 ); + + const float_v& delta = kz11*kz22 - kz12*kz21; + float_v sz1(Vc::Zero); + float_v sz2(Vc::Zero); + + { + float_v aaa1 = -cz*(pz1*bq2*kz22 - pz2*bq1*kz12); + float_v aaa2 = -cz*(pz2*bq1*kz11 - pz1*bq2*kz21); + + aaa1(isStraight2) = -cz*(pz1*kz22 - pz2*bq1*kz12); + aaa2(isStraight2) = -cz*(pz2*bq1*kz11 - pz1*kz21); + + aaa1(isStraight1) = -cz*(pz1*bq2*kz22 - pz2*kz12); + aaa2(isStraight1) = -cz*(pz2*kz11 - pz1*bq2*kz21); + + sz1( abs(delta) > 1.e-16f ) = aaa1 / delta; + sz2( abs(delta) > 1.e-16f ) = aaa2 / delta; + + float_v dkz11dr1[6] = {-(bq1*bq2*xr1), -(bq1*bq2*yr1), 0.f, + -ccc*dy0mod - dx0mod*sss + bq2*yr1 + bq1*(sss*xr2 + ccc*yr2), + ccc*dx0mod - dy0mod*sss - bq2*xr1 + bq1*(-ccc*xr2 + sss*yr2), 2.f*bq2*pz1}; + dkz11dr1[0](isStraight2) = -bq1*xr1; + dkz11dr1[1](isStraight2) = -bq1*yr1; + dkz11dr1[3](isStraight2) = 2.f*ccc*px1 + bq1*(sss*(dS[1]*px2 - x01 + x02) + ccc*(dS[1]*py2 - y01 + y02)); + dkz11dr1[4](isStraight2) = 2.f*ccc*py1 + bq1*(-(ccc*(dS[1]*px2 - x01 + x02)) + sss*(dS[1]*py2 - y01 + y02)); + dkz11dr1[5](isStraight2) = 2.f*pz1; + float_v dkz11dr2[6] = {bq1*bq2*xr1, bq1*bq2*yr1, 0.f, -bq1*yr1 + bq1*(sss1*xr1 + ccc1*yr1), bq1*xr1 + bq1*(-ccc1*xr1 + sss1*yr1), 0.f}; + dkz11dr2[0](isStraight2) = bq1*xr1; + dkz11dr2[1](isStraight2) = bq1*yr1; + dkz11dr2[3](isStraight2) = bq1*dS[1]*xr1; + dkz11dr2[4](isStraight2) = bq1*dS[1]*yr1; + + float_v dkz12dr1[6] = {0.f, 0.f, 0.f, -bq2*(sss*xr2 + ccc*yr2), -bq2*(-ccc*xr2 + sss*yr2), -bq2*pz2}; + dkz12dr1[3](isStraight2) = -(sss*xr2 + ccc*yr2); + dkz12dr1[4](isStraight2) = -(-ccc*xr2 + sss*yr2); + dkz12dr1[5](isStraight2) = -pz2; + float_v dkz12dr2[6] = {0.f, 0.f, 0.f, -bq2*(sss1*xr1 + ccc1*yr1), -bq2*(-ccc1*xr1 + sss1*yr1), -bq2*pz1}; + dkz12dr2[3](isStraight2) = -(sss1*xr1 + ccc1*yr1); + dkz12dr2[4](isStraight2) = -(-ccc1*xr1 + sss1*yr1); + dkz12dr2[5](isStraight2) = -pz1; + float_v dkz21dr1[6] = {0.f, 0.f, 0.f, bq1*(sss*xr2 + ccc*yr2), bq1*(-ccc*xr2 + sss*yr2), bq1*pz2}; + dkz21dr1[3](isStraight1) = yr2; + dkz21dr1[4](isStraight1) = -xr2; + dkz21dr1[5](isStraight1) = pz2; + float_v dkz21dr2[6] = {0.f, 0.f, 0.f, bq1*(sss1*xr1 + ccc1*yr1), bq1*(-ccc1*xr1 + sss1*yr1), bq1*pz1}; + dkz21dr2[3](isStraight1) = (sss1*xr1 + ccc1*yr1); + dkz21dr2[4](isStraight1) = (-ccc1*xr1 + sss1*yr1); + dkz21dr2[5](isStraight1) = pz1; + float_v dkz22dr1[6] = {-bq1*bq2*xr2, -bq1*bq2*yr2, 0.f, bq2*yr2 - bq2*(sss*xr2 + ccc*yr2), -bq2*xr2 - bq2*(-ccc*xr2 + sss*yr2), 0.f}; + dkz22dr1[0](isStraight1) = -(bq2*xr2); + dkz22dr1[1](isStraight1) = -(bq2*yr2); + dkz22dr1[3](isStraight1) = -(bq2*dS[0]*xr2); + dkz22dr1[4](isStraight1) = -(bq2*dS[0]*yr2); + float_v dkz22dr2[6] = {bq1*bq2*xr2, bq1*bq2*yr2, 0.f, + -ccc1*dy0mod - dx0mod*sss1 - bq2*(sss1*xr1 + ccc1*yr1) - bq1*yr2, + ccc1*dx0mod - dy0mod*sss1 + bq1*xr2 - bq2*(-ccc1*xr1 + sss1*yr1), -2.f*bq1*pz2}; + dkz22dr2[0](isStraight1) = bq2*xr2; + dkz22dr2[1](isStraight1) = bq2*yr2; + dkz22dr2[3](isStraight1) = -2.f*ccc1*px2 - bq2*(ccc1*(dy0 + dS[0]*py1) + (dx0 + dS[0]*px1)*sss1); + dkz22dr2[4](isStraight1) = -2.f*ccc1*py2 - bq2*(-(ccc1*(dx0 + dS[0]*px1)) + (dy0 + dS[0]*py1)*sss1); + dkz22dr2[5](isStraight1) = -2.f*pz2; + + float_v dczdr1[6] = {0.f, 0.f, 1.f, 0.f, 0.f, dS[0]}; + float_v dczdr2[6] = {0.f, 0.f, -1.f, 0.f, 0.f, -dS[1]}; + + float_v daaa1dr1[6]; + float_v daaa1dr2[6]; + float_v daaa2dr2[6]; + float_v daaa2dr1[6]; + float_v dDeltadr1[6]; + float_v dDeltadr2[6]; + for(int iP=0; iP<6; iP++) + { + daaa1dr1[iP] = -( dczdr1[iP]*(pz1*bq2*kz22 - pz2*bq1*kz12) + cz*( bq2*pz1*dkz22dr1[iP] - bq1*pz2*dkz12dr1[iP] ) ); + daaa1dr2[iP] = -( dczdr2[iP]*(pz1*bq2*kz22 - pz2*bq1*kz12) + cz*( bq2*pz1*dkz22dr2[iP] - bq1*pz2*dkz12dr2[iP] ) ); + + daaa2dr2[iP] = -( dczdr2[iP]*(pz2*bq1*kz11 - pz1*bq2*kz21) + cz*( bq1*pz2*dkz11dr2[iP] - bq2*pz1*dkz21dr2[iP] ) ); + daaa2dr1[iP] = -( dczdr1[iP]*(pz2*bq1*kz11 - pz1*bq2*kz21) + cz*( bq1*pz2*dkz11dr1[iP] - bq2*pz1*dkz21dr1[iP] ) ); + + dDeltadr1[iP] = kz11*dkz22dr1[iP] + dkz11dr1[iP]*kz11 - kz12*dkz21dr1[iP] - dkz12dr1[iP]*kz21; + dDeltadr2[iP] = kz11*dkz22dr2[iP] + dkz11dr2[iP]*kz11 - kz12*dkz21dr2[iP] - dkz12dr2[iP]*kz21; + } + daaa1dr1[5] -= cz*bq2*kz22; + daaa1dr2[5] += cz*bq1*kz12; + daaa2dr2[5] -= cz*bq1*kz11; + daaa2dr1[5] += cz*bq2*kz21; + + //derivatives by s0 and s1 + float_v dkz11ds0 = bq1*(dy0mod*xr1 - dx0mod*yr1 + bq1*(xr2*yr1 - xr1*yr2)); + dkz11ds0(isStraight2) = -(bq1*(px1*px1 + py1*py1)*sss) + bq1*(bq1*yr1*(dS[1]*px2 - x01 + x02) -bq1*xr1*(dS[1]*py2 - y01 + y02)); + float_v dkz11ds1 = bq1*bq2*( xr1*yr2 - xr2*yr1 ); + dkz11ds1(isStraight2) = bq1*(px2*xr1 + py2*yr1); + float_v dkz12ds0 = bq2*bq1*( xr1*yr2 - xr2*yr1 ); + dkz12ds0(isStraight2) = bq1*( xr1*yr2 - xr2*yr1 ); + float_v dkz12ds1 = bq2*bq2*( xr2*yr1 - xr1*yr2 ); + dkz12ds1(isStraight2) = 0; + float_v dkz21ds0 = bq1*bq1*( xr2*yr1 - xr1*yr2 ); + dkz21ds0(isStraight1) = 0.f; + float_v dkz21ds1 = bq1*bq2*( xr1*yr2 - xr2*yr1 ); + dkz21ds1(isStraight1) = px1*(bq2*ccc1*py2 - bq2*px2*sss1) - py1*(bq2*ccc1*px2 + bq2*py2*sss1); + float_v dkz22ds0 = bq1*bq2*( xr1*yr2 - xr2*yr1 ); + dkz22ds0(isStraight1) = -bq2*(px1*xr2 + py1*yr2); + float_v dkz22ds1 = -bq2*( dy0mod*xr2 - dx0mod*yr2 - bq2*(xr2*yr1 - xr1*yr2) ); + dkz22ds1(isStraight1) = bq2*(px2*px2 + py2*py2)*sss1 - bq2*((dy0 + dS[0]*py1)*(bq2*ccc1*py2 - bq2*px2*sss1) + (dx0 + dS[0]*px1)*(bq2*ccc1*px2 + bq2*py2*sss1)); + const float_v dczds0 = pz1; + const float_v dczds1 = -pz2; + const float_v da1ds0 = -( dczds0*(pz1*bq2*kz22 - pz2*bq1*kz12) + cz*(pz1*bq2*dkz22ds0 - pz2*bq1*dkz12ds0)); + const float_v da1ds1 = -( dczds1*(pz1*bq2*kz22 - pz2*bq1*kz12) + cz*(pz1*bq2*dkz22ds1 - pz2*bq1*dkz12ds1)); + const float_v da2ds0 = -( dczds0*(pz2*bq1*kz11 - pz1*bq2*kz21) + cz*(pz2*bq1*dkz11ds0 - pz1*bq2*dkz21ds0)); + const float_v da2ds1 = -( dczds1*(pz2*bq1*kz11 - pz1*bq2*kz21) + cz*(pz2*bq1*dkz11ds1 - pz1*bq2*dkz21ds1)); + const float_v dDeltads0 = kz11*dkz22ds0 + dkz11ds0*kz11 - kz12*dkz21ds0 - dkz12ds0*kz21; + const float_v dDeltads1 = kz11*dkz22ds1 + dkz11ds1*kz11 - kz12*dkz21ds1 - dkz12ds1*kz21; + + const float_v dsz1ds0 = da1ds0/delta - aaa1*dDeltads0/(delta*delta); + const float_v dsz1ds1 = da1ds1/delta - aaa1*dDeltads1/(delta*delta); + const float_v dsz2ds0 = da2ds0/delta - aaa2*dDeltads0/(delta*delta); + const float_v dsz2ds1 = da2ds1/delta - aaa2*dDeltads1/(delta*delta); + + float_v dszdr[4][6]; + for(int iP=0; iP<6; iP++) + { + dszdr[0][iP] = dsz1ds0*dsdr[0][iP] + dsz1ds1*dsdr[2][iP]; + dszdr[1][iP] = dsz1ds0*dsdr[1][iP] + dsz1ds1*dsdr[3][iP]; + dszdr[2][iP] = dsz2ds0*dsdr[0][iP] + dsz2ds1*dsdr[2][iP]; + dszdr[3][iP] = dsz2ds0*dsdr[1][iP] + dsz2ds1*dsdr[3][iP]; + } + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP]( abs(delta) > 1.e-16f ) += daaa1dr1[iP]/delta - aaa1*dDeltadr1[iP]/(delta*delta) + dszdr[0][iP]; + dsdr[1][iP]( abs(delta) > 1.e-16f ) += daaa1dr2[iP]/delta - aaa1*dDeltadr2[iP]/(delta*delta) + dszdr[1][iP]; + dsdr[2][iP]( abs(delta) > 1.e-16f ) += daaa2dr1[iP]/delta - aaa2*dDeltadr1[iP]/(delta*delta) + dszdr[2][iP]; + dsdr[3][iP]( abs(delta) > 1.e-16f ) += daaa2dr2[iP]/delta - aaa2*dDeltadr2[iP]/(delta*delta) + dszdr[3][iP]; + } + } + + dS[0] += sz1; + dS[1] += sz2; + } +#endif + + //Line correction + { + const float_v& bs1 = bq1*dS[0]; + const float_v& bs2 = bq2*dS[1]; + float_v sss = sin(bs1), ccc = cos(bs1); + + const float_m& bs1Big = abs(bs1) > 1.e-8f; + const float_m& bs2Big = abs(bs2) > 1.e-8f; + + float_v sB(0.f), cB(0.f); + sB(bs1Big) = sss/bq1; + cB(bs1Big) = (1.f-ccc)/bq1; + sB(!bs1Big) = ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS[0]); + cB(!bs1Big) = .5f*sB*bs1; + + const float_v& x1 = x01 + sB*px1 + cB*py1; + const float_v& y1 = y01 - cB*px1 + sB*py1; + const float_v& z1 = z01 + dS[0]*pz1; + const float_v& ppx1 = ccc*px1 + sss*py1; + const float_v& ppy1 = -sss*px1 + ccc*py1; + const float_v& ppz1 = pz1; + + float_v sss1 = sin(bs2), ccc1 = cos(bs2); + + float_v sB1(0.f), cB1(0.f); + sB1(bs2Big) = sss1/bq2; + cB1(bs2Big) = (1.f-ccc1)/bq2; + sB1(!bs2Big) = ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS[1]); + cB1(!bs2Big) = .5f*sB1*bs2; + + const float_v& x2 = x02 + sB1*px2 + cB1*py2; + const float_v& y2 = y02 - cB1*px2 + sB1*py2; + const float_v& z2 = z02 + dS[1]*pz2; + const float_v& ppx2 = ccc1*px2 + sss1*py2; + const float_v& ppy2 = -sss1*px2 + ccc1*py2; + const float_v& ppz2 = pz2; + + const float_v& p12 = ppx1*ppx1 + ppy1*ppy1 + ppz1*ppz1; + const float_v& p22 = ppx2*ppx2 + ppy2*ppy2 + ppz2*ppz2; + const float_v& lp1p2 = ppx1*ppx2 + ppy1*ppy2 + ppz1*ppz2; + + const float_v& dx = (x2 - x1); + const float_v& dy = (y2 - y1); + const float_v& dz = (z2 - z1); + + const float_v& ldrp1 = ppx1*dx + ppy1*dy + ppz1*dz; + const float_v& ldrp2 = ppx2*dx + ppy2*dy + ppz2*dz; + + float_v detp = lp1p2*lp1p2 - p12*p22; + detp(abs(detp)<1.e-4f) = 1; //TODO correct!!! + + //dsdr calculation + const float_v a1 = ldrp2*lp1p2 - ldrp1*p22; + const float_v a2 = ldrp2*p12 - ldrp1*lp1p2; + const float_v lp1p2_ds0 = bq1*( ppx2*ppy1 - ppy2*ppx1); + const float_v lp1p2_ds1 = bq2*( ppx1*ppy2 - ppy1*ppx2); + const float_v ldrp1_ds0 = -p12 + bq1*(ppy1*dx - ppx1*dy); + const float_v ldrp1_ds1 = lp1p2; + const float_v ldrp2_ds0 = -lp1p2; + const float_v ldrp2_ds1 = p22 + bq2*(ppy2*dx - ppx2*dy); + const float_v detp_ds0 = 2.f*lp1p2*lp1p2_ds0; + const float_v detp_ds1 = 2.f*lp1p2*lp1p2_ds1; + const float_v a1_ds0 = ldrp2_ds0*lp1p2 + ldrp2*lp1p2_ds0 - ldrp1_ds0*p22; + const float_v a1_ds1 = ldrp2_ds1*lp1p2 + ldrp2*lp1p2_ds1 - ldrp1_ds1*p22; + const float_v a2_ds0 = ldrp2_ds0*p12 - ldrp1_ds0*lp1p2 - ldrp1*lp1p2_ds0; + const float_v a2_ds1 = ldrp2_ds1*p12 - ldrp1_ds1*lp1p2 - ldrp1*lp1p2_ds1; + + const float_v dsl1ds0 = a1_ds0/detp - a1*detp_ds0/(detp*detp); + const float_v dsl1ds1 = a1_ds1/detp - a1*detp_ds1/(detp*detp); + const float_v dsl2ds0 = a2_ds0/detp - a2*detp_ds0/(detp*detp); + const float_v dsl2ds1 = a2_ds1/detp - a2*detp_ds1/(detp*detp); + + float_v dsldr[4][6]; + for(int iP=0; iP<6; iP++) + { + dsldr[0][iP] = dsl1ds0*dsdr[0][iP] + dsl1ds1*dsdr[2][iP]; + dsldr[1][iP] = dsl1ds0*dsdr[1][iP] + dsl1ds1*dsdr[3][iP]; + dsldr[2][iP] = dsl2ds0*dsdr[0][iP] + dsl2ds1*dsdr[2][iP]; + dsldr[3][iP] = dsl2ds0*dsdr[1][iP] + dsl2ds1*dsdr[3][iP]; + } + + for(int iDS=0; iDS<4; iDS++) + for(int iP=0; iP<6; iP++) + dsdr[iDS][iP] += dsldr[iDS][iP]; + + const float_v lp1p2_dr0[6] = {0.f, 0.f, 0.f, ccc*ppx2 - ppy2*sss, ccc*ppy2 + ppx2*sss, pz2}; + const float_v lp1p2_dr1[6] = {0.f, 0.f, 0.f, ccc1*ppx1 - ppy1*sss1, ccc1*ppy1 + ppx1*sss1, pz1}; + const float_v ldrp1_dr0[6] = {-ppx1, -ppy1, -pz1, cB*ppy1 - ppx1*sB + ccc*dx - sss*dy, -cB*ppx1-ppy1*sB + sss*dx + ccc*dy, -dS[0]*pz1 + dz}; + const float_v ldrp1_dr1[6] = { ppx1, ppy1, pz1, -cB1*ppy1 + ppx1*sB1, cB1*ppx1 + ppy1*sB1, dS[1]*pz1}; + const float_v ldrp2_dr0[6] = {-ppx2, -ppy2, -pz2, cB*ppy2 - ppx2*sB, -cB*ppx2-ppy2*sB, -dS[0]*pz2}; + const float_v ldrp2_dr1[6] = { ppx2, ppy2, pz2, -cB1*ppy2 + ppx2*sB1 + ccc1*dx- sss1*dy, cB1*ppx2 + ppy2*sB1 + sss1*dx + ccc1*dy, dz + dS[1]*pz2}; + const float_v p12_dr0[6] = {0.f, 0.f, 0.f, 2.f*px1, 2.f*py1, 2.f*pz1}; + const float_v p22_dr1[6] = {0.f, 0.f, 0.f, 2.f*px2, 2.f*py2, 2.f*pz2}; + float_v a1_dr0[6], a1_dr1[6], a2_dr0[6], a2_dr1[6], detp_dr0[6], detp_dr1[6]; + for(int iP=0; iP<6; iP++) + { + a1_dr0[iP] = ldrp2_dr0[iP]*lp1p2 + ldrp2*lp1p2_dr0[iP] - ldrp1_dr0[iP]*p22; + a1_dr1[iP] = ldrp2_dr1[iP]*lp1p2 + ldrp2*lp1p2_dr1[iP] - ldrp1_dr1[iP]*p22 - ldrp1*p22_dr1[iP]; + a2_dr0[iP] = ldrp2_dr0[iP]*p12 + ldrp2*p12_dr0[iP] - ldrp1_dr0[iP]*lp1p2 - ldrp1*lp1p2_dr0[iP]; + a2_dr1[iP] = ldrp2_dr1[iP]*p12 - ldrp1_dr1[iP]*lp1p2 - ldrp1*lp1p2_dr1[iP]; + detp_dr0[iP] = 2.f*lp1p2*lp1p2_dr0[iP] - p12_dr0[iP]*p22; + detp_dr1[iP] = 2.f*lp1p2*lp1p2_dr1[iP] - p12*p22_dr1[iP]; + + dsdr[0][iP] += a1_dr0[iP]/detp - a1*detp_dr0[iP]/(detp*detp); + dsdr[1][iP] += a1_dr1[iP]/detp - a1*detp_dr1[iP]/(detp*detp); + dsdr[2][iP] += a2_dr0[iP]/detp - a2*detp_dr0[iP]/(detp*detp); + dsdr[3][iP] += a2_dr1[iP]/detp - a2*detp_dr1[iP]/(detp*detp); + } + + dS[0] += (ldrp2*lp1p2 - ldrp1*p22) /detp; + dS[1] += (ldrp2*p12 - ldrp1*lp1p2)/detp; + } +} + +void KFParticleBaseSIMD::GetDStoParticleBz( float_v B, const KFParticleBaseSIMD &p, + float_v dS[2], const float_v* param1, const float_v* param2 ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field Bz. dS[0] is the transport parameter for the current particle, + ** dS[1] - for the particle "p". + ** Parameters param1 and param2 should be either provided both or both set to null pointers. + ** \param[in] B - magnetic field Bz + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[in] param1 - optional parameter, is used in case if the parameters of the current particles are rotated + ** to other coordinate system (see GetDStoParticleBy() function), otherwise fP are used + ** \param[in] param2 - optional parameter, is used in case if the parameters of the second particles are rotated + ** to other coordinate system (see GetDStoParticleBy() function), otherwise p.fP are used + **/ + + if(!param1) + { + param1 = fP; + param2 = p.fP; + } + + //* Get dS to another particle for Bz field + const float_v kOvSqr6 = 1.f/sqrt(float_v(6.f)); + const float_v kCLight = 0.000299792458f; + + //in XY plane + //first root + const float_v& bq1 = B*simd_cast<float_v>(fQ)*kCLight; + const float_v& bq2 = B*simd_cast<float_v>(p.fQ)*kCLight; + + const float_m& isStraight1 = abs(bq1) < float_v(1.e-8f); + const float_m& isStraight2 = abs(bq2) < float_v(1.e-8f); + + if( isStraight1.isFull() && isStraight2.isFull() ) + { + GetDStoParticleLine(p, dS); + return; + } + + const float_v& px1 = param1[3]; + const float_v& py1 = param1[4]; + const float_v& pz1 = param1[5]; + + const float_v& px2 = param2[3]; + const float_v& py2 = param2[4]; + const float_v& pz2 = param2[5]; + + const float_v& pt12 = px1*px1 + py1*py1; + const float_v& pt22 = px2*px2 + py2*py2; + + const float_v& x01 = param1[0]; + const float_v& y01 = param1[1]; + const float_v& z01 = param1[2]; + + const float_v& x02 = param2[0]; + const float_v& y02 = param2[1]; + const float_v& z02 = param2[2]; + + float_v dS1[2] = {0.f, 0.f}, dS2[2]={0.f, 0.f}; + + const float_v& dx0 = (x01 - x02); + const float_v& dy0 = (y01 - y02); + const float_v& dr02 = dx0*dx0 + dy0*dy0; + const float_v& drp1 = dx0*px1 + dy0*py1; + const float_v& dxyp1 = dx0*py1 - dy0*px1; + const float_v& drp2 = dx0*px2 + dy0*py2; + const float_v& dxyp2 = dx0*py2 - dy0*px2; + const float_v& p1p2 = px1*px2 + py1*py2; + const float_v& dp1p2 = px1*py2 - px2*py1; + + const float_v& k11 = (bq2*drp1 - dp1p2); + const float_v& k21 = (bq1*(bq2*dxyp1 - p1p2) + bq2*pt12); + const float_v& k12 = ((bq1*drp2 - dp1p2)); + const float_v& k22 = (bq2*(bq1*dxyp2 + p1p2) - bq1*pt22); + + const float_v& kp = (dxyp1*bq2 - dxyp2*bq1 - p1p2); + const float_v& kd = dr02/2.f*bq1*bq2 + kp; + const float_v& c1 = -(bq1*kd + pt12*bq2); + const float_v& c2 = bq2*kd + pt22*bq1; + + float_v d1 = pt12*pt22 - kd*kd; + d1(d1 < float_v(Vc::Zero)) = float_v(Vc::Zero); + d1 = sqrt( d1 ); + float_v d2 = pt12*pt22 - kd*kd; + d2(d2 < float_v(Vc::Zero)) = float_v(Vc::Zero); + d2 = sqrt( d2 ); + + // find two points of closest approach in XY plane + if( ! ( (!isStraight1).isEmpty() ) ) + { + dS1[0](!isStraight1) = KFPMath::ATan2( (bq1*k11*c1 + k21*d1*bq1), (bq1*k11*d1*bq1 - k21*c1) )/bq1; + dS1[1](!isStraight1) = KFPMath::ATan2( (bq1*k11*c1 - k21*d1*bq1), (-bq1*k11*d1*bq1 - k21*c1) )/bq1; + } + if( ! ( (!isStraight2).isEmpty() ) ) + { + dS2[0](!isStraight2) = KFPMath::ATan2( (bq2*k12*c2 + k22*d2*bq2), (bq2*k12*d2*bq2 - k22*c2) )/bq2; + dS2[1](!isStraight2) = KFPMath::ATan2( (bq2*k12*c2 - k22*d2*bq2), (-bq2*k12*d2*bq2 - k22*c2) )/bq2; + } + if( ! ( isStraight1.isEmpty() ) ) + { + dS1[0](isStraight1 && (pt12>float_v(Vc::Zero)) ) = (k11*c1 + k21*d1)/(- k21*c1); + dS1[1](isStraight1 && (pt12>float_v(Vc::Zero)) ) = (k11*c1 - k21*d1)/(- k21*c1); + } + if( ! ( isStraight2.isEmpty() ) ) + { + dS2[0](isStraight2 && (pt22>float_v(Vc::Zero)) ) = (k12*c2 + k22*d2)/(- k22*c2); + dS2[1](isStraight2 && (pt22>float_v(Vc::Zero)) ) = (k12*c2 - k22*d2)/(- k22*c2); + } + + //select a point which is close to the primary vertex (with the smallest r) + + float_v dr2[2]; + for(int iP = 0; iP<2; iP++) + { + const float_v& bs1 = bq1*dS1[iP]; + const float_v& bs2 = bq2*dS2[iP]; + float_v sss = KFPMath::Sin(bs1), ccc = KFPMath::Cos(bs1); + + const float_m& bs1Big = abs(bs1) > 1.e-8f; + const float_m& bs2Big = abs(bs2) > 1.e-8f; + + float_v sB(Vc::Zero), cB(Vc::Zero); + sB(bs1Big) = sss/bq1; + sB(!bs1Big) = ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS1[iP]); + cB(bs1Big) = (1.f-ccc)/bq1; + cB(!bs1Big) = .5f*sB*bs1; + + const float_v& x1 = param1[0] + sB*px1 + cB*py1; + const float_v& y1 = param1[1] - cB*px1 + sB*py1; + const float_v& z1 = param1[2] + dS1[iP]*param1[5]; + + sss = KFPMath::Sin(bs2); ccc = KFPMath::Cos(bs2); + + sB(bs2Big) = sss/bq2; + sB(!bs2Big) = ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS2[iP]); + cB(bs2Big) = (1.f-ccc)/bq2; + cB(!bs2Big) = .5f*sB*bs2; + + const float_v& x2 = param2[0] + sB*px2 + cB*py2; + const float_v& y2 = param2[1] - cB*px2 + sB*py2; + const float_v& z2 = param2[2] + dS2[iP]*param2[5]; + + float_v dx = (x1-x2); + float_v dy = (y1-y2); + float_v dz = (z1-z2); + + dr2[iP] = dx*dx + dy*dy + dz*dz; + } + + + const float_m isFirstRoot = (dr2[0] < dr2[1]); + + // if(!(isFirstRoot.isEmpty())) + { + dS[0](isFirstRoot) = dS1[0]; + dS[1](isFirstRoot) = dS2[0]; + } + // if( !( (!isFirstRoot).isEmpty() ) ) + { + dS[0](!isFirstRoot) = dS1[1]; + dS[1](!isFirstRoot) = dS2[1]; + } + + //find correct parts of helices + int_v n1(Vc::Zero); + int_v n2(Vc::Zero); +// float_v dzMin = abs( (z01-z02) + dS[0]*pz1 - dS[1]*pz2 ); + const float_v pi2(6.283185307f); + +// //TODO optimise for loops for neutral particles +// const float_v& i1Float = -bq1/pi2*(z01/pz1+dS[0]); +// for(int di1=-1; di1<=1; di1++) +// { +// int_v i1(Vc::Zero); +// i1(int_m(!isStraight1)) = int_v(i1Float) + di1; +// +// const float_v& i2Float = ( ((z01-z02) + (dS[0]+pi2*i1/bq1)*pz1)/pz2 - dS[1]) * bq2/pi2; +// for(int di2 = -1; di2<=1; di2++) +// { +// int_v i2(Vc::Zero); +// i2(int_m(!isStraight2)) = int_v(i2Float) + di2; +// +// const float_v& z1 = z01 + (dS[0]+pi2*i1/bq1)*pz1; +// const float_v& z2 = z02 + (dS[1]+pi2*i2/bq2)*pz2; +// const float_v& dz = abs( z1-z2 ); +// +// n1(int_m(dz < dzMin)) = i1; +// n2(int_m(dz < dzMin)) = i2; +// dzMin(dz < dzMin) = dz; +// } +// } +// +// dS[0](!isStraight1) += float_v(n1)*pi2/bq1; +// dS[1](!isStraight2) += float_v(n2)*pi2/bq2; + + //Line correction + { + const float_v& bs1 = bq1*dS[0]; + const float_v& bs2 = bq2*dS[1]; + float_v sss = KFPMath::Sin(bs1), ccc = KFPMath::Cos(bs1); + + const float_m& bs1Big = abs(bs1) > 1.e-8f; + const float_m& bs2Big = abs(bs2) > 1.e-8f; + + float_v sB(0.f), cB(0.f); + sB(bs1Big) = sss/bq1; + cB(bs1Big) = (1.f-ccc)/bq1; + sB(!bs1Big) = ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS[0]); + cB(!bs1Big) = .5f*sB*bs1; + + const float_v& x1 = x01 + sB*px1 + cB*py1; + const float_v& y1 = y01 - cB*px1 + sB*py1; + const float_v& z1 = z01 + dS[0]*pz1; + const float_v& ppx1 = ccc*px1 + sss*py1; + const float_v& ppy1 = -sss*px1 + ccc*py1; + const float_v& ppz1 = pz1; + + float_v sss1 = KFPMath::Sin(bs2), ccc1 = KFPMath::Cos(bs2); + + float_v sB1(0.f), cB1(0.f); + sB1(bs2Big) = sss1/bq2; + cB1(bs2Big) = (1.f-ccc1)/bq2; + sB1(!bs2Big) = ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS[1]); + cB1(!bs2Big) = .5f*sB1*bs2; + + const float_v& x2 = x02 + sB1*px2 + cB1*py2; + const float_v& y2 = y02 - cB1*px2 + sB1*py2; + const float_v& z2 = z02 + dS[1]*pz2; + const float_v& ppx2 = ccc1*px2 + sss1*py2; + const float_v& ppy2 = -sss1*px2 + ccc1*py2; + const float_v& ppz2 = pz2; + + const float_v& p12 = ppx1*ppx1 + ppy1*ppy1 + ppz1*ppz1; + const float_v& p22 = ppx2*ppx2 + ppy2*ppy2 + ppz2*ppz2; + const float_v& lp1p2 = ppx1*ppx2 + ppy1*ppy2 + ppz1*ppz2; + + const float_v& dx = (x2 - x1); + const float_v& dy = (y2 - y1); + const float_v& dz = (z2 - z1); + + const float_v& ldrp1 = ppx1*dx + ppy1*dy + ppz1*dz; + const float_v& ldrp2 = ppx2*dx + ppy2*dy + ppz2*dz; + + float_v detp = lp1p2*lp1p2 - p12*p22; + detp(abs(detp)<1.e-4f) = 1; //TODO correct!!! + + dS[0] += (ldrp2*lp1p2 - ldrp1*p22) /detp; + dS[1] += (ldrp2*p12 - ldrp1*lp1p2)/detp; + } +} + +void KFParticleBaseSIMD::GetDStoParticleBy( float_v B, const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field By. dS[0] is the transport parameter for the current particle, + ** dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. + ** The particle parameters are transformed to the coordinate system, where the main component of the magnetic field + ** By is directed along the Z axis: x->x, y->-z, z->y, and the function GetDStoPointBz() is called. Derivatives dsdr are transformed back + ** to the coordinate system of the particle. + ** \param[in] B - magnetic field By + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ + + const float_v param1[6] = { fP[0], -fP[2], fP[1], fP[3], -fP[5], fP[4] }; + const float_v param2[6] = { p.fP[0], -p.fP[2], p.fP[1], p.fP[3], -p.fP[5], p.fP[4] }; + + float_v dsdrBz[4][6]; + for(int i1=0; i1<4; i1++) + for(int i2=0; i2<6; i2++) + dsdrBz[i1][i2] = 0.f; + + GetDStoParticleBz(B, p, dS, dsdrBz, param1, param2); + + for(int iDs=0; iDs<4; iDs++) + { + dsdr[iDs][0] = dsdrBz[iDs][0]; + dsdr[iDs][1] = dsdrBz[iDs][2]; + dsdr[iDs][2] = -dsdrBz[iDs][1]; + dsdr[iDs][3] = dsdrBz[iDs][3]; + dsdr[iDs][4] = dsdrBz[iDs][5]; + dsdr[iDs][5] = -dsdrBz[iDs][4]; + } +} + +void KFParticleBaseSIMD::GetDStoParticleBy( float_v B, const KFParticleBaseSIMD &p, float_v dS[2] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field By. dS[0] is the transport parameter for the current particle, + ** dS[1] - for the particle "p". + ** The particle parameters are transformed to the coordinate system, where the main component of the magnetic field + ** By is directed along the Z axis: x->x, y->-z, z->y, and the function GetDStoPointBz() is called. + ** \param[in] B - magnetic field By + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + **/ + + const float_v param1[6] = { fP[0], -fP[2], fP[1], fP[3], -fP[5], fP[4] }; + const float_v param2[6] = { p.fP[0], -p.fP[2], p.fP[1], p.fP[3], -p.fP[5], p.fP[4] }; + + GetDStoParticleBz(B, p, dS, param1, param2); +} + +void KFParticleBaseSIMD::GetDStoParticleB( float_v B[3], const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field By. dS[0] is the transport parameter for the current particle, + ** dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. + ** The particle parameters are transformed to the coordinate system, where the magnetic field B + ** is directed along the Z axis and the function GetDStoPointBz() is called. Derivatives dsdr are transformed back + ** to the coordinate system of the particle. + ** \param[in] B - magnetic field By + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ + + const float_v& Bx = B[0]; + const float_v& By = B[1]; + const float_v& Bz = B[2]; + + const float_v& Bxz = sqrt(Bx*Bx + Bz*Bz); + const float_v& Br = sqrt(Bx*Bx + By*By + Bz*Bz); + + float_v cosA = 1.f; + float_v sinA = 0.f; + + cosA( abs(Bxz) > 1.e-8f ) = Bz/Bxz; + sinA( abs(Bxz) > 1.e-8f ) = Bx/Bxz; + + const float_v& sinP = By/Br; + const float_v& cosP = Bxz/Br; + + + const float_v param1[6] = { cosA*fP[0] - sinA*fP[2], + -sinA*sinP*fP[0] + cosP*fP[1] - cosA*sinP*fP[2], + cosP*sinA*fP[0] + sinP*fP[1] + cosA*cosP*fP[2], + cosA*fP[3] - sinA*fP[5], + -sinA*sinP*fP[3] + cosP*fP[4] - cosA*sinP*fP[5], + cosP*sinA*fP[3] + sinP*fP[4] + cosA*cosP*fP[5]}; + const float_v param2[6] = { cosA*p.fP[0] - sinA*p.fP[2], + -sinA*sinP*p.fP[0] + cosP*p.fP[1] - cosA*sinP*p.fP[2], + cosP*sinA*p.fP[0] + sinP*p.fP[1] + cosA*cosP*p.fP[2], + cosA*p.fP[3] - sinA*p.fP[5], + -sinA*sinP*p.fP[3] + cosP*p.fP[4] - cosA*sinP*p.fP[5], + cosP*sinA*p.fP[3] + sinP*p.fP[4] + cosA*cosP*p.fP[5]}; + + float_v dsdrBz[4][6]; + for(int i1=0; i1<4; i1++) + for(int i2=0; i2<6; i2++) + dsdrBz[i1][i2] = 0.f; + + GetDStoParticleBz(Br, p, dS, dsdrBz, param1, param2); + + for(int iDs=0; iDs<4; iDs++) + { + dsdr[iDs][0] = dsdrBz[iDs][0]*cosA - dsdrBz[iDs][1]*sinA*sinP + dsdrBz[iDs][2]*sinA*cosP; + dsdr[iDs][1] = dsdrBz[iDs][1]*cosP + dsdrBz[iDs][2]*sinP; + dsdr[iDs][2] = -dsdrBz[iDs][0]*sinA - dsdrBz[iDs][1]*cosA*sinP + dsdrBz[iDs][2]*cosA*cosP; + dsdr[iDs][3] = dsdrBz[iDs][3]*cosA - dsdrBz[iDs][4]*sinA*sinP + dsdrBz[iDs][5]*sinA*cosP; + dsdr[iDs][4] = dsdrBz[iDs][4]*cosP + dsdrBz[iDs][5]*sinP; + dsdr[iDs][5] = -dsdrBz[iDs][3]*sinA - dsdrBz[iDs][4]*cosA*sinP + dsdrBz[iDs][5]*cosA*cosP; + } +} + +void KFParticleBaseSIMD::GetDStoParticleB( float_v B[3], const KFParticleBaseSIMD &p, float_v dS[2] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the constant homogeneous field By. dS[0] is the transport parameter for the current particle, + ** dS[1] - for the particle "p". + ** The particle parameters are transformed to the coordinate system, where the magnetic field B + ** is directed along the Z axis and the function GetDStoPointBz() is called. + ** \param[in] B - magnetic field By + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + **/ + + const float_v& Bx = B[0]; + const float_v& By = B[1]; + const float_v& Bz = B[2]; + + const float_v& Bxz = sqrt(Bx*Bx + Bz*Bz); + const float_v& Br = sqrt(Bx*Bx + By*By + Bz*Bz); + + float_v cosA = 1.f; + float_v sinA = 0.f; + + cosA( abs(Bxz) > 1.e-8f ) = Bz/Bxz; + sinA( abs(Bxz) > 1.e-8f ) = Bx/Bxz; + + const float_v& sinP = By/Br; + const float_v& cosP = Bxz/Br; + + + const float_v param1[6] = { cosA*fP[0] - sinA*fP[2], + -sinA*sinP*fP[0] + cosP*fP[1] - cosA*sinP*fP[2], + cosP*sinA*fP[0] + sinP*fP[1] + cosA*cosP*fP[2], + cosA*fP[3] - sinA*fP[5], + -sinA*sinP*fP[3] + cosP*fP[4] - cosA*sinP*fP[5], + cosP*sinA*fP[3] + sinP*fP[4] + cosA*cosP*fP[5]}; + const float_v param2[6] = { cosA*p.fP[0] - sinA*p.fP[2], + -sinA*sinP*p.fP[0] + cosP*p.fP[1] - cosA*sinP*p.fP[2], + cosP*sinA*p.fP[0] + sinP*p.fP[1] + cosA*cosP*p.fP[2], + cosA*p.fP[3] - sinA*p.fP[5], + -sinA*sinP*p.fP[3] + cosP*p.fP[4] - cosA*sinP*p.fP[5], + cosP*sinA*p.fP[3] + sinP*p.fP[4] + cosA*cosP*p.fP[5]}; + + GetDStoParticleBz(Br, p, dS, param1, param2); +} + +void KFParticleBaseSIMD::GetDStoParticleLine( const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the straight line trajectory. Is used for particles with charge 0 or in case of zero magnetic field. + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ + + float_v p12 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + float_v p22 = p.fP[3]*p.fP[3] + p.fP[4]*p.fP[4] + p.fP[5]*p.fP[5]; + float_v p1p2 = fP[3]*p.fP[3] + fP[4]*p.fP[4] + fP[5]*p.fP[5]; + + float_v drp1 = fP[3]*(p.fP[0]-fP[0]) + fP[4]*(p.fP[1]-fP[1]) + fP[5]*(p.fP[2]-fP[2]); + float_v drp2 = p.fP[3]*(p.fP[0]-fP[0]) + p.fP[4]*(p.fP[1]-fP[1]) + p.fP[5]*(p.fP[2]-fP[2]); + + float_v detp = p1p2*p1p2 - p12*p22; + detp( abs(detp)<float_v(1.e-4f) ) = float_v(1.f); //TODO correct!!! + + dS[0] = (drp2*p1p2 - drp1*p22) /detp; + dS[1] = (drp2*p12 - drp1*p1p2)/detp; + + const float_v x01 = fP[0]; + const float_v y01 = fP[1]; + const float_v z01 = fP[2]; + const float_v px1 = fP[3]; + const float_v py1 = fP[4]; + const float_v pz1 = fP[5]; + + const float_v x02 = p.fP[0]; + const float_v y02 = p.fP[1]; + const float_v z02 = p.fP[2]; + const float_v px2 = p.fP[3]; + const float_v py2 = p.fP[4]; + const float_v pz2 = p.fP[5]; + + const float_v drp1_dr1[6] = {-px1, -py1, -pz1, -x01 + x02, -y01 + y02, -z01 + z02}; + const float_v drp1_dr2[6] = {px1, py1, pz1, 0.f, 0.f, 0.f}; + const float_v drp2_dr1[6] = {-px2, -py2, -pz2, 0.f, 0.f, 0.f}; + const float_v drp2_dr2[6] = {px2, py2, pz2, -x01 + x02, -y01 + y02, -z01 + z02}; + const float_v dp1p2_dr1[6] = {0.f, 0.f, 0.f, px2, py2, pz2}; + const float_v dp1p2_dr2[6] = {0.f, 0.f, 0.f, px1, py1, pz1}; + const float_v dp12_dr1[6] = {0.f, 0.f, 0.f, 2.f*px1, 2.f*py1, 2.f*pz1}; + const float_v dp12_dr2[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + const float_v dp22_dr1[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + const float_v dp22_dr2[6] = {0.f, 0.f, 0.f, 2.f*px2, 2.f*py2, 2.f*pz2}; + const float_v ddetp_dr1[6] = {0.f, 0.f, 0.f, -2.f*p22*px1 + 2.f*p1p2*px2, -2.f*p22*py1 + 2.f*p1p2*py2, -2.f*p22*pz1 + 2.f*p1p2*pz2}; + const float_v ddetp_dr2[6] = {0.f, 0.f, 0.f, 2.f*p1p2*px1 - 2.f*p12*px2, 2.f*p1p2*py1 - 2.f*p12*py2, 2.f*p1p2*pz1 - 2.f*p12*pz2}; + + + float_v da1_dr1[6], da1_dr2[6], da2_dr1[6], da2_dr2[6]; + + const float_v a1 = drp2*p1p2 - drp1*p22; + const float_v a2 = drp2*p12 - drp1*p1p2; + for(int i=0; i<6; i++) + { + da1_dr1[i] = drp2_dr1[i]*p1p2 + drp2*dp1p2_dr1[i] - drp1_dr1[i]*p22 - drp1*dp22_dr1[i]; + da1_dr2[i] = drp2_dr2[i]*p1p2 + drp2*dp1p2_dr2[i] - drp1_dr2[i]*p22 - drp1*dp22_dr2[i]; + + da2_dr1[i] = drp2_dr1[i]*p12 + drp2*dp12_dr1[i] - drp1_dr1[i]*p1p2 - drp1*dp1p2_dr1[i]; + da2_dr2[i] = drp2_dr2[i]*p12 + drp2*dp12_dr2[i] - drp1_dr2[i]*p1p2 - drp1*dp1p2_dr2[i]; + + dsdr[0][i] = da1_dr1[i]/detp - a1/(detp*detp)*ddetp_dr1[i]; + dsdr[1][i] = da1_dr2[i]/detp - a1/(detp*detp)*ddetp_dr2[i]; + + dsdr[2][i] = da2_dr1[i]/detp - a2/(detp*detp)*ddetp_dr1[i]; + dsdr[3][i] = da2_dr2[i]/detp - a2/(detp*detp)*ddetp_dr2[i]; + } +} + +void KFParticleBaseSIMD::GetDStoParticleLine( const KFParticleBaseSIMD &p, float_v dS[2] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** under the assumption of the straight line trajectory. Is used for particles with charge 0 or in case of zero magnetic field. + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + **/ + + float_v p12 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + float_v p22 = p.fP[3]*p.fP[3] + p.fP[4]*p.fP[4] + p.fP[5]*p.fP[5]; + float_v p1p2 = fP[3]*p.fP[3] + fP[4]*p.fP[4] + fP[5]*p.fP[5]; + + float_v drp1 = fP[3]*(p.fP[0]-fP[0]) + fP[4]*(p.fP[1]-fP[1]) + fP[5]*(p.fP[2]-fP[2]); + float_v drp2 = p.fP[3]*(p.fP[0]-fP[0]) + p.fP[4]*(p.fP[1]-fP[1]) + p.fP[5]*(p.fP[2]-fP[2]); + + float_v detp = p1p2*p1p2 - p12*p22; + detp( abs(detp)<float_v(1.e-4f) ) = float_v(1.f); //TODO correct!!! + + dS[0] = (drp2*p1p2 - drp1*p22) /detp; + dS[1] = (drp2*p12 - drp1*p1p2)/detp; +} + +void KFParticleBaseSIMD::GetDStoParticleCBM( const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** in case of the CBM-like nonhomogeneous magnetic field. + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. + ** For this the y-component of the magnetic field at the position of the current particle is obtained and + ** the GetDStoParticleBy() is called. It is assumed that particles are already close to each other and that the difference + ** in magnetic field approximation between two particles can be neglected. If the charge of both particles + ** is zero or if the magnetic field is zero the function GetDStoParticleLine() is called. + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ + + float_v fld[3]; + GetFieldValue( fP, fld ); + + const float_v& bq1 = fld[1]*simd_cast<float_v>(fQ); + const float_v& bq2 = fld[1]*simd_cast<float_v>(p.fQ); + const float_m& isStraight1 = abs(bq1) < float_v(1.e-8f); + const float_m& isStraight2 = abs(bq2) < float_v(1.e-8f); + + if( isStraight1.isFull() && isStraight2.isFull() ) + GetDStoParticleLine(p, dS, dsdr); + else + GetDStoParticleBy(fld[1], p, dS, dsdr); +} + +void KFParticleBaseSIMD::GetDStoParticleCBM( const KFParticleBaseSIMD &p, float_v dS[2] ) const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particle; \n + ** in case of the CBM-like nonhomogeneous magnetic field. + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** For this the y-component of the magnetic field at the position of the current particle is obtained and + ** the GetDStoParticleBy() is called. It is assumed that particles are already close to each other and that the difference + ** in magnetic field approximation between two particles can be neglected. If the charge of both particles + ** is zero or if the magnetic field is zero the function GetDStoParticleLine() is called. + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + **/ + + float_v fld[3]; + GetFieldValue( fP, fld ); + + const float_v& bq1 = fld[1]*simd_cast<float_v>(fQ); + const float_v& bq2 = fld[1]*simd_cast<float_v>(p.fQ); + const float_m& isStraight1 = abs(bq1) < float_v(1.e-8f); + const float_m& isStraight2 = abs(bq2) < float_v(1.e-8f); + + if( isStraight1.isFull() && isStraight2.isFull() ) + GetDStoParticleLine(p, dS); + else + GetDStoParticleBy(fld[1], p, dS); +} + +void KFParticleBaseSIMD::TransportCBM( float_v dS, const float_v* dsdr, float_v P[], float_v C[], float_v* dsdr1, float_v* F, float_v* F1 ) const +{ + /** Transports the parameters and their covariance matrix of the current particle assuming CBM-like nonhomogeneous + ** magnetic field on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters and covariance matrix are stored to the arrays P and + ** C respectively. P and C can be set to the parameters fP and covariance matrix fC of the current particle. In this + ** case the particle parameters will be modified. Dependence of the transport parameter dS on the state vector of the + ** current particle is taken into account in the covariance matrix using partial derivatives dsdr = d(dS)/d(fP). If + ** a pointer to F is initialised the transport jacobian F = d(fP new)/d(fP old) is stored. + ** Since dS can depend on the state vector r1 of other particle or vertex, the corelation matrix + ** F1 = d(fP new)/d(r1) can be optionally calculated if a pointer F1 is provided. + * Parameters F and F1 should be either both initialised or both set to null pointer. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[in] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + ** \param[out] P[8] - array, where transported parameters should be stored + ** \param[out] C[36] - array, where transported covariance matrix (8x8) should be stored in the lower triangular form + ** \param[in] dsdr1[6] = ds/dr - partial derivatives of the parameter dS over the state vector of another particle + ** or vertex + ** \param[out] F[36] - optional parameter, transport jacobian, 6x6 matrix F = d(fP new)/d(fP old) + ** \param[out] F1[36] - optional parameter, corelation 6x6 matrix betweeen the current particle and particle or vertex + ** with the state vector r1, to which the current particle is being transported, F1 = d(fP new)/d(r1) + **/ + + if( (fQ == int_v(Vc::Zero)).isFull() ){ + TransportLine( dS, dsdr, P, C, dsdr1, F, F1 ); + return; + } + + const float_v kCLight = 0.000299792458f; + + float_v c = simd_cast<float_v>(fQ)*kCLight; + + // construct coefficients + + float_v + px = fP[3], + py = fP[4], + pz = fP[5]; + + float_v sx=0.f, sy=0.f, sz=0.f, syy=0.f, syz=0.f, syyy=0.f, ssx=0.f, ssy=0.f, ssz=0.f, ssyy=0.f, ssyz=0.f, ssyyy=0.f; + + { // get field integrals + + float_v fld[3][3]; + float_v p0[3], p1[3], p2[3]; + + // line track approximation + + p0[0] = fP[0]; + p0[1] = fP[1]; + p0[2] = fP[2]; + + p2[0] = fP[0] + px*dS; + p2[1] = fP[1] + py*dS; + p2[2] = fP[2] + pz*dS; + + p1[0] = 0.5f*(p0[0]+p2[0]); + p1[1] = 0.5f*(p0[1]+p2[1]); + p1[2] = 0.5f*(p0[2]+p2[2]); + + // first order track approximation + { + GetFieldValue( p0, fld[0] ); + GetFieldValue( p1, fld[1] ); + GetFieldValue( p2, fld[2] ); + + float_v ssy1 = ( 7.f*fld[0][1] + 6.f*fld[1][1]-fld[2][1] )*c*dS*dS/96.f; + float_v ssy2 = ( fld[0][1] + 2.f*fld[1][1] )*c*dS*dS/6.f; + + p1[0] -= ssy1*pz; + p1[2] += ssy1*px; + p2[0] -= ssy2*pz; + p2[2] += ssy2*px; + } + + GetFieldValue( p0, fld[0] ); + GetFieldValue( p1, fld[1] ); + GetFieldValue( p2, fld[2] ); + + for(int iF1=0; iF1<3; iF1++) + for(int iF2=0; iF2<3; iF2++) + fld[iF1][iF2](abs(fld[iF1][iF2]) > float_v(100.f)) = 0.f; + + sx = c*( fld[0][0] + 4*fld[1][0] + fld[2][0] )*dS/6.f; + sy = c*( fld[0][1] + 4*fld[1][1] + fld[2][1] )*dS/6.f; + sz = c*( fld[0][2] + 4*fld[1][2] + fld[2][2] )*dS/6.f; + + ssx = c*( fld[0][0] + 2*fld[1][0])*dS*dS/6.f; + ssy = c*( fld[0][1] + 2*fld[1][1])*dS*dS/6.f; + ssz = c*( fld[0][2] + 2*fld[1][2])*dS*dS/6.f; + + float_v c2[3][3] = { { 5.f, -4.f, -1.f},{ 44.f, 80.f, -4.f},{ 11.f, 44.f, 5.f} }; // /=360. + float_v cc2[3][3] = { { 38.f, 8.f, -4.f},{ 148.f, 208.f, -20.f},{ 3.f, 36.f, 3.f} }; // /=2520. + for(Int_t n=0; n<3; n++) + for(Int_t m=0; m<3; m++) + { + syz += c2[n][m]*fld[n][1]*fld[m][2]; + ssyz += cc2[n][m]*fld[n][1]*fld[m][2]; + } + + syz *= c*c*dS*dS/360.f; + ssyz *= c*c*dS*dS*dS/2520.f; + + syy = c*( fld[0][1] + 4.f*fld[1][1] + fld[2][1] )*dS; + syyy = syy*syy*syy / 1296.f; + syy = syy*syy/72.f; + + ssyy = ( fld[0][1]*( 38.f*fld[0][1] + 156.f*fld[1][1] - fld[2][1] )+ + fld[1][1]*( 208.f*fld[1][1] +16.f*fld[2][1] )+ + fld[2][1]*( 3.f*fld[2][1] ) + )*dS*dS*dS*c*c/2520.f; + ssyyy = + ( + fld[0][1]*( fld[0][1]*( 85.f*fld[0][1] + 526.f*fld[1][1] - 7.f*fld[2][1] )+ + fld[1][1]*( 1376.f*fld[1][1] +84.f*fld[2][1] )+ + fld[2][1]*( 19.f*fld[2][1] ) )+ + fld[1][1]*( fld[1][1]*( 1376.f*fld[1][1] +256.f*fld[2][1] )+ + fld[2][1]*( 62.f*fld[2][1] ) )+ + fld[2][1]*fld[2][1] *( 3.f*fld[2][1] ) + )*dS*dS*dS*dS*c*c*c/90720.f; + + } + +// float_v mJ[11]; +// +// mJ[0]=dS-ssyy; mJ[1]=ssx; mJ[2]=ssyyy-ssy; +// mJ[3]=-ssz; mJ[4]=dS; mJ[5]=ssx+ssyz; +// +// mJ[6]=1-syy; mJ[7]=sx; mJ[8]=syyy-sy; +// mJ[9]=-sz; mJ[10]=sx+syz; +// +// +// +// P[0] = fP[0] + mJ[0]*px + mJ[1]*py + mJ[2]*pz; +// P[1] = fP[1] + mJ[3]*px + mJ[4]*py + mJ[5]*pz; +// P[2] = fP[2] - mJ[2]*px - mJ[1]*py + mJ[0]*pz; +// P[3] = mJ[6]*px + mJ[7]*py + mJ[8]*pz; +// P[4] = mJ[9]*px + py + mJ[10]*pz; +// P[5] = -mJ[8]*px - mJ[7]*py + mJ[6]*pz; +// P[6] = fP[6]; +// P[7] = fP[7]; + +// if(C!=fC) +// { +// for(int iC=0; iC<36; iC++) +// C[iC] = fC[iC]; +// } +// +// multQSQt1( mJ, C); + + float_v mJ[8][8]; + for( Int_t i=0; i<8; i++ ) for( Int_t j=0; j<8; j++) mJ[i][j]=0; + + mJ[0][0]=1; mJ[0][1]=0; mJ[0][2]=0; mJ[0][3]=dS-ssyy; mJ[0][4]=ssx; mJ[0][5]=ssyyy-ssy; + mJ[1][0]=0; mJ[1][1]=1; mJ[1][2]=0; mJ[1][3]=-ssz; mJ[1][4]=dS; mJ[1][5]=ssx+ssyz; + mJ[2][0]=0; mJ[2][1]=0; mJ[2][2]=1; mJ[2][3]=ssy-ssyyy; mJ[2][4]=-ssx; mJ[2][5]=dS-ssyy; + + mJ[3][0]=0; mJ[3][1]=0; mJ[3][2]=0; mJ[3][3]=1-syy; mJ[3][4]=sx; mJ[3][5]=syyy-sy; + mJ[4][0]=0; mJ[4][1]=0; mJ[4][2]=0; mJ[4][3]=-sz; mJ[4][4]=1; mJ[4][5]=sx+syz; + mJ[5][0]=0; mJ[5][1]=0; mJ[5][2]=0; mJ[5][3]=sy-syyy; mJ[5][4]=-sx; mJ[5][5]=1-syy; + mJ[6][6] = mJ[7][7] = 1; + + P[0] = fP[0] + mJ[0][3]*px + mJ[0][4]*py + mJ[0][5]*pz; + P[1] = fP[1] + mJ[1][3]*px + mJ[1][4]*py + mJ[1][5]*pz; + P[2] = fP[2] + mJ[2][3]*px + mJ[2][4]*py + mJ[2][5]*pz; + P[3] = mJ[3][3]*px + mJ[3][4]*py + mJ[3][5]*pz; + P[4] = mJ[4][3]*px + mJ[4][4]*py + mJ[4][5]*pz; + P[5] = mJ[5][3]*px + mJ[5][4]*py + mJ[5][5]*pz; + P[6] = fP[6]; + P[7] = fP[7]; + + float_v mJds[6][6]; + for( Int_t i=0; i<6; i++ ) for( Int_t j=0; j<6; j++) mJds[i][j]=0; + + mJds[0][3]= 1.f; + mJds[1][4]= 1.f; + mJds[2][5]= 1.f; + + mJds[0][3](abs(dS)>0.f)= 1.f - 3.f*ssyy/dS; mJds[0][4](abs(dS)>0.f)= 2.f*ssx/dS; mJds[0][5](abs(dS)>0.f)= (4.f*ssyyy-2.f*ssy)/dS; + mJds[1][3](abs(dS)>0.f)= -2.f*ssz/dS; mJds[1][4](abs(dS)>0.f)= 1.f; mJds[1][5](abs(dS)>0.f)= (2.f*ssx + 3.f*ssyz)/dS; + mJds[2][3](abs(dS)>0.f)= (2.f*ssy-4.f*ssyyy)/dS; mJds[2][4](abs(dS)>0.f)=-2.f*ssx/dS; mJds[2][5](abs(dS)>0.f)= 1.f - 3.f*ssyy/dS; + + mJds[3][3](abs(dS)>0.f)= -2.f*syy/dS; mJds[3][4](abs(dS)>0.f)= sx/dS; mJds[3][5](abs(dS)>0.f)= 3.f*syyy/dS - sy/dS; + mJds[4][3](abs(dS)>0.f)= -sz/dS; mJds[4][4](abs(dS)>0.f)=0.f; mJds[4][5](abs(dS)>0.f) = sx/dS + 2.f*syz/dS; + mJds[5][3](abs(dS)>0.f)= sy/dS - 3.f*syyy/dS; mJds[5][4](abs(dS)>0.f)=-sx/dS; mJds[5][5](abs(dS)>0.f)= -2.f*syy/dS; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + mJ[i1][i2] += mJds[i1][3]*px*dsdr[i2] + mJds[i1][4]*py*dsdr[i2] + mJds[i1][5]*pz*dsdr[i2]; + + MultQSQt( mJ[0], fC, C, 8); + + if(F) + { + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + F[i*6+j] = mJ[i][j]; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + F1[i1*6 + i2] = mJds[i1][3]*px*dsdr1[i2] + mJds[i1][4]*py*dsdr1[i2] + mJds[i1][5]*pz*dsdr1[i2]; + } +} + +void KFParticleBaseSIMD::TransportCBM( float_v dS, float_v P[] ) const +{ + /** Transports the parameters of the current particle assuming CBM-like nonhomogeneous + ** magnetic field on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters and covariance matrix are stored to the array P. + ** P can be set to the parameters fP. In this + ** case the particle parameters will be modified. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[out] P[8] - array, where transported parameters should be stored + **/ + if( (fQ == int_v(Vc::Zero)).isFull() ){ + TransportLine( dS, P ); + return; + } + + const float_v kCLight = 0.000299792458f; + + float_v c = simd_cast<float_v>(fQ)*kCLight; + + // construct coefficients + + float_v + px = fP[3], + py = fP[4], + pz = fP[5]; + + float_v sx=0.f, sy=0.f, sz=0.f, syy=0.f, syz=0.f, syyy=0.f, ssx=0.f, ssy=0.f, ssz=0.f, ssyy=0.f, ssyz=0.f, ssyyy=0.f; + + { // get field integrals + + float_v fld[3][3]; + float_v p0[3], p1[3], p2[3]; + + // line track approximation + + p0[0] = fP[0]; + p0[1] = fP[1]; + p0[2] = fP[2]; + + p2[0] = fP[0] + px*dS; + p2[1] = fP[1] + py*dS; + p2[2] = fP[2] + pz*dS; + + p1[0] = 0.5f*(p0[0]+p2[0]); + p1[1] = 0.5f*(p0[1]+p2[1]); + p1[2] = 0.5f*(p0[2]+p2[2]); + + // first order track approximation + { + GetFieldValue( p0, fld[0] ); + GetFieldValue( p1, fld[1] ); + GetFieldValue( p2, fld[2] ); + + float_v ssy1 = ( 7.f*fld[0][1] + 6.f*fld[1][1]-fld[2][1] )*c*dS*dS/96.f; + float_v ssy2 = ( fld[0][1] + 2.f*fld[1][1] )*c*dS*dS/6.f; + + p1[0] -= ssy1*pz; + p1[2] += ssy1*px; + p2[0] -= ssy2*pz; + p2[2] += ssy2*px; + } + + GetFieldValue( p0, fld[0] ); + GetFieldValue( p1, fld[1] ); + GetFieldValue( p2, fld[2] ); + + for(int iF1=0; iF1<3; iF1++) + for(int iF2=0; iF2<3; iF2++) + fld[iF1][iF2](abs(fld[iF1][iF2]) > float_v(100.f)) = 0.f; + + sx = c*( fld[0][0] + 4*fld[1][0] + fld[2][0] )*dS/6.f; + sy = c*( fld[0][1] + 4*fld[1][1] + fld[2][1] )*dS/6.f; + sz = c*( fld[0][2] + 4*fld[1][2] + fld[2][2] )*dS/6.f; + + ssx = c*( fld[0][0] + 2*fld[1][0])*dS*dS/6.f; + ssy = c*( fld[0][1] + 2*fld[1][1])*dS*dS/6.f; + ssz = c*( fld[0][2] + 2*fld[1][2])*dS*dS/6.f; + + float_v c2[3][3] = { { 5.f, -4.f, -1.f},{ 44.f, 80.f, -4.f},{ 11.f, 44.f, 5.f} }; // /=360. + float_v cc2[3][3] = { { 38.f, 8.f, -4.f},{ 148.f, 208.f, -20.f},{ 3.f, 36.f, 3.f} }; // /=2520. + for(Int_t n=0; n<3; n++) + for(Int_t m=0; m<3; m++) + { + syz += c2[n][m]*fld[n][1]*fld[m][2]; + ssyz += cc2[n][m]*fld[n][1]*fld[m][2]; + } + + syz *= c*c*dS*dS/360.f; + ssyz *= c*c*dS*dS*dS/2520.f; + + syy = c*( fld[0][1] + 4.f*fld[1][1] + fld[2][1] )*dS; + syyy = syy*syy*syy / 1296.f; + syy = syy*syy/72.f; + + ssyy = ( fld[0][1]*( 38.f*fld[0][1] + 156.f*fld[1][1] - fld[2][1] )+ + fld[1][1]*( 208.f*fld[1][1] +16.f*fld[2][1] )+ + fld[2][1]*( 3.f*fld[2][1] ) + )*dS*dS*dS*c*c/2520.f; + ssyyy = + ( + fld[0][1]*( fld[0][1]*( 85.f*fld[0][1] + 526.f*fld[1][1] - 7.f*fld[2][1] )+ + fld[1][1]*( 1376.f*fld[1][1] +84.f*fld[2][1] )+ + fld[2][1]*( 19.f*fld[2][1] ) )+ + fld[1][1]*( fld[1][1]*( 1376.f*fld[1][1] +256.f*fld[2][1] )+ + fld[2][1]*( 62.f*fld[2][1] ) )+ + fld[2][1]*fld[2][1] *( 3.f*fld[2][1] ) + )*dS*dS*dS*dS*c*c*c/90720.f; + + } + + float_v mJ[8][8]; + for( Int_t i=0; i<8; i++ ) for( Int_t j=0; j<8; j++) mJ[i][j]=0; + + mJ[0][0]=1; mJ[0][1]=0; mJ[0][2]=0; mJ[0][3]=dS-ssyy; mJ[0][4]=ssx; mJ[0][5]=ssyyy-ssy; + mJ[1][0]=0; mJ[1][1]=1; mJ[1][2]=0; mJ[1][3]=-ssz; mJ[1][4]=dS; mJ[1][5]=ssx+ssyz; + mJ[2][0]=0; mJ[2][1]=0; mJ[2][2]=1; mJ[2][3]=ssy-ssyyy; mJ[2][4]=-ssx; mJ[2][5]=dS-ssyy; + + mJ[3][0]=0; mJ[3][1]=0; mJ[3][2]=0; mJ[3][3]=1-syy; mJ[3][4]=sx; mJ[3][5]=syyy-sy; + mJ[4][0]=0; mJ[4][1]=0; mJ[4][2]=0; mJ[4][3]=-sz; mJ[4][4]=1; mJ[4][5]=sx+syz; + mJ[5][0]=0; mJ[5][1]=0; mJ[5][2]=0; mJ[5][3]=sy-syyy; mJ[5][4]=-sx; mJ[5][5]=1-syy; + mJ[6][6] = mJ[7][7] = 1; + + P[0] = fP[0] + mJ[0][3]*px + mJ[0][4]*py + mJ[0][5]*pz; + P[1] = fP[1] + mJ[1][3]*px + mJ[1][4]*py + mJ[1][5]*pz; + P[2] = fP[2] + mJ[2][3]*px + mJ[2][4]*py + mJ[2][5]*pz; + P[3] = mJ[3][3]*px + mJ[3][4]*py + mJ[3][5]*pz; + P[4] = mJ[4][3]*px + mJ[4][4]*py + mJ[4][5]*pz; + P[5] = mJ[5][3]*px + mJ[5][4]*py + mJ[5][5]*pz; + P[6] = fP[6]; + P[7] = fP[7]; +} + +void KFParticleBaseSIMD::TransportBz( float_v Bz, float_v dS, const float_v* dsdr, float_v P[], float_v C[], float_v* dsdr1, float_v* F, float_v* F1 ) const +{ + /** Transports the parameters and their covariance matrix of the current particle assuming constant homogeneous + ** magnetic field Bz on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters and covariance matrix are stored to the arrays P and + ** C respectively. P and C can be set to the parameters fP and covariance matrix fC of the current particle. In this + ** case the particle parameters will be modified. Dependence of the transport parameter dS on the state vector of the + ** current particle is taken into account in the covariance matrix using partial derivatives dsdr = d(dS)/d(fP). If + ** a pointer to F is initialised the transport jacobian F = d(fP new)/d(fP old) is stored. + ** Since dS can depend on the state vector r1 of other particle or vertex, the corelation matrix + ** F1 = d(fP new)/d(r1) can be optionally calculated if a pointer F1 is provided. + * Parameters F and F1 should be either both initialised or both set to null pointer. + ** \param[in] Bz - z-component of the constant homogeneous magnetic field Bz + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[in] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + ** \param[out] P[8] - array, where transported parameters should be stored + ** \param[out] C[36] - array, where transported covariance matrix (8x8) should be stored in the lower triangular form + ** \param[in] dsdr1[6] = ds/dr - partial derivatives of the parameter dS over the state vector of another particle + ** or vertex + ** \param[out] F[36] - optional parameter, transport jacobian, 6x6 matrix F = d(fP new)/d(fP old) + ** \param[out] F1[36] - optional parameter, corelation 6x6 matrix betweeen the current particle and particle or vertex + ** with the state vector r1, to which the current particle is being transported, F1 = d(fP new)/d(r1) + **/ + + const float_v kCLight = 0.000299792458f; + Bz = Bz*simd_cast<float_v>(fQ)*kCLight; + float_v bs= Bz*dS; + float_v s = sin(bs), c = cos(bs); + + float_v sB(Vc::Zero), cB(Vc::Zero); + + const float_v kOvSqr6 = 1.f/sqrt(float_v(6.f)); + const float_v LocalSmall = 1.e-10f; + + Bz(abs(bs) <= LocalSmall) = LocalSmall; + sB(LocalSmall < abs(bs)) = s/Bz; + sB(LocalSmall >= abs(bs)) = (1.f-bs*kOvSqr6)*(1.f+bs*kOvSqr6)*dS; + cB(LocalSmall < abs(bs)) = (1.f-c)/Bz; + cB(LocalSmall >= abs(bs)) = .5f*sB*bs; + + float_v px = fP[3]; + float_v py = fP[4]; + float_v pz = fP[5]; + + P[0] = fP[0] + sB*px + cB*py; + P[1] = fP[1] - cB*px + sB*py; + P[2] = fP[2] + dS*pz; + P[3] = c*px + s*py; + P[4] = -s*px + c*py; + P[5] = fP[5]; + P[6] = fP[6]; + P[7] = fP[7]; + + float_v mJ[8][8]; + for( Int_t i=0; i<8; i++ ) for( Int_t j=0; j<8; j++) mJ[i][j]=0; + + for(int i=0; i<8; i++) mJ[i][i]=1; + mJ[0][3] = sB; mJ[0][4] = cB; + mJ[1][3] = -cB; mJ[1][4] = sB; + mJ[2][5] = dS; + mJ[3][3] = c; mJ[3][4] = s; + mJ[4][3] = -s; mJ[4][4] = c; + + + float_v mJds[6][6]; + for( Int_t i=0; i<6; i++ ) for( Int_t j=0; j<6; j++) mJds[i][j]=0; + mJds[0][3] = c; mJds[0][4] = s; + mJds[1][3] = -s; mJds[1][4] = c; + mJds[2][5] = 1; + mJds[3][3] = -Bz*s; mJds[3][4] = Bz*c; + mJds[4][3] = -Bz*c; mJds[4][4] = -Bz*s; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + mJ[i1][i2] += mJds[i1][3]*px*dsdr[i2] + mJds[i1][4]*py*dsdr[i2] + mJds[i1][5]*pz*dsdr[i2]; + + MultQSQt( mJ[0], fC, C, 8); + + if(F) + { + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + F[i*6+j] = mJ[i][j]; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + F1[i1*6 + i2] = mJds[i1][3]*px*dsdr1[i2] + mJds[i1][4]*py*dsdr1[i2] + mJds[i1][5]*pz*dsdr1[i2]; + } +} + +void KFParticleBaseSIMD::TransportBz( float_v Bz, float_v dS, float_v P[] ) const +{ + /** Transports the parameters of the current particle assuming constant homogeneous + ** magnetic field Bz on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters are stored to the array P. + ** P be set to the parameters fP of the current particle. In this + ** case the particle parameters will be modified. + ** \param[in] Bz - z-component of the constant homogeneous magnetic field Bz + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[out] P[8] - array, where transported parameters should be stored + **/ + + const float_v kCLight = 0.000299792458f; + Bz = Bz*simd_cast<float_v>(fQ)*kCLight; + float_v bs= Bz*dS; + float_v s = KFPMath::Sin(bs), c = KFPMath::Cos(bs); + + float_v sB(Vc::Zero), cB(Vc::Zero); + + const float_v kOvSqr6 = 1.f/sqrt(float_v(6.f)); + const float_v LocalSmall = 1.e-10f; + + Bz(abs(bs) <= LocalSmall) = LocalSmall; + sB(LocalSmall < abs(bs)) = s/Bz; + sB(LocalSmall >= abs(bs)) = (1.f-bs*kOvSqr6)*(1.f+bs*kOvSqr6)*dS; + cB(LocalSmall < abs(bs)) = (1.f-c)/Bz; + cB(LocalSmall >= abs(bs)) = .5f*sB*bs; + + float_v px = fP[3]; + float_v py = fP[4]; + float_v pz = fP[5]; + + P[0] = fP[0] + sB*px + cB*py; + P[1] = fP[1] - cB*px + sB*py; + P[2] = fP[2] + dS*pz; + P[3] = c*px + s*py; + P[4] = -s*px + c*py; + P[5] = fP[5]; + P[6] = fP[6]; + P[7] = fP[7]; +} + + + +float_v KFParticleBaseSIMD::GetDistanceFromVertex( const KFParticleBaseSIMD &Vtx ) const +{ + /** Returns the DCA distance from vertex in the KFParticle format in 3D. + ** \param[in] Vtx - the vertex in the KFParticle format + **/ + + return GetDistanceFromVertex( Vtx.fP ); +} + +float_v KFParticleBaseSIMD::GetDistanceFromVertex( const float_v vtx[] ) const +{ + /** Returns the DCA distance from vertex in 3D. + ** \param[in] vtx[3] - the vertex coordinates {X, Y, Z} + **/ + + float_v mP[8], mC[36]; + float_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + const float_v dS = GetDStoPoint(vtx, dsdr); + Transport( dS, dsdr, mP, mC ); + float_v d[3]={ vtx[0]-mP[0], vtx[1]-mP[1], vtx[2]-mP[2]}; + return sqrt( d[0]*d[0]+d[1]*d[1]+d[2]*d[2] ); +} + +float_v KFParticleBaseSIMD::GetDistanceFromParticle( const KFParticleBaseSIMD &p ) const +{ + /** Returns the DCA distance from another particle p. + ** \param[in] p - the second particle + **/ + + float_v dS[2]; + GetDStoParticleFast( p, dS ); + float_v mP[8], mP1[8]; + TransportFast( dS[0], mP ); + p.TransportFast( dS[1], mP1 ); + float_v dx = mP[0]-mP1[0]; + float_v dy = mP[1]-mP1[1]; + float_v dz = mP[2]-mP1[2]; + return sqrt(dx*dx+dy*dy+dz*dz); +} + +float_v KFParticleBaseSIMD::GetDeviationFromVertex( const KFParticleBaseSIMD &Vtx ) const +{ + /** Returns Chi2 deviation of the current particle from the vertex in the KFParticle format in 3D. + ** \param[in] Vtx - the vertex in KFPartcile format + **/ + + return GetDeviationFromVertex( Vtx.fP, Vtx.fC ); +} + + +float_v KFParticleBaseSIMD::GetDeviationFromVertex( const float_v v[], const float_v Cv[] ) const +{ + /** Returns Chi2 deviation of the current particle from the vertex v with the covariance matrix Cv in 3D. + ** \param[in] v[3] - coordinates of the vertex {X, Y, Z} + ** \param[in] Cv[6] - covariance matrix of the vertex {Cxx, Cxy, Cyy, Cxz, Czy, Czz} + **/ + + float_v mP[8]; + float_v mC[36]; + float_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + const float_v dS = GetDStoPoint(v, dsdr); + float_v dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f}; + float_v F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0.f; + F1[i2] = 0.f; + } + Transport( dS, dsdr, mP, mC, dsdp, F, F1 ); + + if(Cv) + { + float_v VFT[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<6; j++) + { + VFT[i][j] = 0; + for(int k=0; k<3; k++) + { + VFT[i][j] += Cv[IJ(i,k)] * F1[j*6+k]; + } + } + + float_v FVFT[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + FVFT[i][j] = 0; + for(int k=0; k<3; k++) + { + FVFT[i][j] += F1[i*6+k] * VFT[k][j]; + } + } + mC[0] += FVFT[0][0] + Cv[0]; + mC[1] += FVFT[1][0] + Cv[1]; + mC[2] += FVFT[1][1] + Cv[2]; + mC[3] += FVFT[2][0] + Cv[3]; + mC[4] += FVFT[2][1] + Cv[4]; + mC[5] += FVFT[2][2] + Cv[5]; + } + + InvertCholetsky3(mC); + + float_v d[3]={ v[0]-mP[0], v[1]-mP[1], v[2]-mP[2]}; + + return ( ( mC[0]*d[0] + mC[1]*d[1] + mC[3]*d[2])*d[0] + +(mC[1]*d[0] + mC[2]*d[1] + mC[4]*d[2])*d[1] + +(mC[3]*d[0] + mC[4]*d[1] + mC[5]*d[2])*d[2] ); +} + +float_v KFParticleBaseSIMD::GetDeviationFromParticle( const KFParticleBaseSIMD &p ) const +{ + /** Returns Chi2 deviation of the current particle from another particle in 3D. + ** \param[in] p - the second particle + **/ + + float_v ds[2] = {0.f,0.f}; + float_v dsdr[4][6]; + float_v F1[36], F2[36], F3[36], F4[36]; + for(int i1=0; i1<36; i1++) + { + F1[i1] = 0; + F2[i1] = 0; + F3[i1] = 0; + F4[i1] = 0; + } + GetDStoParticle( p, ds, dsdr ); + + float_v V0Tmp[36] ; + float_v V1Tmp[36] ; + + + float_v mP1[8], mC1[36]; + float_v mP2[8], mC2[36]; + + Transport(ds[0], dsdr[0], mP1, mC1, dsdr[1], F1, F2); + p.Transport(ds[1], dsdr[3], mP2, mC2, dsdr[2], F4, F3); + + MultQSQt(F2, p.fC, V0Tmp, 6); + MultQSQt(F3, fC, V1Tmp, 6); + + for(int iC=0; iC<6; iC++) + mC1[iC] += V0Tmp[iC] + mC2[iC] + V1Tmp[iC]; + + float_v d[3]={ mP2[0]-mP1[0], mP2[1]-mP1[1], mP2[2]-mP1[2]}; + + return ( ( mC1[0]*d[0] + mC1[1]*d[1] + mC1[3]*d[2])*d[0] + +(mC1[1]*d[0] + mC1[2]*d[1] + mC1[4]*d[2])*d[1] + +(mC1[3]*d[0] + mC1[4]*d[1] + mC1[5]*d[2])*d[2] ); +} + +void KFParticleBaseSIMD::SubtractFromVertex( KFParticleBaseSIMD &Vtx ) const +{ + /** Subtract the current particle from vertex Vtx using the Kalman filter mathematics. + ** \param[in] Vtx - vertex from which particle should be subtracted + **/ + + float_v m[8]; + float_v mCm[36]; + float_v D[3][3]; + Vtx.GetMeasurement( *this, m, mCm, D ); + //* + + float_v mS[6] = { mCm[0] - Vtx.fC[0] + (D[0][0] + D[0][0]), + mCm[1] - Vtx.fC[1] + (D[1][0] + D[0][1]), mCm[2] - Vtx.fC[2] + (D[1][1] + D[1][1]), + mCm[3] - Vtx.fC[3] + (D[2][0] + D[0][2]), mCm[4] - Vtx.fC[4] + (D[1][2] + D[2][1]), mCm[5] - Vtx.fC[5] + (D[2][2] + D[2][2]) }; + InvertCholetsky3(mS); + + //* Residual (measured - estimated) + + float_v zeta[3] = { m[0]-Vtx.fP[0], m[1]-Vtx.fP[1], m[2]-Vtx.fP[2] }; + + //* mCHt = mCH' - D' + + float_v mCHt0[3], mCHt1[3], mCHt2[3]; + + mCHt0[0]=Vtx.fC[ 0] ; mCHt1[0]=Vtx.fC[ 1] ; mCHt2[0]=Vtx.fC[ 3] ; + mCHt0[1]=Vtx.fC[ 1] ; mCHt1[1]=Vtx.fC[ 2] ; mCHt2[1]=Vtx.fC[ 4] ; + mCHt0[2]=Vtx.fC[ 3] ; mCHt1[2]=Vtx.fC[ 4] ; mCHt2[2]=Vtx.fC[ 5] ; + + //* Kalman gain K = mCH'*S + + float_v k0[3], k1[3], k2[3]; + + for(Int_t i=0;i<3;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + //* New estimation of the vertex position r += K*zeta + + float_v dChi2 = ((mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]); + + for(Int_t i=0;i<3;++i) + Vtx.fP[i] -= k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + //* New covariance matrix C -= K*(mCH')' + + for(Int_t i=0, k=0;i<3;++i){ + for(Int_t j=0;j<=i;++j,++k) + Vtx.fC[k] += k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j]; + } + + //* Calculate Chi^2 + + Vtx.fNDF -= 2; + Vtx.fChi2 -= dChi2; +} + +void KFParticleBaseSIMD::SubtractFromParticle( KFParticleBaseSIMD &Vtx ) const +{ + /** Subtract the current particle from another particle Vtx using the Kalman filter mathematics. + ** The function is depricated and is kept for compatibility reasons. Should be replaced with SubtractDaughter(). + ** \param[in] Vtx - particle from which the current particle should be subtracted + **/ + + float_v m[8]; + float_v mV[36]; + + float_v D[3][3]; + Vtx.GetMeasurement( *this, m, mV, D ); + + float_v mS[6] = { mV[0] - Vtx.fC[0] + (D[0][0] + D[0][0]), + mV[1] - Vtx.fC[1] + (D[1][0] + D[0][1]), mV[2] - Vtx.fC[2] + (D[1][1] + D[1][1]), + mV[3] - Vtx.fC[3] + (D[2][0] + D[0][2]), mV[4] - Vtx.fC[4] + (D[1][2] + D[2][1]), mV[5] - Vtx.fC[5] + (D[2][2] + D[2][2]) }; + InvertCholetsky3(mS); + + //* Residual (measured - estimated) + + float_v zeta[3] = { m[0]-Vtx.fP[0], m[1]-Vtx.fP[1], m[2]-Vtx.fP[2] }; + + //* CHt = CH' - D' + + float_v mCHt0[7], mCHt1[7], mCHt2[7]; + + mCHt0[0]=mV[ 0] ; mCHt1[0]=mV[ 1] ; mCHt2[0]=mV[ 3] ; + mCHt0[1]=mV[ 1] ; mCHt1[1]=mV[ 2] ; mCHt2[1]=mV[ 4] ; + mCHt0[2]=mV[ 3] ; mCHt1[2]=mV[ 4] ; mCHt2[2]=mV[ 5] ; + mCHt0[3]=Vtx.fC[ 6]-mV[ 6]; mCHt1[3]=Vtx.fC[ 7]-mV[ 7]; mCHt2[3]=Vtx.fC[ 8]-mV[ 8]; + mCHt0[4]=Vtx.fC[10]-mV[10]; mCHt1[4]=Vtx.fC[11]-mV[11]; mCHt2[4]=Vtx.fC[12]-mV[12]; + mCHt0[5]=Vtx.fC[15]-mV[15]; mCHt1[5]=Vtx.fC[16]-mV[16]; mCHt2[5]=Vtx.fC[17]-mV[17]; + mCHt0[6]=Vtx.fC[21]-mV[21]; mCHt1[6]=Vtx.fC[22]-mV[22]; mCHt2[6]=Vtx.fC[23]-mV[23]; + + //* Kalman gain K = mCH'*S + + float_v k0[7], k1[7], k2[7]; + + for(Int_t i=0;i<7;++i){ + k0[i] = mCHt0[i]*mS[0] + mCHt1[i]*mS[1] + mCHt2[i]*mS[3]; + k1[i] = mCHt0[i]*mS[1] + mCHt1[i]*mS[2] + mCHt2[i]*mS[4]; + k2[i] = mCHt0[i]*mS[3] + mCHt1[i]*mS[4] + mCHt2[i]*mS[5]; + } + + //* Add the daughter momentum to the particle momentum + + Vtx.fP[ 3] -= m[ 3]; + Vtx.fP[ 4] -= m[ 4]; + Vtx.fP[ 5] -= m[ 5]; + Vtx.fP[ 6] -= m[ 6]; + + Vtx.fC[ 9] -= mV[ 9]; + Vtx.fC[13] -= mV[13]; + Vtx.fC[14] -= mV[14]; + Vtx.fC[18] -= mV[18]; + Vtx.fC[19] -= mV[19]; + Vtx.fC[20] -= mV[20]; + Vtx.fC[24] -= mV[24]; + Vtx.fC[25] -= mV[25]; + Vtx.fC[26] -= mV[26]; + Vtx.fC[27] -= mV[27]; + + //* New estimation of the vertex position r += K*zeta + + for(Int_t i=0;i<3;++i) + Vtx.fP[i] = m[i] - (k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]); + for(Int_t i=3;i<7;++i) + Vtx.fP[i] = Vtx.fP[i] - (k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]); + + //* New covariance matrix C -= K*(mCH')' + + float_v ffC[28] = {-mV[ 0], + -mV[ 1], -mV[ 2], + -mV[ 3], -mV[ 4], -mV[ 5], + mV[ 6], mV[ 7], mV[ 8], Vtx.fC[ 9], + mV[10], mV[11], mV[12], Vtx.fC[13], Vtx.fC[14], + mV[15], mV[16], mV[17], Vtx.fC[18], Vtx.fC[19], Vtx.fC[20], + mV[21], mV[22], mV[23], Vtx.fC[24], Vtx.fC[25], Vtx.fC[26], Vtx.fC[27] }; + + for(Int_t i=0, k=0;i<7;++i){ + for(Int_t j=0;j<=i;++j,++k){ + Vtx.fC[k] = ffC[k] + (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); + } + } + + //* Calculate Chi^2 + Vtx.fNDF -= 2; + Vtx.fQ -= GetQ(); + Vtx.fSFromDecay = 0; + Vtx.fChi2 -= ((mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2])*zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2])*zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2])*zeta[2]); +} + +void KFParticleBaseSIMD::TransportLine( float_v dS, const float_v* dsdr, float_v P[], float_v C[], float_v* dsdr1, float_v* F, float_v* F1 ) const +{ + /** Transports the parameters and their covariance matrix of the current particle assuming the straight line trajectory + ** on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters and covariance matrix are stored to the arrays P and + ** C respectively. P and C can be set to the parameters fP and covariance matrix fC of the current particle. In this + ** case the particle parameters will be modified. Dependence of the transport parameter dS on the state vector of the + ** current particle is taken into account in the covariance matrix using partial derivatives dsdr = d(dS)/d(fP). If + ** a pointer to F is initialised the transport jacobian F = d(fP new)/d(fP old) is stored. + ** Since dS can depend on the state vector r1 of other particle or vertex, the corelation matrix + ** F1 = d(fP new)/d(r1) can be optionally calculated if a pointer F1 is provided. + * Parameters F and F1 should be either both initialised or both set to null pointer. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[in] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + ** \param[out] P[8] - array, where transported parameters should be stored + ** \param[out] C[36] - array, where transported covariance matrix (8x8) should be stored in the lower triangular form + ** \param[in] dsdr1[6] = ds/dr - partial derivatives of the parameter dS over the state vector of another particle + ** or vertex + ** \param[out] F[36] - optional parameter, transport jacobian, 6x6 matrix F = d(fP new)/d(fP old) + ** \param[out] F1[36] - optional parameter, corelation 6x6 matrix betweeen the current particle and particle or vertex + ** with the state vector r1, to which the current particle is being transported, F1 = d(fP new)/d(r1) + **/ + + float_v mJ[8][8]; + for( Int_t i=0; i<8; i++ ) for( Int_t j=0; j<8; j++) mJ[i][j]=0; + + mJ[0][0]=1; mJ[0][1]=0; mJ[0][2]=0; mJ[0][3]=dS; mJ[0][4]=0; mJ[0][5]=0; + mJ[1][0]=0; mJ[1][1]=1; mJ[1][2]=0; mJ[1][3]=0; mJ[1][4]=dS; mJ[1][5]=0; + mJ[2][0]=0; mJ[2][1]=0; mJ[2][2]=1; mJ[2][3]=0; mJ[2][4]=0; mJ[2][5]=dS; + + mJ[3][0]=0; mJ[3][1]=0; mJ[3][2]=0; mJ[3][3]=1; mJ[3][4]=0; mJ[3][5]=0; + mJ[4][0]=0; mJ[4][1]=0; mJ[4][2]=0; mJ[4][3]=0; mJ[4][4]=1; mJ[4][5]=0; + mJ[5][0]=0; mJ[5][1]=0; mJ[5][2]=0; mJ[5][3]=0; mJ[5][4]=0; mJ[5][5]=1; + mJ[6][6] = mJ[7][7] = 1; + + float_v px = fP[3], py = fP[4], pz = fP[5]; + + P[0] = fP[0] + dS*fP[3]; + P[1] = fP[1] + dS*fP[4]; + P[2] = fP[2] + dS*fP[5]; + P[3] = fP[3]; + P[4] = fP[4]; + P[5] = fP[5]; + P[6] = fP[6]; + P[7] = fP[7]; + + float_v mJds[6][6]; + for( Int_t i=0; i<6; i++ ) for( Int_t j=0; j<6; j++) mJds[i][j]=0; + + mJds[0][3]= 1; + mJds[1][4]= 1; + mJds[2][5]= 1; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + mJ[i1][i2] += mJds[i1][3]*px*dsdr[i2] + mJds[i1][4]*py*dsdr[i2] + mJds[i1][5]*pz*dsdr[i2]; + MultQSQt( mJ[0], fC, C, 8); + + if(F) + { + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + F[i*6+j] = mJ[i][j]; + + for(int i1=0; i1<6; i1++) + for(int i2=0; i2<6; i2++) + F1[i1*6 + i2] = mJds[i1][3]*px*dsdr1[i2] + mJds[i1][4]*py*dsdr1[i2] + mJds[i1][5]*pz*dsdr1[i2]; + } +} + +void KFParticleBaseSIMD::TransportLine( float_v dS, float_v P[] ) const +{ + /** Transports the parameters of the current particle assuming the straight line trajectory + ** on the length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. The obtained parameters are stored to the array P + ** P can be set to the parameters fP of the current particle. In this + ** case the particle parameters will be modified. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[out] P[8] - array, where transported parameters should be stored + **/ + + P[0] = fP[0] + dS*fP[3]; + P[1] = fP[1] + dS*fP[4]; + P[2] = fP[2] + dS*fP[5]; + P[3] = fP[3]; + P[4] = fP[4]; + P[5] = fP[5]; + P[6] = fP[6]; + P[7] = fP[7]; +} + +void KFParticleBaseSIMD::GetArmenterosPodolanski(KFParticleBaseSIMD& positive, KFParticleBaseSIMD& negative, float_v QtAlfa[2] ) +{ + /** Calculates parameters for the Armenteros-Podolanski plot for two particles. + ** Example how to use:\n + ** KFParticle PosParticle(...) \n + ** KFParticle NegParticle(...) \n + ** Gamma.ConstructGamma(PosParticle, NegParticle); \n + ** float VertexGamma[3] = {Gamma.GetX(), Gamma.GetY(), Gamma.GetZ()}; \n + ** PosParticle.TransportToPoint(VertexGamma); \n + ** NegParticle.TransportToPoint(VertexGamma); \n + ** float armenterosQtAlfa[2] = {0.}; \n + ** KFParticle::GetArmenterosPodolanski(PosParticle, NegParticle, armenterosQtAlfa ); \n + ** \param[in] positive - first particle, positive or neutral + ** \param[in] negative - second particle, negative or neutral + ** \param[out] QtAlfa[2] - parameters for the Armenteros-Podolanski plot: QtAlfa[0] = qt - projection of the + ** momenta of the particles on the transverse direction with respect to the total momentum, same for both particles; + ** QtAlfa[1] = (Pl+ - Pl-)/(Pl+ + Pl-) - combination of the longitudinal components. + **/ + + float_v alpha = 0.f, qt = 0.f; + float_v spx = positive.GetPx() + negative.GetPx(); + float_v spy = positive.GetPy() + negative.GetPy(); + float_v spz = positive.GetPz() + negative.GetPz(); + float_v sp = sqrt(spx*spx + spy*spy + spz*spz); + float_m mask = float_m( abs(sp) < float_v(1.e-10f)); + float_v pn, pp, pln, plp; + + pn = sqrt(negative.GetPx()*negative.GetPx() + negative.GetPy()*negative.GetPy() + negative.GetPz()*negative.GetPz()); + pp = sqrt(positive.GetPx()*positive.GetPx() + positive.GetPy()*positive.GetPy() + positive.GetPz()*positive.GetPz()); + pln = (negative.GetPx()*spx+negative.GetPy()*spy+negative.GetPz()*spz)/sp; + plp = (positive.GetPx()*spx+positive.GetPy()*spy+positive.GetPz()*spz)/sp; + + mask = float_m(mask & float_m( abs(pn) < float_v(1.E-10f))); + float_v ptm = (1.f-((pln/pn)*(pln/pn))); + qt(ptm >= 0.f) = pn*sqrt(ptm); + alpha = (plp-pln)/(plp+pln); + + QtAlfa[0](mask) = qt; + QtAlfa[1](mask) = alpha; +} + +void KFParticleBaseSIMD::RotateXY(float_v angle, float_v Vtx[3]) +{ + /** Rotates the KFParticle object around OZ axis, OZ axis is set by the vertex position. + ** \param[in] angle - angle of rotation in XY plane in [rad] + ** \param[in] Vtx[3] - position of the vertex in [cm] + **/ + + // Before rotation the center of the coordinat system should be moved to the vertex position; move back after rotation + X() = X() - Vtx[0]; + Y() = Y() - Vtx[1]; + Z() = Z() - Vtx[2]; + + // Rotate the kf particle + float_v s = sin(angle); + float_v c = cos(angle); + + float_v mA[8][ 8]; + for( Int_t i=0; i<8; i++ ){ + for( Int_t j=0; j<8; j++){ + mA[i][j] = 0; + } + } + for( int i=0; i<8; i++ ){ + mA[i][i] = 1; + } + mA[0][0] = c; mA[0][1] = s; + mA[1][0] = -s; mA[1][1] = c; + mA[3][3] = c; mA[3][4] = s; + mA[4][3] = -s; mA[4][4] = c; + + float_v mAC[8][8]; + float_v mAp[8]; + + for( Int_t i=0; i<8; i++ ){ + mAp[i] = 0; + for( Int_t k=0; k<8; k++){ + mAp[i]+=mA[i][k] * fP[k]; + } + } + + for( Int_t i=0; i<8; i++){ + fP[i] = mAp[i]; + } + + for( Int_t i=0; i<8; i++ ){ + for( Int_t j=0; j<8; j++ ){ + mAC[i][j] = 0; + for( Int_t k=0; k<8; k++ ){ + mAC[i][j]+= mA[i][k] * GetCovariance(k,j); + } + } + } + + for( Int_t i=0; i<8; i++ ){ + for( Int_t j=0; j<=i; j++ ){ + float_v xx = 0.f; + for( Int_t k=0; k<8; k++){ + xx+= mAC[i][k]*mA[j][k]; + } + Covariance(i,j) = xx; + } + } + + X() = GetX() + Vtx[0]; + Y() = GetY() + Vtx[1]; + Z() = GetZ() + Vtx[2]; +} + +void KFParticleBaseSIMD::InvertCholetsky3(float_v a[6]) +{ + /** Inverts symmetric 3x3 matrix a using modified Choletsky decomposition. The result is stored to the same matrix a. + ** \param[in,out] a - 3x3 symmetric matrix + **/ + + float_v d[3], uud, u[3][3]; + for(int i=0; i<3; i++) + { + d[i]=0.f; + for(int j=0; j<3; j++) + u[i][j]=0.f; + } + + for(int i=0; i<3 ; i++) + { + uud=0.f; + for(int j=0; j<i; j++) + uud += u[j][i]*u[j][i]*d[j]; + uud = a[i*(i+3)/2] - uud; + + uud(abs(uud)<1.e-8f) = 1.e-8f; + d[i] = uud/abs(uud); + u[i][i] = sqrt(abs(uud)); + + for(int j=i+1; j<3; j++) + { + uud = 0.f; + for(int k=0; k<i; k++) + uud += u[k][i]*u[k][j]*d[k]; + uud = a[j*(j+1)/2+i] - uud; + u[i][j] = d[i]/u[i][i]*uud; + } + } + + float_v u1[3]; + + for(int i=0; i<3; i++) + { + u1[i] = u[i][i]; + u[i][i] = 1.f/u[i][i]; + } + for(int i=0; i<2; i++) + { + u[i][i+1] = - u[i][i+1]*u[i][i]*u[i+1][i+1]; + } + for(int i=0; i<1; i++) + { + u[i][i+2] = u[i][i+1]*u1[i+1]*u[i+1][i+2]-u[i][i+2]*u[i][i]*u[i+2][i+2]; + } + + for(int i=0; i<3; i++) + a[i+3] = u[i][2]*u[2][2]*d[2]; + for(int i=0; i<2; i++) + a[i+1] = u[i][1]*u[1][1]*d[1] + u[i][2]*u[1][2]*d[2]; + a[0] = u[0][0]*u[0][0]*d[0] + u[0][1]*u[0][1]*d[1] + u[0][2]*u[0][2]*d[2]; +} + +void KFParticleBaseSIMD::MultQSQt( const float_v Q[], const float_v S[], float_v SOut[], const int kN ) +{ + /** Matrix multiplication SOut = Q*S*Q^T, where Q - square matrix, S - symmetric matrix. + ** \param[in] Q - square matrix + ** \param[in] S - input symmetric matrix + ** \param[out] SOut - output symmetric matrix + ** \param[in] kN - dimensionality of the matrices + **/ + + float_v* mA = new float_v[kN*kN]; + + for( Int_t i=0, ij=0; i<kN; i++ ){ + for( Int_t j=0; j<kN; j++, ++ij ){ + mA[ij] = 0 ; + for( Int_t k=0; k<kN; ++k ) mA[ij]+= S[( k<=i ) ? i*(i+1)/2+k :k*(k+1)/2+i] * Q[ j*kN+k]; + } + } + + for( Int_t i=0; i<kN; i++ ){ + for( Int_t j=0; j<=i; j++ ){ + Int_t ij = ( j<=i ) ? i*(i+1)/2+j :j*(j+1)/2+i; + SOut[ij] = 0 ; + for( Int_t k=0; k<kN; k++ ) SOut[ij] += Q[ i*kN+k ] * mA[ k*kN+j ]; + } + } + + if(mA) delete[] mA; +} + + +// 72-charachters line to define the printer border +//3456789012345678901234567890123456789012345678901234567890123456789012 + diff --git a/external/KFParticle/KFParticle/KFParticleBaseSIMD.h b/external/KFParticle/KFParticle/KFParticleBaseSIMD.h new file mode 100644 index 0000000000000000000000000000000000000000..c39dec909fd2ea7eda937cd78b90995506d82118 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleBaseSIMD.h @@ -0,0 +1,341 @@ +//--------------------------------------------------------------------------------- +// The KFParticleBaseSIMD class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 13.05.07 +// +// Class to reconstruct and store the decayed particle parameters. +// The method is described in CBM-SOFT note 2007-003, +// ``Reconstruction of decayed particles based on the Kalman filter'', +// http://www.gsi.de/documents/DOC-2007-May-14-1.pdf +// +// This class describes general mathematics which is used by KFParticle class +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//_________________________________________________________________________________ + + +#ifndef KFParticleBaseSIMD_H +#define KFParticleBaseSIMD_H + +#ifdef HLTCA_STANDALONE +#include "RootTypesDef.h" +#endif + +#include <vector> +#include "KFParticleDef.h" + +/** @class KFParticleBaseSIMD + ** @brief The base of KFParticleSIMD class. + ** @author M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** Contains the main mathematics of the vectorised KF Particle. Will be merged with the KFParticleSIMD class. + ** The class stores all the data in a format of SIMD vectors, the mathematics is fully vectorised. + ** THe mathematics is implemented in single precision. + ** The functionality of the vectorised and scalar classes is the same. + **/ + +class KFParticleBaseSIMD { + + public: + + //* + //* ABSTRACT METHODS HAVE TO BE DEFINED IN USER CLASS + //* +#if __GNUC__ && ( defined(ENVIRONMENT32) || GCC_VERSION < 40300 ) + +#else + + void *operator new(size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new(size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void operator delete(void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + void operator delete[](void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + +#endif + + /** Virtual method to access the magnetic field**/ + virtual void GetFieldValue(const float_v xyz[], float_v B[]) const = 0; + + //* Virtual methods needed for particle transportation + //* One can use particular implementations for collider (only Bz component) + //* geometry and for fixed-target (CBM-like) geometry which are provided below + //* in TRANSPORT section + + //* Get dS to xyz[] space point + + /** Virtual method to get extrapolation parameter dS=l/p to . Is defined in KFParticleSIMD.**/ + virtual float_v GetDStoPoint( const float_v xyz[3], float_v dsdr[6] ) const = 0; + + float_v GetDStoPointLine( const float_v xyz[3], float_v dsdr[6] ) const; + float_v GetDStoPointBz( float_v Bz, const float_v xyz[3], float_v dsdr[6], const float_v* param = 0 ) const; + float_v GetDStoPointBy( float_v By, const float_v xyz[3], float_v dsdr[6] ) const; + float_v GetDStoPointCBM( const float_v xyz[3], float_v dsdr[6] ) const; + + /** Virtual method to get extrapolation parameter dS=l/p and ds/dr partial derivatives to another particle. Is defined in KFParticleSIMD.**/ + virtual void GetDStoParticle( const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const = 0; + /** Virtual method to get extrapolation parameter dS=l/p to another particle. Is defined in KFParticleSIMD.**/ + virtual void GetDStoParticleFast( const KFParticleBaseSIMD &p, float_v dS[2] ) const = 0; + + void GetDStoParticleLine( const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const ; + void GetDStoParticleLine( const KFParticleBaseSIMD &p, float_v dS[2] ) const ; + void GetDStoParticleBz( float_v Bz, const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6], const float_v* param1 =0, const float_v* param2 =0 ) const ; + void GetDStoParticleBz( float_v Bz, const KFParticleBaseSIMD &p, float_v dS[2], const float_v* param1 =0, const float_v* param2 =0 ) const ; + void GetDStoParticleBy( float_v B, const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const ; + void GetDStoParticleBy( float_v B, const KFParticleBaseSIMD &p, float_v dS[2] ) const ; + void GetDStoParticleB( float_v B[3], const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const; + void GetDStoParticleB( float_v B[3], const KFParticleBaseSIMD &p, float_v dS[2] ) const; + void GetDStoParticleCBM( const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const ; + void GetDStoParticleCBM( const KFParticleBaseSIMD &p, float_v dS[2] ) const ; + + /** Virtual method to transport a particle parameters and covariance matrix on a certain distance along the trajectory. Is defined in KFParticleSIMD.**/ + virtual void Transport( float_v dS, const float_v dsdr[6], float_v P[], float_v C[], float_v* dsdr1=0, float_v* F=0, float_v* F1=0 ) const = 0; + /** Virtual method to transport a particle parameters on a certain distance along the trajectory. Is defined in KFParticleSIMD.**/ + virtual void TransportFast( float_v dS, float_v P[] ) const = 0; + + + + //* + //* INITIALIZATION + //* + + //* Constructor + + KFParticleBaseSIMD(); + + //* Destructor + + virtual ~KFParticleBaseSIMD() { ; } ///< The default destructor. + + void Initialize( const float_v Param[], const float_v Cov[], int_v Charge, float_v Mass ); + void Initialize(); + + void SetConstructMethod(Int_t m) {fConstructMethod = m;} ///< Defines the construction method for the current particle (see description of fConstructMethod). + void SetMassHypo(float_v m) { fMassHypo = m;} ///< Sets the mass hypothesis to the particle, is used when fConstructMethod = 2. + const float_v& GetMassHypo() const { return fMassHypo; } ///< Returns the mass hypothesis. + const float_v& GetSumDaughterMass() const {return SumDaughterMass;} ///< Returns the sum of masses of the daughters. + + //* + //* ACCESSORS + //* + + //* Simple accessors + + float_v GetX () const { return fP[0]; } ///< Returns the sum of masses of the daughters + float_v GetY () const { return fP[1]; } ///< Returns the sum of masses of the daughters + float_v GetZ () const { return fP[2]; } ///< Returns the sum of masses of the daughters + float_v GetPx () const { return fP[3]; } ///< Returns the sum of masses of the daughters + float_v GetPy () const { return fP[4]; } ///< Returns the sum of masses of the daughters + float_v GetPz () const { return fP[5]; } ///< Returns the sum of masses of the daughters + float_v GetE () const { return fP[6]; } ///< Returns the sum of masses of the daughters + float_v GetS () const { return fP[7]; } ///< Returns the sum of masses of the daughters + int_v GetQ () const { return fQ; } ///< Returns the sum of masses of the daughters + float_v GetChi2 () const { return fChi2; } ///< Returns the sum of masses of the daughters + int_v GetNDF () const { return fNDF; } ///< Returns the sum of masses of the daughters + + const float_v& X () const { return fP[0]; } ///< Retruns X coordinate of the particle, fP[0]. + const float_v& Y () const { return fP[1]; } ///< Retruns Y coordinate of the particle, fP[1]. + const float_v& Z () const { return fP[2]; } ///< Retruns Z coordinate of the particle, fP[2]. + const float_v& Px () const { return fP[3]; } ///< Retruns X component of the momentum, fP[3]. + const float_v& Py () const { return fP[4]; } ///< Retruns Y component of the momentum, fP[4]. + const float_v& Pz () const { return fP[5]; } ///< Retruns Z component of the momentum, fP[5]. + const float_v& E () const { return fP[6]; } ///< Returns energy of the particle, fP[6]. + const float_v& S () const { return fP[7]; } ///< Returns dS=l/p, l - decay length, fP[7], defined if production vertex is set. + const int_v& Q () const { return fQ; } ///< Returns charge of the particle. + const float_v& Chi2 () const { return fChi2; } ///< Returns Chi2 of the fit. + const int_v& NDF () const { return fNDF; } ///< Returns number of decrease of freedom. + + float_v GetParameter ( Int_t i ) const { return fP[i]; } ///< Returns P[i] parameter. + float_v GetCovariance( Int_t i ) const { return fC[i]; } ///< Returns C[i] element of the covariance matrix in the lower triangular form. + float_v GetCovariance( Int_t i, Int_t j ) const { return fC[IJ(i,j)]; } ///< Returns C[i,j] element of the covariance matrix. + + //* Accessors with calculations( &value, &estimated sigma ) + //* error flag returned (0 means no error during calculations) + + float_m GetMomentum ( float_v &p, float_v &error ) const ; + float_m GetPt ( float_v &pt, float_v &error ) const ; + float_m GetEta ( float_v &eta, float_v &error ) const ; + float_m GetPhi ( float_v &phi, float_v &error ) const ; + float_m GetMass ( float_v &m, float_v &error ) const ; + float_m GetDecayLength ( float_v &l, float_v &error ) const ; + float_m GetDecayLengthXY ( float_v &l, float_v &error ) const ; + float_m GetLifeTime ( float_v &ctau, float_v &error ) const ; + float_m GetR ( float_v &r, float_v &error ) const ; + + //* + //* MODIFIERS + //* + + float_v & X () { return fP[0]; } ///< Modifier of X coordinate of the particle, fP[0]. + float_v & Y () { return fP[1]; } ///< Modifier of Y coordinate of the particle, fP[1]. + float_v & Z () { return fP[2]; } ///< Modifier of Z coordinate of the particle, fP[2]. + float_v & Px () { return fP[3]; } ///< Modifier of X component of the momentum, fP[3]. + float_v & Py () { return fP[4]; } ///< Modifier of Y component of the momentum, fP[4]. + float_v & Pz () { return fP[5]; } ///< Modifier of Z component of the momentum, fP[5]. + float_v & E () { return fP[6]; } ///< Modifier of energy of the particle, fP[6]. + float_v & S () { return fP[7]; } ///< Modifier of dS=l/p, l - decay length, fP[7], defined if production vertex is set. + int_v & Q () { return fQ; } ///< Modifier of charge of the particle. + float_v & Chi2 () { return fChi2; } ///< Modifier of Chi2 of the fit. + int_v & NDF () { return fNDF; } ///< Modifier of number of decrease of freedom. + + float_v & Parameter ( Int_t i ) { return fP[i]; } ///< Modifier of P[i] parameter. + float_v & Covariance( Int_t i ) { return fC[i]; } ///< Modifier of C[i] element of the covariance matrix in the lower triangular form. + float_v & Covariance( Int_t i, Int_t j ) { return fC[IJ(i,j)]; } ///< Modifier of C[i,j] element of the covariance matrix. + + + //* + //* CONSTRUCTION OF THE PARTICLE BY ITS DAUGHTERS AND MOTHER + //* USING THE KALMAN FILTER METHOD + //* + + + //* Simple way to add daughter ex. D0+= Pion; + + void operator +=( const KFParticleBaseSIMD &Daughter ); + + //* Add daughter track to the particle + + void AddDaughter( const KFParticleBaseSIMD &Daughter ); + void SubtractDaughter( const KFParticleBaseSIMD &Daughter ); + + void AddDaughterWithEnergyFit( const KFParticleBaseSIMD &Daughter ); + void AddDaughterWithEnergyFitMC( const KFParticleBaseSIMD &Daughter ); + //with mass constrained + + //* Set production vertex + + void SetProductionVertex( const KFParticleBaseSIMD &Vtx ); + + //* Set mass constraint + + void SetNonlinearMassConstraint( float_v Mass ); + void SetMassConstraint( float_v Mass, float_v SigmaMass = float_v(0.f) ); + + //* Set no decay length for resonances + + void SetNoDecayLength(); + + + //* Everything in one go + + void Construct( const KFParticleBaseSIMD *vDaughters[], Int_t nDaughters, const KFParticleBaseSIMD *ProdVtx=0, Float_t Mass=-1 ); + + + //* + //* TRANSPORT + //* + //* ( main transportation parameter is S = SignedPath/Momentum ) + //* ( parameters of decay & production vertices are stored locally ) + //* + + + //* Transport the particle to its decay vertex + + void TransportToDecayVertex(); + + //* Transport the particle to its production vertex + + void TransportToProductionVertex(); + + //* Transport the particle on dS parameter (SignedPath/Momentum) + + void TransportToDS( float_v dS, const float_v* dsdr ); + void TransportToDSLine( float_v dS, const float_v* dsdr ); + //* Particular extrapolators one can use + void TransportBz( float_v Bz, float_v dS, const float_v* dsdr, float_v P[], float_v C[], float_v* dsdr1=0, float_v* F=0, float_v* F1=0 ) const; + void TransportBz( float_v Bz, float_v dS, float_v P[] ) const; + void TransportCBM( float_v dS, const float_v* dsdr, float_v P[], float_v C[], float_v* dsdr1=0, float_v* F=0, float_v* F1=0 ) const; + void TransportCBM( float_v dS, float_v P[] ) const; + + //* + //* OTHER UTILITIES + //* + + //* Calculate distance from another object [cm] + + float_v GetDistanceFromVertex( const float_v vtx[] ) const; + float_v GetDistanceFromVertex( const KFParticleBaseSIMD &Vtx ) const; + float_v GetDistanceFromParticle( const KFParticleBaseSIMD &p ) const; + + //* Calculate CAMath::Sqrt(Chi2/ndf) deviation from vertex + //* v = [xyz], Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix + + float_v GetDeviationFromVertex( const float_v v[], + const float_v Cv[]=0 ) const; + float_v GetDeviationFromVertex( const KFParticleBaseSIMD &Vtx ) const; + float_v GetDeviationFromParticle( const KFParticleBaseSIMD &p ) const; + + //* Subtract the particle from the vertex + + void SubtractFromVertex( KFParticleBaseSIMD &Vtx ) const; + void SubtractFromParticle( KFParticleBaseSIMD &Vtx ) const; + + static void GetArmenterosPodolanski(KFParticleBaseSIMD& positive, KFParticleBaseSIMD& negative, float_v QtAlfa[2] ); + void RotateXY(float_v angle, float_v Vtx[3]); + + int_v Id() const { return fId; } ///< Returns Id of the particle. + int NDaughters() const { return fDaughterIds.size(); } ///< Returns number of daughter particles. + std::vector<int_v> & DaughterIds() { return fDaughterIds; } ///< Returns the vector with the indices of daughter particles. + int_v GetDaughterId(int iD) const { return fDaughterIds[iD]; } ///< Returns the daughter Id with the index iD. + + void SetId( int_v id ){ fId = id; } ///< Sets the Id of the particle. After the construction of a particle should be set by user. + void SetNDaughters( int n ) { fDaughterIds.reserve(n); } ///< Reserves the size of the vector with daughter Ids to n + void AddDaughterId( int_v id ){ fDaughterIds.push_back(id); } ///< Adds index of the daughter particle. + void CleanDaughtersId() { fDaughterIds.clear(); } ///< Cleans the vector with the indices of daughter particles. + + void SetPDG ( int pdg ) { fPDG = pdg; } ///< Sets the PDG hypothesis common for all elements of the SIMD vector. + void SetPDG ( int_v& pdg ) { fPDG = pdg; } ///< Sets the PDG hypothesis individual for each entry of the SIMD vector. + const int_v& GetPDG () const { return fPDG; } ///< Returns the PDG hypothesis. + const int_v& PDG () const { return fPDG; } ///< Returns the PDG hypothesis. + + void GetDistanceToVertexLine( const KFParticleBaseSIMD &Vertex, float_v &l, float_v &dl, float_m *isParticleFromVertex = 0 ) const; + + static void MultQSQt( const float_v Q[], const float_v S[], float_v SOut[], const int kN ); + + protected: + /** Converts a pair of indices {i,j} of the covariance matrix to one index corresponding to the triangular form. */ + static Int_t IJ( Int_t i, Int_t j ){ + return ( j<=i ) ? i*(i+1)/2+j :j*(j+1)/2+i; + } + /** Return an element of the covariance matrix with {i,j} indices. */ + float_v & Cij( Int_t i, Int_t j ){ return fC[IJ(i,j)]; } + + void TransportLine( float_v S, const float_v* dsdr, float_v P[], float_v C[], float_v* dsdr1=0, float_v* F=0, float_v* F1=0 ) const ; + void TransportLine( float_v S, float_v P[] ) const ; + + static void InvertCholetsky3(float_v a[6]); + + void GetMeasurement( const KFParticleBaseSIMD& daughter, float_v m[], float_v V[], float_v D[3][3] ) ; + + //* Mass constraint function. is needed for the nonlinear mass constraint and a fit with mass constraint + void SetMassConstraint( float_v *mP, float_v *mC, float_v mJ[7][7], float_v mass, float_m mask ); + + float_v fP[8]; ///< Particle parameters { X, Y, Z, Px, Py, Pz, E, S[=DecayLength/P]}. + float_v fC[36]; ///< Low-triangle covariance matrix of fP. + int_v fQ; ///< The charge of the particle in the units of the elementary charge. + int_v fNDF; ///< Number of degrees of freedom. + float_v fChi2; ///< Chi^2. + float_v fSFromDecay; ///< Distance from the decay vertex to the current position. + float_v SumDaughterMass; ///< Sum of the daughter particles masses. Needed to set the constraint on the minimum mass during particle construction. + float_v fMassHypo; ///< The mass hypothesis, used for the constraints during particle construction. + int_v fId; ///< Id of the particle. + Bool_t fAtProductionVertex; ///< Flag shows if particle is at the production point. + int_v fPDG; ///< The PDG hypothesis assigned to the particle. + /** \brief Determines the method for the particle construction. \n + ** 0 - Energy considered as an independent veriable, fitted independently from momentum, without any constraints on mass \n + ** 2 - Energy considered as an independent variable, fitted independently from momentum, with constraints on mass of daughter particle + **/ + Int_t fConstructMethod; + /** \brief A vector with ids of the daughter particles: \n + ** 1) if particle is created from a track - the index of the track, in this case the size of the vector is always equal to one; \n + ** 2) if particle is constructed from other particles - indices of these particles in the same array. + **/ + std::vector<int_v> fDaughterIds; // id of particles it created from. if size == 1 then this is id of track. + +} __attribute__((aligned(sizeof(float_v)))); + +#endif diff --git a/external/KFParticle/KFParticle/KFParticleDatabase.cxx b/external/KFParticle/KFParticle/KFParticleDatabase.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e89afd8b6021223bcb563f530493e33f643b3bba --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleDatabase.cxx @@ -0,0 +1,98 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFParticleDatabase.h" + +KFParticleDatabase* KFParticleDatabase::fDatabase = 0; + +KFParticleDatabase::KFParticleDatabase(): + fMassPi0PDG(0.13498), +#ifdef PANDA_STT + fMassPi0PDGSigma(0.009), +#elif defined ALICE_ITS + fMassPi0PDGSigma(0.006), +#elif defined STAR_HFT + fMassPi0PDGSigma(0.006), +#elif defined CBM + fMassPi0PDGSigma(0.006), +#else + fMassPi0PDGSigma(0.006), +#endif + fMassD0PDG(1.86484), +#ifdef CBM + fMassD0PDGSigma(0.0145), +#else + fMassD0PDGSigma(0.0154), +#endif + fMassDPlusPDG(1.86962), +#ifdef CBM + fMassDPlusPDGSigma(0.0145) +#else + fMassDPlusPDGSigma(0.0115) +#endif +{ + /** The default constructor. Initialises masses and widths of the peaks. + ** Be aware, that widths of the peaks are experiment specific. + **/ + fMass[0] = 0.000510999; + fMass[1] = 0.105658; + fMass[2] = 0.13957; + fMass[3] = 0.493667; + fMass[4] = 0.9382723; + fMass[5] = 1.876124; + fMass[6] = 2.809432; + fMass[7] = 2.809413; + fMass[8] = 3.728400; + fMass[9] = 1.197449; + fMass[10] = 1.18937; + fMass[11] = 1.32171; + fMass[12] = 1.67245; + + fMassSecPDG[0] = 0.497614; //K0 + fMassSecPDG[1] = 1.115683; //Lambda + fMassSecPDG[2] = 1.32171; //Xi + fMassSecPDG[3] = 0; //gamma + fMassSecPDG[4] = 1.67245; //Omega + fMassSecPDG[5] = 2.99339; //H3L + fMassSecPDG[6] = 3.93070; //He4L + fMassSecPDG[7] = 4.86824; //He5L + +#ifdef PANDA_STT + fMassSecPDGSigma[0]=12.0e-3; //K0 TODO tune + fMassSecPDGSigma[1]=2.7e-3; //Lambda + fMassSecPDGSigma[2]=2.8e-3; //Xi TODO tune +#elif defined ALICE_ITS + fMassSecPDGSigma[0]=17.7e-3; + fMassSecPDGSigma[1]=5.9e-3; + fMassSecPDGSigma[2]=7.3e-3; +#elif defined STAR_HFT + fMassSecPDGSigma[0]=17.7e-3; + fMassSecPDGSigma[1]=5.9e-3; + fMassSecPDGSigma[2]=7.3e-3; +#elif defined CBM + fMassSecPDGSigma[0]=3.7e-3; //2.2e-3; + fMassSecPDGSigma[1]=1.5e-3; //1.2e-3; + fMassSecPDGSigma[2]=2.0e-3; +#else //STAR + fMassSecPDGSigma[0]=4.9e-3; + fMassSecPDGSigma[1]=2.1e-3; + fMassSecPDGSigma[2]=2.1e-3; +#endif + fMassSecPDGSigma[3]=6.0e-3; //TODO tune //Gamma + fMassSecPDGSigma[4]=2.1e-3; //Omega + fMassSecPDGSigma[5]=3.0e-3; //H3L + fMassSecPDGSigma[6]=3.0e-3; //He4L + fMassSecPDGSigma[7]=3.0e-3; //He5L + + fDatabase = this; +} + +KFParticleDatabase kfPartDatabase; //create instance diff --git a/external/KFParticle/KFParticle/KFParticleDatabase.h b/external/KFParticle/KFParticle/KFParticleDatabase.h new file mode 100644 index 0000000000000000000000000000000000000000..1b8523260f2b95cc1194233c1892d5e0e7dca07e --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleDatabase.h @@ -0,0 +1,176 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +#ifndef KFParticleDatabase_H +#define KFParticleDatabase_H + +#include "Vc/Vc" + +/** @class KFParticleDatabase + ** @brief The class stores information about particle masses and expected width of the peacks. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class contains information required for the reconstruction of decay trees: \n + ** - masses of the stable particles; \n + ** - masses of the intermediate daughter particles (like Lambda, K0, Xi, D0, etc.);\n + ** - expected widths of the peaks. + **/ + +class KFParticleDatabase +{ + public: + KFParticleDatabase(); + + ~KFParticleDatabase() {}; + + float GetMass(const int pdg) const + { + /** Returns scalar float variable with the mass of the stable particle with the given PDG code. + ** If the given PDG code is not the list of the current database mass of the pion is returned. + ** \param[in] pdg - the input PDG code + **/ + int pdgIndex = 2; + switch ( abs(pdg) ) + { + case 11: pdgIndex = 0; break; + case 13: pdgIndex = 1; break; + case 19: pdgIndex = 1; break; + case 211: pdgIndex = 2; break; + case 321: pdgIndex = 3; break; + case 2212: pdgIndex = 4; break; + case 1000010020: pdgIndex = 5; break; + case 1000010030: pdgIndex = 6; break; + case 1000020030: pdgIndex = 7; break; + case 1000020040: pdgIndex = 8; break; + case 3112: pdgIndex = 9; break; + case 3222: pdgIndex = 10; break; + case 3312: pdgIndex = 11; break; + case 3334: pdgIndex = 12; break; + default: pdgIndex = 2; break; + } + + return fMass[pdgIndex]; + } + + Vc::float_v GetMass(const Vc::int_v& pdg) const + { + /** Returns vector float variable with the mass of the stable particles with the given PDG codes. + ** If the given PDG code is not in the list of the current database mass of the pion is returned. + ** \param[in] pdg - the input PDG codes of a set of particles in the SIMD-vector format + **/ + Vc::int_v pdgIndex(2); + pdgIndex(Vc::abs(pdg) == 11) = 0; + pdgIndex(Vc::abs(pdg) == 13) = 1; + pdgIndex(Vc::abs(pdg) == 19) = 1; + pdgIndex(Vc::abs(pdg) == 211) = 2; + pdgIndex(Vc::abs(pdg) == 321) = 3; + pdgIndex(Vc::abs(pdg) == 2212) = 4; + pdgIndex(Vc::abs(pdg) == 1000010020) = 5; + pdgIndex(Vc::abs(pdg) == 1000010030) = 6; + pdgIndex(Vc::abs(pdg) == 1000020030) = 7; + pdgIndex(Vc::abs(pdg) == 1000020040) = 8; + pdgIndex(Vc::abs(pdg) == 3112) = 9; + pdgIndex(Vc::abs(pdg) == 3222) = 10; + pdgIndex(Vc::abs(pdg) == 3312) = 11; + pdgIndex(Vc::abs(pdg) == 3334) = 12; + Vc::float_v mass(fMass, pdgIndex); + return mass; + } + + void GetMotherMass(const Vc::int_v& pdg, Vc::float_v& massMotherPDG, Vc::float_v& massMotherPDGSigma) const + { + /** Returns vector float variable with the mass of the short-lived particles with the given PDG codes + ** and the expected widths of the corresponding peaks. + ** If the given PDG code is not in the list of the current database mass of K0s is returned. + ** \param[in] pdg - the input PDG code + ** \param[out] massMotherPDG - the output table mass for the given PDG code + ** \param[out] massMotherPDGSigma - expected width of the corresponding peak + **/ + + Vc::int_v pdgIndex(0); + pdgIndex(pdg == 310) = 0; + pdgIndex(Vc::abs(pdg) == 3122) = 1; + pdgIndex(Vc::abs(pdg) == 3312) = 2; + pdgIndex(pdg == 22) = 3; + pdgIndex(Vc::abs(pdg) == 3334) = 4; + pdgIndex(Vc::abs(pdg) == 3004) = 5; + pdgIndex(Vc::abs(pdg) == 3006) = 6; + pdgIndex(Vc::abs(pdg) == 3007) = 7; + + massMotherPDG.gather(fMassSecPDG, pdgIndex); + massMotherPDGSigma.gather(fMassSecPDGSigma, pdgIndex); + } + + void GetMotherMass(const int pdg, float& massMotherPDG, float& massMotherPDGSigma) const + { + /** Returns scalar float variables with the mass of the short-lived particle with the given PDG code + ** and the expected width of the corresponding peak. + ** If the given PDG code is not in the list of the current database mass of K0s is returned. + ** \param[in] pdg - the input PDG code + ** \param[out] massMotherPDG - the output table mass for the given PDG code + ** \param[out] massMotherPDGSigma - expected width of the corresponding peak + **/ + + int pdgIndex = 2; + switch ( abs(pdg) ) + { + case 310: pdgIndex = 0; break; + case 3122: pdgIndex = 1; break; + case 3312: pdgIndex = 2; break; + case 22: pdgIndex = 3; break; + case 3334: pdgIndex = 4; break; + case 3004: pdgIndex = 5; break; + case 3006: pdgIndex = 6; break; + case 3007: pdgIndex = 7; break; + default: pdgIndex = 0; break; + } + + massMotherPDG = fMassSecPDG[pdgIndex]; + massMotherPDGSigma = fMassSecPDGSigma[pdgIndex]; + } + + const float& GetPi0Mass() const { return fMassPi0PDG; } ///< Returns the table PDG pi0 mass. + const float& GetPi0MassSigma() const { return fMassPi0PDGSigma; } ///< Returns expected width of the pi0 peak. + const float& GetD0Mass() const { return fMassD0PDG; } ///< Returns the table PDG D0 mass. + const float& GetD0MassSigma() const { return fMassD0PDGSigma; } ///< Returns expected width of the D0 peak. + const float& GetDPlusMass() const { return fMassDPlusPDG; } ///< Returns the table PDG D+ mass. + const float& GetDPlusMassSigma() const { return fMassDPlusPDGSigma; } ///< Returns expected width of the D+ peak. + + static const KFParticleDatabase* Instance() { return fDatabase; } ///< Returns a pointer to the singleton object. + + private: + /** Table PDG masses of particles, which can be registered by the tracking detector directly: \n + ** [ 0] - electron; \n [ 1] - muon; \n [ 2] - pion; \n [ 3] - kaon; \n [ 4] - proton; \n [ 5] - deutron; \n [ 6] - triton; \n [ 7] - He3; \n + ** [ 8] - He4; \n [ 9] - Sigma-; \n [10] - Sigma+; \n [11] - Xi; \n [12] - Omega. */ + float fMass[13]; + + /** Table PDG masses of short-lived particles, which are used for reconstruction of the decay trees: \n + ** [ 0] - K0s; \n [ 1] - Lambda; \n [ 2] - Xi; \n [ 3] - gamma; \n [ 4] - Omega; \n [ 5] - H3Lambda; \n [ 6] - He4Lambda; \n [ 7] - He5Lambda. */ + float fMassSecPDG[8]; + /** Expected widths of peaks of short-lived particles, which are used for reconstruction of the decay trees: \n + ** [ 0] - K0s; \n [ 1] - Lambda; \n [ 2] - Xi; \n [ 3] - gamma; \n [ 4] - Omega; \n [ 5] - H3Lambda; \n [ 6] - He4Lambda; \n [ 7] - He5Lambda. */ + float fMassSecPDGSigma[8]; + + float fMassPi0PDG; ///< Table mass of pi0 + float fMassPi0PDGSigma; ///< Expected width of the pi0 peak + + float fMassD0PDG; ///< Table mass of D0 + float fMassD0PDGSigma; ///< Expected width of the D0 peak + float fMassDPlusPDG; ///< Table mass of D+ + float fMassDPlusPDGSigma; ///< Expected width of the D+ peak + + static KFParticleDatabase* fDatabase; ///< A singleton object. +}; + +#endif \ No newline at end of file diff --git a/external/KFParticle/KFParticle/KFParticleDef.h b/external/KFParticle/KFParticle/KFParticleDef.h new file mode 100644 index 0000000000000000000000000000000000000000..ced9c0a32270d2435ced3194d427c474af222e3e --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleDef.h @@ -0,0 +1,145 @@ +//--------------------------------------------------------------------------------- +// The KFParticleBaseSIMD class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 13.05.07 +// +// Class to reconstruct and store the decayed particle parameters. +// The method is described in CBM-SOFT note 2007-003, +// ``Reconstruction of decayed particles based on the Kalman filter'', +// http://www.gsi.de/documents/DOC-2007-May-14-1.pdf +// +// This class describes general mathematics which is used by KFParticle class +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//_________________________________________________________________________________ + + +#ifndef KFParticleDef_H +#define KFParticleDef_H + +#ifdef __ROOT__ //for the STAR experiment +#define HomogeneousField +#endif + +#ifdef HLTCA_STANDALONE +#include "RootTypesDef.h" +#else +#include "TObject.h" +#endif + +#define NInputSets 8 + +#include <Vc/Vc> +#include <Vc/version.h> +#include <Vc/limits> +using ::Vc::float_v; +using ::Vc::double_v; +using ::Vc::float_v; +using ::Vc::int_v; +using ::Vc::uint_v; +using ::Vc::VectorAlignment; +using ::Vc::double_m; +using ::Vc::float_m; +using ::Vc::int_m; +using ::Vc::uint_m; +using ::Vc::atan2; +using ::Vc::asin; +using ::Vc::round; +using ::Vc::isfinite; + +#ifdef VC_VERSION_NUMBER +#if VC_VERSION_NUMBER < VC_VERSION_CHECK(1,0,0) +template <typename To, typename From> To simd_cast(From &&x) { return static_cast<To>(x); } +#endif +#elif defined(Vc_VERSION_NUMBER) +#if Vc_VERSION_NUMBER < Vc_VERSION_CHECK(1,0,0) +template <typename To, typename From> To simd_cast(From &&x) { return static_cast<To>(x); } +#endif +#endif + +const int float_vLen = float_v::Size; + +#if defined(HLTCA_STANDALONE) +typedef unsigned char UChar_t; +typedef UChar_t Byte_t; +typedef int Int_t; +typedef double Double_t; +#else +#include "Rtypes.h" +#endif + +#include "KFPSimdAllocator.h" +typedef std::vector<float_v, KFPSimdAllocator<float_v> > kfvector_floatv; + +typedef std::vector<float, KFPSimdAllocator<float> > kfvector_float; +typedef std::vector<int, KFPSimdAllocator<int> > kfvector_int; +typedef std::vector<unsigned int, KFPSimdAllocator<unsigned int> > kfvector_uint; + +namespace KFPMath +{ + static inline __attribute__((always_inline)) float_v Sin ( const float_v &phi ) + { + const float_v pi(3.1415926535897932f); + const float_v nTurnsF = (phi + pi) / (float_v(2.f)*pi); + int_v nTurns = simd_cast<int_v>( nTurnsF ); + nTurns( (nTurns<=int_v(Vc::Zero)) && simd_cast<int_m>(phi<-pi)) -= 1; + + const float_v& x = phi - simd_cast<float_v>(nTurns)*(float_v(2.f)*pi); + + const float_v& B = 4.f/pi; + const float_v& C = -B/pi; + + float_v y = (B + C * Vc::abs(x)) * x; + + const float_v& P = 0.218f; + y = P * (y * Vc::abs(y) - y) + y; + + return y; + } + static inline __attribute__((always_inline)) float_v Cos ( const float_v &phi ) + { + return Sin( phi + 1.570796326795f ); //x + pi/2 + } + static inline __attribute__((always_inline)) float_v ATan2( const float_v &y, const float_v &x ) + { + const float_v pi(3.1415926535897932f); + const float_v zero(Vc::Zero); + + const float_m &xZero = (x == zero); + const float_m &yZero = (y == zero); + const float_m &xNeg = (x < zero); + const float_m &yNeg = (y < zero); + + const float_v &absX = Vc::abs(x); + const float_v &absY = Vc::abs(y); + + float_v a = absY / absX; + const float_m >_tan_3pi_8 = (a > float_v(2.414213562373095f)); + const float_m >_tan_pi_8 = (a > float_v(0.4142135623730950f)) && (!gt_tan_3pi_8); + float_v b(Vc::Zero); + b(gt_tan_3pi_8) = pi/2.f; + b(gt_tan_pi_8) = pi/4.f; + a(gt_tan_3pi_8) = (-1.f / a); + a(gt_tan_pi_8) = ((absY - absX) / (absY + absX)) ; + const float_v &a2 = a * a; + b += (((8.05374449538e-2f * a2 + - 1.38776856032E-1f) * a2 + + 1.99777106478E-1f) * a2 + - 3.33329491539E-1f) * a2 * a + + a; + b(xNeg ^ yNeg) = -b; + b(xNeg && !yNeg) = (b+pi); + b(xNeg && yNeg) = (b-pi); + b(xZero && yZero) = zero; + b(xZero && yNeg) = (-pi/2.f); + return b; + } + template<typename T> static inline __attribute__((always_inline)) + typename Vc::Vector<T>::Mask Finite(const Vc::Vector<T> &x) { return Vc::isfinite( x ); } + template<typename T> static inline __attribute__((always_inline)) T Log ( const T &x ) { return std::log( x ); } + template<typename T> static inline __attribute__((always_inline)) T ACos( const T &x ) { return (3.1415926535897f/2.f - asin( x )); } +} + +#endif diff --git a/external/KFParticle/KFParticle/KFParticleField.h b/external/KFParticle/KFParticle/KFParticleField.h new file mode 100644 index 0000000000000000000000000000000000000000..605c63a66373eaa7ee057776e9b53107cf604241 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleField.h @@ -0,0 +1,190 @@ +//---------------------------------------------------------------------------- +// Class for approximation of the magnetic field for KF Particle +// . +// @author I.Kisel, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFParticleField_h +#define KFParticleField_h 1 + +#include <iostream> + +/** @class KFParticleFieldValue + ** @brief A class to store a vector with the magnetic field values {Bx, By, Bz} at the certain point. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is used to represent the vector of the magnetic field at the certain position of the track. + ** It contains three components of the magnetic field: Bx, By and Bz. It allows to combine the current + ** field measurement with another measurement using a weight. + **/ + +class KFParticleFieldValue +{ + public: + KFParticleFieldValue():x(0.f),y(0.f),z(0.f){}; + + float_v x; ///< Bx component of the magnetic field + float_v y; ///< By component of the magnetic field + float_v z; ///< Bz component of the magnetic field + + void Combine( KFParticleFieldValue &B, float_v w ) + { + /** Function allows to combine the current magntic field measurement with another measurement + ** weighted by "w" + ** \param[in] B - another field measurement to be combined with the current value + ** \param[in] w - weight of the measurement being added + **/ + x+= w*( B.x - x ); + y+= w*( B.y - y ); + z+= w*( B.z - z ); + } + + /** Operator to print components of the magnetic field in order Bx, By, Bz. + ** \param[in] out - output stream where the values will be printed + ** \param[in] B - field vecrot to be printed + **/ + friend std::ostream& operator<<(std::ostream& out, KFParticleFieldValue &B){ + return out << B.x[0] << " | " << B.y[0] << " | " << B.z[0]; + }; +}; + +/** @class KFParticleFieldRegion + ** @brief A class to store an approximation of the magnetic field along the particle trajectory. Is used for nonhomogeneous field. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is used to store the approximation of the magnetic field along the particle trajectory. + ** Each component Bx, By, Bz is approximated with a parabola function depending on the z coordinate. + ** The class is fully vectorised, all parameters are stored in SIMD vectors. + ** The class is used in case of the CBM-like nonhomogenious magnetic field. + **/ + +class KFParticleFieldRegion +{ + public: + KFParticleFieldRegion() {}; + KFParticleFieldRegion(const float field[10]) + { + /** Sets current vectorised representation of the magnetic field approximation from the scalar input array. + ** \param[in] field[10] - the scalar input array with the magnetic field approximation + **/ + for(int i=0; i<10; i++) + fField[i] = field[i]; + } + + KFParticleFieldValue Get(const float_v z) + { + /** Returns a magnetic field vector calculated using current parametrisation at the given Z coordinate. + ** \param[in] z - value of the Z coordinate, where magnetic field should be calculated. + **/ + float_v dz = (z-fField[9]); + float_v dz2 = dz*dz; + KFParticleFieldValue B; + B.x = fField[0] + fField[1]*dz + fField[2]*dz2; + B.y = fField[3] + fField[4]*dz + fField[5]*dz2; + B.z = fField[6] + fField[7]*dz + fField[8]*dz2; + return B; + } + + void Set( const KFParticleFieldValue &B0, const float_v B0z, + const KFParticleFieldValue &B1, const float_v B1z, + const KFParticleFieldValue &B2, const float_v B2z ) + { + /** Approximates the magnetic field with the parabolas using three points along the particle trajectory. + ** \param[in] B0 - magnetic field vector at the first point + ** \param[in] B0z - Z position of the first point + ** \param[in] B1 - magnetic field vector at the second point + ** \param[in] B1z - Z position of the second point + ** \param[in] B2 - magnetic field vector at the third point + ** \param[in] B2z - Z position of the third point + **/ + fField[9] = B0z; + float_v dz1 = B1z-B0z, dz2 = B2z-B0z; + float_v det = 1.f/(float_v(dz1*dz2*(dz2-dz1))); + float_v w21 = -dz2*det; + float_v w22 = dz1*det; + float_v w11 = -dz2*w21; + float_v w12 = -dz1*w22; + + float_v dB1 = B1.x - B0.x; + float_v dB2 = B2.x - B0.x; + fField[0] = B0.x; + fField[1] = dB1*w11 + dB2*w12 ; + fField[2] = dB1*w21 + dB2*w22 ; + + dB1 = B1.y - B0.y; + dB2 = B2.y - B0.y; + fField[3] = B0.y; + fField[4] = dB1*w11 + dB2*w12 ; + fField[5] = dB1*w21 + dB2*w22 ; + + dB1 = B1.z - B0.z; + dB2 = B2.z - B0.z; + fField[6] = B0.z; + fField[7] = dB1*w11 + dB2*w12 ; + fField[8] = dB1*w21 + dB2*w22 ; + } + + void Set( const KFParticleFieldValue &B0, const float_v B0z, + const KFParticleFieldValue &B1, const float_v B1z ) + { + /** Approximates the magnetic field with the strainght line using two points. + ** \param[in] B0 - magnetic field vector at the first point + ** \param[in] B0z - Z position of the first point + ** \param[in] B1 - magnetic field vector at the second point + ** \param[in] B1z - Z position of the second point + **/ + fField[9] = B0z; + float_v dzi = 1.f/(float_v( B1z - B0z)); + fField[0] = B0.x; + fField[3] = B0.y; + fField[6] = B0.z; + fField[1] = ( B1.x - B0.x )*dzi; + fField[4] = ( B1.y - B0.y )*dzi; + fField[7] = ( B1.z - B0.z )*dzi; + fField[2] = fField[5] = fField[8] = 0.f; + } + + void SetOneEntry( const float* field, int iEntry=0 ) + { + /** Sets one element of the SIMD vector with index iEntry. + ** \param[in] field - a scalar input array with the approximation of the magnetic field + ** \param[in] iEntry - entry number of the current SIMD vectors to be set with the input approximation + **/ + for(int i=0; i<10; i++) + fField[i][iEntry] = field[i]; + } + + void SetOneEntry( const int i0, const KFParticleFieldRegion &f1, const int i1 ) + { + /** Copies the field approximation from the vector f1 with index i1 to the SIMD vector elemets of the current object with index i0. + ** \param[in] i0 - index of the SIMD vector elements of the current field approximation to be set + ** \param[in] f1 - input approximation of the magnetic field + ** \param[in] i1 - index of the SIMD vector elements of the input approximation to be copied to the current object + **/ + for(int i=0; i<10; i++) + fField[i][i0] = f1.fField[i][i1]; + } + + /** The coefficients of the field approximation: \n + ** cx0 = fField[0], cx1 = fField[1], cx2 = fField[2] - coefficients of the Bx approximation; \n + ** cy0 = fField[3], cy1 = fField[4], cy2 = fField[5] - coefficients of the By approximation; \n + ** cz0 = fField[6], cz1 = fField[7], cz2 = fField[8] - coefficients of the Bz approximation; \n + ** z0 = fField[9] - reference Z coordinate. \n + ** Bx(z) = cx0 + cx1*(z-z0) + cx2*(z-z0)^2 \n + ** By(z) = cy0 + cy1*(z-z0) + cy2*(z-z0)^2 \n + ** Bz(z) = cz0 + cz1*(z-z0) + cz2*(z-z0)^2 + **/ + float_v fField[10]; +}; + + +#endif diff --git a/external/KFParticle/KFParticle/KFParticleFinder.cxx b/external/KFParticle/KFParticle/KFParticleFinder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..78bc5048aec1fe16d9ed9e5ef396593cf1f6a9c8 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleFinder.cxx @@ -0,0 +1,3114 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFParticleFinder.h" + +using std::map; +using std::vector; + +#include "KFParticleDatabase.h" +#include "KFPEmcCluster.h" + +KFParticleFinder::KFParticleFinder(): + fNPV(-1),fNThreads(1),fDistanceCut(1.f),fLCut(-5.f),fCutCharmPt(0.2f),fCutCharmChiPrim(85.f),fCutLVMPt(0.0f),fCutLVMP(0.0f),fCutJPsiPt(1.0f), + fD0(0), fD0bar(0), fD04(0), fD04bar(0), fD0KK(0), fD0pipi(0), fDPlus(0), fDMinus(0), + fDPlus3Pi(0), fDMinus3Pi(0), fDsPlusK2Pi(0), fDsMinusK2Pi(0), fLcPlusP2Pi(0), fLcMinusP2Pi(0), + fLPi(0), fLPiPIndex(0), fHe3Pi(0), fHe3PiBar(0), fHe4Pi(0), fHe4PiBar(0), + fHe4L(0), fHe5L(0), fLLn(0), fH5LL(0), + fSecCandidates(), fPrimCandidates(), fPrimCandidatesTopo(),fPrimCandidatesTopoMass(), + fEmcClusters(0), fMixedEventAnalysis(0), fDecayReconstructionList() +{ + /** The default constructor. Initialises all cuts to the default values. **/ + //Cuts + //track + track + //chi2_prim chi2_geo ldl + fCuts2D[0] = 3.f; fCuts2D[1] = 3.f; fCuts2D[2] = 5.f; + //cuts to select primary and secondary particles + //mass chi2_topo ldl +#ifdef PANDA_STT + fSecCuts[0] = 3.f; fSecCuts[1] = -3.f; fSecCuts[2] = 10.f; +#else + fSecCuts[0] = 3.f; fSecCuts[1] = 5.f; fSecCuts[2] = 10.f; +#endif + +#ifdef __ROOT__ + fCutCharmChiPrim = 8; +#endif + + //track + particle + // ldl chi2_topo chi2_geo + fCutsTrackV0[0][0] = 5; fCutsTrackV0[0][1] = 5; fCutsTrackV0[0][2] = 6; //Xi, Omega + fCutsTrackV0[1][0] = 5; fCutsTrackV0[1][1] = 5; fCutsTrackV0[1][2] = 6; //Charm, H0, Sigma+ + fCutsTrackV0[2][0] = -100.; fCutsTrackV0[2][1] = 10000.; fCutsTrackV0[2][2] = 3; //resonances + + //charm + //chi2 l/dl chi2_topo + fCutsCharm[0] = 3.f; fCutsCharm[1] = 10.f; fCutsCharm[2] = 3.f; //D0 -> pi+ K- + + //cuts on particles reconstructed from short-lived particles + //ldl, chi2_topo chi2_geo + //H0 -> Lambda Lambda, Xi0 -> Lambda pi0 + fCutsPartPart[0][0] = 10; fCutsPartPart[0][1] = 3; fCutsPartPart[0][2] = 3; + //Sigma0 -> Lambda Gamma, pi0 -> Gamma Gamma, K* -> K pi0, Sigma*0 -> Lambda pi0, Xi* -> Xi pi0 + fCutsPartPart[1][0] = -10; fCutsPartPart[1][1] = 3; fCutsPartPart[1][2] = 3; +} + +//________________________________________________________________________________ +void KFParticleFinder::Init(int nPV) +{ + /** Initialises the new event: all vectors with temporary candidates are cleaned, the number of + ** primary vertices is set to "nPV", vectors with primary candidates are resized correspondingly. + ** \param[in] nPV - number of primary vertices in the event which will be processed + **/ + + fNPV = nPV; +// Particles.reserve(vRTracks.size() + nPart); + + fD0.clear(); + fD0bar.clear(); + fD04.clear(); + fD04bar.clear(); + fD0KK.clear(); + fD0pipi.clear(); + fDPlus.clear(); + fDMinus.clear(); + fDPlus3Pi.clear(); + fDMinus3Pi.clear(); + fDsPlusK2Pi.clear(); + fDsMinusK2Pi.clear(); + fLcPlusP2Pi.clear(); + fLcMinusP2Pi.clear(); + fLPi.clear(); + fLPiPIndex.clear(); + fHe3Pi.clear(); + fHe3PiBar.clear(); + fHe4Pi.clear(); + fHe4PiBar.clear(); + fHe4L.clear(); + fHe5L.clear(); + fLLn.clear(); + fH5LL.clear(); + + for(int iCandidates=0; iCandidates<fNSecCandidatesSets; iCandidates++) + fSecCandidates[iCandidates].clear(); + + for(int iCandidates=0; iCandidates<fNPrimCandidatesSets; iCandidates++) + { + fPrimCandidates[iCandidates].clear(); + fPrimCandidates[iCandidates].resize(fNPV); + } + + for(int iCandidates=0; iCandidates<fNPrimCandidatesTopoSets; iCandidates++) + { + fPrimCandidatesTopo[iCandidates].clear(); + fPrimCandidatesTopo[iCandidates].resize(fNPV); + + fPrimCandidatesTopoMass[iCandidates].clear(); + fPrimCandidatesTopoMass[iCandidates].resize(fNPV); + } + +} +//________________________________________________________________________________ + +void KFParticleFinder::FindParticles(KFPTrackVector* vRTracks, kfvector_float* ChiToPrimVtx, std::vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, int nPV) +{ + /** The main interface which runs reconstruction of short-lived particles:\n + ** 1) a new event is initialised; \n + ** 2) long-lived particles formed from tracks are stored to the output array "Particles"; \n + ** 3) 2-daughter channels are reconstructed (KFParticleFinder::Find2DaughterDecay()); \n + ** 4) the 2-daughter same-signed background is collected for resonances (KFParticleFinder::ConstructPrimaryBG()); \n + ** 5) found primary candidates of \f$K_s^0\f$, \f$\Lambda\f$, \f$\overline{\Lambda}\f$ and \f$\gamma\f$ are transported + ** to the point of the closest approach with the corresponding primary vertex (KFParticleFinder::ExtrapolateToPV()); \n + ** 6) reconstruction with the missing mass method (KFParticleFinder::NeutralDaughterDecay()); \n + ** 7) all other decays are reconstructed one after another. \n + ** If analysis is run in the mixed event mode only steps 1) and 2) are performed. + ** \param[in] vRTracks - pointer to the array with vectors of tracks:\n + ** 0) secondary positive at the first hit position; \n + ** 1) secondary negative at the first hit position; \n + ** 2) primary positive at the first hit position; \n + ** 3) primary negative at the first hit position; \n + ** 4) secondary positive at the last hit position; \n + ** 5) secondary negative at the last hit position; \n + ** 6) primary positive at the last hit position; \n + ** 7) primary negative at the last hit position. \n + ** \param[in] ChiToPrimVtx - arrays with vectors of the \f$\chi^2_{prim}\f$ deviations for track vectors 1) and 2). + ** \param[out] Particles - output vector with particles. + ** \param[in] PrimVtx - vector with primary vertices. + ** \param[in] nPV - number of the input primary vertices. + **/ + + Init(nPV); + const int nPartPrim = vRTracks[2].NPions() * vRTracks[3].NKaons() + + vRTracks[3].NPions() * vRTracks[2].NKaons() + + vRTracks[2].NKaons() * vRTracks[3].NKaons() + + vRTracks[2].NKaons() * vRTracks[3].NProtons() + + vRTracks[3].NKaons() * vRTracks[2].NProtons() + + vRTracks[2].NElectrons() * vRTracks[3].NElectrons() + + vRTracks[2].NMuons() * vRTracks[3].NMuons(); + + const int nPart = vRTracks[0].NPions() * vRTracks[1].NPions() + + vRTracks[0].NPions() * vRTracks[1].NProtons() + + vRTracks[1].NPions() * vRTracks[0].NProtons() + nPartPrim; + int nEmcClusters = 0; + if(fEmcClusters) + nEmcClusters = fEmcClusters->Size(); + vector<KFParticle> vGammaPrimEmc; + + int nPartEstimation = nPart+vRTracks[0].Size()+vRTracks[1].Size()+vRTracks[2].Size()+vRTracks[3].Size() + nEmcClusters; + + if(nPartEstimation < 100000) + Particles.reserve(nPartEstimation); + //* Finds particles (K0s and Lambda) from a given set of tracks + { + KFPTrack kfTrack; + for(int iV=0; iV<4; iV++) + { + for(int iTr=0; iTr < vRTracks[iV].Size(); iTr++) + { + vRTracks[iV].GetTrack(kfTrack, iTr); + int pdg = vRTracks[iV].PDG()[iTr]; + if( pdg == 19 ) pdg = 13; + if( pdg ==-19 ) pdg = -13; + KFParticle tmp(kfTrack, pdg); + tmp.SetPDG(pdg); + tmp.SetId(Particles.size()); + vRTracks[iV].SetId(Particles.size(),iTr); + if(vRTracks[iV+4].Size() > 0) + vRTracks[iV+4].SetId(Particles.size(),iTr); + tmp.AddDaughterId( kfTrack.Id() ); +#ifdef NonhomogeneousField + for(int iF=0; iF<10; iF++) + tmp.SetFieldCoeff( vRTracks[iV].FieldCoefficient(iF)[iTr], iF); +#endif + Particles.push_back(tmp); + } + } + + if(fEmcClusters) + { + KFParticleSIMD tmpGammaSIMD; + KFParticle tmpGamma; + + for(int iEmc=0; iEmc < fEmcClusters->Size(); iEmc += float_vLen) + { + const int NClustersVec = (iEmc + float_vLen < fEmcClusters->Size()) ? float_vLen : (fEmcClusters->Size() - iEmc); + tmpGammaSIMD.Load(*fEmcClusters, iEmc, PrimVtx[0]); + for(int iV=0; iV<NClustersVec; iV++) + { + tmpGammaSIMD.GetKFParticle(tmpGamma, iV); + tmpGamma.SetPDG(22); //gamma pdg + tmpGamma.SetId(Particles.size()); + tmpGamma.CleanDaughtersId(); + tmpGamma.AddDaughterId(fEmcClusters->Id()[iEmc+iV]); + Particles.push_back(tmpGamma); + vGammaPrimEmc.push_back(tmpGamma); + } + } + } + } + + + + Find2DaughterDecay(vRTracks, ChiToPrimVtx, + Particles, PrimVtx, fCuts2D, + fSecCuts, fPrimCandidates, fSecCandidates); + + if(!fMixedEventAnalysis) + { + //Construct two-particle background from positive primary tracks for subtraction from the resonance spectra + ConstructPrimaryBG(vRTracks, Particles, PrimVtx, fCuts2D, fSecCuts, fPrimCandidates, fSecCandidates); + + for(int iPV=0; iPV<fNPV; iPV++ ) + { + ExtrapolateToPV(fPrimCandidates[0][iPV],PrimVtx[iPV]); + ExtrapolateToPV(fPrimCandidates[1][iPV],PrimVtx[iPV]); + ExtrapolateToPV(fPrimCandidates[2][iPV],PrimVtx[iPV]); + ExtrapolateToPV(fPrimCandidates[3][iPV],PrimVtx[iPV]); + } + + NeutralDaughterDecay(vRTracks, Particles); + + //Xi- -> Lambda pi-, Omega- -> Lambda K- + FindTrackV0Decay(fSecCandidates[1], 3122, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastKaon(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1]), &fPrimCandidates[5]); + //Xi+ -> Lambda pi+, Omega+ -> Lambda K+ + FindTrackV0Decay(fSecCandidates[2], -3122, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastKaon(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0]), &fPrimCandidates[6]); + + for(int iPV=0; iPV<fNPV; iPV++ ) + { + ExtrapolateToPV(fPrimCandidates[5][iPV],PrimVtx[iPV]); + ExtrapolateToPV(fPrimCandidates[6][iPV],PrimVtx[iPV]); + + ExtrapolateToPV(fPrimCandidates[7][iPV],PrimVtx[iPV]); + ExtrapolateToPV(fPrimCandidates[8][iPV],PrimVtx[iPV]); + } + + //K*+ -> K0 pi+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[0][iPV], 310, vRTracks[2], 1, vRTracks[2].FirstPion(), vRTracks[2].LastPion(), + Particles, PrimVtx, iPV, 0); + //K*- -> K0 pi- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[0][iPV], 310, vRTracks[3], -1, vRTracks[3].FirstPion(), vRTracks[3].LastPion(), + Particles, PrimVtx, iPV, 0); + //Sigma*+ -> Lambda pi+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[1][iPV], 3122, vRTracks[2], 1, vRTracks[2].FirstPion(), vRTracks[2].LastPion(), + Particles, PrimVtx, iPV, 0); + //Sigma*- -> Lambda pi-, Xi*- -> Lambda K- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[1][iPV], 3122, vRTracks[3], -1, vRTracks[3].FirstPion(), vRTracks[3].LastKaon(), + Particles, PrimVtx, iPV, 0); + //Sigma*+_bar -> Lambda_bar pi- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[2][iPV], -3122, vRTracks[3], -1, vRTracks[3].FirstPion(), vRTracks[3].LastPion(), + Particles, PrimVtx, iPV, 0); + //Sigma*-_bar -> Lambda_bar pi+, Xi*+ -> Lambda_bar + K+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[2][iPV], -3122, vRTracks[2], 1, vRTracks[2].FirstPion(), vRTracks[2].LastKaon(), + Particles, PrimVtx, iPV, 0); + //Xi*0 -> Xi- pi+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[5][iPV], 3312, vRTracks[2], 1, vRTracks[2].FirstPion(), vRTracks[2].LastPion(), + Particles, PrimVtx, iPV, 0, &fPrimCandidates[9]); + //Xi*0_bar -> Xi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[6][iPV], -3312, vRTracks[3], -1, vRTracks[3].FirstPion(), vRTracks[3].LastPion(), + Particles, PrimVtx, iPV, 0, &fPrimCandidates[10]); + //Omega*- -> Xi- pi+ K- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[9][iPV], 3324, vRTracks[3], -1, vRTracks[3].FirstKaon(), vRTracks[3].LastKaon(), + Particles, PrimVtx, iPV, 0); + //Omega*+ -> Xi+ pi- K+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[10][iPV], -3324, vRTracks[2], 1, vRTracks[2].FirstKaon(), vRTracks[2].LastKaon(), + Particles, PrimVtx, iPV, 0); + //Hypernuclei + //He4L -> He3 p pi- + FindTrackV0Decay(fHe3Pi , 3004, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), Particles, PrimVtx, -1, 0, 0, &fHe4L); + //LLn -> H3L pi- + FindTrackV0Decay(fHe3Pi , 3004, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), Particles, PrimVtx, -1, 0 ); + //He4L_bar -> He3_bar p- pi+ + FindTrackV0Decay(fHe3PiBar,-3004, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastProton(), Particles, PrimVtx, -1, 0); + //He5L -> He4 p pi- + FindTrackV0Decay(fHe4Pi , 3005, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), Particles, PrimVtx, -1, 0, 0, &fHe5L); + //He5L_bar -> He4_bar p- pi+ + FindTrackV0Decay(fHe4PiBar,-3005, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastProton(), Particles, PrimVtx, -1, 0); + //H4LL -> He4L pi- + FindTrackV0Decay(fHe4L , 3006, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), Particles, PrimVtx, -1, 0 ); + //H5LL -> He5L pi- + FindTrackV0Decay(fHe5L , 3007, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), Particles, PrimVtx, -1, 0 ); + //H4LL -> H3L p pi- + FindTrackV0Decay(fLLn , 3203, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), Particles, PrimVtx, -1, 0 ); + //He6LL -> He5L p pi- + FindTrackV0Decay(fH5LL , 3010, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), Particles, PrimVtx, -1, 0 ); + // Charm + //LambdaC -> pi+ K- p, Ds+ -> pi+ K- K+, D+ -> pi+ K- pi+ + FindTrackV0Decay(fD0, 421, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastProton(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0])); + //LambdaC_bar -> pi- K+ p-, Ds- -> pi- K+ K-, D- -> pi- K+ pi- + FindTrackV0Decay(fD0bar, -421, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastProton(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1])); + //D0->pi+ K- pi+ pi- + FindTrackV0Decay(fDPlus, 411, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1])); + //D0_bar->pi- K+ pi- pi+ + FindTrackV0Decay(fDMinus, -411, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastPion(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0])); + //B+ -> D0_bar pi+, B+ -> D0_bar K+ + FindTrackV0Decay(fD0bar, -421, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastKaon(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0])); + //B- -> D0 pi-, B- -> D0 K- + FindTrackV0Decay(fD0, 421, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastKaon(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1])); + //B0 -> D- pi+, B0 -> D- K+ + FindTrackV0Decay(fDMinus, -419, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastKaon(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0])); + //B0_bar -> D+ pi-, B0_bar -> D+ K- + FindTrackV0Decay(fDPlus, 419, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastKaon(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1])); + //D0 -> pi+ K- + SelectParticles(Particles,fD0,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //D0_bar -> pi+ K- + SelectParticles(Particles,fD0bar,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //D*+->D0 pi+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fD0, 421, vRTracks[2], 1, vRTracks[2].FirstPion(), vRTracks[2].LastPion(), + Particles, PrimVtx, iPV, 0); + //D*- -> D0_bar pi- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fD0, -421, vRTracks[3], -1, vRTracks[3].FirstPion(), vRTracks[3].LastPion(), + Particles, PrimVtx, iPV, 0); + //D0 -> pi+ K- pi+ pi- + SelectParticles(Particles,fD04,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //D0_bar -> pi- K+ pi- pi+ + SelectParticles(Particles,fD04bar,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //D*+->D0 pi+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fD04, 429, vRTracks[2], 1, vRTracks[2].FirstPion(), vRTracks[2].LastPion(), + Particles, PrimVtx, iPV, 0); + //D0*- -> D0_bar pi- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fD04bar, -429, vRTracks[3], -1, vRTracks[3].FirstPion(), vRTracks[3].LastPion(), + Particles, PrimVtx, iPV, 0); + //D+ + SelectParticles(Particles,fDPlus,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetDPlusMass(), KFParticleDatabase::Instance()->GetDPlusMassSigma(), fSecCuts[0]); + //D- + SelectParticles(Particles,fDMinus,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetDPlusMass(), KFParticleDatabase::Instance()->GetDPlusMassSigma(), fSecCuts[0]); + //D*0->D+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fDPlus, 411, vRTracks[3], -1, vRTracks[3].FirstPion(), vRTracks[3].LastPion(), + Particles, PrimVtx, iPV, 0); + //D*0_bar->D- pi+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fDMinus, -411, vRTracks[2], 1, vRTracks[2].FirstPion(), vRTracks[2].LastPion(), + Particles, PrimVtx, iPV, 0); + + float cutsD0[3] = {fCutsCharm[1], fCutsCharm[2], fCutsCharm[0]}; +// float cutsD0[3] = {-5, 1e10, 1e10}; + //D0 -> K0 pi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fD0pipi, fPrimCandidates[0][iPV], Particles, PrimVtx, cutsD0, -1, 425, 0, 1); + //D0 -> K0 K+ K- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fD0KK, fPrimCandidates[0][iPV], Particles, PrimVtx, cutsD0, -1, 427, 0, 1); + + + //LambdaC -> p pi+ pi-, Ds+ -> K+ pi+ pi-, D+ -> pi+ pi+ pi- + FindTrackV0Decay(fD0pipi, 420, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastProton(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0])); + //LambdaC_bar -> p_bar pi+ pi-, Ds- -> K- pi+ pi-, D- -> pi+ pi- pi- + FindTrackV0Decay(fD0pipi, 420, vRTracks[1],-1, vRTracks[1].FirstPion(), vRTracks[1].LastProton(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1])); + + //D+ -> K0 pi+ pi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fDPlus3Pi, fPrimCandidates[0][iPV], Particles, PrimVtx, cutsD0, -1, 200411, 0, 1); + //D- -> K0 pi+ pi- pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fDMinus3Pi, fPrimCandidates[0][iPV], Particles, PrimVtx, cutsD0, -1, -200411, 0, 1); + //Lc+ -> Lambda pi+ pi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fDPlus3Pi, fPrimCandidates[1][iPV], Particles, PrimVtx, cutsD0, -1, 404122, 0, 1); + //Lc- -> Lambda_bar pi+ pi- pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fDMinus3Pi, fPrimCandidates[2][iPV], Particles, PrimVtx, cutsD0, -1, -404122, 0, 1); + //Xic0 -> Xi- pi+ pi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fDPlus3Pi, fPrimCandidates[5][iPV], Particles, PrimVtx, cutsD0, -1, 4132, 0, 1); + //Xic0_bar -> Xi+ pi+ pi- pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fDMinus3Pi, fPrimCandidates[6][iPV], Particles, PrimVtx, cutsD0, -1, -4132, 0, 1); + + //Ds+ -> K0 K+ pi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fDsPlusK2Pi, fPrimCandidates[0][iPV], Particles, PrimVtx, cutsD0, -1, 300431, 0, 1); + //Ds- -> K0 K- pi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fDsMinusK2Pi, fPrimCandidates[0][iPV], Particles, PrimVtx, cutsD0, -1, -300431, 0, 1); + + //Lc+ -> p K0 pi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fLcPlusP2Pi, fPrimCandidates[0][iPV], Particles, PrimVtx, cutsD0, -1, 204122, 0, 1); + //Lc- -> p- K0 pi+ pi- + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fLcMinusP2Pi, fPrimCandidates[0][iPV], Particles, PrimVtx, cutsD0, -1, -204122, 0, 1); + + //D0 -> pi+ pi- + SelectParticles(Particles,fD0pipi,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //D0 -> K+ K- + SelectParticles(Particles,fD0KK,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //D+ -> pi+ pi+ pi- + SelectParticles(Particles,fDPlus3Pi,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetDPlusMass(), KFParticleDatabase::Instance()->GetDPlusMassSigma(), fSecCuts[0]); + //D- -> pi+ pi- pi- + SelectParticles(Particles,fDMinus3Pi,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetDPlusMass(), KFParticleDatabase::Instance()->GetDPlusMassSigma(), fSecCuts[0]); + //Ds+ -> K+ pi+ pi-, + SelectParticles(Particles,fDsPlusK2Pi,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //Ds- -> K- pi+ pi- + SelectParticles(Particles,fDsMinusK2Pi,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //LambdaC -> p pi+ pi- + SelectParticles(Particles,fLcPlusP2Pi,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //LambdaC_bar -> p_bar pi+ pi- + SelectParticles(Particles,fLcMinusP2Pi,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + + + //D+ -> K0 pi+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[0][iPV], 310, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastPion(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0]) ); + //D- -> K0 pi- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[0][iPV], 310, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1]) ); + //Ds+ -> K0 K+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[0][iPV], 310, vRTracks[0], 1, vRTracks[0].FirstKaon(), vRTracks[0].LastKaon(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0]) ); + //Ds- -> K0 K- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[0][iPV], 310, vRTracks[1], -1, vRTracks[1].FirstKaon(), vRTracks[1].LastKaon(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1]) ); + //Lambdac+ -> Lambda pi+ + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[1][iPV], 3122, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastPion(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0]) ); + //Lambdac_bar- -> Lambda_bar pi- + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[2][iPV], -3122, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1]) ); + //Lambdac+ -> p K0s + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[0][iPV], 310, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[0]) ); + //Lambdac_bar- -> p_bar K0s + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[0][iPV], 310, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastProton(), + Particles, PrimVtx, -1, &(ChiToPrimVtx[1]) ); + + //H0 -> Lambda Lambda + CombinePartPart(fSecCandidates[1], fSecCandidates[1], Particles, PrimVtx, fCutsPartPart[0], -1, 3000, 1, 1); + //H0 -> Lambda p pi- + FindTrackV0Decay(fLPi, 3002, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), + Particles, PrimVtx, -1); + //Sigma0 -> Lambda Gamma + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[3][iPV], fPrimCandidates[1][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, 3212); + //Sigma0_bar -> Lambda_bar Gamma + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[3][iPV], fPrimCandidates[2][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, -3212); + //pi0 -> gamma gamma + const float& mPi0 = KFParticleDatabase::Instance()->GetPi0Mass(); + const float& mPi0Sigma = KFParticleDatabase::Instance()->GetPi0MassSigma(); + CombinePartPart(fSecCandidates[3], fSecCandidates[3], Particles, PrimVtx, fCutsPartPart[1], -1, 111, 1, 0, &fPrimCandidates[4], &fSecCandidates[4], mPi0, mPi0Sigma); + for(int iPV=0; iPV<fNPV; iPV++) + { + CombinePartPart(fPrimCandidates[3][iPV], fPrimCandidates[3][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, 111, 1, 0, &fPrimCandidates[4], &fSecCandidates[4], mPi0, mPi0Sigma); + CombinePartPart(fSecCandidates[3], fPrimCandidates[3][iPV], Particles, PrimVtx, fCutsPartPart[1], -1, 111, 0, 0, &fPrimCandidates[4], &fSecCandidates[4], mPi0, mPi0Sigma); + } + for(int iPV=0; iPV<fNPV; iPV++ ) + ExtrapolateToPV(fPrimCandidates[4][iPV],PrimVtx[iPV]); + //eta -> pi0 pi0 pi0 + //TODO implement this + //Sigma+ -> p pi0 + FindTrackV0Decay(fSecCandidates[4], 111, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), + Particles, PrimVtx, -1); + //Sigma+_bar -> p- pi0 + FindTrackV0Decay(fSecCandidates[4], 111, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastProton(), + Particles, PrimVtx, -1); + //Xi0 -> Lambda pi0 + CombinePartPart(fSecCandidates[4], fSecCandidates[1], Particles, PrimVtx, fCutsPartPart[0], -1, 3322); + //Xi0_bar -> Lambda_bar pi0 + CombinePartPart(fSecCandidates[4], fSecCandidates[2], Particles, PrimVtx, fCutsPartPart[0], -1, -3322); + //K*+ -> K+ pi0 + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[4][iPV], 111, vRTracks[2], 1, vRTracks[2].FirstKaon(), vRTracks[2].LastKaon(), + Particles, PrimVtx, -1); + //K*- -> K- pi0 + for(int iPV=0; iPV<fNPV; iPV++) + FindTrackV0Decay(fPrimCandidates[4][iPV], 111, vRTracks[3], -1, vRTracks[3].FirstKaon(), vRTracks[3].LastKaon(), + Particles, PrimVtx, -1); + //K*0 -> K0 pi0 + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[4][iPV], fPrimCandidates[0][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, 100313, 0, 1); + //Sigma*0 -> Lambda pi0 + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[4][iPV], fPrimCandidates[1][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, 3214, 0, 1); + //Sigma*0_bar -> Lambda_bar pi0 + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[4][iPV], fPrimCandidates[2][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, -3214, 0, 1); + //Xi*- -> Xi- pi0 + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[4][iPV], fPrimCandidates[5][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, 3314, 0, 1); + //Xi*+ -> Xi+ pi0 + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[4][iPV], fPrimCandidates[6][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, -3314, 0, 1); + //JPsi -> Lambda Lambda_bar + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[1][iPV], fPrimCandidates[2][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, 300443, 0, 1); + //JPsi -> Xi- Xi+ + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[5][iPV], fPrimCandidates[6][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, 400443, 0, 1); + //Psi -> Omega- Omega+ + for(int iPV=0; iPV<fNPV; iPV++) + CombinePartPart(fPrimCandidates[7][iPV], fPrimCandidates[8][iPV], Particles, PrimVtx, fCutsPartPart[1], iPV, 500443, 0, 1); + + //reconstruct particles with daughters in ElectroMagnetic Calorimeter +// if(fEmcClusters) +// { +// //pi0 -> gamma gamma, EMC +// vector< vector<KFParticle> > vPi0PrimEmc(1); +// vector<KFParticle> vPi0SecEmc; +// vector< vector<KFParticle> > vD0PrimEmc(1); +// CombinePartPart(vGammaPrimEmc, vGammaPrimEmc, Particles, PrimVtx, fCutsPartPart[1], 0, 111, 1, 0, &vPi0PrimEmc, &vPi0SecEmc, mPi0, mPi0Sigma); +// +// //D+ -> K0 pi+ +// FindTrackV0Decay(fSecCandidates[0], 310, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastPion(), Particles, PrimVtx, -1/*, &(ChiToPrimVtx[0])*/); +// //D0 -> K0 pi+ pi- +// FindTrackV0Decay(fK0PiPlus, 100411, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), Particles, PrimVtx, -1/*, &(ChiToPrimVtx[0])*/); +// //D0 -> K0 pi+ pi- pi0 +// CombinePartPart(fK0PiPi, vPi0PrimEmc[0], Particles, PrimVtx, fCutsPartPart[1], -1, 428, 0, 0, &vD0PrimEmc, 0, +// KFParticleDatabase::Instance()->GetD0Mass(), 0.025); +// +// for(int iPV=0; iPV<1; iPV++ ) +// { +// ExtrapolateToPV(vPi0PrimEmc[iPV],PrimVtx[iPV]); +// ExtrapolateToPV(vD0PrimEmc[iPV],PrimVtx[iPV]); +// } +// //D0* -> D0 pi0 +// CombinePartPart(vD0PrimEmc[0], vPi0PrimEmc[0], Particles, PrimVtx, fCutsPartPart[1], 0, 10428); +// } + } + else + { + //D0 -> pi+ K- + SelectParticles(Particles,fD0,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + //D0_bar -> pi+ K- + SelectParticles(Particles,fD0bar,PrimVtx,fCutsCharm[2],fCutsCharm[1], + KFParticleDatabase::Instance()->GetD0Mass(), KFParticleDatabase::Instance()->GetD0MassSigma(), fSecCuts[0]); + } +} + +void KFParticleFinder::ExtrapolateToPV(vector<KFParticle>& vParticles, KFParticleSIMD& PrimVtx) +{ + /** Extrapolates all particles from the input vector to the DCA point with the primary vertex. + ** \param[in,out] vParticles - array of particles to be transported. + ** \param[in] PrimVtx - the primary vertex, where particles should be transported. + **/ + KFParticle* parts[float_vLen]; + KFParticle tmpPart[float_vLen]; + + for(int iv=0; iv<float_vLen; iv++) + parts[iv] = &tmpPart[iv]; + + for(unsigned int iL=0; iL<vParticles.size(); iL += float_vLen) + { + + unsigned int nPart = vParticles.size(); + unsigned int nEntries = (iL + float_vLen < nPart) ? float_vLen : (nPart - iL); + + + for(unsigned int iv=0; iv<nEntries; iv++) + tmpPart[iv] = vParticles[iL+iv]; + + KFParticleSIMD tmp(parts,nEntries); + + tmp.TransportToPoint(PrimVtx.Parameters()); + + for(unsigned int iv=0; iv<nEntries; iv++) + { + tmp.GetKFParticle(vParticles[iL+iv], iv); + } + } +} + +inline void KFParticleFinder::ConstructV0(KFPTrackVector* vTracks, + int iTrTypePos, + int iTrTypeNeg, + uint_v& idPosDaughters, + uint_v& idNegDaughters, + int_v& daughterPosPDG, + int_v& daughterNegPDG, + KFParticleSIMD& mother, + KFParticle& mother_temp, + const unsigned short NTracks, + kfvector_floatv& l, + kfvector_floatv& dl, + vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* cuts, + const int_v& pvIndex, + const float* secCuts, + const float_v& massMotherPDG, + const float_v& massMotherPDGSigma, + KFParticleSIMD& motherPrimSecCand, + int& nPrimSecCand, + vector< vector<KFParticle> >* vMotherPrim, + vector<KFParticle>* vMotherSec + ) +{ + /** Combines two SIMD vectors of particles into 2-daughter candidate. + ** \param[in] vRTracks - pointer to the array with vectors of tracks:\n + ** 0) secondary positive at the first hit position; \n + ** 1) secondary negative at the first hit position; \n + ** 2) primary positive at the first hit position; \n + ** 3) primary negative at the first hit position; \n + ** 4) secondary positive at the last hit position; \n + ** 5) secondary negative at the last hit position; \n + ** 6) primary positive at the last hit position; \n + ** 7) primary negative at the last hit position. \n + ** \param[in] iTrTypePos - index of the first vector with tracks in the vTracks array. + ** \param[in] iTrTypeNeg - index of the second vector with tracks in the vTracks array. + ** \param[in] idPosDaughters - indices of particles from the first vector of tracks. + ** \param[in] idNegDaughters - indices of particles from the second vector of tracks. + ** \param[in] daughterPosPDG - PDG hypothesis of the first SIMD vector of tracks. + ** \param[in] daughterNegPDG - PDG hypothesis of the second SIMD vector of tracks. + ** \param[out] mother - constructed 2-daughter SIMD-candidate. + ** \param[in] mother_temp - temporary object to extract KFParticle from constructed KFParticleSIMD mother. Preallocated for better performance. + ** \param[in] NTracks - number of tracks in each SIMD vector. + ** \param[in] l - SIMD-vector with extracted distance to the primary vertex. Is preallocated for better performance. + ** \param[in] dl - SIMD-vector with extracted error of distance to the primary vertex. Is preallocated for better performance. + ** \param[out] Particles - the output array with the reconstructed particle-candidates. + ** \param[in] PrimVtx - array with primary vertices. + ** \param[in] cuts - set of cuts: \f$\chi^2_{prim}\f$, \f$\chi^2_{geo}\f$, \f$l/\Delta l\f$. + ** \param[in] pvIndex - index of the primary vertex for reconstruction of resonances. Tracks should come from the same vertex. + ** in case of other particles the value should be "-1". + ** \param[in] secCuts - cuts to select primary and secondary candidates from the reconstructed set: \f$\sigma_{M}\f$, \f$\chi^2_{topo}\f$, \f$l/\Delta l\f$. + ** \param[in] massMotherPDG - PDG table mass for the mother particle, is used for selection of primary and secondary candidates. + ** \param[in] massMotherPDGSigma - sigma of the peak width, is used for selection of primary and secondary candidates. + ** \param[out] motherPrimSecCand - a SIMD-particle with possible primary and secondary candidates. + ** \param[out] nPrimSecCand - number of possible primary and secondary candidates. Can be "0" if no of them are found. + ** \param[out] vMotherPrim - array with output primary candidates if any. + ** \param[out] vMotherSec - array with output secondary candidates if any. + **/ + float_m isPrimary(simd_cast<float_m>(pvIndex>-1)); + int_v trackId; + KFParticleSIMD posDaughter(vTracks[iTrTypePos],idPosDaughters, daughterPosPDG); + trackId.gather( &(vTracks[iTrTypePos].Id()[0]), idPosDaughters ); + posDaughter.SetId(trackId); + + KFParticleSIMD negDaughter(vTracks[iTrTypeNeg],idNegDaughters, daughterNegPDG); + trackId.gather( &(vTracks[iTrTypeNeg].Id()[0]), idNegDaughters ); + negDaughter.SetId(trackId); +#ifdef CBM + float_v ds[2] = {0.f,0.f}; + float_v dsdr[4][6]; + negDaughter.GetDStoParticle( posDaughter, ds, dsdr ); + negDaughter.TransportToDS(ds[0], dsdr[0]); + posDaughter.TransportToDS(ds[1], dsdr[3]); +#endif + const KFParticleSIMD* vDaughtersPointer[2] = {&negDaughter, &posDaughter}; + mother.Construct(vDaughtersPointer, 2, 0); + + float_m saveParticle(simd_cast<float_m>(int_v::IndexesFromZero() < int(NTracks))); + float_v chi2Cut = cuts[1]; + float_v ldlCut = cuts[2]; + if( !(simd_cast<float_m>(abs(mother.PDG()) == 421 || abs(mother.PDG()) == 426 || abs(mother.PDG()) == 420)).isEmpty() ) + { + chi2Cut( simd_cast<float_m>(abs(mother.PDG()) == 421 || abs(mother.PDG()) == 426 || abs(mother.PDG()) == 420) ) = fCutsCharm[0]; + ldlCut( simd_cast<float_m>(abs(mother.PDG()) == 421 || abs(mother.PDG()) == 426 || abs(mother.PDG()) == 420) ) = -1;//fCutsCharm[1]; + } + + saveParticle &= (mother.Chi2()/simd_cast<float_v>(mother.NDF()) < chi2Cut ); + saveParticle &= KFPMath::Finite(mother.GetChi2()); + saveParticle &= (mother.GetChi2() > 0.0f); + saveParticle &= (mother.GetChi2() == mother.GetChi2()); + + if( saveParticle.isEmpty() ) return; + + float_v lMin(1.e8f); + float_v ldlMin(1.e8f); + float_m isParticleFromVertex(false); + + for(int iP=0; iP<fNPV; iP++) + { + float_m isParticleFromVertexLocal; + mother.GetDistanceToVertexLine(PrimVtx[iP], l[iP], dl[iP], &isParticleFromVertexLocal); + isParticleFromVertex |= isParticleFromVertexLocal; + float_v ldl = (l[iP]/dl[iP]); + lMin( (l[iP] < lMin) && saveParticle) = l[iP]; + ldlMin( (ldl < ldlMin) && saveParticle) = ldl; + } + + saveParticle &= (lMin < 200.f); +#ifdef NonhomogeneousField + KFParticleSIMD motherTopo; + ldlMin = 1.e8f; + for(int iP=0; iP<fNPV; iP++) + { + motherTopo = mother; + motherTopo.SetProductionVertex(PrimVtx[iP]); + motherTopo.GetDecayLength(l[iP], dl[iP]); + float_v ldl = (l[iP]/dl[iP]); + ldlMin( (ldl < ldlMin) && saveParticle) = ldl; + } +#endif + saveParticle &= ( (float_m(!isPrimary) && ldlMin > ldlCut) || float_m(isPrimary) ); + + saveParticle &= (float_m(!isPrimary) && isParticleFromVertex) || isPrimary; + if( saveParticle.isEmpty() ) return; + + float_m isK0 = saveParticle && simd_cast<float_m>(mother.PDG() == int_v(310)); + float_m isLambda = saveParticle && simd_cast<float_m>(abs(mother.PDG()) == int_v(3122)); + float_m isGamma = saveParticle && simd_cast<float_m>(mother.PDG() == int_v(22)); + float_m isHyperNuclei = saveParticle && simd_cast<float_m>(abs(mother.PDG()) > 3000 && abs(mother.PDG()) < 3104); + + saveParticle &= ( ((isK0 || isLambda || isHyperNuclei) && lMin > float_v(fLCut)) || !(isK0 || isLambda || isHyperNuclei) ); + + float_m saveMother(false); + + if( !(isK0.isEmpty()) || !(isLambda.isEmpty()) || !(isGamma.isEmpty())) + { + float_v mass, errMass; + + mother.GetMass(mass, errMass); + saveMother = saveParticle; + saveMother &= (abs(mass - massMotherPDG)/massMotherPDGSigma) < secCuts[0]; + saveMother &= ((ldlMin > secCuts[2]) && !isGamma) || isGamma; + saveMother &= (isK0 || isLambda || isGamma); + } + + for(int iv=0; iv<NTracks; iv++) + { + if(!saveParticle[iv]) continue; + + mother.GetKFParticle(mother_temp, iv); + int motherId = Particles.size(); + mother_temp.SetId(Particles.size()); + if( mother.PDG()[iv] == 421 ) + { + fD0.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == -421 ) + { + fD0bar.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == 426 ) + { + fD0KK.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == 420 ) + { + fD0pipi.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == 3004) + fHe3Pi.push_back(mother_temp); + if( mother.PDG()[iv] == -3004) + fHe3PiBar.push_back(mother_temp); + if( mother.PDG()[iv] == 3005) + fHe4Pi.push_back(mother_temp); + if( mother.PDG()[iv] == -3005) + fHe4PiBar.push_back(mother_temp); + + Particles.push_back(mother_temp); + + if( mother.PDG()[iv] == 22 && isPrimary[iv] ) + { + float negPt2 = negDaughter.Px()[iv]*negDaughter.Px()[iv] + negDaughter.Py()[iv]*negDaughter.Py()[iv]; + float posPt2 = posDaughter.Px()[iv]*posDaughter.Px()[iv] + posDaughter.Py()[iv]*posDaughter.Py()[iv]; + + if( (negPt2 >fCutLVMPt*fCutLVMPt) && (posPt2 >fCutLVMPt*fCutLVMPt) ) + { + mother_temp.SetPDG(100113); + mother_temp.SetId(Particles.size()); + Particles.push_back(mother_temp); + + if( (negPt2 >fCutJPsiPt*fCutJPsiPt) && (posPt2 >fCutJPsiPt*fCutJPsiPt) ) + { + mother_temp.SetPDG(443); + mother_temp.SetId(Particles.size()); + Particles.push_back(mother_temp); + } + } + } + + if( mother.PDG()[iv] == 200113 ) + { + float negPt2 = negDaughter.Px()[iv]*negDaughter.Px()[iv] + negDaughter.Py()[iv]*negDaughter.Py()[iv]; + float posPt2 = posDaughter.Px()[iv]*posDaughter.Px()[iv] + posDaughter.Py()[iv]*posDaughter.Py()[iv]; + + if( (negPt2 >fCutJPsiPt*fCutJPsiPt) && (posPt2 >fCutJPsiPt*fCutJPsiPt) && (abs(daughterPosPDG[iv]) == 13) && (abs(daughterNegPDG[iv]) == 13)) + { + mother_temp.SetPDG(100443); + mother_temp.SetId(Particles.size()); + Particles.push_back(mother_temp); + } + } + + if(saveMother[iv]) + { + mother.SetId(motherId); + motherPrimSecCand.SetOneEntry(nPrimSecCand,mother,iv); + + nPrimSecCand++; + if(nPrimSecCand==float_vLen) + { + SaveV0PrimSecCand(motherPrimSecCand,nPrimSecCand,mother_temp,PrimVtx,secCuts,vMotherPrim,vMotherSec); + nPrimSecCand = 0; + } + } + } +} + +inline void KFParticleFinder::SaveV0PrimSecCand(KFParticleSIMD& mother, + int& NParticles, + KFParticle& mother_temp, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* secCuts, + vector< vector<KFParticle> >* vMotherPrim, + vector<KFParticle>* vMotherSec) +{ + /** The function which decides if primary and secondary candidates found by KFParticleFinder::ConstructV0() + ** should be stored and stores them to the provided arrays. + ** \param[in] mother - constructed SIMD vector of particle candidates. + ** \param[in] NParticles - number of particles in the SIMD vector. + ** \param[in] mother_temp - temporary object to extract KFParticle from constructed KFParticleSIMD mother. Preallocated for better performance. + ** \param[in] PrimVtx - array with primary vertices. + ** \param[in] secCuts - cuts to select primary and secondary candidates from the reconstructed set: \f$\sigma_{M}\f$, \f$\chi^2_{topo}\f$, \f$l/\Delta l\f$. + ** \param[out] vMotherPrim - array with output primary candidates if any. + ** \param[out] vMotherSec - array with output secondary candidates if any. + **/ + + KFParticleSIMD motherTopo; + float_v massMotherPDG, massMotherPDGSigma; + + float_m isSec(false); + float_m isPrim(false); + vector<int> iPrimVert[float_vLen]; + + KFParticleDatabase::Instance()->GetMotherMass(mother.PDG(),massMotherPDG,massMotherPDGSigma); + + float_m isK0 = simd_cast<float_m>(mother.PDG() == int_v(310)); + float_m isLambda = simd_cast<float_m>(abs(mother.PDG()) == int_v(3122)); + float_m isGamma = simd_cast<float_m>(mother.PDG() == int_v(22)); + + int_v arrayIndex(-1); //for saving primary candidates; + + arrayIndex(mother.PDG() == int_v(310)) = 0; + arrayIndex(mother.PDG() == int_v(3122)) = 1; + arrayIndex(mother.PDG() == int_v(-3122)) = 2; + arrayIndex(mother.PDG() == int_v(22)) = 3; + + float_m isPrimaryPart(false); + + float_v chi2TopoMin = 1.e4f; + + for(int iP=0; iP< fNPV; iP++) + { + motherTopo = mother; + motherTopo.SetProductionVertex(PrimVtx[iP]); + + const float_v& motherTopoChi2Ndf = motherTopo.GetChi2()/simd_cast<float_v>(motherTopo.GetNDF()); + chi2TopoMin(motherTopoChi2Ndf < chi2TopoMin) = motherTopoChi2Ndf; + const float_m isPrimaryPartLocal = ( motherTopoChi2Ndf < secCuts[1] ); + if(isPrimaryPartLocal.isEmpty()) continue; + isPrimaryPart |= isPrimaryPartLocal; + for(int iV=0; iV<NParticles; iV++) + { + if(isPrimaryPartLocal[iV]) + { + motherTopo.GetKFParticle(mother_temp, iV); + fPrimCandidatesTopo[arrayIndex[iV]][iP].push_back(mother_temp); + iPrimVert[iV].push_back(iP); + } + } + + motherTopo.SetNonlinearMassConstraint(massMotherPDG); + for(int iV=0; iV<NParticles; iV++) + { + if(isPrimaryPartLocal[iV]) + { + motherTopo.GetKFParticle(mother_temp, iV); + fPrimCandidatesTopoMass[arrayIndex[iV]][iP].push_back(mother_temp); + } + } + } + + isPrim |= ( ( isPrimaryPart ) && (isK0 || isLambda || isGamma) ); +#ifdef __ROOT__ + isSec |= ( (!isPrimaryPart ) && (isK0 || isLambda || isGamma) && (chi2TopoMin < float_v(500.f)) ); +#else + isSec |= ( (!isPrimaryPart ) && (isK0 || isLambda || isGamma) ); +#endif + + mother.SetNonlinearMassConstraint(massMotherPDG); + + for(int iv=0; iv<NParticles; iv++) + { + if(isPrim[iv] || isSec[iv]) + { + mother.GetKFParticle(mother_temp, iv); + + if(isPrim[iv] ) + { + for(unsigned int iP = 0; iP<iPrimVert[iv].size(); iP++) + vMotherPrim[arrayIndex[iv]][iPrimVert[iv][iP]].push_back(mother_temp); + } + + if(isSec[iv] ) + vMotherSec[arrayIndex[iv]].push_back(mother_temp); + } + } +} + +void KFParticleFinder::Find2DaughterDecay(KFPTrackVector* vTracks, kfvector_float* ChiToPrimVtx, + vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* cuts, + const float* secCuts, + vector< vector<KFParticle> >* vMotherPrim, + vector<KFParticle>* vMotherSec ) +{ + /** Reconstructs all 2-daughter decays. + ** \param[in] vRTracks - pointer to the array with vectors of tracks:\n + ** 0) secondary positive at the first hit position; \n + ** 1) secondary negative at the first hit position; \n + ** 2) primary positive at the first hit position; \n + ** 3) primary negative at the first hit position; \n + ** 4) secondary positive at the last hit position; \n + ** 5) secondary negative at the last hit position; \n + ** 6) primary positive at the last hit position; \n + ** 7) primary negative at the last hit position. \n + ** \param[in] ChiToPrimVtx - arrays with vectors of the \f$\chi^2_{prim}\f$ deviations for track vectors 1) and 2). + ** \param[out] Particles - output vector with particles. + ** \param[in] PrimVtx - vector with primary vertices. + ** \param[in] cuts - set of cuts: \f$\chi^2_{prim}\f$, \f$\chi^2_{geo}\f$, \f$l/\Delta l\f$. + ** \param[in] secCuts - cuts to select primary and secondary candidates from the reconstructed set: \f$\sigma_{M}\f$, \f$\chi^2_{topo}\f$, \f$l/\Delta l\f$. + ** \param[out] vMotherPrim - array with output primary candidates. + ** \param[out] vMotherSec - array with output secondary candidates. + **/ + KFParticle mother_temp; + KFParticleSIMD mother; + kfvector_floatv l(fNPV), dl(fNPV); + + KFParticleSIMD daughterNeg, daughterPos; + + // for secondary V0 + unsigned int nBufEntry = 0; + uint_v idNegDaughters; + uint_v idPosDaughters; + int_v daughterPosPDG(-1); + int_v daughterNegPDG(-1); + + int_v pvIndexMother(-1); + + float_v massMotherPDG(Vc::Zero), massMotherPDGSigma(Vc::Zero); + int_v V0PDG(Vc::Zero); + + KFParticleSIMD motherPrimSecCand; + int nPrimSecCand =0; + + int trTypeIndexPos[2] = {0,2}; + int trTypeIndexNeg[2] = {1,3}; + + for( int iTrTypeNeg = 0; iTrTypeNeg<2; iTrTypeNeg++) + { + KFPTrackVector& negTracks = vTracks[ trTypeIndexNeg[iTrTypeNeg] ]; + + for(int iTrTypePos=0; iTrTypePos<2; iTrTypePos++) + { + KFPTrackVector& posTracks = vTracks[ trTypeIndexPos[iTrTypePos] ]; + int_v negTracksSize = negTracks.Size(); + int nPositiveTracks = posTracks.Size(); + + //track categories + int nTC = 5; + int startTCPos[5] = {0}; + int endTCPos[5] = {0}; + int startTCNeg[5] = {0}; + int endTCNeg[5] = {0}; + + if((iTrTypeNeg == 0) && (iTrTypePos == 0)) + { + // Secondary particles + nTC = 5; + // e- + startTCPos[0] = 0; endTCPos[0] = nPositiveTracks; //posTracks.LastElectron(); + startTCNeg[0] = 0; endTCNeg[0] = negTracksSize[0]; //negTracks.LastElectron(); + //mu- + startTCPos[1] = 0; endTCPos[1] = 0; + startTCNeg[1] = 0; endTCNeg[1] = 0; + //pi- + ghosts + startTCPos[2] = posTracks.FirstPion(); endTCPos[2] = nPositiveTracks; + startTCNeg[2] = negTracks.FirstPion(); endTCNeg[2] = negTracks.LastPion(); + //K- + startTCPos[3] = posTracks.FirstPion(); endTCPos[3] = posTracks.LastKaon(); + startTCNeg[3] = negTracks.FirstKaon(); endTCNeg[3] = negTracks.LastKaon(); + //p-, d-, t-, he3-, he4- + startTCPos[4] = posTracks.FirstPion(); endTCPos[4] = posTracks.LastPion(); + startTCNeg[4] = negTracks.FirstProton(); endTCNeg[4] = negTracksSize[0]; + } + + if( iTrTypeNeg != iTrTypePos ) + { + //Mixed particles - only gamma -> e+ e- + nTC = 1; + startTCPos[0] = 0; endTCPos[0] = nPositiveTracks; //posTracks.LastElectron(); + startTCNeg[0] = 0; endTCNeg[0] = negTracksSize[0]; //negTracks.LastElectron(); + } + + if((iTrTypeNeg == 1) && (iTrTypePos == 1)) + { + //primary particles + nTC = 5; + // e- + startTCPos[0] = 0; endTCPos[0] = nPositiveTracks; //posTracks.LastElectron(); + startTCNeg[0] = 0; endTCNeg[0] = negTracksSize[0]; //negTracks.LastElectron(); + //mu- + startTCPos[1] = posTracks.FirstMuon(); endTCPos[1] = posTracks.LastMuon(); + startTCNeg[1] = negTracks.FirstMuon(); endTCNeg[1] = negTracks.LastMuon(); + //pi- + ghosts + startTCPos[2] = posTracks.FirstPion(); endTCPos[2] = posTracks.LastProton(); + startTCNeg[2] = negTracks.FirstPion(); endTCNeg[2] = negTracks.LastPion(); + //K- + startTCPos[3] = posTracks.FirstPion(); endTCPos[3] = nPositiveTracks; + startTCNeg[3] = negTracks.FirstKaon(); endTCNeg[3] = negTracks.LastKaon(); + //p- + startTCPos[4] = posTracks.FirstPion(); endTCPos[4] = posTracks.LastProton(); + startTCNeg[4] = negTracks.FirstProton(); endTCNeg[4] = negTracks.LastProton(); + } + + for(int iTC=0; iTC<nTC; iTC++) + { + for(int iTrN=startTCNeg[iTC]; iTrN < endTCNeg[iTC]; iTrN += float_vLen) + { + const int NTracksNeg = (iTrN + float_vLen < negTracks.Size()) ? float_vLen : (negTracks.Size() - iTrN); + + int_v negInd = int_v::IndexesFromZero() + int(iTrN); + + int_v negPDG = reinterpret_cast<const int_v&>(negTracks.PDG()[iTrN]); + int_v negPVIndex = reinterpret_cast<const int_v&>(negTracks.PVIndex()[iTrN]); + int_v negNPixelHits = reinterpret_cast<const int_v&>(negTracks.NPixelHits()[iTrN]); + + int_v trackPdgNeg = negPDG; + int_m activeNeg = (negPDG != -1); +#ifdef CBM + if( !((negPDG == -1).isEmpty()) ) + { + trackPdgNeg(negPVIndex<0 && (negPDG == -1) ) = -211; + + activeNeg |= int_m(negPVIndex < 0) && int_m(negPDG == -1) ; + } +#endif + activeNeg &= (int_v::IndexesFromZero() < int(NTracksNeg)); + + daughterNeg.Load(negTracks, iTrN, negPDG); + + float_v chiPrimNeg(Vc::Zero); + float_v chiPrimPos(Vc::Zero); + + if( (iTrTypeNeg == 0) && (iTrTypePos == 0) ) + chiPrimNeg = reinterpret_cast<const float_v&>( ChiToPrimVtx[trTypeIndexNeg[iTrTypeNeg]][iTrN]); + + for(int iTrP=startTCPos[iTC]; iTrP < endTCPos[iTC]; iTrP += float_vLen) + { + const int NTracks = (iTrP + float_vLen < nPositiveTracks) ? float_vLen : (nPositiveTracks - iTrP); + + const int_v& posPDG = reinterpret_cast<const int_v&>(posTracks.PDG()[iTrP]); + const int_v& posPVIndex = reinterpret_cast<const int_v&>(posTracks.PVIndex()[iTrP]); + const int_v& posNPixelHits = reinterpret_cast<const int_v&>(posTracks.NPixelHits()[iTrP]); + const int_m& isPosSecondary = (posPVIndex < 0); + + daughterPos.Load(posTracks, iTrP, posPDG); + + if( (iTrTypeNeg == 0) && (iTrTypePos == 0) ) + chiPrimPos = reinterpret_cast<const float_v&>( ChiToPrimVtx[trTypeIndexPos[iTrTypePos]][iTrP]); + + for(int iRot = 0; iRot<float_vLen; iRot++) + { +// if(iRot>0) + { + negPDG = negPDG.rotated(1); + negPVIndex = negPVIndex.rotated(1); + negNPixelHits = negNPixelHits.rotated(1); + negInd = negInd.rotated(1); + trackPdgNeg = trackPdgNeg.rotated(1); + + daughterNeg.Rotate(); + chiPrimNeg = chiPrimNeg.rotated(1); + + activeNeg = ( (negPDG != -1) || ( (negPVIndex < 0) && (negPDG == -1) ) ) && (negInd < negTracksSize); + } + const int_m& isSecondary = int_m( negPVIndex < 0 ) && isPosSecondary; + const int_m& isPrimary = int_m( negPVIndex >= 0 ) && (!isPosSecondary); + + float_m closeDaughters = simd_cast<float_m>(activeNeg && (int_v::IndexesFromZero() < int_v(NTracks))); + + if(closeDaughters.isEmpty() && (iTC != 0)) continue; + + + int_v trackPdgPos[2]; + int_m active[2]; + + active[0] = (posPDG != -1); + active[0] &= ((isPrimary && (posPVIndex == negPVIndex)) || !(isPrimary)); + + active[1] = int_m(false); + + trackPdgPos[0] = posPDG; +#ifdef CBM + int nPDGPos = 2; + if( (posPDG == -1).isEmpty() && (posPDG > 1000000000).isEmpty() && (posPDG == 211).isEmpty() ) + { + nPDGPos = 1; + } + else + { + trackPdgPos[0](isSecondary && posPDG == -1) = 211; + trackPdgPos[1] = 2212; + + active[0] |= isSecondary && int_m(posPDG == -1); + active[1] = isSecondary && (int_m(posPDG == -1) || (posPDG > 1000000000) || (posPDG == 211)); + } +#else + int nPDGPos = 1; +#endif + active[0] &= simd_cast<int_m>(closeDaughters); + active[1] &= simd_cast<int_m>(closeDaughters); + + if(iTC==0) + { + nPDGPos = 1; + active[0] = (negInd < negTracksSize) && (int_v::IndexesFromZero() < int_v(NTracks)); + } + + for(int iPDGPos=0; iPDGPos<nPDGPos; iPDGPos++) + { + if(active[iPDGPos].isEmpty()) continue; + + //detetrmine a pdg code of the mother particle + + int_v motherPDG(-1); + + if(!fMixedEventAnalysis) + { + if(iTC==0) + { + motherPDG( (abs(trackPdgPos[iPDGPos]) == 11) || int_m(abs(trackPdgNeg) == 11) || isSecondary ) = 22; //gamma -> e+ e- + } + else if(iTC==1) + { + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 13 || abs(trackPdgPos[iPDGPos])==19) + && (int_m(abs(trackPdgNeg) == 13) || int_m(abs(trackPdgNeg) == 19)) ) = 200113; //rho -> mu+ mu- + } + else if(iTC==2) + { + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 211) ) = 310; //K0 -> pi+ pi- + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 2212) && int_m(abs(trackPdgNeg) == 211) ) = 3122; //Lambda -> p+ pi- + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000010020) && int_m(abs(trackPdgNeg) == 211) ) = 3003; //LambdaN -> d+ pi- + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000010030) && int_m(abs(trackPdgNeg) == 211) ) = 3103; //LambdaNN -> t+ pi- + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000020030) && int_m(abs(trackPdgNeg) == 211) ) = 3004; //H3Lambda -> He3+ pi- + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000020040) && int_m(abs(trackPdgNeg) == 211) ) = 3005; //H4Lambda -> He4+ pi- + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 321) && int_m(abs(trackPdgNeg) == 211) ) = -421; //D0_bar -> pi- K+ + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 321) && int_m(abs(trackPdgNeg) == 211) ) = 313; //K*0 -> K+ pi- + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 211) ) = 113; //rho -> pi+ pi- + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 2212) && int_m(abs(trackPdgNeg) == 211) ) = 2114; //Delta0 -> p pi- + } + else if(iTC==3) + { + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 321) ) = 421; //D0 -> pi+ K- + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 321) && int_m(abs(trackPdgNeg) == 321) ) = 426; //D0 -> K+ K- + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 321) ) = -313; //K*0_bar -> K- pi+ + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 2212) && int_m(abs(trackPdgNeg) == 321) ) = 3124; //Lambda* -> p K- + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 321) && int_m(abs(trackPdgNeg) == 321) ) = 333; //phi -> K+ K- + } + else if(iTC==4) + { + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 2212) ) = -3122; //Lambda_bar -> p- pi+ + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 1000010020) ) = -3003; //LambdaN_bar -> d- pi+ + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 1000010030) ) = -3103; //LambdaNN_bar -> t- pi+ + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 1000020030) ) = -3004; //H3Lambda_bar -> He3- pi+ + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 1000020040) ) = -3005; //H4Lambda_bar -> He4- pi+ + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 321) && int_m(abs(trackPdgNeg) == 2212) ) = -3124; //Lambda*_bar -> p- K+ + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 2212) && int_m(abs(trackPdgNeg) == 2212) ) = 200443; //JPsi -> p- p + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 2212) ) = -2114; //Delta0_bar -> p- pi+ + } + } + else + { + if(iTC==0) + motherPDG( (abs(trackPdgPos[iPDGPos])== 11) && int_m(abs(trackPdgNeg) == 11) ) = 22; //gamma -> e+ e- + else if(iTC==1) + motherPDG( isPrimary && (abs(trackPdgPos[iPDGPos])== 13 || abs(trackPdgPos[iPDGPos])==19) + && (int_m(abs(trackPdgNeg) == 13) || int_m(abs(trackPdgNeg) == 19)) ) = 200113; //rho -> mu+ mu- + else if(iTC==2) + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 321) && int_m(abs(trackPdgNeg) == 211) ) = -421; //D0_bar -> pi- K+ + else if(iTC==3) + motherPDG( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && int_m(abs(trackPdgNeg) == 321) ) = 421; //D0 -> pi+ K- + } + + if( (iTrTypeNeg == 0) && (iTrTypePos == 0) ) + { + float_v chiprimCut = fCuts2D[0]; + chiprimCut( simd_cast<float_m>(abs(motherPDG) == 421 || abs(motherPDG) == 426) ) = fCutCharmChiPrim; + active[iPDGPos] &= simd_cast<int_m>(chiPrimNeg > chiprimCut && chiPrimPos > chiprimCut); + } + + active[iPDGPos] &= (motherPDG != -1); + if(!(fDecayReconstructionList.empty())) + { + for(int iV=0; iV<float_vLen; iV++) + { + if(!(active[iPDGPos][iV])) continue; + if(fDecayReconstructionList.find(motherPDG[iV]) == fDecayReconstructionList.end()) + motherPDG[iV] = -1; + } + active[iPDGPos] &= (motherPDG != -1); + } + if(active[iPDGPos].isEmpty()) continue; + + if(!( (iTrTypePos == 1) && (iTrTypeNeg == 1) ) ) + { + float_v dS[2]; + daughterNeg.GetDStoParticleFast( daughterPos, dS ); + float_v negParameters[8], posParameters[8]; + daughterNeg.TransportFast( dS[0], negParameters ); + daughterPos.TransportFast( dS[1], posParameters ); + float_v dx = negParameters[0]-posParameters[0]; + float_v dy = negParameters[1]-posParameters[1]; + float_v dz = negParameters[2]-posParameters[2]; + float_v dr = sqrt(dx*dx+dy*dy+dz*dz); + + active[iPDGPos] &= simd_cast<int_m>(dr < float_v(fDistanceCut)); + if(active[iPDGPos].isEmpty()) continue; + + float_v p1p2 = posParameters[3]*negParameters[3] + posParameters[4]*negParameters[4] + posParameters[5]*negParameters[5]; + float_v p12 = posParameters[3]*posParameters[3] + posParameters[4]*posParameters[4] + posParameters[5]*posParameters[5]; + float_v p22 = negParameters[3]*negParameters[3] + negParameters[4]*negParameters[4] + negParameters[5]*negParameters[5]; + active[iPDGPos] &= simd_cast<int_m>(p1p2 > -p12); + active[iPDGPos] &= simd_cast<int_m>(p1p2 > -p22); + } + + const float_v& ptNeg2 = daughterNeg.Px()*daughterNeg.Px() + daughterNeg.Py()*daughterNeg.Py(); + const float_v& ptPos2 = daughterPos.Px()*daughterPos.Px() + daughterPos.Py()*daughterPos.Py(); + if( !((abs(motherPDG) == 421 || abs(motherPDG) == 426).isEmpty()) ) + { + active[iPDGPos] &= ( (abs(motherPDG) == 421 || abs(motherPDG) == 426) && + simd_cast<int_m>(ptNeg2 >= fCutCharmPt*fCutCharmPt) && + simd_cast<int_m>(ptPos2 >= fCutCharmPt*fCutCharmPt) && + simd_cast<int_m>(chiPrimNeg > fCutCharmChiPrim) && simd_cast<int_m>(chiPrimPos > fCutCharmChiPrim) && + int_m(negNPixelHits >= int_v(3)) && int_m(posNPixelHits >= int_v(3)) ) + || (!(abs(motherPDG) == 421 || abs(motherPDG) == 426)); + } + + if(active[iPDGPos].isEmpty()) continue; + + for(int iV=0; iV<float_vLen; iV++) + { + if(!(active[iPDGPos][iV])) continue; + + + idPosDaughters[nBufEntry] = iTrP+iV; + idNegDaughters[nBufEntry] = negInd[iV]; + + daughterPosPDG[nBufEntry] = trackPdgPos[iPDGPos][iV]; + daughterNegPDG[nBufEntry] = trackPdgNeg[iV]; + + if(motherPDG[iV] == 22) + { + daughterPosPDG[nBufEntry] = -11; + daughterNegPDG[nBufEntry] = 11; + } + + pvIndexMother[nBufEntry] = isPrimary[iV] ? negPVIndex[iV] : -1; + + if( iTrTypeNeg != iTrTypePos ) pvIndexMother[nBufEntry] = 0; + + V0PDG[nBufEntry] = motherPDG[iV]; + + nBufEntry++; + + if(int(nBufEntry) == float_vLen) + { + KFParticleDatabase::Instance()->GetMotherMass(V0PDG,massMotherPDG,massMotherPDGSigma); + mother.SetPDG( V0PDG ); + ConstructV0(vTracks, trTypeIndexPos[iTrTypePos], trTypeIndexNeg[iTrTypeNeg], + idPosDaughters, idNegDaughters, daughterPosPDG, daughterNegPDG, + mother, mother_temp, + nBufEntry, l, dl, Particles, PrimVtx, + cuts, pvIndexMother, secCuts, massMotherPDG, + massMotherPDGSigma, motherPrimSecCand, nPrimSecCand, vMotherPrim, vMotherSec); + nBufEntry = 0; + } + + //TODO optimize this part of code for D-mesons + if(motherPDG[iV] == 310 && + (fDecayReconstructionList.empty() || + (!(fDecayReconstructionList.empty()) && !(fDecayReconstructionList.find(420) == fDecayReconstructionList.end()) ) ) && + negNPixelHits[iV] >= 3 && posNPixelHits[iV] >= 3 && + chiPrimNeg[iV] > fCutCharmChiPrim && chiPrimPos[iV] > fCutCharmChiPrim && + ptNeg2[iV] >= fCutCharmPt*fCutCharmPt && ptPos2[iV] >= fCutCharmPt*fCutCharmPt ) + { + idPosDaughters[nBufEntry] = iTrP+iV; + idNegDaughters[nBufEntry] = negInd[iV]; + + daughterPosPDG[nBufEntry] = trackPdgPos[iPDGPos][iV]; + daughterNegPDG[nBufEntry] = trackPdgNeg[iV]; + + pvIndexMother[nBufEntry] = isPrimary[iV] ? negPVIndex[iV] : -1; + + V0PDG[nBufEntry] = 420; + + nBufEntry++; + + if(int(nBufEntry) == float_vLen) + { + KFParticleDatabase::Instance()->GetMotherMass(V0PDG,massMotherPDG,massMotherPDGSigma); + mother.SetPDG( V0PDG ); + ConstructV0(vTracks, trTypeIndexPos[iTrTypePos], trTypeIndexNeg[iTrTypeNeg], + idPosDaughters, idNegDaughters, daughterPosPDG, daughterNegPDG, + mother, mother_temp, + nBufEntry, l, dl, Particles, PrimVtx, + cuts, pvIndexMother, secCuts, massMotherPDG, + massMotherPDGSigma, motherPrimSecCand, nPrimSecCand, vMotherPrim, vMotherSec); + nBufEntry = 0; + } + } + + }//iV + }//iPDGPos + }//iRot + }//iTrP + }//iTrN + + if( nBufEntry>0 ) + { + for(int iV=nBufEntry; iV<float_vLen; iV++) + { + idPosDaughters[iV] = idPosDaughters[0]; + idNegDaughters[iV] = idNegDaughters[0]; + } + + KFParticleDatabase::Instance()->GetMotherMass(V0PDG,massMotherPDG,massMotherPDGSigma); + mother.SetPDG( V0PDG ); + + ConstructV0(vTracks, trTypeIndexPos[iTrTypePos], trTypeIndexNeg[iTrTypeNeg], + idPosDaughters, idNegDaughters, daughterPosPDG, daughterNegPDG, + mother, mother_temp, + nBufEntry, l, dl, Particles, PrimVtx, + cuts, pvIndexMother, secCuts, massMotherPDG, + massMotherPDGSigma, motherPrimSecCand, nPrimSecCand, vMotherPrim, vMotherSec); + nBufEntry = 0; + } + + if(nPrimSecCand>0) + { + SaveV0PrimSecCand(motherPrimSecCand,nPrimSecCand,mother_temp,PrimVtx,secCuts,vMotherPrim,vMotherSec); + nPrimSecCand = 0; + } + }//iTC + }//iTrTypeNeg + }//iTrTypePos +} + +void KFParticleFinder::ConstructPrimaryBG(KFPTrackVector* vTracks, + vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* cuts, + const float* secCuts, + vector< vector<KFParticle> >* vMotherPrim, + vector<KFParticle>* vMotherSec ) +{ + /** Constructs same-sign background candidates for 2-daughter resonances. + ** \param[in] vRTracks - pointer to the array with vectors of tracks:\n + ** 0) secondary positive at the first hit position; \n + ** 1) secondary negative at the first hit position; \n + ** 2) primary positive at the first hit position; \n + ** 3) primary negative at the first hit position; \n + ** 4) secondary positive at the last hit position; \n + ** 5) secondary negative at the last hit position; \n + ** 6) primary positive at the last hit position; \n + ** 7) primary negative at the last hit position. \n + ** \param[out] Particles - the output array with the reconstructed particle-candidates. + ** \param[in] PrimVtx - vector with primary vertices. + ** \param[in] cuts - set of cuts: \f$\chi^2_{prim}\f$, \f$\chi^2_{geo}\f$, \f$l/\Delta l\f$. + ** \param[in] secCuts - cuts to select primary and secondary candidates from the reconstructed set: \f$\sigma_{M}\f$, \f$\chi^2_{topo}\f$, \f$l/\Delta l\f$. + ** \param[out] vMotherPrim - array with output primary candidates. Is provided for consistency with KFParticleFinder::ConstructV0(). + ** \param[out] vMotherSec - array with output secondary candidates. Is provided for consistency with KFParticleFinder::ConstructV0(). + **/ + KFParticle mother_temp; + KFParticleSIMD mother; + kfvector_floatv l(fNPV), dl(fNPV); + + KFParticleSIMD daughterNeg, daughterPos; + + // for secondary V0 + unsigned int nBufEntry = 0; + float_v dS; + uint_v idNegDaughters; + uint_v idPosDaughters; + int_v daughterPosPDG(-1); + int_v daughterNegPDG(-1); + + int_v pvIndexMother(-1); + + float_v massMotherPDG(Vc::Zero), massMotherPDGSigma(Vc::Zero); + int_v V0PDG(Vc::Zero); + + KFParticleSIMD motherPrimSecCand; + int nPrimSecCand =0; + + for(int iSet=2; iSet<4; iSet++) + { + int signPDG = 1; + if(iSet == 3) + signPDG = -1; + + KFPTrackVector& positivePrimaryTracks = vTracks[iSet]; + int nPositiveTracks = positivePrimaryTracks.Size(); + + for(int iTrN = positivePrimaryTracks.FirstPion(); iTrN < positivePrimaryTracks.LastProton(); iTrN += float_vLen) + { + int_v negPDG = positivePrimaryTracks.PDG()[iTrN]; + int_v negPVIndex = positivePrimaryTracks.PVIndex()[iTrN]; + + int_m activeNeg = (negPDG != -1); + + for(int iTrP = iTrN+1; iTrP < positivePrimaryTracks.LastProton(); iTrP += float_vLen) + { + const int NTracks = (iTrP + float_vLen < nPositiveTracks) ? float_vLen : (nPositiveTracks - iTrP); + + int_v posPDG(0); // = reinterpret_cast<const int_v&>(positivePrimaryTracks.PDG()[iTrP]); + int_v posPVIndex(0); // = reinterpret_cast<const int_v&>(positivePrimaryTracks.PVIndex()[iTrP]); + for(int iV=0; iV<NTracks; iV++) + { + posPDG[iV] = positivePrimaryTracks.PDG()[iTrP+iV]; + posPVIndex[iV] = positivePrimaryTracks.PVIndex()[iTrP+iV]; + } + + int_m active = (activeNeg && (int_v::IndexesFromZero() < int_v(NTracks))); + if(active.isEmpty()) continue; + + active &= (posPDG != int_v(-1)); + active &= (posPVIndex == negPVIndex); + + if(active.isEmpty()) continue; + + //detetrmine a pdg code of the mother particle + + int_v motherPDG(-1); + + motherPDG( (abs(posPDG)== 211) && int_m(abs(negPDG) == 211) ) = signPDG*9001; //pi+pi+ + motherPDG( (abs(posPDG)== 321) && int_m(abs(negPDG) == 211) ) = signPDG*9002; //pi+K+ + motherPDG( (abs(posPDG)== 211) && int_m(abs(negPDG) == 321) ) = signPDG*9002; //pi+K+ + motherPDG( (abs(posPDG)== 211) && int_m(abs(negPDG) == 2212) ) = signPDG*2224; //pi+p + motherPDG( (abs(posPDG)== 2212) && int_m(abs(negPDG) == 211) ) = signPDG*2224; //pi+p + motherPDG( (abs(posPDG)== 321) && int_m(abs(negPDG) == 321) ) = signPDG*9003; //K+K+ + motherPDG( (abs(posPDG)== 321) && int_m(abs(negPDG) == 2212) ) = signPDG*9004; //K+p + motherPDG( (abs(posPDG)== 2212) && int_m(abs(negPDG) == 321) ) = signPDG*9004; //K+p + + active &= (motherPDG != -1); + if(!(fDecayReconstructionList.empty())) + { + for(int iV=0; iV<float_vLen; iV++) + { + if(!(active[iV])) continue; + if(fDecayReconstructionList.find(motherPDG[iV]) == fDecayReconstructionList.end()) + motherPDG[iV] = -1; + } + active &= (motherPDG != -1); + } + if(active.isEmpty()) continue; + + + if(active.isEmpty()) continue; + + for(int iV=0; iV<NTracks; iV++) + { + if(!(active[iV])) continue; + + idPosDaughters[nBufEntry] = iTrP+iV; + idNegDaughters[nBufEntry] = iTrN; + + daughterPosPDG[nBufEntry] = posPDG[iV]; + daughterNegPDG[nBufEntry] = negPDG[iV]; + + pvIndexMother[nBufEntry] = negPVIndex[iV]; + + V0PDG[nBufEntry] = motherPDG[iV]; + + nBufEntry++; + + if(int(nBufEntry) == float_vLen) + { + KFParticleDatabase::Instance()->GetMotherMass(V0PDG,massMotherPDG,massMotherPDGSigma); + mother.SetPDG( V0PDG ); + ConstructV0(vTracks, iSet, iSet, + idPosDaughters, idNegDaughters, daughterPosPDG, daughterNegPDG, + mother, mother_temp, + nBufEntry, l, dl, Particles, PrimVtx, + cuts, pvIndexMother, secCuts, massMotherPDG, + massMotherPDGSigma, motherPrimSecCand, nPrimSecCand, vMotherPrim, vMotherSec); + nBufEntry = 0; + } + }//iV + }//iTrP + + if( nBufEntry>0 ) + { + for(int iV=nBufEntry; iV<float_vLen; iV++) + { + idPosDaughters[iV] = idPosDaughters[0]; + idNegDaughters[iV] = idNegDaughters[0]; + } + + KFParticleDatabase::Instance()->GetMotherMass(V0PDG,massMotherPDG,massMotherPDGSigma); + mother.SetPDG( V0PDG ); + + ConstructV0(vTracks, iSet, iSet, + idPosDaughters, idNegDaughters, daughterPosPDG, daughterNegPDG, + mother, mother_temp, + nBufEntry, l, dl, Particles, PrimVtx, + cuts, pvIndexMother, secCuts, massMotherPDG, + massMotherPDGSigma, motherPrimSecCand, nPrimSecCand, vMotherPrim, vMotherSec); + nBufEntry = 0; + } + + if(nPrimSecCand>0) + { + SaveV0PrimSecCand(motherPrimSecCand,nPrimSecCand,mother_temp,PrimVtx,secCuts,vMotherPrim,vMotherSec); + nPrimSecCand = 0; + } + } + } +} + +void KFParticleFinder::ConstructTrackV0Cand(KFPTrackVector& vTracks, + uint_v& idTracks, + int_v& trackPDG, + KFParticle* vV0[], + KFParticleSIMD& mother, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& motherTopo, + KFParticle& mother_temp, + const unsigned short nElements, + kfvector_floatv& l, + kfvector_floatv& dl, + std::vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float_v* cuts, + const int_v& pvIndex, + const float_v& massMotherPDG, + const float_v& massMotherPDGSigma, + std::vector< std::vector<KFParticle> >* vMotherPrim, + std::vector<KFParticle>* vMotherSec) +{ + /** Constructs a candidate from a track and already reconstructed particle candidate. + ** \param[in] vTracks - vector with tracks. + ** \param[in] idTracks - indices of particles from the vector of tracks. + ** \param[in] trackPDG - PDG hypothesis of the SIMD vector of tracks. + ** \param[in] vV0 - array with already reconstructed particle candidate with the size of SIMD vector. + ** \param[out] mother - constructed 2-daughter SIMD-candidate. + ** \param[in] motherTopo - preallocated SIMD vector for topological constraint for better performance. + ** \param[in] mother_temp - temporary object to extract KFParticle from constructed KFParticleSIMD mother. Preallocated for better performance. + ** \param[in] nElements - number of elements in each SIMD vector. + ** \param[in] l - SIMD-vector with extracted distance to the primary vertex. Is preallocated for better performance. + ** \param[in] dl - SIMD-vector with extracted error of distance to the primary vertex. Is preallocated for better performance. + ** \param[out] Particles - the output array with the reconstructed particle-candidates. + ** \param[in] PrimVtx - array with primary vertices. + ** \param[in] cuts - set of cuts: \f$l/\Delta l\f$, \f$\chi^2_{topo}\f$, \f$\chi^2_{geo}\f$. + ** \param[in] pvIndex - index of the primary vertex for reconstruction of resonances. Tracks should come from the same vertex. + ** in case of other particles the value should be "-1". + ** \param[in] massMotherPDG - PDG table mass for the mother particle, is used for selection of primary and secondary candidates. + ** \param[in] massMotherPDGSigma - sigma of the peak width, is used for selection of primary and secondary candidates. + ** \param[out] vMotherPrim - array with output primary candidates if any. If pointer is set to NULL - not filled. + ** \param[out] vMotherSec - array with output secondary candidates if any. If pointer is set to NULL - not filled. + **/ + + float_m isPrimary(simd_cast<float_m>(pvIndex>-1)); + + int_v trackId( &(vTracks.Id()[0]), idTracks ); + KFParticleSIMD V0(vV0,nElements); + KFParticleSIMD track(vTracks, idTracks, trackPDG); + track.SetId(trackId); + + float_m isSameParticle = simd_cast<float_m>((abs(mother.PDG()) == int_v(4122)) || + (abs(mother.PDG()) == int_v(114122)) || + (abs(mother.PDG()) == int_v(204122)) || + (abs(mother.PDG()) == int_v(504122)) || + (abs(mother.PDG()) == int_v(404122)) || + (abs(mother.PDG()) == int_v(425)) || + (abs(mother.PDG()) == int_v(427)) || + (abs(mother.PDG()) == int_v(200411)) || + (abs(mother.PDG()) == int_v(300411)) || + (abs(mother.PDG()) == int_v(300431)) || + (abs(mother.PDG()) == int_v(400431)) || + (abs(mother.PDG()) == int_v(411)) || + (abs(mother.PDG()) == int_v(431)) || + (abs(mother.PDG()) == int_v(429)) || + (abs(mother.PDG()) == int_v(1003334)) || + (abs(mother.PDG()) == int_v(3001)) || + (abs(mother.PDG()) == int_v(3006)) || + (abs(mother.PDG()) == int_v(3007)) || + (abs(mother.PDG()) == int_v(3009)) || + (abs(mother.PDG()) == int_v(3011)) ); + if( isSameParticle.isEmpty() ) + { +#ifdef CBM + float_v ds[2] = {0.f,0.f}; + float_v dsdr[4][6]; + track.GetDStoParticle( V0, ds, dsdr ); + track.TransportToDS(ds[0], dsdr[0]); + V0.TransportToDS(ds[1], dsdr[3]); +#endif + const KFParticleSIMD* vDaughtersPointer[2] = {&track, &V0}; + mother.Construct(vDaughtersPointer, 2, 0); + } + else + { + int_v motherPDG = mother.PDG(); + mother = V0; + mother.SetPDG(motherPDG); + track.TransportToPoint(V0.Parameters()); + mother += track; + } + + float_m active = simd_cast<float_m>(int_v::IndexesFromZero() < int(nElements)); + + float_m saveParticle(active); + saveParticle &= (mother.Chi2()/simd_cast<float_v>(mother.NDF()) < cuts[2] ); + saveParticle &= KFPMath::Finite(mother.GetChi2()); + saveParticle &= (mother.GetChi2() > 0.0f); + saveParticle &= (mother.GetChi2() == mother.GetChi2()); + + if( saveParticle.isEmpty() ) { return; } + + int_m isSameTrack(false); + for(unsigned int iD=0; iD<V0.DaughterIds().size(); iD++) + isSameTrack |= ( int_v(V0.DaughterIds()[iD]) == int_v(trackId) ); + + saveParticle &= ( !simd_cast<float_m>(isSameTrack)); + if( saveParticle.isEmpty() ) { return; } + + float_v lMin(1.e8f); + float_v ldlMin(1.e8f); + float_m isParticleFromVertex(false); + + for(int iP=0; iP<fNPV; iP++) + { + float_m isParticleFromVertexLocal; + mother.GetDistanceToVertexLine(PrimVtx[iP], l[iP], dl[iP], &isParticleFromVertexLocal); + isParticleFromVertex |= isParticleFromVertexLocal; + float_v ldl = (l[iP]/dl[iP]); + lMin( (l[iP] < lMin) && active) = l[iP]; + ldlMin( (ldl < ldlMin) && active) = ldl; + } + saveParticle &= (lMin < 200.f); + saveParticle &= ((float_m(!isPrimary) && isParticleFromVertex) || float_m(isPrimary) ); + if( saveParticle.isEmpty() ) { return; } + + isSameParticle = isSameParticle || isPrimary; + if(!((isSameParticle).isFull())) + { + float_m isParticleFromVertexLocal; + float_v l1, dl1; + V0.GetDistanceToVertexLine(mother, l1, dl1, &isParticleFromVertexLocal); + + saveParticle &= ( isSameParticle || ((!isSameParticle) && isParticleFromVertexLocal)); + if( saveParticle.isEmpty() ) { return; } + } + + saveParticle &= ( (float_m(!isPrimary) && ldlMin > cuts[0]) || float_m(isPrimary) ); + + int_m setLCut = abs(mother.PDG()) == 3312 || abs(mother.PDG()) == 3334 || abs(mother.PDG()) == 3001; + saveParticle &= ( (simd_cast<float_m>(setLCut) && lMin > float_v(fLCut)) || simd_cast<float_m>(!setLCut) ); + + ldlMin = 1.e8f; + for(int iP=0; iP<fNPV; iP++) + { + motherTopo[iP] = mother; + motherTopo[iP].SetProductionVertex(PrimVtx[iP]); + motherTopo[iP].GetDecayLength(l[iP], dl[iP]); + float_v ldl = (l[iP]/dl[iP]); + ldlMin( (ldl < ldlMin) && active) = ldl; + } + + vector<int> iPrimVert[float_vLen]; + float_m isPrimaryPart(false); + + for(int iP=0; iP<fNPV; iP++) + { + const float_v& motherTopoChi2Ndf = motherTopo[iP].GetChi2()/simd_cast<float_v>(motherTopo[iP].GetNDF()); + const float_m isPrimaryPartLocal = ( motherTopoChi2Ndf < cuts[1] ); + isPrimaryPart |= isPrimaryPartLocal; + for(int iV=0; iV<float_vLen; iV++) + { + if(isPrimaryPartLocal[iV]) + iPrimVert[iV].push_back(iP); + } + } + + for(unsigned int iv=0; iv<nElements; iv++) + { + if(!saveParticle[iv]) continue; + + mother.GetKFParticle(mother_temp, iv); + if( mother.PDG()[iv] == 3312 ) + { + fLPi.push_back(mother_temp); + fLPiPIndex.push_back( V0.DaughterIds()[1][iv] ); + } + +// if( mother.PDG()[iv] == 100411 ) +// { +// fK0PiPlus.push_back(mother_temp); +// fK0PiMinusIndex.push_back( V0.DaughterIds()[0][iv] ); +// continue; +// } + + //TODO check if needed with current implementation + // reset daughter ids for 3- and 4-particle decays + if( (abs(mother.PDG()[iv]) == 411) || + (abs(mother.PDG()[iv]) == 429) || + (abs(mother.PDG()[iv]) == 431) || + (abs(mother.PDG()[iv]) == 4122) || + (abs(mother.PDG()[iv]) == 114122) || + (abs(mother.PDG()[iv]) == 204122) || + (abs(mother.PDG()[iv]) == 314122) || + (abs(mother.PDG()[iv]) == 404122) || + (abs(mother.PDG()[iv]) == 504122) || + (abs(mother.PDG()[iv]) == 425) || + (abs(mother.PDG()[iv]) == 427) || + (abs(mother.PDG()[iv]) == 200411) || + (abs(mother.PDG()[iv]) == 300411) || + (abs(mother.PDG()[iv]) == 300431) || + (abs(mother.PDG()[iv]) == 400431) || + (abs(mother.PDG()[iv]) == 1003334) || + (abs(mother.PDG()[iv]) == 3001) ) + { + mother_temp.CleanDaughtersId(); + for(int iD=0; iD < vV0[iv]->NDaughters(); iD++) + mother_temp.AddDaughterId( vV0[iv]->DaughterIds()[iD] ); + mother_temp.AddDaughterId(trackId[iv]); + } + + if( mother.PDG()[iv] == 411 ) + { + fDPlus.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == -411 ) + { + fDMinus.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == 300411 ) + { + fDPlus3Pi.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == -300411 ) + { + fDMinus3Pi.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == 400431 ) + { + fDsPlusK2Pi.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == -400431 ) + { + fDsMinusK2Pi.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == 504122 ) + { + fLcPlusP2Pi.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == -504122 ) + { + fLcMinusP2Pi.push_back(mother_temp); + continue; + } +// if( mother.PDG()[iv] == 427 ) +// { +// fK0PiPi.push_back(mother_temp); +// continue; +// } + + if( mother.PDG()[iv] == 429 ) + { + fD04.push_back(mother_temp); + continue; + } + if( mother.PDG()[iv] == -429 ) + { + fD04bar.push_back(mother_temp); + continue; + } + + if( mother.PDG()[iv] == 3203 ) + fLLn.push_back(mother_temp); + if( mother.PDG()[iv] == 3010 ) + fH5LL.push_back(mother_temp); + + mother_temp.SetId(Particles.size()); + + if(!(isPrimaryPart[iv])) + { + if( vMotherSec ) + { + float mass, errMass; + mother_temp.GetMass(mass, errMass); + if(abs(mother.PDG()[iv]) == 3324) + { + vMotherSec->push_back(mother_temp); + } + else + { + if( (fabs(mass - massMotherPDG[iv])/massMotherPDGSigma[iv]) <= 3 ) + { + KFParticle mother_sec = mother_temp; + mother_sec.SetNonlinearMassConstraint(massMotherPDG[iv]); + vMotherSec->push_back(mother_temp); + } + } + } + if(!(mother.PDG()[iv] == 3006 || mother.PDG()[iv] == 3007)) + continue; + } + + //check Ds+ and Lc+ candidates not to be D+ +// if(abs(mother_temp.GetPDG())==431 || abs(mother_temp.GetPDG())==4122) +// { +// KFPTrack dPionTrack; +// vTracks.GetTrack(dPionTrack, idTracks[iv]); +// KFParticle dPion(dPionTrack, 211); +// +// KFParticle dMeson = *vV0[iv]; +// dMeson += dPion; +// float dMass, dMassError; +// dMeson.GetMass(dMass, dMassError); +// if(fabs(dMass - KFParticleDatabase::Instance()->GetDPlusMass())/KFParticleDatabase::Instance()->GetDPlusMassSigma() < 3) continue; +// } + + if(abs(mother.GetPDG()[iv]) == 521 || abs(mother.GetPDG()[iv]) == 529 || abs(mother.GetPDG()[iv]) == 511 || abs(mother.GetPDG()[iv]) == 519) + { + KFParticle daughter_temp = *vV0[iv]; + float massPDG = KFParticleDatabase::Instance()->GetDPlusMass(); + float massSigmaPDG = KFParticleDatabase::Instance()->GetDPlusMassSigma(); + if(abs(mother.GetPDG()[iv]) == 521 || abs(mother.GetPDG()[iv]) == 529) + { + massPDG = KFParticleDatabase::Instance()->GetD0Mass(); + massSigmaPDG = KFParticleDatabase::Instance()->GetD0MassSigma(); + } + float mass, dm; + daughter_temp.GetMass(mass,dm); + if( (fabs(mass - massPDG)/massSigmaPDG) > 3 ) continue; + +// KFParticleSIMD daughter_tempSIMD(daughter_temp); +// daughter_tempSIMD.SetProductionVertex(PrimVtx[0]); +// if(daughter_tempSIMD.GetChi2()[0]/daughter_tempSIMD.GetNDF()[0] < 3. ) continue; + + daughter_temp.SetId(Particles.size()); + daughter_temp.SetPDG(-1); + mother_temp.SetId(Particles.size()+1); + mother_temp.CleanDaughtersId(); + mother_temp.AddDaughterId(Particles.size()); + mother_temp.AddDaughterId(trackId[iv]); + Particles.push_back(daughter_temp); + } + Particles.push_back(mother_temp); + + if( abs(mother.GetPDG()[iv]) == 3334 ) //Omega- + { + float mass, errMass; + mother_temp.GetMass(mass, errMass); + + vector< vector<KFParticle> >* motherVector = &fPrimCandidates[7]; + if( mother.GetPDG()[iv] == 3334 ) + motherVector = &fPrimCandidates[8]; + + mother_temp.SetNonlinearMassConstraint(massMotherPDG[iv]); + + if( (fabs(mass - massMotherPDG[iv])/massMotherPDGSigma[iv]) <= 3 ) + for(unsigned int iP=0; iP<iPrimVert[iv].size(); iP++) + (*motherVector)[iPrimVert[iv][iP]].push_back(mother_temp); + } + + if(vMotherPrim) + { + if( !((abs(mother.GetPDG()[iv]) == 3312) || (abs(mother.GetPDG()[iv]) == 3324))) continue; + float mass, errMass; + + mother_temp.GetMass(mass, errMass); + if(abs(mother.PDG()[iv]) == 3324) + { + for(unsigned int iP=0; iP<iPrimVert[iv].size(); iP++) + (*vMotherPrim)[iPrimVert[iv][iP]].push_back(mother_temp); + } + else + { + mother_temp.SetNonlinearMassConstraint(massMotherPDG[iv]); + + if( (fabs(mass - massMotherPDG[iv])/massMotherPDGSigma[iv]) <= 3 ) + for(unsigned int iP=0; iP<iPrimVert[iv].size(); iP++) + (*vMotherPrim)[iPrimVert[iv][iP]].push_back(mother_temp); + } + } + } +} + +void KFParticleFinder::FindTrackV0Decay(vector<KFParticle>& vV0, + const int V0PDG, + KFPTrackVector& vTracks, + const int q, + const int firstTrack, + const int lastTrack, + vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + int v0PVIndex, + kfvector_float* ChiToPrimVtx, + vector< vector<KFParticle> >* vMotherPrim, + vector<KFParticle>* vMotherSec) +{ + /** Combines tracks and already reconstructed particle candidate of certain type in the next candidate. + ** \param[in] vV0 - the input vector with already reconstructed particle candidate. + ** \param[in] V0PDG - PDG code of the provided particle candidates. + ** \param[in] vTracks - vector with input tracks. + ** \param[in] q - charge of the provided tracks. + ** \param[in] firstTrack - index of the first track to be used. + ** \param[in] lastTrack - index of the last track to be used. + ** \param[out] Particles - the output array with the reconstructed particle-candidates. + ** \param[in] PrimVtx - array with primary vertices. + ** \param[in] v0PVIndex - index of the corresponding primary vertex if the tracks are primary. If not "-1" should be set. + ** \param[in] ChiToPrimVtx - vector with the \f$\chi^2_{prim}\f$ deviations for provided tracks. If tracks are primary NULL pointer is provided. + ** \param[out] vMotherPrim - array with output primary candidates. + ** \param[out] vMotherSec - array with output secondary candidates. + **/ + + if( (vV0.size() < 1) || ((lastTrack-firstTrack) < 1) ) return; + KFParticle mother_temp; + + KFParticle* v0Pointer[float_v::Size]; + + KFParticleSIMD mother, track; + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> > motherTopo(fNPV); + + kfvector_floatv l(fNPV), dl(fNPV); + + float_v cuts[3]; + + // for secondary V0 + unsigned int nBufEntry = 0; + float_v dS; + uint_v idTrack; + int_v trackPDGMother(-1); + + int_v pvIndexMother(-1); + + float_v massMotherPDG(Vc::Zero), massMotherPDGSigma(Vc::Zero); + int_v motherParticlePDG(Vc::Zero); +// Particles.reserve(Particles.size() + vV0.size()); + + bool isCharm = ((abs(V0PDG) == 421) || (abs(V0PDG) == 411) || (abs(V0PDG) == 429) || (abs(V0PDG) == 420) || (abs(V0PDG) == 419)) && (v0PVIndex<0); + + for(unsigned int iV0=0; iV0 < vV0.size(); iV0++) + { + int iNegDaughter = vV0[iV0].DaughterIds()[0]; + int iPosDaughter = vV0[iV0].DaughterIds()[1]; + + for(int iTr=firstTrack; iTr < lastTrack; iTr += float_vLen) + { + const int NTracks = (iTr + float_vLen < lastTrack) ? float_vLen : (lastTrack - iTr); + + const int_v& trackPDG = reinterpret_cast<const int_v&>(vTracks.PDG()[iTr]); + const int_v& trackPVIndex = reinterpret_cast<const int_v&>(vTracks.PVIndex()[iTr]); + + const int_m& isTrackSecondary = (trackPVIndex < 0); + const int_m& isSecondary = int_m( v0PVIndex < 0 ) && isTrackSecondary; + const int_m& isPrimary = int_m( v0PVIndex >= 0 ) && (!isTrackSecondary); + const int_m& isSamePV = (isPrimary && (v0PVIndex == trackPVIndex)) || !(isPrimary); + + float_m closeDaughters = simd_cast<float_m>(isSamePV) && simd_cast<float_m>(int_v::IndexesFromZero() < int(NTracks)); + +// if(v0PVIndex < 0) +// { +// KFParticleSIMD v0(vV0[iV0]); +// track.Load(vTracks, iTr, trackPDG); + +// float_v dsV0, dsTrack; +// float_v dsdrV0[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; +// float_v dsdrTrack[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; +// float_v par1[8], cov1[36], par2[8], cov2[36]; +// v0.GetDStoParticle(track, dsV0, dsTrack); +// v0.Transport(dsV0, dsdrV0, par1, cov1); +// track.Transport(dsTrack, dsdrTrack, par2, cov2); +// +// const float_v& dx = par1[0] - par2[0]; +// const float_v& dy = par1[1] - par2[1]; +// const float_v& dz = par1[2] - par2[2]; +// const float_v& r2 = dx*dx + dy*dy + dz*dz; +// +// const float_v vtx[3] = {(par1[0] + par2[0])/2.f, +// (par1[1] + par2[1])/2.f, +// (par1[2] + par2[2])/2.f, }; +// +// v0.CorrectErrorsOnS(par1, vtx, cov1); +// track.CorrectErrorsOnS(par2, vtx, cov2); +// +// const float_v cov[6] = {cov1[0]+cov2[0], +// cov1[1]+cov2[1], +// cov1[2]+cov2[2], +// cov1[3]+cov2[3], +// cov1[4]+cov2[4], +// cov1[5]+cov2[5] }; +// const float_v& err2 = cov[0]*dx*dx + cov[2]*dy*dy + cov[5]*dz*dz + 2.f*( cov[1]*dx*dy + cov[3]*dx*dz + cov[4]*dy*dz ); +// +// closeDaughters &= ( (r2 < float_v(1.f)) && (r2*r2/err2) < float_v(3.f) && isSecondary); +// closeDaughters &= v0.GetDeviationFromParticle(track) < float_v(10.f); +// } + + if(v0PVIndex < 0) + { + KFParticleSIMD v0(vV0[iV0]); + track.Load(vTracks, iTr, trackPDG); + closeDaughters &= v0.GetDistanceFromParticle(track) < float_v(fDistanceCut); + if(closeDaughters.isEmpty()) continue; + } + + int_v trackPdgPos[2]; + int_m active[2]; + + int nPDGPos = 2; + + active[0] = simd_cast<int_m>(closeDaughters); + active[1] = (trackPDG == -1) && isSecondary && simd_cast<int_m>(closeDaughters); + + trackPdgPos[0] = trackPDG; + + if( (trackPDG == -1).isEmpty() || (abs(V0PDG) == 421) || (abs(V0PDG) == 411) ) + { + nPDGPos = 1; + } + else + { + trackPdgPos[0](trackPDG == -1) = q*211; + nPDGPos = 1;//TODO + trackPdgPos[1](isSecondary) = q*321; + } + + for(int iPDGPos=0; iPDGPos<nPDGPos; iPDGPos++) + { + + if(active[iPDGPos].isEmpty()) continue; + + //detetrmine a pdg code of the mother particle + + int_v motherPDG(-1); + + if( V0PDG == 3122 ) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = 3312; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = 304122; + motherPDG( isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 321) ) = 3334; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 211) ) = 3224; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -211) ) = 3114; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -321) ) = 1003314; + } + else if( V0PDG == -3122 ) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = -3312; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = -304122; + motherPDG( isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 321) ) = -3334; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -211) ) = -3224; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 211) ) = -3114; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 321) ) = -1003314; + } + else if( V0PDG == 310) + { + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 211) ) = 323; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -211) ) = -323; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = 100411; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = -100411; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 321) ) = 100431; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -321) ) = -100431; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 2212) ) = 104122; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -2212) ) = -104122; + } + else if( V0PDG == 3312 ) + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 211) ) = 3324; + else if( V0PDG == -3312) + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -211) ) = -3324; + else if( V0PDG == 3324 ) + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -321) ) = 1003334; + else if( V0PDG == -3324 ) + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 321) ) = -1003334; + else if(V0PDG == 421) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = 411; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 321) ) = 431; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 2212) ) = 4122; + const int_v& id = reinterpret_cast<const int_v&>(vTracks.Id()[iTr]); + int_m isDMeson = isSecondary && int_m(trackPdgPos[iPDGPos] == 211); + active[iPDGPos] &= (!(isDMeson)) || (isDMeson && ( id > iPosDaughter) ); + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = -521; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -321) ) = -529; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 211) ) = 10411; + } + else if(V0PDG == -421) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = -411; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -321) ) = -431; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] ==-2212) ) = -4122; + const int_v& id = reinterpret_cast<const int_v&>(vTracks.Id()[iTr]); + int_m isDMeson = isSecondary && int_m(trackPdgPos[iPDGPos] == -211); + active[iPDGPos] &= (!(isDMeson)) || (isDMeson && ( id > iNegDaughter) ); + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = 521; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 321) ) = 529; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -211) ) = -10411; + } + else if(V0PDG == 420 && q>0) + { + motherPDG( isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 211) ) = 300411; + motherPDG( isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 321) ) = 400431; + motherPDG( isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 2212) ) = 504122; + const int_v& id = reinterpret_cast<const int_v&>(vTracks.Id()[iTr]); + int_m isDMeson = isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 211); + active[iPDGPos] &= (!(isDMeson)) || (isDMeson && ( id > iPosDaughter) ); + } + else if(V0PDG == 420 && q<0) + { + motherPDG( isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 211) ) = -300411; + motherPDG( isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 321) ) = -400431; + motherPDG( isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 2212) ) = -504122; + const int_v& id = reinterpret_cast<const int_v&>(vTracks.Id()[iTr]); + int_m isDMeson = isSecondary && int_m(abs(trackPdgPos[iPDGPos]) == 211); + active[iPDGPos] &= (!(isDMeson)) || (isDMeson && ( id > iNegDaughter) ); + } + else if(V0PDG == 411) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = 429; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -211) ) = 10421; + } + else if(V0PDG == -411) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = -429; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 211) ) = -10421; + } + else if(V0PDG == 419) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = -511; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -321) ) = -519; + } + else if(V0PDG == -419) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = 511; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 321) ) = 519; + } + else if(V0PDG == 429) + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 211) ) = 20411; + else if(V0PDG == -429) + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -211) ) = -20411; + else if( V0PDG == 3002 ) + { + const int_v& id = reinterpret_cast<const int_v&>(vTracks.Id()[iTr]); + int_m isSameProton = (id == fLPiPIndex[iV0]); + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 2212) && (!isSameProton)) = 3001; + } + else if( V0PDG == 100411 ) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = 425; + } + else if( V0PDG == 100431 ) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -321) ) = 427; + } + else if( V0PDG == 425) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = 200411; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = -200411; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 321) ) = 300431; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -321) ) = -300431; + } + else if( V0PDG == 111 ) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 2212) ) = 3222; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -2212) ) = -3222; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == 321) ) = 100323; + motherPDG( isPrimary && int_m(trackPdgPos[iPDGPos] == -321) ) = -100323; + } + else if( V0PDG == 3004 ) + { + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 2212) ) = 3006; + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = 3203; + } + else if( V0PDG == -3004 ) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -2212) ) = -3006; + else if( V0PDG == 3005 ) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 2212) ) = 3007; + else if( V0PDG == -3005 ) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -2212) ) = -3007; + else if( V0PDG == 3006 ) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = 3008; + else if( V0PDG == 3007 ) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = 3010; + else if( V0PDG == 3203 ) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 2212) ) = 3009; + else if( V0PDG == 3010 ) + { + const int_v& id = reinterpret_cast<const int_v&>(vTracks.Id()[iTr]); + int_m isSameProton = (id == Particles[vV0[iV0].DaughterIds()[1]].DaughterIds()[2]); + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 2212) && (!isSameProton)) = 3011; + } + else if(V0PDG == 304122) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = 314122; + else if(V0PDG == -304122) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = -314122; + else if(V0PDG == 314122) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = 404122; + else if(V0PDG == -314122) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = -404122; + else if(V0PDG == 104122) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = 114122; + else if(V0PDG == -104122) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = -114122; + else if(V0PDG == 114122) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == -211) ) = 204122; + else if(V0PDG == -114122) + motherPDG( isSecondary && int_m(trackPdgPos[iPDGPos] == 211) ) = -204122; + + active[iPDGPos] &= (motherPDG != -1); + if(!(fDecayReconstructionList.empty())) + { + for(int iV=0; iV<float_vLen; iV++) + { + if(!(active[iPDGPos][iV])) continue; + if(fDecayReconstructionList.find(motherPDG[iV]) == fDecayReconstructionList.end()) + motherPDG[iV] = -1; + } + active[iPDGPos] &= (motherPDG != -1); + } + if(ChiToPrimVtx) + active[iPDGPos] &= ( !( (abs(motherPDG) == 3334 || abs(motherPDG) == 3312 ) ) || + ( (abs(motherPDG) == 3334 || abs(motherPDG) == 3312 ) && simd_cast<int_m>(reinterpret_cast<const float_v&>((*ChiToPrimVtx)[iTr]) > float_v(fCuts2D[0])) ) ); + + if(active[iPDGPos].isEmpty()) continue; + + if(isCharm) + { + track.Load(vTracks, iTr, trackPDG); + const float_v& trackPt = track.Px()*track.Px() + track.Py()*track.Py(); + const int_v& nPixelHits = reinterpret_cast<const int_v&>(vTracks.NPixelHits()[iTr]); + + active[iPDGPos] &= simd_cast<int_m>(trackPt >= fCutCharmPt*fCutCharmPt) && simd_cast<int_m>(reinterpret_cast<const float_v&>((*ChiToPrimVtx)[iTr]) > fCutCharmChiPrim ) && int_m(nPixelHits >= int_v(3)); + } + { + int_m isCharmParticle = (abs(motherPDG) == 104122) || + (abs(motherPDG) == 204122) || + (abs(motherPDG) == 304122) || + (abs(motherPDG) == 404122) || + (abs(motherPDG) == 425) || + (abs(motherPDG) == 426) || + (abs(motherPDG) == 427) || + (abs(motherPDG) == 100411) || + (abs(motherPDG) == 200411) || + (abs(motherPDG) == 100431) || + (abs(motherPDG) == 300431) ; + + if(!(isCharmParticle.isEmpty())) + { + track.Load(vTracks, iTr, trackPDG); + const float_v& trackPt = track.Px()*track.Px() + track.Py()*track.Py(); + const int_v& nPixelHits = reinterpret_cast<const int_v&>(vTracks.NPixelHits()[iTr]); + + active[iPDGPos] &= ( (simd_cast<int_m>(trackPt >= fCutCharmPt*fCutCharmPt) && simd_cast<int_m>(reinterpret_cast<const float_v&>((*ChiToPrimVtx)[iTr]) > fCutCharmChiPrim ) && (nPixelHits >= int_v(3)) ) && isCharmParticle ) || (!isCharmParticle); + } + } + + for(int iV=0; iV<NTracks; iV++) + { + if(!(active[iPDGPos][iV])) continue; + + + idTrack[nBufEntry] = iTr+iV; + v0Pointer[nBufEntry] = &vV0[iV0]; + + trackPDGMother[nBufEntry] = trackPdgPos[iPDGPos][iV]; + + pvIndexMother[nBufEntry] = v0PVIndex; + + float massMother, massMotherSigma; + KFParticleDatabase::Instance()->GetMotherMass(motherPDG[iV],massMother,massMotherSigma); + + massMotherPDG[nBufEntry] = massMother; + massMotherPDGSigma[nBufEntry] = massMotherSigma; + motherParticlePDG[nBufEntry] = motherPDG[iV]; + + int motherType = 0; + + switch (abs(motherPDG[iV])) + { + case 3312: motherType = 0; break; //Xi + case 3334: motherType = 0; break; //Omega + case 4122: motherType = 1; break; //LambdaC + case 104122: motherType = 1; break; //LambdaC + case 304122: motherType = 1; break; //LambdaC + case 504122: motherType = 1; break; //LambdaC + case 425: motherType = 1; break; //D0 + case 426: motherType = 1; break; //D0 + case 427: motherType = 1; break; //D0 + case 100411: motherType = 1; break; //D+ + case 300411: motherType = 1; break; //D+ + case 100431: motherType = 1; break; //Ds+ + case 400431: motherType = 1; break; //Ds+ + case 431: motherType = 1; break; //Ds+- + case 411: motherType = 1; break; //D+- + case 428: motherType = 1; break; //D0 + case 429: motherType = 1; break; //D0 + case 521: motherType = 1; break; //B+ + case 529: motherType = 1; break; //B+ + case 511: motherType = 1; break; //B0 + case 519: motherType = 1; break; //B0 + case 3001: motherType = 1; break; //H0 + case 3222: motherType = 1; break; //Sigma+ + case 3006: motherType = 1; break; //He4L + case 3007: motherType = 1; break; //He5L + case 3008: motherType = 1; break; //H4LL + case 3009: motherType = 1; break; //H4LL + case 3011: motherType = 1; break; //He6LL + default: motherType = 2; break; //resonances + } + for(int iCut=0; iCut<3; iCut++) + cuts[iCut][nBufEntry] = fCutsTrackV0[motherType][iCut]; + + nBufEntry++; + + if(int(nBufEntry) == float_vLen) + { + mother.SetPDG( motherParticlePDG ); + ConstructTrackV0Cand(vTracks, + idTrack, trackPDGMother, v0Pointer, + mother, motherTopo, mother_temp, + nBufEntry, l, dl, Particles, PrimVtx, + cuts, pvIndexMother, massMotherPDG, + massMotherPDGSigma, vMotherPrim, vMotherSec); + nBufEntry = 0; + } + }//iV + }//iPDGPos + }//iTr + } + + if(nBufEntry > 0) + { + for(int iV=nBufEntry; iV<float_vLen; iV++) + idTrack[iV] = idTrack[0]; + + mother.SetPDG( motherParticlePDG ); + ConstructTrackV0Cand(vTracks, + idTrack, trackPDGMother, v0Pointer, + mother, motherTopo, mother_temp, + nBufEntry, l, dl, Particles, PrimVtx, + cuts, pvIndexMother, massMotherPDG, + massMotherPDGSigma, vMotherPrim, vMotherSec); + nBufEntry = 0; + } +} + +void KFParticleFinder::SelectParticles(vector<KFParticle>& Particles, + vector<KFParticle>& vCandidates, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float& cutChi2Topo, + const float& cutLdL, + const float& mass, + const float& massErr, + const float& massCut) +{ + /** Selects particles from a set of candidates "vCandidates" according to the provided cuts + ** on \f$\chi^2_{topo}\f$ and \f$l/\Delta l\f$ + ** and stores them to the output array "Particles". Also, "vCandidates" is cleaned, only + ** selected particles with additional cut on \f$\sigma_{M}\f$ are left there. + ** \param[out] Particles - output vector with particles. + ** \param[in,out] vCandidates - vector with the input candidates. + ** \param[in] PrimVtx - vector with primary vertices. + ** \param[in] cutChi2Topo - \f$\chi^2_{topo}\f$ cut. + ** \param[in] cutLdL - \f$l/\Delta l\f$ cut. + ** \param[in] mass - table mass for the given PDG hypothesis. + ** \param[in] massErr - sigma of the peak width for the given PDG hypothesis. + ** \param[in] massCut - \f$\sigma_{M}\f$ cut. + **/ + KFParticle* cand[float_vLen]; + int nCand = vCandidates.size(); + + vector<KFParticle> newCandidates; + kfvector_floatv l(fNPV), dl(fNPV); + + for(int iC=0; iC < nCand; iC += float_vLen) + { + int nEntries = (iC + float_vLen < nCand) ? float_vLen : (nCand - iC); + + for(int iv=0; iv<nEntries; iv++) + cand[iv] = &vCandidates[iC+iv]; + + KFParticleSIMD mother(cand,nEntries); + + float_m saveParticle(simd_cast<float_m>(int_v::IndexesFromZero() < int(nEntries))); + + float_v lMin(1.e8f); + float_v ldlMin(1.e8f); + float_m isParticleFromVertex(false); + + for(int iP=0; iP<fNPV; iP++) + { + float_m isParticleFromVertexLocal; + mother.GetDistanceToVertexLine(PrimVtx[iP], l[iP], dl[iP], &isParticleFromVertexLocal); + isParticleFromVertex |= isParticleFromVertexLocal; + float_v ldl = (l[iP]/dl[iP]); + lMin( (l[iP] < lMin) && saveParticle) = l[iP]; + ldlMin( (ldl < ldlMin) && saveParticle) = ldl; + } + saveParticle &= ldlMin > cutLdL; + saveParticle &= (lMin < 200.f); + saveParticle &= isParticleFromVertex; + if( saveParticle.isEmpty() ) continue; + + KFParticleSIMD* candTopo = new KFParticleSIMD[fNPV]; + + for(int iP=0; iP<fNPV; iP++) + { + candTopo[iP] = mother; + candTopo[iP].SetProductionVertex(PrimVtx[iP]); + } + + for(int iv=0; iv<nEntries; iv++) + { + if(!saveParticle[iv]) continue; + + bool isPrimary = 0; + for(int iP=0; iP<fNPV; iP++) + { + if( !(KFPMath::Finite(candTopo[iP].GetChi2())[iv]) ) continue; + if(!(candTopo[iP].GetChi2()[iv] > 0.0f)) continue; + if(!(candTopo[iP].GetChi2()[iv]==candTopo[iP].GetChi2()[iv])) continue; + + if(float(candTopo[iP].GetChi2()[iv])/float(candTopo[iP].GetNDF()[iv]) <= cutChi2Topo ) + isPrimary = 1; + } + if(!isPrimary) + continue; + + vCandidates[iC+iv].SetId(Particles.size()); + Particles.push_back(vCandidates[iC+iv]); + + float m, dm; + vCandidates[iC+iv].GetMass(m,dm); + if( (fabs(m - mass)/massErr) > massCut ) continue; + + vCandidates[iC+iv].SetNonlinearMassConstraint(mass); + newCandidates.push_back(vCandidates[iC+iv]); + } + if(candTopo) delete [] candTopo; + } + + vCandidates = newCandidates; +} + +void KFParticleFinder::CombinePartPart(vector<KFParticle>& particles1, + vector<KFParticle>& particles2, + vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* cuts, + int iPV, + const int MotherPDG, + bool isSameInputPart, + bool saveOnlyPrimary, + vector< vector<KFParticle> >* vMotherPrim, + vector<KFParticle>* vMotherSec, + float massMotherPDG, + float massMotherPDGSigma) +{ + /** Combines two already constructed candidates into a new particle. + ** \param[in] particles1 - vector with the first set of particles. + ** \param[in] particles2 - vector with the second set of particles. + ** \param[out] Particles - output vector with particles. + ** \param[in] PrimVtx - vector with primary vertices. + ** \param[in] cuts - set of cuts: \f$l/\Delta l\f$, \f$\chi^2_{topo}\f$, \f$\chi^2_{geo}\f$. + ** \param[in] iPV - index of the primary vertex for reconstruction of resonances. Tracks should come from the same vertex. + ** \param[in] MotherPDG - PDG hypothesis of the constructed mother particles. + ** \param[in] isSameInputPart - shows if vectors of input particles are the same to avoid double reconstruction of the same candidate. + ** \param[in] saveOnlyPrimary - defines if only primary particles should be searched and \f$\chi^2_{topo}\f$ should be applied. + ** \param[out] vMotherPrim - array with output primary candidates if any. If pointer is set to NULL - not filled. + ** \param[out] vMotherSec - array with output secondary candidates if any. If pointer is set to NULL - not filled. + ** \param[in] massMotherPDG - PDG table mass for the mother particle, is used for selection of primary and secondary candidates. + ** \param[in] massMotherPDGSigma - sigma of the peak width, is used for selection of primary and secondary candidates. + **/ + if( (particles1.size() == 0) || (particles2.size() == 0) ) return; + if(!(fDecayReconstructionList.empty()) && (fDecayReconstructionList.find(MotherPDG) == fDecayReconstructionList.end())) return; + + KFParticle mother_temp; + KFParticleSIMD mother; + KFParticleSIMD *motherTopo = new KFParticleSIMD[fNPV]; + mother.SetPDG( MotherPDG ); + + kfvector_floatv l(fNPV), dl(fNPV); + + KFParticle* tmpPart2[float_vLen]; + int nPart2 = particles2.size(); + + bool isPrimary = (iPV >= 0); + bool isCharm = (MotherPDG == 425) || + (MotherPDG == 427) || + (abs(MotherPDG) == 200411) || + (abs(MotherPDG) == 404122) || + (abs(MotherPDG) == 4132) || + (abs(MotherPDG) == 300431) || + (abs(MotherPDG) == 204122); + + for(unsigned int iP1=0; iP1 < particles1.size(); iP1++) + { + KFParticleSIMD vDaughters[2] = {KFParticleSIMD(particles1[iP1]), KFParticleSIMD()}; + + unsigned int startIndex=0; + if(isSameInputPart) startIndex=iP1+1; + for(int iP2=startIndex; iP2 < nPart2; iP2 += float_vLen) + { + int nElements = (iP2 + float_vLen < nPart2) ? float_vLen : (nPart2 - iP2); + float_m active(simd_cast<float_m>(int_v::IndexesFromZero() < int(nElements))); + + for(int iv=0; iv<nElements; iv++) + tmpPart2[iv] = &particles2[iP2+iv]; + + vDaughters[1] = KFParticleSIMD(tmpPart2,nElements); + +// if( reconstructPi0 ) +// { +// int indexOffset = fEmcClusters->Id()[0]; +// uint_v gammaIndex1( (unsigned int)0); +// uint_v gammaIndex2( (unsigned int)0); +// for(int iv=0; iv<nElements; iv++) +// { +// gammaIndex1[iv] = Particles[ particles2[iP2+iv].DaughterIds()[0] ].DaughterIds()[0] - indexOffset; +// gammaIndex2[iv] = Particles[ particles2[iP2+iv].DaughterIds()[1] ].DaughterIds()[0] - indexOffset; +// } +// +// KFParticleSIMD gamma1(*fEmcClusters, gammaIndex1, vDaughters[0]); +// KFParticleSIMD gamma2(*fEmcClusters, gammaIndex2, vDaughters[0]); +// const KFParticleSIMD* pi0Daughters[2] = {&gamma1, &gamma2}; +// +// int_v gammaId = vDaughters[1].Id(); +// vDaughters[1].SetVtxGuess(vDaughters[0].X(), vDaughters[0].Y(), vDaughters[0].Z()); +// vDaughters[1].Construct(pi0Daughters, 2); +// vDaughters[1].SetId(gammaId); +// +// float_v mass, dm; +// vDaughters[1].GetMass(mass,dm); +// const float& mPi0 = KFParticleDatabase::Instance()->GetPi0Mass(); +// const float& mPi0Sigma = KFParticleDatabase::Instance()->GetPi0MassSigma(); +// active &= (abs(mass - mPi0)/mPi0Sigma) < 3.f; +// vDaughters[1].SetNonlinearMassConstraint(mPi0); +// if(active.isEmpty()) continue; +// } + + if(isCharm) + { + mother = vDaughters[0]; + mother += vDaughters[1]; + mother.SetPDG( MotherPDG ); + } + else + { + const KFParticleSIMD* vDaughtersPointer[2] = {&vDaughters[0], &vDaughters[1]}; + mother.Construct(vDaughtersPointer, 2, 0); + } + + float_m saveParticle(active); + saveParticle &= (mother.Chi2()/simd_cast<float_v>(mother.NDF()) < cuts[2] ); + saveParticle &= KFPMath::Finite(mother.GetChi2()); + saveParticle &= (mother.GetChi2() >= 0.0f); + saveParticle &= (mother.GetChi2() == mother.GetChi2()); + + if( saveParticle.isEmpty() ) { continue; } + + int_m isSameTrack(false); + for(unsigned int iD=0; iD<vDaughters[0].DaughterIds().size(); iD++) + for(unsigned int iD1=0; iD1<vDaughters[1].DaughterIds().size(); iD1++) + isSameTrack |= ( int_v(vDaughters[0].DaughterIds()[iD]) == int_v(vDaughters[1].DaughterIds()[iD1]) ); + saveParticle &= ( !simd_cast<float_m>(isSameTrack)); + if( saveParticle.isEmpty() ) { continue; } + + float_v lMin(1.e8f); + float_v ldlMin(1.e8f); + float_m isParticleFromVertex(false); + + for(int iP=0; iP<fNPV; iP++) + { + if( (iPV > -1) && (iP !=iPV) ) continue; + float_m isParticleFromVertexLocal; + mother.GetDistanceToVertexLine(PrimVtx[iP], l[iP], dl[iP], &isParticleFromVertexLocal); + isParticleFromVertex |= isParticleFromVertexLocal; + float_v ldl = (l[iP]/dl[iP]); + lMin( (l[iP] < lMin) && active) = l[iP]; + ldlMin( (ldl < ldlMin) && active) = ldl; + } + saveParticle &= ( (float_m(!isPrimary) && ldlMin > cuts[0]) || float_m(isPrimary) ); + saveParticle &= (lMin < 200.f); + + int_m setLCut = abs(mother.PDG()) == 3000; + saveParticle &= ( (simd_cast<float_m>(setLCut) && lMin > float_v(fLCut)) || simd_cast<float_m>(!setLCut) ); + +// if(isPrimary && (float(ldlMin > 3) )) continue; + saveParticle &= ((float_m(!isPrimary) && isParticleFromVertex) || float_m(isPrimary) ); + if( saveParticle.isEmpty() ) { continue; } + + float_m isSameParticle(isPrimary || isCharm); + if(!((isSameParticle).isFull())) + { + float_m isParticleFromVertexLocal; + float_v l1, dl1; + vDaughters[0].GetDistanceToVertexLine(mother, l1, dl1, &isParticleFromVertexLocal); + + saveParticle &= ( isSameParticle || ((!isSameParticle) && isParticleFromVertexLocal)); + if( saveParticle.isEmpty() ) { continue; } + } + + for(int iP=0; iP<fNPV; iP++) + { + if( (iPV > -1) && (iP !=iPV) ) continue; + motherTopo[iP] = mother; + motherTopo[iP].SetProductionVertex(PrimVtx[iP]); + } + + vector<int> iPrimVert[float_vLen]; + float_m isPrimaryPart(false); + + for(int iP=0; iP<fNPV; iP++) + { + if( (iPV > -1) && (iP !=iPV) ) continue; + const float_v& motherTopoChi2Ndf = motherTopo[iP].GetChi2()/simd_cast<float_v>(motherTopo[iP].GetNDF()); + const float_m isPrimaryPartLocal = ( motherTopoChi2Ndf < float_v(cuts[1]) ); + isPrimaryPart |= isPrimaryPartLocal; + for(int iV=0; iV<float_vLen; iV++) + { + if(isPrimaryPartLocal[iV]) + iPrimVert[iV].push_back(iP); + } + } + + for(int iv=0; iv<nElements; iv++) + { + if(!saveParticle[iv]) continue; + + mother.GetKFParticle(mother_temp, iv); + + // reset daughter ids for 3- and 4-particle decays + if( (abs(mother.PDG()[iv]) == 428)) + { + mother_temp.CleanDaughtersId(); + for(int iD=0; iD < particles1[iP1].NDaughters(); iD++) + mother_temp.AddDaughterId( particles1[iP1].DaughterIds()[iD] ); + mother_temp.AddDaughterId(tmpPart2[iv]->Id()); + } + + if(saveOnlyPrimary) + { + if(isPrimaryPart[iv]) + { + mother_temp.SetId(Particles.size()); + Particles.push_back(mother_temp); + } + } + else + { + mother_temp.SetId(Particles.size()); + Particles.push_back(mother_temp); + } + + if(vMotherPrim || vMotherSec) + { + float mass, errMass; + mother_temp.GetMass(mass, errMass); + if( (fabs(mass - massMotherPDG)/massMotherPDGSigma) > 3.f ) continue; + mother_temp.SetNonlinearMassConstraint(massMotherPDG); + + if(MotherPDG == 428) + { + mother_temp.CleanDaughtersId(); + for(int iD=0; iD < tmpPart2[iv]->NDaughters(); iD++) + mother_temp.AddDaughterId( tmpPart2[iv]->DaughterIds()[iD] ); + for(int iD=0; iD < particles1[iP1].NDaughters(); iD++) + mother_temp.AddDaughterId( particles1[iP1].DaughterIds()[iD] ); + } + + if(vMotherSec && (!(isPrimaryPart[iv])) ) + vMotherSec->push_back(mother_temp); + if(vMotherPrim) + for(unsigned int iP=0; iP<iPrimVert[iv].size(); iP++) + (*vMotherPrim)[iPrimVert[iv][iP]].push_back(mother_temp); + } + } + } + } + + if(motherTopo) delete [] motherTopo; +} + + +void KFParticleFinder::NeutralDaughterDecay(KFPTrackVector* vTracks, + vector<KFParticle>& Particles) +{ + /** Reconstructs particles by the missing mass method. + ** \param[in] vRTracks - pointer to the array with vectors of tracks:\n + ** 0) secondary positive at the first hit position; \n + ** 1) secondary negative at the first hit position; \n + ** 2) primary positive at the first hit position; \n + ** 3) primary negative at the first hit position; \n + ** 4) secondary positive at the last hit position; \n + ** 5) secondary negative at the last hit position; \n + ** 6) primary positive at the last hit position; \n + ** 7) primary negative at the last hit position. \n + ** \param[out] Particles - the output array with the reconstructed particle-candidates. + **/ + KFParticle mother_temp; + KFParticleSIMD ChargedDaughter, MotherTrack; + + uint_v idMotherTrack; + uint_v idChargedDaughter; + int_v ChargedDaughterPDG(-1); + + int_v pvIndexMother(-1); + + int outNeutralDaughterPDG[4][5]; //[iTC][iHypothesis] + int outMotherPDG[4][5]; + + int trTypeIndexMother[2] = {6,7}; + int trTypeIndexDaughter[2] = {0,1}; + + for( int iTrTypeDaughter = 0; iTrTypeDaughter<2; iTrTypeDaughter++) + { + KFPTrackVector& DaughterTracks = vTracks[ trTypeIndexDaughter[iTrTypeDaughter] ]; + KFPTrackVector& MotherTracks = vTracks[ trTypeIndexMother[iTrTypeDaughter] ]; + + int_v DaughterTracksSize = DaughterTracks.Size(); + int MotherTracksSize = MotherTracks.Size(); + + //track categories + int nTC = 4; + int startTCMother[4] = {0,0,0,0}; + int endTCMother[4] = {0,0,0,0}; + int startTCDaughter[4] = {0,0,0,0}; + int endTCDaughter[4] = {0,0,0,0}; + + nTC = 4; + vector<int> nMotherHypothesis(nTC,0); + vector< vector<int> > motherPDGHypothesis(nTC); + vector< vector<float> > neutralDaughterMassHypothesis(nTC); + + + //mu+, mu- + startTCMother[0] = 0; endTCMother[0] = MotherTracksSize; + startTCDaughter[0] = DaughterTracks.FirstMuon(); endTCDaughter[0] = DaughterTracks.LastMuon(); + + nMotherHypothesis[0] = 2; + + + motherPDGHypothesis[0].push_back(211); + motherPDGHypothesis[0].push_back(321); + + neutralDaughterMassHypothesis[0].push_back(0.); + neutralDaughterMassHypothesis[0].push_back(0.); + + outNeutralDaughterPDG[0][0]=-7000014; + outNeutralDaughterPDG[0][1]=-8000014; + + outMotherPDG[0][0]=-7000211; + outMotherPDG[0][1]=-7000321; + + //Pi+, Pi- + startTCMother[1] = 0; endTCMother[1] = MotherTracksSize; + startTCDaughter[1] = DaughterTracks.FirstPion(); endTCDaughter[1] = DaughterTracks.LastPion(); + + nMotherHypothesis[1] = 5; + + motherPDGHypothesis[1].push_back(3112); + motherPDGHypothesis[1].push_back(3222); + motherPDGHypothesis[1].push_back(3312); + motherPDGHypothesis[1].push_back(3334); + motherPDGHypothesis[1].push_back(321); + + neutralDaughterMassHypothesis[1].push_back(0.939565); + neutralDaughterMassHypothesis[1].push_back(0.939565); + neutralDaughterMassHypothesis[1].push_back(1.115683); + neutralDaughterMassHypothesis[1].push_back(1.31486); + neutralDaughterMassHypothesis[1].push_back(0.1349766); + + outNeutralDaughterPDG[1][0]= 7002112; + outNeutralDaughterPDG[1][1]=-8002112; + outNeutralDaughterPDG[1][2]= 7003122; + outNeutralDaughterPDG[1][3]= 7003322; + outNeutralDaughterPDG[1][4]=-9000111; + + outMotherPDG[1][0]= 7003112; + outMotherPDG[1][1]=-7003222; + outMotherPDG[1][2]= 7003312; + outMotherPDG[1][3]= 7003334; + outMotherPDG[1][4]=-9000321; + + //K+, K- + startTCMother[2] = 0; endTCMother[2] = MotherTracksSize; + startTCDaughter[2] = DaughterTracks.FirstKaon(); endTCDaughter[2] = DaughterTracks.LastKaon(); + + nMotherHypothesis[2] = 1; + + motherPDGHypothesis[2].push_back(3334); + + neutralDaughterMassHypothesis[2].push_back(1.115683); + + outNeutralDaughterPDG[2][0]= 8003122; + + outMotherPDG[2][0]= 8003334; + + //p+, p- + startTCMother[3] = 0; endTCMother[3] = MotherTracksSize; + startTCDaughter[3] = DaughterTracks.FirstProton(); endTCDaughter[3] = DaughterTracks.LastProton(); + + nMotherHypothesis[3] = 1; + + motherPDGHypothesis[3].push_back(3222); + + neutralDaughterMassHypothesis[3].push_back(0.1349766); + + outNeutralDaughterPDG[3][0]=-8000111; + + outMotherPDG[3][0]=-8003222; + + + + for(int iTC=0; iTC<nTC; iTC++) + { + for(unsigned short iTrD=startTCDaughter[iTC]; iTrD < endTCDaughter[iTC]; iTrD += float_vLen) + { + const unsigned short NTracksDaughter = (iTrD + float_vLen < DaughterTracks.Size()) ? float_vLen : (DaughterTracks.Size() - iTrD); + + int_v DaughterInd = int_v::IndexesFromZero() + int(iTrD); + + int_v DaughterPDG = reinterpret_cast<const int_v&>(DaughterTracks.PDG()[iTrD]); + int_v DaughterPVIndex = reinterpret_cast<const int_v&>(DaughterTracks.PVIndex()[iTrD]); + int_v daughterId = reinterpret_cast<const int_v&>(DaughterTracks.Id()[iTrD]); + + int_v trackPdgDaughter = DaughterPDG; + int_m activeDaughter = (DaughterPDG != -1); + + if( !((DaughterPDG == -1).isEmpty()) ) + { + trackPdgDaughter(DaughterPVIndex<0 && (DaughterPDG == -1) ) = 211; + +// activeDaughter |= int_m(DaughterPVIndex < 0) && int_m(DaughterPDG == -1) ; + } + + activeDaughter = (int_v::IndexesFromZero() < int(NTracksDaughter)); + + ChargedDaughter.Load(DaughterTracks, iTrD, DaughterPDG); + ChargedDaughter.SetId(daughterId); + + for(unsigned short iTrM=startTCMother[iTC]; iTrM < endTCMother[iTC]; iTrM += float_vLen) + { + const unsigned short NTracks = (iTrM + float_vLen < MotherTracksSize) ? float_vLen : (MotherTracksSize - iTrM); + + //const int_v& MotherPDG = reinterpret_cast<const int_v&>(MotherTracks.PDG()[iTrM]); + //const int_v& MotherPVIndex = reinterpret_cast<const int_v&>(MotherTracks.PVIndex()[iTrM]); + const int_v& motherTrackId = reinterpret_cast<const int_v&>(MotherTracks.Id()[iTrM]); + + for(int iRot = 0; iRot<float_vLen; iRot++) + { + if(iRot>0) + { + DaughterPDG = DaughterPDG.rotated(1); + DaughterPVIndex = DaughterPVIndex.rotated(1); + DaughterInd = DaughterInd.rotated(1); + trackPdgDaughter = trackPdgDaughter.rotated(1); + + ChargedDaughter.Rotate(); + + activeDaughter = /*( (DaughterPDG != -1) || ( (DaughterPVIndex < 0) && (DaughterPDG == -1) ) ) &&*/ (DaughterInd < DaughterTracksSize); + } + + int_v trackPdgMother; + + if(iTC==0) + activeDaughter &= abs(DaughterPDG)==13; + if(iTC==1) + activeDaughter &= abs(DaughterPDG)==211; + if(iTC==2) + activeDaughter &= abs(DaughterPDG)==321; + if(iTC==3) + activeDaughter &= abs(DaughterPDG)==2212; + if (activeDaughter.isEmpty()) continue; + + + for(int iHypothesis=0; iHypothesis<nMotherHypothesis[iTC]; iHypothesis++) + { + int motherKFPDG = outMotherPDG[iTC][iHypothesis]; + if(iTrTypeDaughter==0) motherKFPDG = -outMotherPDG[iTC][iHypothesis]; + if(!(fDecayReconstructionList.empty()) && (fDecayReconstructionList.find(motherKFPDG) == fDecayReconstructionList.end())) continue; + + int_m active = activeDaughter && (int_v::IndexesFromZero() < int(NTracks)); + + MotherTrack.Load(MotherTracks, iTrM, motherPDGHypothesis[iTC][iHypothesis]); + + float_v zMother = MotherTrack.Z(); + float_v zCD = ChargedDaughter.Z(); + + //daughter particle should start after the last hit of a mother track + active &= simd_cast<int_m>(zCD >= (zMother - float_v(0.5f))); + if( active.isEmpty() ) continue; + + KFParticleSIMD neutralDaughter = MotherTrack; + //energy of the mother particle should be greater then of the daughter particle + active &= simd_cast<int_m>(neutralDaughter.E() > ChargedDaughter.E()); + if( active.isEmpty() ) continue; + + neutralDaughter.AddDaughterId(motherTrackId); + neutralDaughter.NDF() = -1; + neutralDaughter.Chi2() = 0.f; + neutralDaughter.SubtractDaughter(ChargedDaughter); + + //decay point shoud be between mother and daughter tracks + active &= simd_cast<int_m>(neutralDaughter.Z() >= zMother - float_v(10.0f)); + active &= simd_cast<int_m>(neutralDaughter.Z() <= zCD + float_v(10.0f)); + //set cut on chi2 of the fit of the neutral daughter + active &= simd_cast<int_m>(neutralDaughter.NDF() >= int_v(Vc::Zero)); + active &= simd_cast<int_m>(neutralDaughter.Chi2()/simd_cast<float_v>(neutralDaughter.NDF()) <= fCuts2D[1]); + //fit should converge + active &= simd_cast<int_m>(neutralDaughter.Chi2() >= float_v(Vc::Zero)); + active &= simd_cast<int_m>(neutralDaughter.Chi2() == neutralDaughter.Chi2()); + if( active.isEmpty() ) continue; + + //kill particle-candidates produced by clones + active &= simd_cast<int_m>( neutralDaughter.GetRapidity()<6.f && neutralDaughter.GetRapidity()>0.f); + if ((iTC==1 && iHypothesis<4) || iTC==2) + active &= simd_cast<int_m>( !( (neutralDaughter.GetPt())<0.5f && neutralDaughter.GetRapidity()<0.5f ) ); + if (iTC==3) + active &= simd_cast<int_m>( !( (neutralDaughter.GetPt())<0.2f && neutralDaughter.GetRapidity()<1.f ) ); + if( active.isEmpty() ) continue; + + KFParticleSIMD neutralDaughterUnconstr = neutralDaughter; + neutralDaughter.SetNonlinearMassConstraint(neutralDaughterMassHypothesis[iTC][iHypothesis]); + + const KFParticleSIMD* daughters[2] = {&neutralDaughter, &ChargedDaughter}; + KFParticleSIMD mother; + mother.Construct(daughters, 2); + + //decay point shoud be between mother and daughter tracks + active &= simd_cast<int_m>(mother.Z() >= zMother); + active &= simd_cast<int_m>(mother.Z() <= zCD); + //set cut on chi2 of the fit of the mother particle + active &= simd_cast<int_m>(mother.NDF() >= int_v(Vc::Zero)); + active &= simd_cast<int_m>(mother.Chi2()/simd_cast<float_v>(mother.NDF()) <= fCuts2D[1]); + //fit should converge + active &= simd_cast<int_m>(mother.Chi2() >= float_v(Vc::Zero)); + active &= simd_cast<int_m>(mother.Chi2() == mother.Chi2()); + if( active.isEmpty() ) continue; + + for(int iV=0; iV<NTracks; iV++) + { + if(!active[iV]) continue; + + neutralDaughterUnconstr.GetKFParticle(mother_temp, iV); + int neutralId = Particles.size(); + mother_temp.SetId(neutralId); + if (iTrTypeDaughter==0) + mother_temp.SetPDG(-outNeutralDaughterPDG[iTC][iHypothesis]); + else + mother_temp.SetPDG(outNeutralDaughterPDG[iTC][iHypothesis]); + Particles.push_back(mother_temp); + + mother.GetKFParticle(mother_temp, iV); + mother_temp.SetId(Particles.size()); + mother_temp.CleanDaughtersId(); + mother_temp.AddDaughterId(ChargedDaughter.Id()[iV]); + mother_temp.AddDaughterId(neutralId); + + if (iTrTypeDaughter==0) + mother_temp.SetPDG(-outMotherPDG[iTC][iHypothesis]); + else + mother_temp.SetPDG(outMotherPDG[iTC][iHypothesis]); + Particles.push_back(mother_temp); + } + } + }//iRot + }//iTrM + }//iTrD + }//iTC + }//iTrTypeDaughter +} + +void KFParticleFinder::AddCandidate(const KFParticle& candidate, int iPV) +{ + /** Adds an externally found particle to either set of secondary or primary candidates:\n + ** 1) if iPV is negative the candidate is stored to KFParticleFinder::fSecCandidates;\n + ** 2) if iPV is not negative and smaller then the set number of primary vertices and + ** NDF=2 the candidate is stored to KFParticleFinder::fPrimCandidates;\n + ** 3) if iPV is not negative and smaller then the set number of primary vertices and + ** NDF=3 the candidate is stored to KFParticleFinder::fPrimCandidatesTopo;\n + ** 4) if iPV is not negative and smaller then the set number of primary vertices and + ** NDF=4 the candidate is stored to KFParticleFinder::fPrimCandidatesTopoMass.\n + ** Only those particles will be stored which have accepted PDG. Please check the documentation + ** of the corresponding vectors for the list of particles. + ** \param[in] candidate - candidate to be added + ** \param[in] iPV - index of the associated PV + **/ + + //0 Ks, 1 Lambda,2 LambdaBar, 3 gamma, 4 pi0, 5 Xi, 6 XiBar, 7 Omega, 8 OmegaBar, 9 XiStar + int iSet = -1; + if(candidate.GetPDG() == 310) iSet = 0; + if(candidate.GetPDG() == 3122) iSet = 1; + if(candidate.GetPDG() == -3122) iSet = 2; + if(candidate.GetPDG() == 22) iSet = 3; + if(candidate.GetPDG() == 111) iSet = 4; + if(candidate.GetPDG() == 3312) iSet = 5; + if(candidate.GetPDG() == -3312) iSet = 6; + if(candidate.GetPDG() == 3334) iSet = 7; + if(candidate.GetPDG() == -3334) iSet = 8; + + if(iSet > -1) + { + if(iPV >= 0 && iPV<fNPV) + { + if(candidate.NDF() == 2) + fPrimCandidates[iSet][iPV].push_back(candidate); + if(candidate.NDF() == 3) + fPrimCandidatesTopo[iSet][iPV].push_back(candidate); + if(candidate.NDF() == 4) + fPrimCandidatesTopoMass[iSet][iPV].push_back(candidate); + } + else if(iPV < 0) + { + fSecCandidates[iSet].push_back(candidate); + } + } +} + +void KFParticleFinder::SetNPV(int nPV) +{ + /** Sets the number of primary vertices to "nPV", resizes all vectors + ** with primary candidates correspondingly. + ** \param[in] nPV - number of the primary vertices in the event to be set. + **/ + + fNPV = nPV; + + for(int iCandidates=0; iCandidates<fNPrimCandidatesSets; iCandidates++) + { + fPrimCandidates[iCandidates].clear(); + fPrimCandidates[iCandidates].resize(fNPV); + } + + for(int iCandidates=0; iCandidates<fNPrimCandidatesTopoSets; iCandidates++) + { + fPrimCandidatesTopo[iCandidates].clear(); + fPrimCandidatesTopo[iCandidates].resize(fNPV); + + fPrimCandidatesTopoMass[iCandidates].clear(); + fPrimCandidatesTopoMass[iCandidates].resize(fNPV); + } +} diff --git a/external/KFParticle/KFParticle/KFParticleFinder.h b/external/KFParticle/KFParticle/KFParticleFinder.h new file mode 100644 index 0000000000000000000000000000000000000000..1e914489ffdb3dd2b06867da75c82a712a140aa0 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleFinder.h @@ -0,0 +1,460 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +#ifndef KFParticleFinder_h +#define KFParticleFinder_h + +#include "KFParticle.h" +#include "KFParticleSIMD.h" +#include "KFPTrackVector.h" + +#include <vector> +#include <map> + +class KFPEmcCluster; + +/** @class KFParticleFinder + ** @brief Class for reconstruction short-lived particles. + ** @author I.Kisel, M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class reconstructs short-lived particles by combining long-lived + ** and already reconstructed short-lived particles. As an input it requires + ** tracks and primary vertices. All short-lived particles are stored to one + ** array. The default values of cuts are initialised in the constructor. + **/ + +class KFParticleFinder +{ + public: + + KFParticleFinder(); + ~KFParticleFinder() {}; + + void Init(int nPV); + void SetNThreads(short int n) { fNThreads = n;} ///< Sets the number of threads to by run in parallel. Currently not used. + + void FindParticles(KFPTrackVector* vRTracks, kfvector_float* ChiToPrimVtx, + std::vector<KFParticle>& Particles, std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, int nPV); + + void ExtrapolateToPV(std::vector<KFParticle>& vParticles, KFParticleSIMD& PrimVtx); + + inline void ConstructV0(KFPTrackVector* vTracks, + int iTrTypePos, + int iTrTypeNeg, + uint_v& idPosDaughters, + uint_v& idNegDaughters, + int_v& daughterPosPDG, + int_v& daughterNegPDG, + KFParticleSIMD& mother, + KFParticle& mother_temp, + const unsigned short NTracks, + kfvector_floatv& l, + kfvector_floatv& dl, + std::vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* cuts, + const int_v& pvIndex, + const float* secCuts, + const float_v& massMotherPDG, + const float_v& massMotherPDGSigma, + KFParticleSIMD& motherPrimSecCand, + int& nPrimSecCand, + std::vector< std::vector<KFParticle> >* vMotherPrim = 0, + std::vector<KFParticle>* vMotherSec = 0 + ) __attribute__((always_inline)); + + void SaveV0PrimSecCand(KFParticleSIMD& mother, + int& NParticles, + KFParticle& mother_temp, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* secCuts, + std::vector< std::vector<KFParticle> >* vMotherPrim, + std::vector<KFParticle>* vMotherSec); + + void ConstructTrackV0Cand(KFPTrackVector& vTracks, + uint_v& idTracks, + int_v& trackPDG, + KFParticle* vV0[], + KFParticleSIMD& mother, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& motherTopo, + KFParticle& mother_temp, + const unsigned short nElements, + kfvector_floatv& l, + kfvector_floatv& dl, + std::vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float_v* cuts, + const int_v& pvIndex, + const float_v& massMotherPDG, + const float_v& massMotherPDGSigma, + std::vector< std::vector<KFParticle> >* vMotherPrim, + std::vector<KFParticle>* vMotherSec); + + void Find2DaughterDecay(KFPTrackVector* vTracks, kfvector_float* ChiToPrimVtx, + std::vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* cuts, + const float* secCuts, + std::vector< std::vector<KFParticle> >* vMotherPrim, + std::vector<KFParticle>* vMotherSec ); + + void ConstructPrimaryBG(KFPTrackVector* vTracks, + std::vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* cuts, + const float* secCuts, + std::vector< std::vector<KFParticle> >* vMotherPrim, + std::vector<KFParticle>* vMotherSec ); + + void NeutralDaughterDecay(KFPTrackVector* vTracks, std::vector<KFParticle>& Particles); + + void FindTrackV0Decay(std::vector<KFParticle>& vV0, + const int V0PDG, + KFPTrackVector& vTracks, + const int q, + const int firstTrack, + const int lastTrack, + std::vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + int v0PVIndex = -1, + kfvector_float* ChiToPrimVtx = 0, + std::vector< std::vector<KFParticle> >* vMotherPrim = 0, + std::vector<KFParticle>* vMotherSec = 0); + + void SelectParticles(std::vector<KFParticle>& Particles, + std::vector<KFParticle>& vCandidates, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float& cutChi2Topo, + const float& cutLdL, + const float& mass, + const float& massErr, + const float& massCut); + + void CombinePartPart(std::vector<KFParticle>& particles1, + std::vector<KFParticle>& particles2, + std::vector<KFParticle>& Particles, + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> >& PrimVtx, + const float* cuts, + int iPV, + const int MotherPDG, + bool isSameInputPart = 0, + bool saveOnlyPrimary = 1, + std::vector< std::vector<KFParticle> >* vMotherPrim = 0, + std::vector<KFParticle>* vMotherSec = 0, + float massMotherPDG = 0.f, + float massMotherPDGSigma = 0.f); + + //Set Emc clusters containing gammas + void SetEmcClusters(KFPEmcCluster* clusters) { fEmcClusters = clusters; } ///< Set a pointer to the gamma-clusters from the electromagnetic calorimeter. + + // Mixed Event Analysis + void SetMixedEventAnalysis() { fMixedEventAnalysis = 1; } ///< Switch KFParticleFinder to the mixed event mode. + + //Get secondary particles with the mass constraint + /** Returns number of sets of vectors with secondary candidates for different decays. */ + static int GetNSecondarySets() { return fNSecCandidatesSets; } + /** Returns a pointer to array with sets of vectors with secondary candidates for different decays. */ + const std::vector<KFParticle>* GetSecondaryCandidates() const { return fSecCandidates; } + /** Returns a constant reference to the vector with secondary candidates for \f$K_s^0\rightarrow\pi^+\pi^-\f$. **/ + const std::vector<KFParticle>& GetSecondaryK0() const { return fSecCandidates[0]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\Lambda\rightarrow p\pi^-\f$. **/ + const std::vector<KFParticle>& GetSecondaryLambda() const { return fSecCandidates[1]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\overline{\Lambda}\rightarrow \overline{p}\pi^+\f$. **/ + const std::vector<KFParticle>& GetSecondaryAntiLambda() const { return fSecCandidates[2]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\gamma\rightarrow e^+e^-\f$ conversion. **/ + const std::vector<KFParticle>& GetSecondaryGamma() const { return fSecCandidates[3]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\pi^0\rightarrow \gamma\gamma\f$. **/ + const std::vector<KFParticle>& GetSecondaryPi0() const { return fSecCandidates[4]; } + + //Get primary particles with the mass constraint + /** Returns number of sets of vectors with primary candidates for different decays. */ + static int GetNPrimarySets() { return fNPrimCandidatesTopoSets; } + /** Returns a pointer to array with sets of vectors with primary candidates for different decays. */ + const std::vector< std::vector<KFParticle> >* GetPrimaryCandidates() const { return fPrimCandidates; } + /** Returns a constant reference to the vector with primary candidates for \f$K_s^0\rightarrow\pi^+\pi^-\f$. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryK0() const { return fPrimCandidates[0]; } + /** Returns a constant reference to the vector with primary candidates for \f$\Lambda\rightarrow p\pi^-\f$. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryLambda() const { return fPrimCandidates[1]; } + /** Returns a constant reference to the vector with primary candidates for \f$\overline{\Lambda}\rightarrow \overline{p}\pi^+\f$. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryAntiLambda() const { return fPrimCandidates[2]; } + /** Returns a constant reference to the vector with primary candidates for \f$\gamma\rightarrow e^+e^-\f$ conversion. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryGamma() const { return fPrimCandidates[3]; } + /** Returns a constant reference to the vector with primary candidates for \f$\pi^0\rightarrow \gamma\gamma\f$. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryPi0() const { return fPrimCandidates[4]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\Xi^-\rightarrow \Lambda\pi^-\f$. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryXi() const { return fPrimCandidates[5]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\overline{\Xi}^-\rightarrow \overline{\Lambda}\pi^+\f$. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryAntiXi() const { return fPrimCandidates[6]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\Omega^-\rightarrow \Lambda K^-\f$. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryOmega() const { return fPrimCandidates[7]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\overline{\Omega}^-\rightarrow \overline{\Lambda} K^+\f$. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryAntiOmega() const { return fPrimCandidates[8]; } + + //Get primary particles with the topologigal constraint + /** Returns a pointer to array with sets of vectors with primary candidates for different decays with topological constraint set on. */ + const std::vector< std::vector<KFParticle> >* GetPrimaryTopoCandidates() const { return fPrimCandidatesTopo; } + /** Returns a constant reference to the vector with primary candidates for \f$K_s^0\rightarrow\pi^+\pi^-\f$ + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoK0() const { return fPrimCandidatesTopo[0]; } + /** Returns a constant reference to the vector with primary candidates for \f$\Lambda\rightarrow p\pi^-\f$ + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoLambda() const { return fPrimCandidatesTopo[1]; } + /** Returns a constant reference to the vector with primary candidates for \f$\overline{\Lambda}\rightarrow \overline{p}\pi^+\f$ + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoAntiLambda() const { return fPrimCandidatesTopo[2]; } + /** Returns a constant reference to the vector with primary candidates for \f$\gamma\rightarrow e^+e^-\f$ conversion + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoGamma() const { return fPrimCandidatesTopo[3]; } + /** Returns a constant reference to the vector with primary candidates for \f$\pi^0\rightarrow \gamma\gamma\f$ + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoPi0() const { return fPrimCandidatesTopo[4]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\Xi^-\rightarrow \Lambda\pi^-\f$ + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoXi() const { return fPrimCandidatesTopo[5]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\overline{\Xi}^-\rightarrow \overline{\Lambda}\pi^+\f$ + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoAntiXi() const { return fPrimCandidatesTopo[6]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\Omega^-\rightarrow \Lambda K^-\f$ + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoOmega() const { return fPrimCandidatesTopo[7]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\overline{\Omega}^-\rightarrow \overline{\Lambda} K^+\f$ + ** with topological constraint set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoAntiOmega() const { return fPrimCandidatesTopo[8]; } + + //Get primary particles with the topologigal and mass constraint + /** Returns a pointer to array with sets of vectors with primary candidates for different decays with topological and mass constraints set on. */ + const std::vector< std::vector<KFParticle> >* GetPrimaryTopoMassCandidates() const { return fPrimCandidatesTopoMass; } + /** Returns a constant reference to the vector with primary candidates for \f$K_s^0\rightarrow\pi^+\pi^-\f$ + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassK0() const { return fPrimCandidatesTopoMass[0]; } + /** Returns a constant reference to the vector with primary candidates for \f$\Lambda\rightarrow p\pi^-\f$ + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassLambda() const { return fPrimCandidatesTopoMass[1]; } + /** Returns a constant reference to the vector with primary candidates for \f$\overline{\Lambda}\rightarrow \overline{p}\pi^+\f$ + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassAntiLambda() const { return fPrimCandidatesTopoMass[2]; } + /** Returns a constant reference to the vector with primary candidates for \f$\gamma\rightarrow e^+e^-\f$ conversion + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassGamma() const { return fPrimCandidatesTopoMass[3]; } + /** Returns a constant reference to the vector with primary candidates for \f$\pi^0\rightarrow \gamma\gamma\f$ + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassPi0() const { return fPrimCandidatesTopoMass[4]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\Xi^-\rightarrow \Lambda\pi^-\f$ + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassXi() const { return fPrimCandidatesTopoMass[5]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\overline{\Xi}^-\rightarrow \overline{\Lambda}\pi^+\f$ + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassAntiXi() const { return fPrimCandidatesTopoMass[6]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\Omega^-\rightarrow \Lambda K^-\f$ + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassOmega() const { return fPrimCandidatesTopoMass[7]; } + /** Returns a constant reference to the vector with secondary candidates for \f$\overline{\Omega}^-\rightarrow \overline{\Lambda} K^+\f$ + ** with topological and mass constraints set on. **/ + const std::vector< std::vector<KFParticle> >& GetPrimaryTopoMassAntiOmega() const { return fPrimCandidatesTopoMass[8]; } + + void AddCandidate(const KFParticle& candidate, int iPV = -1); + void SetNPV(int nPV); + + //Functionality to change cuts, all cuts have default values set in the constructor + void SetMaxDistanceBetweenParticlesCut(float cut) { fDistanceCut = cut; } ///< Sets cut on the distance between secondary tracks at the DCA point. + void SetLCut(float cut) { fLCut = cut; } ///< Sets cut on the distance to the primary vertex from the decay vertex. + + void SetChiPrimaryCut2D(float cut) { fCuts2D[0] = cut; } ///< Sets cut on \f$\chi^2_{prim}\f$ of each track for 2-daughter decays. + void SetChi2Cut2D(float cut) { fCuts2D[1] = cut; } ///< Sets cut on \f$\chi^2_{geo}\f$ for 2-daughter decays. + void SetLdLCut2D(float cut) { fCuts2D[2] = cut; } ///< Sets cut on \f$l/\Delta l\f$ for 2-daughter decays. + + /** \brief Sets cuts on selection of secondary and primary candidates: \f$\sigma_{M}\f$, \f$\chi^2_{topo}\f$, \f$l/\Delta l\f$. */ + void SetSecondaryCuts(const float sigmaMass = 3.f, const float chi2Topo = 5.f, const float ldl = 10.f) { + fSecCuts[0] = sigmaMass; + fSecCuts[1] = chi2Topo; + fSecCuts[2] = ldl; + } + + void SetLdLCutXiOmega(float cut) { fCutsTrackV0[0][0] = cut; } ///< Sets \f$l/\Delta l\f$ cut for \f$\Xi\f$ and \f$\Omega\f$. + void SetChi2TopoCutXiOmega(float cut) { fCutsTrackV0[0][1] = cut; } ///< Sets \f$\chi^2_{topo}\f$ cut for \f$\Xi\f$ and \f$\Omega\f$. + void SetChi2CutXiOmega(float cut) { fCutsTrackV0[0][2] = cut; } ///< Sets \f$\chi^2_{geo}\f$ cut for \f$\Xi\f$ and \f$\Omega\f$. + + void SetChi2TopoCutResonances(float cut) { fCutsTrackV0[2][1] = cut; } ///< Sets \f$\chi^2_{topo}\f$ cut for resonances. + void SetChi2CutResonances(float cut) { fCutsTrackV0[2][2] = cut; } ///< Sets \f$\chi^2_{geo}\f$ cut for resonances. + + void SetPtCutLMVM(float cut) { fCutLVMPt = cut; } ///< Sets the cut on transverse momentum of each daughter track of low mass vector mesons. + void SetPCutLMVM(float cut) { fCutLVMP = cut; } ///< Sets the cut on momentum of each daughter track of low mass vector mesons in dimuon channel. + void SetPtCutJPsi(float cut) { fCutJPsiPt = cut; } ///< Sets the cut on transverse momentum of each daughter track of \f$J/\psi\f$. + + void SetPtCutCharm(float cut) { fCutCharmPt = cut; } ///< Sets the cut on transverse momentum of each daughter track of open charm particles. + void SetChiPrimaryCutCharm(float cut) { fCutCharmChiPrim = cut; } ///< Sets cut on \f$\chi^2_{prim}\f$ of each track for open charm particles. + void SetLdLCutCharmManybodyDecays(float cut) { fCutsTrackV0[1][0] = cut; } ///< Sets \f$l/\Delta l\f$ cut for open charm with >=3 daughters. + void SetChi2TopoCutCharmManybodyDecays(float cut) { fCutsTrackV0[1][1] = cut; } ///< Sets \f$\chi^2_{topo}\f$ cut for open charm with >=3 daughters. + void SetChi2CutCharmManybodyDecays(float cut) { fCutsTrackV0[1][2] = cut; } ///< Sets \f$\chi^2_{geo}\f$ cut for open charm with >=3 daughters. + + void SetLdLCutCharm2D(float cut) { fCutsCharm[1] = cut; } ///< Sets \f$l/\Delta l\f$ cut for open charm with 2 daughters. + void SetChi2TopoCutCharm2D(float cut) { fCutsCharm[2] = cut; } ///< Sets \f$\chi^2_{topo}\f$ cut for open charm with 2 daughters. + void SetChi2CutCharm2D(float cut) { fCutsCharm[0] = cut; } ///< Sets \f$\chi^2_{geo}\f$ cut for open charm with 2 daughters. + + void CopyCuts(const KFParticleFinder* finder) + { + /** Copies all cuts from the external KFParticleFinder "finder" to the current object. + ** \param[in] finder - constant pointer to the external KFParticleFinder object + **/ + fDistanceCut = finder->fDistanceCut; + fLCut = finder->fLCut; + for(int iCut=0; iCut<3; iCut++) + fCuts2D[iCut] = finder->fCuts2D[iCut]; + for(int iCut=0; iCut<3; iCut++) + fSecCuts[iCut] = finder->fSecCuts[iCut]; + for(int iCut=0; iCut<3; iCut++) + for(int jCut=0; jCut<3; jCut++) + fCutsTrackV0[iCut][jCut] = finder->fCutsTrackV0[iCut][jCut]; + for(int iCut=0; iCut<2; iCut++) + for(int jCut=0; jCut<3; jCut++) + fCutsPartPart[iCut][jCut] = finder->fCutsPartPart[iCut][jCut]; + fCutCharmPt = finder->fCutCharmPt; + fCutCharmChiPrim = finder->fCutCharmChiPrim; + for(int iCut=0; iCut<3; iCut++) + fCutsCharm[iCut] = finder->fCutsCharm[iCut]; + fCutLVMPt = finder->fCutLVMPt; + fCutLVMP = finder->fCutLVMP; + fCutJPsiPt = finder->fCutJPsiPt; + } + + //Functionality to check the cuts + const float GetMaxDistanceBetweenParticlesCut() const { return fDistanceCut; } ///< Returns cut on the distance between secondary tracks at the DCA point. + const float GetLCut() const { return fLCut; } ///< Returns cut on the distance to the primary vertex from the decay vertex. + + const float GetChiPrimaryCut2D() const { return fCuts2D[0]; } ///< Returns cut on \f$\chi^2_{prim}\f$ of each track for 2-daughter decays. + const float GetChi2Cut2D() const { return fCuts2D[1]; } ///< Returns cut on \f$\chi^2_{geo}\f$ for 2-daughter decays. + const float GetLdLCut2D() const { return fCuts2D[2]; } ///< Returns cut on \f$l/\Delta l\f$ for 2-daughter decays. + + const float GetSecondarySigmaMassCut() const { return fSecCuts[0]; } ///< Returns \f$\sigma_{M}\f$ cut for selection of primary and secondary candidates. + const float GetSecondaryChi2TopoCut() const { return fSecCuts[1]; } ///< Returns \f$\chi^2_{topo}\f$ cut for selection of primary and secondary candidates. + const float GetSecondaryLdLCut() const { return fSecCuts[2]; } ///< Returns \f$l/\Delta l\f$ cut for selection of primary and secondary candidates. + + const float GetLdLCutXiOmega() const { return fCutsTrackV0[0][0]; } ///< Returns \f$l/\Delta l\f$ cut for \f$\Xi\f$ and \f$\Omega\f$. + const float GetChi2TopoCutXiOmega() const { return fCutsTrackV0[0][1]; } ///< Returns \f$\chi^2_{topo}\f$ cut for \f$\Xi\f$ and \f$\Omega\f$. + const float GetChi2CutXiOmega() const { return fCutsTrackV0[0][2]; } ///< Returns \f$\chi^2_{geo}\f$ cut for \f$\Xi\f$ and \f$\Omega\f$. + + const float GetChi2TopoCutResonances() const { return fCutsTrackV0[2][1]; } ///< Returns \f$\chi^2_{topo}\f$ cut for resonances. + const float GetChi2CutResonances() const { return fCutsTrackV0[2][2]; } ///< Returns \f$\chi^2_{geo}\f$ cut for resonances. + + const float GetPtCutLMVM() const { return fCutLVMPt; } ///< Returns cut on transverse momentum of each daughter track of low mass vector mesons. + const float GetPCutLMVM() const { return fCutLVMP; } ///< Returns cut on momentum of each daughter track of low mass vector mesons in dimuon channel. + const float GetPtCutJPsi() const { return fCutJPsiPt; } ///< Returns cut on transverse momentum of each daughter track of \f$J/\psi\f$. + + const float GetPtCutCharm() const { return fCutCharmPt; } ///< Returns the cut on transverse momentum of each daughter track of open charm particles. + const float GetChiPrimaryCutCharm() const { return fCutCharmChiPrim; } ///< Returns cut on \f$\chi^2_{prim}\f$ of each track for open charm particles. + const float GetLdLCutCharmManybodyDecays() const { return fCutsTrackV0[1][0]; } ///< Returns \f$l/\Delta l\f$ cut for open charm with >=3 daughters. + const float GetChi2TopoCutCharmManybodyDecays() const { return fCutsTrackV0[1][1]; } ///< Returns \f$\chi^2_{topo}\f$ cut for open charm with >=3 daughters. + const float GetChi2CutCharmManybodyDecays() const { return fCutsTrackV0[1][2]; } ///< Returns \f$\chi^2_{geo}\f$ cut for open charm with >=3 daughters. + + const float GetLdLCutCharm2D() const { return fCutsCharm[1]; } ///< Returns \f$l/\Delta l\f$ cut for open charm with 2 daughters. + const float GetChi2TopoCutCharm2D() const { return fCutsCharm[2]; } ///< Returns \f$\chi^2_{topo}\f$ cut for open charm with 2 daughters. + const float GetChi2CutCharm2D() const { return fCutsCharm[0]; } ///< Returns \f$\chi^2_{geo}\f$ cut for open charm with 2 daughters. + + /** Add decay to the reconstruction list. If at least one is added - only those channels are considered which are in the list. Otherwise + ** all decays are reconstructed. + ** \param[in] pdg - PDG code of the decay which should be reconstructed + **/ + void AddDecayToReconstructionList(int pdg) { fDecayReconstructionList[pdg] = true; } + const std::map<int,bool> GetReconstructionList() const { return fDecayReconstructionList; } ///< Returns list of decays to be reconstructed. + void SetReconstructionList(const std::map<int,bool>& decays) { fDecayReconstructionList = decays; } ///< Set enitre reconstruction list + + private: + + short int fNPV; ///< Number of primary vertex candidates in the event. + short int fNThreads; ///< Number of threads to be run in parallel. Currently is not used. + + float fDistanceCut; ///< Cut on the distance between secondary tracks at the DCA point, is soft and used to speed up the algorithm only. + float fLCut; ///< Cut on the distance to the primary vertex from the decay vertex. Is applied to \f$K^0_s\f$, \f$\Lambda\f$, \f$\Xi\f$, \f$\Omega\f$, hypernuclei and dibaryons. + + float fCuts2D[3]; ///< Cuts on 2-daughter decays: \f$\chi^2_{prim}\f$, \f$\chi^2_{geo}\f$, \f$l/\Delta l\f$ + float fSecCuts[3]; ///< Cuts to select secondary and primary particle candidates: \f$\sigma_{M}\f$, \f$\chi^2_{topo}\f$, \f$l/\Delta l\f$ + /** \brief Cuts on the combination of track and short-lived particle candidate: \f$l/\Delta l\f$, \f$\chi^2_{topo}\f$, \f$\chi^2_{geo}\f$. + ** Three sets of cuts are defined: 1) for \f$\Xi\f$ and \f$\Omega\f$, 2) for hypernuclei and open charm, 3) for resonances. **/ + float fCutsTrackV0[3][3]; + /** \brief Cuts on the combination of two short-lived particle candidates: \f$l/\Delta l\f$, \f$\chi^2_{topo}\f$, \f$\chi^2_{geo}\f$. + ** Two sets are defined: 1) for particles that fly away from the primary vertex and 2) for resonances. **/ + float fCutsPartPart[2][3]; + + //cuts on open charm particles with 2 daughters + float fCutCharmPt; ///< Cut on transverse momentum of the track for open charm reconstruction. + float fCutCharmChiPrim; ///< Cut on the \f$\chi^2_{prim}\f$ deviation of the track from the primary vertex for open charm reconstruction. + float fCutsCharm[3]; ///< Cuts on reconstructed 2-daughter charm candidates: \f$\chi^2_{geo}\f$, \f$l/\Delta l\f$, \f$\chi^2_{topo}\f$. + + //cuts on LVM + float fCutLVMPt; ///< Cut on transverse momentum of daughter tracks for low mass vector mesons. + float fCutLVMP; ///< Cut on momentum of low mass vector mesons in dimuon channel. + + //cuts on J/Psi + float fCutJPsiPt; ///< Cut on transverse momentum of daughter tracks for \f$J/\psi\f$. + + //vectors with temporary particles for charm reconstruction + std::vector<KFParticle> fD0; ///<Vector with temporary D0->K-pi+ candidates. + std::vector<KFParticle> fD0bar; ///<Vector with temporary D0_bar->K+pi- candidates. + std::vector<KFParticle> fD04; ///<Vector with temporary D0->K-pi+pi+pi- candidates. + std::vector<KFParticle> fD04bar; ///<Vector with temporary D0_bar->K+pi+pi-pi- candidates. + std::vector<KFParticle> fD0KK; ///<Vector with temporary D0->K+K- candidates. + std::vector<KFParticle> fD0pipi; ///<Vector with temporary D0->pi+pi- candidates. + std::vector<KFParticle> fDPlus; ///<Vector with temporary D+->K-pi+pi+ candidates. + std::vector<KFParticle> fDMinus; ///<Vector with temporary D-->K+pi-pi- candidates. + std::vector<KFParticle> fDPlus3Pi; ///<Vector with temporary D+->pi+pi+pi- candidates. + std::vector<KFParticle> fDMinus3Pi; ///<Vector with temporary D-->pi+pi-pi- candidates. + std::vector<KFParticle> fDsPlusK2Pi; ///<Vector with temporary Ds+->K+pi+pi- candidates. + std::vector<KFParticle> fDsMinusK2Pi;///<Vector with temporary Ds-->K-pi+pi- candidates. + std::vector<KFParticle> fLcPlusP2Pi; ///<Vector with temporary Lambda_c->p pi+pi- candidates. + std::vector<KFParticle> fLcMinusP2Pi;///<Vector with temporary Lambda_c_bar->p-pi+pi- candidates. + + //vectors with temporary particles for H0 + std::vector<KFParticle> fLPi; ///< Temporary Lambda pi+ combinations + std::vector<int> fLPiPIndex; ///< Index of the proton in Labmda for Lambda pi+ combinations + std::vector<KFParticle> fHe3Pi; ///< Temporary He3+ pi- combinations + std::vector<KFParticle> fHe3PiBar; ///< Temporary He3- pi+ combinations + std::vector<KFParticle> fHe4Pi; ///< Temporary He4+ pi- combinations + std::vector<KFParticle> fHe4PiBar; ///< Temporary He4- pi+ combinations + std::vector<KFParticle> fHe4L; ///< Vector with temporary He4_Lambda->He3 p pi- candidates + std::vector<KFParticle> fHe5L; ///< Vector with temporary He4_Lambda->He4 p pi- candidates + std::vector<KFParticle> fLLn; ///< Vector with temporary H3_Lambda pi- candidates + std::vector<KFParticle> fH5LL; ///< Vector with temporary H5_LL->He5_Lambda pi- candidates + + //vectors of candidates with the mass constraint + static const int fNSecCandidatesSets = 5; ///< Number of sets of secondary particle candidates. + /** \brief Array of vectors with secondary candidates: 0) \f$K_s^0\f$, 1) \f$\Lambda\f$, 2) \f$\overline{\Lambda}\f$, 3) \f$\gamma\f$, 4) \f$\pi^0\f$. */ + std::vector<KFParticle> fSecCandidates[fNSecCandidatesSets]; + static const int fNPrimCandidatesSets = 11; ///< Number of sets of primary particle candidates. + /** \brief Array of vectors with primary candidates for each primary vertex: + ** 0) \f$K_s^0\f$, 1) \f$\Lambda\f$, 2) \f$\overline{\Lambda}\f$, 3) \f$\gamma\f$, 4) \f$\pi^0\f$, + ** 5) \f$\Xi^-\f$, 6) \f$\overline{\Xi}^+\f$, 7) \f$\Omega^-\f$, 8) \f$\overline{\Omega}^+\f$, 9) \f$\Xi^{0*}\f$, 10) \f$\overline{\Xi}^{0*}\f$. */ + std::vector< std::vector<KFParticle> > fPrimCandidates[fNPrimCandidatesSets]; // + static const int fNPrimCandidatesTopoSets = 9; ///< Number of sets of primary particle candidates with topological constraint. + /** \brief Array of vectors with primary candidates for each primary vertex with a topological constraint set: + ** 0) \f$K_s^0\f$, 1) \f$\Lambda\f$, 2) \f$\overline{\Lambda}\f$, 3) \f$\gamma\f$, 4) \f$\pi^0\f$, + ** 5) \f$\Xi^-\f$, 6) \f$\overline{\Xi}^+\f$, 7) \f$\Omega^-\f$, 8) \f$\overline{\Omega}^+\f$. */ + std::vector< std::vector<KFParticle> > fPrimCandidatesTopo[fNPrimCandidatesTopoSets]; + /** \brief Array of vectors with primary candidates for each primary vertex with a topological and mass constraints set: + ** 0) \f$K_s^0\f$, 1) \f$\Lambda\f$, 2) \f$\overline{\Lambda}\f$, 3) \f$\gamma\f$, 4) \f$\pi^0\f$, + ** 5) \f$\Xi^-\f$, 6) \f$\overline{\Xi}^+\f$, 7) \f$\Omega^-\f$, 8) \f$\overline{\Omega}^+\f$. */ + std::vector< std::vector<KFParticle> > fPrimCandidatesTopoMass[fNPrimCandidatesTopoSets]; + + KFPEmcCluster* fEmcClusters; ///< Pointer to the input gamma-clusters from the electromagnetic calorimeter. + + bool fMixedEventAnalysis; ///< Flag defines if the mixed event analysis is run. In mixed event mode limited number of decays is reconstructed. + + /** \brief Map defines if the reconstruction of the decay with a certain PDG hypothesis should be run. If the map is empty - all decays are reconstructed. If at least one decay is added - only those decays will be reconstructed which are specified in the list. **/ + std::map<int,bool> fDecayReconstructionList; + + KFParticleFinder(const KFParticleFinder&); ///< Copying is disabled for this class. + KFParticleFinder& operator=(const KFParticleFinder&); ///< Copying is disabled for this class. +}; + +#endif /* !KFParticleFinder_h */ + diff --git a/external/KFParticle/KFParticle/KFParticlePVReconstructor.cxx b/external/KFParticle/KFParticle/KFParticlePVReconstructor.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a2e7a93afd2069a8dc623fc8d4f0846018c9eac5 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticlePVReconstructor.cxx @@ -0,0 +1,359 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFParticlePVReconstructor.h" +#include "KFPTrackVector.h" +#include "KFParticle.h" + +using std::vector; + +void KFParticlePVReconstructor::Init(KFPTrackVector *tracks, int nParticles) +{ + /** The function initialises an input for the search of primary vertices:\n + ** 1) it receives as an input an array with tracks;\n + ** 2) tracks are converted to KFParticle objects assuming pion mass;\n + ** 3) the position of the primary vertex is estimated with simplified + ** Kalman filter equations using all tracks; \n + ** 4) tracks are checked to deviate from the obtained estimation within + ** KFParticlePVReconstructor::fChi2CutPreparation; \n + ** 5) from the selected tracks a more precise estimation is obtained + ** using KFVertex::ConstructPrimaryVertex() with soft cut + ** KFParticlePVReconstructor::fChi2CutPreparation; \n + ** 6) input particles are transported to the DCA point with the obtained + ** estimation;\n + ** 7) the weight for each particle is calculated according to its errors, + ** if errors are not defined after extrapolation or if particle 10 cm + ** away from the {0,0,0} point the weight of -100 is assigned. + ** \param[in] tracks - a pointer to the KFPTrackVector with input tracks + ** \param[in] nParticles - number of the input tracks + **/ + + fNParticles = nParticles; + fParticles.resize(fNParticles); + fWeight.resize(fNParticles); + + float C[3] = {0,0,0}; + int nC[3] = {0,0,0}; + + KFPTrack track; + for ( int iTr = 0; iTr < fNParticles; iTr++ ) { + tracks->GetTrack(track,iTr); + fParticles[iTr] = KFParticle( track, 211 ); + fParticles[iTr].AddDaughterId(track.Id()); + float zeroPoint[3]{0,0,0}; + fParticles[iTr].TransportToPoint(zeroPoint); + + for(int iC=0; iC<3; iC++) + { + if(!(fParticles[0].Covariance(iC,iC)==fParticles[0].Covariance(iC,iC))) continue; + if(fParticles[0].Covariance(iC,iC) < 10.f && fParticles[0].Covariance(iC,iC) > 0.f ) + { + C[iC] += fParticles[0].Covariance(iC,iC); + nC[iC]++; + } + } + } + + fPrimVertices.clear(); + fClusters.clear(); + + float pvEstimation[3] = {0.}; + float pvEstimationTr[3] = {0.}; + + float parTmp[8] = {0.}; + float covTmp[36] = {0.}; + + for(int iC=0; iC<3; iC++) + { + if(nC[iC] >0) + C[iC] /= nC[iC]; + else + C[iC] = 1.e-2; + } + + for(int iIter=0; iIter<3; iIter++) + { + C[0]*=100.f; C[1]*=100.f; C[2]*=100.f; + for ( int iTr = 0; iTr < fNParticles; iTr++ ) { + float ds = 0.f; + float dsdr[6] = {0.f}; + if(iIter>0) + ds = fParticles[iTr].GetDStoPoint(pvEstimationTr, dsdr); + fParticles[iTr].Transport( ds, dsdr, parTmp, covTmp); + + float r2 = parTmp[0]*parTmp[0] + parTmp[1]*parTmp[1]; + if(!(r2==r2)) continue; + if(r2 > 25 ) continue; + + const float V[3] = {covTmp[0], covTmp[2], covTmp[5]}; + + for(int iComp=0; iComp<3; iComp++) + { + float K = C[iComp]/(C[iComp]+V[iComp]); + if (fabs(V[iComp]) < 1.e-8) continue; + if(C[iComp] > 16*V[iComp]) + K = 1.f - V[iComp]/C[iComp]; + const float dzeta = parTmp[iComp]-pvEstimation[iComp]; + if(K!=K) continue; + if(K<0. || K>0.999) continue; + pvEstimation[iComp] += K*dzeta; + C[iComp] -= K*C[iComp]; + } + } + pvEstimationTr[0] = pvEstimation[0]; + pvEstimationTr[1] = pvEstimation[1]; + pvEstimationTr[2] = pvEstimation[2]; + } + + for(int iP=0; iP<fNParticles; iP++) + { + fParticles[iP].TransportToPoint(pvEstimation); + + fWeight[iP] = fParticles[iP].CovarianceMatrix()[0] + + fParticles[iP].CovarianceMatrix()[2] + fParticles[iP].CovarianceMatrix()[5]; + + if(fWeight[iP] > 0.f) + fWeight[iP] = 1.f/sqrt(fWeight[iP]); + else + fWeight[iP] = -100; + + if( (fParticles[iP].X()*fParticles[iP].X() + fParticles[iP].Y()*fParticles[iP].Y()) > 100.f ) fWeight[iP] = -100.f; + } +} // void KFParticlePVReconstructor::Init + +void KFParticlePVReconstructor::FindPrimaryClusters( int cutNDF ) +{ + /** The functions searches for a set of clusters of particles - candidates for the primary + ** vertex:\n + ** 1) input particles are assumed to be transported to the beam line or target position;\n + ** 2) at first, the best particle with the highest weight is selected;\n + ** 3) then a cluster is formed around this particle;\n + ** 4) if a beam line is set it is used for the reconstruction as an additional track, + ** but will not be added to the resulting cluster of daughter particles;\n + ** 5) the primary vertex candidate is fitted with KFVertex::ConstructPrimaryVertex() + ** using KFParticlePVReconstructor::fChi2Cut;\n + ** 6) cluster is cleaned from particles deviating more then the fChi2Cut from the fitted + ** candidate;\n + ** 7) the cluster and the vertex candidate are stored if they satisfy the provided cutNDF;\n + ** 8) the procedure is repeated until not used tracks with well-defined weight are left. + ** + ** \param[in] cutNDF - cut on the number of degrees of freedom (effectively - number of + ** particles used for the reconstruction), if resulting NDF is smaller then this cut - + ** the PV-candidate is rejected + **/ + + if( IsBeamLine() ) + cutNDF += 2; + + vector<unsigned short int> notUsedTracks(fNParticles); + vector<unsigned short int> *notUsedTracksPtr = ¬UsedTracks; + int nNotUsedTracks = fNParticles; + + vector<unsigned short int> notUsedTracksNew(fNParticles); + vector<unsigned short int> *notUsedTracksNewPtr = ¬UsedTracksNew; + int nNotUsedTracksNew = 0; + + for(int iTr=0; iTr<fNParticles; iTr++) + (*notUsedTracksPtr)[iTr] = iTr; + + while(nNotUsedTracks>0) + { + short int bestTrack = 0; + float bestWeight = -1.f; + + for(unsigned short int iTr = 0; iTr < nNotUsedTracks; iTr++) + { + unsigned short int &curTrack = (*notUsedTracksPtr)[iTr]; + + if (fWeight[curTrack] > bestWeight) + { + bestWeight = fWeight[curTrack]; + bestTrack = curTrack; + } + } + + if(bestWeight < 0.f) break; + + KFParticleCluster cluster; + cluster.fTracks.reserve(nNotUsedTracks); + + const float *rBest = fParticles[bestTrack].Parameters(); + const float *covBest = fParticles[bestTrack].CovarianceMatrix(); + + float rVertex[3] = {0.f}; + float covVertex[6] = {0.f}; + float weightVertex = 0.f; + + for(unsigned short int iTr = 0; iTr < nNotUsedTracks; iTr++) + { + unsigned short int &curTrack = (*notUsedTracksPtr)[iTr]; + float chi2deviation = fParticles[curTrack].GetDeviationFromVertex(rBest, covBest); + if( ( chi2deviation < fChi2CutPreparation && chi2deviation >= 0 && fWeight[curTrack] > -1.f) || curTrack == bestTrack) + { + for(int iP=0; iP<3; iP++) + rVertex[iP] += fWeight[curTrack] * fParticles[curTrack].Parameters()[iP]; + + float weight2 = fWeight[curTrack] * fWeight[curTrack]; + for(int iC=0; iC<6; iC++) + covVertex[iC] += weight2 *fParticles[curTrack].CovarianceMatrix()[iC]; + + weightVertex += fWeight[curTrack]; + cluster.fTracks.push_back(curTrack); + } + else + { + (*notUsedTracksNewPtr)[nNotUsedTracksNew] = curTrack; + nNotUsedTracksNew++; + } + } + + vector<unsigned short int> *notUsedTracksPtrSave = notUsedTracksPtr; + notUsedTracksPtr = notUsedTracksNewPtr; + notUsedTracksNewPtr = notUsedTracksPtrSave; + + nNotUsedTracks = nNotUsedTracksNew; + nNotUsedTracksNew = 0; + + if(cluster.fTracks.size() < 2) continue; + if((cluster.fTracks.size() < 3) && (fNParticles>3)) continue; + + for(int iP=0; iP<3; iP++) + cluster.fP[iP] = rVertex[iP]/weightVertex; + + for(int iC=0; iC<6; iC++) + cluster.fC[iC] = covVertex[iC]/(weightVertex*weightVertex); + + + int nPrimCand = cluster.fTracks.size(); // 1 is reserved for a beam line + int nTracks = cluster.fTracks.size(); + + const KFParticle **pParticles = new const KFParticle*[nPrimCand+1]; // tmp array + + for ( int iP = 0; iP < nPrimCand; iP++ ) + pParticles[iP] = &fParticles[ cluster.fTracks[iP] ]; + + if( IsBeamLine() ) + { + pParticles[nPrimCand] = &fBeamLine; + nPrimCand++; + } + + + // find prim vertex + KFVertex primVtx; + + if(fNParticles>1) + { + // construct PV candidate from a cluster + bool *vFlags = new bool[nPrimCand]; // flags returned by the vertex finder + for(int iFl=0; iFl<nPrimCand; iFl++) + vFlags[iFl] = true; +// primVtx.SetVtxGuess(cluster.fP[0], cluster.fP[1], cluster.fP[2]); + primVtx.SetConstructMethod(0); + primVtx.ConstructPrimaryVertex( pParticles, nPrimCand, vFlags, fChi2Cut ); + + // clean cluster + vector<int> clearClusterInd; + clearClusterInd.reserve(cluster.fTracks.size()); + for ( int iP = 0; iP < nTracks; iP++ ){ + if(cluster.fTracks[iP] == bestTrack) { + clearClusterInd.push_back(cluster.fTracks[iP]); + continue; + } + if(vFlags[iP]) + clearClusterInd.push_back(cluster.fTracks[iP]); + else + { + (*notUsedTracksPtr)[nNotUsedTracks] = cluster.fTracks[iP]; + nNotUsedTracks++; + } + } + + for(unsigned short int iTr = 0; iTr < nNotUsedTracks; iTr++) + { + unsigned short int &curTrack = (*notUsedTracksPtr)[iTr]; + if( fParticles[curTrack].GetDeviationFromVertex(primVtx)<fChi2Cut ) + { + primVtx += fParticles[curTrack]; + clearClusterInd.push_back(curTrack); + } + else + { + (*notUsedTracksNewPtr)[nNotUsedTracksNew] = curTrack; + nNotUsedTracksNew++; + } + } + cluster.fTracks = clearClusterInd; + + notUsedTracksPtrSave = notUsedTracksPtr; + notUsedTracksPtr = notUsedTracksNewPtr; + notUsedTracksNewPtr = notUsedTracksPtrSave; + + nNotUsedTracks = nNotUsedTracksNew; + nNotUsedTracksNew = 0; + + // save PV +#ifdef CBM + if( primVtx.GetNDF() >= cutNDF && ((cluster.fTracks.size()>0.1f*fNParticles && fNParticles > 30) || fNParticles<=30 ) ) //at least 2 particles +#else + if( primVtx.GetNDF() >= cutNDF) +#endif + { + fPrimVertices.push_back(primVtx); + fClusters.push_back(cluster); + } + + if(vFlags) delete [] vFlags; + } + if(pParticles) delete [] pParticles; + } +} + +void KFParticlePVReconstructor::ReconstructPrimVertex() +{ + /** Reconstructs primary vertices and corresponding clusters of tracks. + ** For this it calls KFParticlePVReconstructor::FindPrimaryClusters(), + ** if no vertex is found empty primary vertex is used. + **/ + + FindPrimaryClusters(); + + if ( fPrimVertices.size() == 0 ) + { + float X=0,Y=0,Z=0; + + KFPVertex primVtx_tmp; + primVtx_tmp.SetXYZ(X, Y, Z); + primVtx_tmp.SetCovarianceMatrix( 0, 0, 0, 0, 0, 0 ); + primVtx_tmp.SetNContributors(0); + primVtx_tmp.SetChi2(-100); + + fPrimVertices.push_back(primVtx_tmp); + + KFParticleCluster cluster; + fClusters.push_back(cluster); + } +} + +void KFParticlePVReconstructor::AddPV(const KFVertex &pv, const vector<int> &tracks) +{ + fPrimVertices.push_back(pv); + KFParticleCluster cluster; + cluster.fTracks = tracks; + fClusters.push_back(cluster); +} + +void KFParticlePVReconstructor::AddPV(const KFVertex &pv) +{ + fPrimVertices.push_back(pv); + KFParticleCluster cluster; + fClusters.push_back(cluster); +} diff --git a/external/KFParticle/KFParticle/KFParticlePVReconstructor.h b/external/KFParticle/KFParticle/KFParticlePVReconstructor.h new file mode 100644 index 0000000000000000000000000000000000000000..c59ace9680c859d79e13f7b76749bd6a33b1fd19 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticlePVReconstructor.h @@ -0,0 +1,107 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +#ifndef KFParticlePVReconstructor_H +#define KFParticlePVReconstructor_H + +#include "KFVertex.h" +#include "assert.h" + +#include <vector> + +class KFParticle; +class KFPTrackVector; + +/** @class KFParticlePVReconstructor + ** @brief Class for reconstruction of primary vertices. + ** @author I.Kisel, M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is based on KFVertex. For reconstruction of primary vertices + ** the Kalman filter mathematics is used. Allows reconstruction of multiple + ** primary vertices. + **/ + +class KFParticlePVReconstructor{ + public: + KFParticlePVReconstructor():fParticles(0), fNParticles(0), fWeight(0.f), fBeamLine(), fIsBeamLine(0), fClusters(0), fPrimVertices(0), fChi2CutPreparation(100), fChi2Cut(16) {}; + ~KFParticlePVReconstructor(){}; + + void Init(KFPTrackVector *tracks, int nParticles); + + void ReconstructPrimVertex(); + + int NPrimaryVertices() const { return fPrimVertices.size(); } ///< Returns number of the found candidates for the primary vertex. + KFParticle &GetPrimVertex(int iPV=0) { return fPrimVertices[iPV]; } ///< Returns primary vertex candidate in KFParticle with index "iPV". + KFVertex &GetPrimKFVertex(int iPV=0) { return fPrimVertices[iPV]; } ///< Returns primary vertex candidate in KFVertex with index "iPV". + std::vector<int>& GetPVTrackIndexArray(int iPV=0) { return fClusters[iPV].fTracks; } ///< Returns vector with track indices from a cluster with index "iPV". + KFParticle &GetParticle(int i){ assert( i < fNParticles ); return fParticles[i]; } ///< Returns input particle with index "i". + + void SetBeamLine(KFParticle& p) { fBeamLine = p; fIsBeamLine = 1; } ///< Sets the beam line position and direction, sets corresponding flag to "true". + bool IsBeamLine() const { return fIsBeamLine; } ///< Check if the beam line is set. + + /** Adds externally found primary vertex to the list together with the cluster of + ** tracks from this vertex. + ** \param[in] pv - external primary vertex + ** \param[in] tracks - vector with indices of tracks associated with the provided primary vertex. + **/ + void AddPV(const KFVertex &pv, const std::vector<int> &tracks); + /** Adds externally found primary vertex to the list. + ** \param[in] pv - external primary vertex + **/ + void AddPV(const KFVertex &pv); + void CleanPV() { fClusters.clear(); fPrimVertices.clear(); } ///< Clean vectors with primary vertex candidates and corresponding clusters. + + /** \brief Sets cut fChi2Cut on chi2-deviation of primary tracks from the vertex candidate to "chi2" + ** and a soft preparation cut fChi2CutPreparation to "10*chi2". */ + void SetChi2PrimaryCut(float chi2) { fChi2Cut = chi2; fChi2CutPreparation = chi2*5; } + + private: + KFParticlePVReconstructor &operator=(KFParticlePVReconstructor &); ///< Is not defined. Deny copying of the objects of this class. + KFParticlePVReconstructor(KFParticlePVReconstructor &); ///< Is not defined. Deny copying of the objects of this class. + + void FindPrimaryClusters( int cutNDF = 1); + + std::vector<KFParticle> fParticles; ///< Array of the input particles constructed from tracks. + int fNParticles; ///< Number of the input particles. + + std::vector<float> fWeight; ///< Vector with weights of each track, the weight is defined in KFParticlePVReconstructor::Init(). + + KFParticle fBeamLine; ///< Position and direction of the beam line. + bool fIsBeamLine; ///< Flag showing if the beam line is set. + + /** @class KFParticleCluster + ** @brief A helper structure for reconstruction of a primary vertex. + ** @author I.Kisel, M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** Contains a list of track and initial approximation for the vertex position, + ** which are then provided to KFVertex object for fit. + **/ + struct KFParticleCluster { + KFParticleCluster():fTracks(0) {}; + std::vector<int> fTracks; ///< List of tracks in a cluster. + float fP[3]; ///< Estimation of the vertex position based on the current cluster: {X, Y, Z}. + float fC[6]; ///< Estimated errors of the position approximation. + }; + + std::vector< KFParticleCluster > fClusters; ///< Vector with clusters to be used for fit of a primary vertex. + std::vector<KFVertex> fPrimVertices; ///< Vector with reconstructed candidates for a primary vertex. + + float fChi2CutPreparation; ///< A soft cut on the chi2-deviation which is used to form a cluster. + float fChi2Cut; ///< Cut on the chi2-deviation of the tracks to the primary vertex \see KFVertex::ConstructPrimaryVertex(), where it is used. +}; // class KFParticlePVReconstructor + + +#endif // KFParticlePVReconstructor_H + diff --git a/external/KFParticle/KFParticle/KFParticleSIMD.cxx b/external/KFParticle/KFParticle/KFParticleSIMD.cxx new file mode 100644 index 0000000000000000000000000000000000000000..994fdffe68cef0c69367aadefc22424f286ad51a --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleSIMD.cxx @@ -0,0 +1,1036 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + + +#include "KFParticleSIMD.h" +#include "KFParticle.h" +#include "KFParticleDatabase.h" + +#ifdef HomogeneousField +float_v KFParticleSIMD::fgBz = -5.f; //* Bz compoment of the magnetic field +#endif + +KFParticleSIMD::KFParticleSIMD( const KFParticleSIMD &d1, const KFParticleSIMD &d2 ): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructs a particle from two input daughter particles + ** \param[in] d1 - the first daughter particle + ** \param[in] d2 - the second daughter particle + **/ + + KFParticleSIMD mother; + mother+= d1; + mother+= d2; + *this = mother; +} + +void KFParticleSIMD::Create( const float_v Param[], const float_v Cov[], int_v Charge, float_v mass /*Int_t PID*/ ) +{ + /** Constructor from a "cartesian" track, mass hypothesis should be provided + ** + ** \param[in] Param[6] = { X, Y, Z, Px, Py, Pz } - position and momentum + ** \param[in] Cov[21] - lower-triangular part of the covariance matrix:@n + ** \verbatim + ( 0 . . . . . ) + ( 1 2 . . . . ) + Cov[21] = ( 3 4 5 . . . ) + ( 6 7 8 9 . . ) + ( 10 11 12 13 14 . ) + ( 15 16 17 18 19 20 ) + \endverbatim + ** \param[in] Charge - charge of the particle in elementary charge units + ** \param[in] mass - the mass hypothesis + **/ + + float_v C[21]; + for( int i=0; i<21; i++ ) C[i] = Cov[i]; + + KFParticleBaseSIMD::Initialize( Param, C, Charge, mass ); +} + +KFParticleSIMD::KFParticleSIMD( const KFPTrack *track, Int_t PID ): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructor of the particle from an array of tracks. + ** \param[in] track - pointer to the array of n=float_vLen tracks + ** \param[in] PID - the PID hypothesis common for all elements of the SIMD vector + **/ + + Double_t r[3]; + Double_t C[21]; + + for(Int_t iPart = 0; iPart<float_vLen; iPart++) + { + track[iPart].XvYvZv(r); + for(Int_t i=0; i<3; i++) + fP[i][iPart] = r[i]; + track[iPart].PxPyPz(r); + for(Int_t i=0; i<3; i++) + fP[i+3][iPart] = r[i]; + fQ[iPart] = track[iPart].Charge(); + track[iPart].GetCovarianceXYZPxPyPz( C ); + for(Int_t i=0; i<21; i++) + fC[i][iPart] = C[i]; + } + + float_v mass = KFParticleDatabase::Instance()->GetMass(PID); + Create(fP,fC,fQ,mass); + + for(Int_t iPart = 0; iPart<float_vLen; iPart++) + { + fChi2[iPart] = track[iPart].GetChi2(); + fNDF[iPart] = track[iPart].GetNDF(); + } +} + +KFParticleSIMD::KFParticleSIMD(KFPTrack &Track, const Int_t *pdg): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructor of the particle from a single track. The same track is put to each element of the SIMD vector. + ** \param[in] Track - track in the KFPTrack format + ** \param[in] PID - the PID hypothesis common for all elements of the SIMD vector + **/ + + Double_t r[3]; + Double_t C[21]; + + Track.XvYvZv(r); + for(Int_t i=0; i<3; i++) + fP[i] = r[i]; + Track.PxPyPz(r); + for(Int_t i=0; i<3; i++) + fP[i+3] = r[i]; + fQ = Track.Charge(); + Track.GetCovarianceXYZPxPyPz( C ); + for(Int_t i=0; i<21; i++) + fC[i] = C[i]; + + float_v mass = KFParticleDatabase::Instance()->GetMass(*pdg); + Create(fP,fC,fQ,mass); + + fChi2 = Track.GetChi2(); + fNDF = Track.GetNDF(); +} + +KFParticleSIMD::KFParticleSIMD(KFPTrackVector &track, int n, const Int_t *pdg): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructor of the particle from a single track with index "n" stored in the KFPTrackVector format. + ** The same track is put to each element of the SIMD vector. + ** \param[in] track - an array with tracks in the KFPTrackVector format + ** \param[in] n - index of the track to be used + ** \param[in] pdg - pointer to the pdg hypothesis + **/ + + for(int i=0; i<6; i++) + fP[i] = track.Parameter(i)[n]; + for(int i=0; i<21; i++) + fC[i] = track.Covariance(i)[n]; +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField.fField[i] = track.FieldCoefficient(i)[n]; +#endif + fQ = track.Q()[n]; + + float_v mass = KFParticleDatabase::Instance()->GetMass(*pdg); + Create(fP,fC,fQ,mass); +} + + +KFParticleSIMD::KFParticleSIMD(KFPTrack* Track[], int NTracks, const Int_t *pdg): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructor of the particle from an array tracks. + ** \param[in] Track - an array of pointers to tracks in the KFPTrack format + ** \param[in] NTracks - number of tracks in the arry + ** \param[in] pdg - pointer to the pdg hypothesis common for all elements of the SIMD vector + **/ + Create(Track, NTracks, pdg); +} + +void KFParticleSIMD::Create(KFPTrack* Track[], int NTracks, const Int_t *pdg) +{ + /** Create a particle from from an array tracks. + ** \param[in] Track - an array of pointers to tracks in the KFPTrack format + ** \param[in] NTracks - number of tracks in the arry + ** \param[in] pdg - pointer to the pdg hypothesis common for all elements of the SIMD vector + **/ + + Double_t r[3]; + Double_t C[21]; + + for(Int_t iPart = 0; iPart<float_vLen; iPart++) + { + Int_t iEntry = (iPart < NTracks) ? iPart : 0; + Track[iEntry]->XvYvZv(r); + for(Int_t i=0; i<3; i++) + fP[i][iEntry] = r[i]; + Track[iEntry]->PxPyPz(r); + for(Int_t i=0; i<3; i++) + fP[i+3][iEntry] = r[i]; + fQ[iEntry] = Track[iEntry]->Charge(); + Track[iEntry]->GetCovarianceXYZPxPyPz( C ); + for(Int_t i=0; i<21; i++) + fC[i][iEntry] = C[i]; + } + + float_v mass = KFParticleDatabase::Instance()->GetMass(*pdg); + Create(fP,fC,fQ,mass); + + for(Int_t iPart = 0; iPart<float_vLen; iPart++) + { + Int_t iEntry = (iPart < NTracks) ? iPart : 0; + fChi2[iEntry] = Track[iEntry]->GetChi2(); + fNDF[iEntry] = Track[iEntry]->GetNDF(); + } +} + +KFParticleSIMD::KFParticleSIMD(KFPTrackVector &track, uint_v& index, const int_v& pdg): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructor of the particle from a set of tracks with random indices "index" stored in the KFPTrackVector format. + ** \param[in] track - an array with tracks in the KFPTrackVector format + ** \param[in] index - indices of the tracks to be converted to the KFParticleSIMD object + ** \param[in] pdg - a SIMD vector with an individual pdg hypothesis for each element + **/ + + Create(track, index, pdg); +} + +void KFParticleSIMD::Create(KFPTrackVector &track, uint_v& index, const int_v& pdg) +{ + /** Create a particle from a set of tracks with indices "index" stored in the KFPTrackVector format. + ** The function should be used in case if indices are random. If they are aligned please use function Load() + ** that will benefit of the aligned memory reading and result in a faster code. + ** \param[in] track - an array with tracks in the KFPTrackVector format + ** \param[in] index - indices of the tracks to be converted to the KFParticleSIMD object + ** \param[in] pdg - a SIMD vector with an individual pdg hypothesis for each element + **/ + + for(int i=0; i<6; i++) + fP[i].gather(&(track.Parameter(i)[0]), index); + for(int i=0; i<21; i++) + fC[i].gather(&(track.Covariance(i)[0]), index); +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField.fField[i].gather(&(track.FieldCoefficient(i)[0]), index); +#endif + + // fPDG.gather(&(track.PDG()[0]), index); + fQ.gather(&(track.Q()[0]), index); + + float_v mass = KFParticleDatabase::Instance()->GetMass(pdg); + Create(fP,fC,fQ,mass); +} + +void KFParticleSIMD::Load(KFPTrackVector &track, int index, const int_v& pdg) +{ + /** Create a particle from a set of consequetive tracks stored in the KFPTrackVector format + ** starting from the index "index". + ** \param[in] track - an array with tracks in the KFPTrackVector format + ** \param[in] index - index of the first track + ** \param[in] pdg - a SIMD vector with an individual pdg hypothesis for each element + **/ + + for(int i=0; i<6; i++) + fP[i] = reinterpret_cast<const float_v&>(track.Parameter(i)[index]); + for(int i=0; i<21; i++) + fC[i] = reinterpret_cast<const float_v&>(track.Covariance(i)[index]); +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField.fField[i] = reinterpret_cast<const float_v&>(track.FieldCoefficient(i)[index]); +#endif + + // fPDG.gather(&(track.PDG()[0]), index); + fQ = reinterpret_cast<const int_v&>(track.Q()[index]); + + float_v mass = KFParticleDatabase::Instance()->GetMass(pdg); + Create(fP,fC,fQ,mass); +} + +void KFParticleSIMD::Rotate() +{ + /** Rotates the entries of each SIMD vector of the data members. */ + + for(int i=0; i<7; i++) + fP[i] = fP[i].rotated(1); + for(int i=0; i<27; i++) + fC[i] = fC[i].rotated(1); +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField.fField[i] = fField.fField[i].rotated(1); +#endif + fQ = fQ.rotated(1); + fId = fId.rotated(1); +} + +KFParticleSIMD::KFParticleSIMD(KFPEmcCluster &track, uint_v& index, const KFParticleSIMD& vertexGuess): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructor of gamma particles from a set of clusters of the electromagnetic calorimeter (EMC) + ** with random indices "index". The vertex hypothesis should be provided for the estimation of the momentum. + ** \param[in] track - an array of EMC clusters + ** \param[in] index - indices of the clusters to be converted to the KFParticleSIMD object + ** \param[in] vertexGuess - vertex guess for estimation of the momentum of created gamma particles + **/ + + Create(track, index, vertexGuess); +} + +void KFParticleSIMD::Create(KFPEmcCluster &track, uint_v& index, const KFParticleSIMD& vertexGuess) +{ + /** Creates gamma particles from a set of clusters of the electromagnetic calorimeter (EMC) + ** with random indices "index". The vertex hypothesis should be provided for the estimation of the momentum. + ** \param[in] track - an array of EMC clusters + ** \param[in] index - indices of the clusters to be converted to the KFParticleSIMD object + ** \param[in] vertexGuess - vertex guess for estimation of the momentum of created gamma particles + **/ + + for(int i=0; i<3; i++) + fP[i].gather(&(track.Parameter(i)[0]), index); + fP[6].gather(&(track.Parameter(3)[0]), index); + + const float_v& dx = fP[0] - vertexGuess.fP[0]; + const float_v& dy = fP[1] - vertexGuess.fP[1]; + const float_v& dz = fP[2] - vertexGuess.fP[2]; + const float_v& dl2 = dx*dx + dy*dy + dz*dz; + const float_v& dl = sqrt(dl2); + + fP[0] = vertexGuess.fP[0]; + fP[1] = vertexGuess.fP[1]; + fP[2] = vertexGuess.fP[2]; + + fP[3] = dx/dl * fP[6]; + fP[4] = dy/dl * fP[6]; + fP[5] = dz/dl * fP[6]; + + float_v V[10]; + for(int i=0; i<10; i++) + V[i].gather(&(track.Covariance(i)[0]), index); + + float_v J[7][4]; + for(int i=0; i<7; i++) + for(int j=0; j<4; j++) + J[i][j] = 0.f; + J[0][0] = 1.f; J[1][1] = 1.f; J[2][2] = 1.f; J[6][3] = 1.f; + J[3][0] = fP[6]/dl * (1.f - dx*dx/dl2); J[3][1] = -dx*dy*fP[6]/(dl*dl2); J[3][2] = -dx*dz*fP[6]/(dl*dl2); J[3][3] = dx/dl; + J[4][0] = -dx*dy*fP[6]/(dl*dl2); J[4][1] = fP[6]/dl * (1.f - dy*dy/dl2); J[4][2] = -dy*dz*fP[6]/(dl*dl2); J[4][3] = dy/dl; + J[5][0] = -dx*dz*fP[6]/(dl*dl2); J[5][1] = -dy*dz*fP[6]/(dl*dl2); J[5][2] = fP[6]/dl * (1.f - dz*dz/dl2); J[5][3] = dz/dl; + + float_v VJT[4][7]; // V*J^T + for(Int_t i=0; i<4; i++) + { + for(Int_t j=0; j<7; j++) + { + VJT[i][j] = 0.f; + for(Int_t k=0; k<4; k++) + VJT[i][j] += V[IJ(i,k)]*J[j][k]; + } + } + //Calculate the covariance matrix of the particle fC + for( Int_t i=0; i<36; i++ ) fC[i] = 0.f; + + for(Int_t i=0; i<7; ++i) + for(Int_t j=0; j<=i; ++j) + for(Int_t l=0; l<4; l++) + fC[IJ(i,j)]+= J[i][l]*VJT[l][j]; + fC[35] = 1.f; + + fQ = int_v(Vc::Zero); + fNDF = 0; + fChi2 = 0; + + SumDaughterMass = float_v(Vc::Zero); + fMassHypo = float_v(Vc::Zero); +} + +KFParticleSIMD::KFParticleSIMD(KFPEmcCluster &track, int index, const KFParticleSIMD& vertexGuess): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructr gamma particles from a set of consequetive clusters of the electromagnetic calorimeter (EMC) + ** starting from the index "index". The vertex hypothesis should be provided for the estimation of the momentum. + ** \param[in] track - an array with tracks in the KFPTrackVector format + ** \param[in] index - index of the first EMC cluster + ** \param[in] vertexGuess - vertex guess for estimation of the momentum of created gamma particles + **/ + + Load(track, index, vertexGuess); +} + +void KFParticleSIMD::Load(KFPEmcCluster &track, int index, const KFParticleSIMD& vertexGuess) +{ + /** Create gamma particles from a set of consequetive clusters of the electromagnetic calorimeter (EMC) + ** starting from the index "index". The vertex hypothesis should be provided for the estimation of the momentum. + ** \param[in] track - an array with tracks in the KFPTrackVector format + ** \param[in] index - index of the first EMC cluster + ** \param[in] vertexGuess - vertex guess for estimation of the momentum of created gamma particles + **/ + + for(int i=0; i<3; i++) + fP[i] = reinterpret_cast<const float_v&>(track.Parameter(i)[index]); + fP[6] = reinterpret_cast<const float_v&>(track.Parameter(3)[index]); + const float_v& dx = fP[0] - vertexGuess.fP[0]; + const float_v& dy = fP[1] - vertexGuess.fP[1]; + const float_v& dz = fP[2] - vertexGuess.fP[2]; + const float_v& dl2 = dx*dx + dy*dy + dz*dz; + const float_v& dl = sqrt(dl2); + + fP[0] = vertexGuess.fP[0]; + fP[1] = vertexGuess.fP[1]; + fP[2] = vertexGuess.fP[2]; + + fP[3] = dx/dl * fP[6]; + fP[4] = dy/dl * fP[6]; + fP[5] = dz/dl * fP[6]; + + float_v V[10]; + for(int i=0; i<10; i++) + V[i] = reinterpret_cast<const float_v&>(track.Covariance(i)[index]); + + float_v J[7][4]; + for(int i=0; i<7; i++) + for(int j=0; j<4; j++) + J[i][j] = 0.f; + J[0][0] = 1.f; J[1][1] = 1.f; J[2][2] = 1.f; J[6][3] = 1.f; + J[3][0] = fP[6]/dl * (1.f - dx*dx/dl2); J[3][1] = -dx*dy*fP[6]/(dl*dl2); J[3][2] = -dx*dz*fP[6]/(dl*dl2); J[3][3] = dx/dl; + J[4][0] = -dx*dy*fP[6]/(dl*dl2); J[4][1] = fP[6]/dl * (1.f - dy*dy/dl2); J[4][2] = -dy*dz*fP[6]/(dl*dl2); J[4][3] = dy/dl; + J[5][0] = -dx*dz*fP[6]/(dl*dl2); J[5][1] = -dy*dz*fP[6]/(dl*dl2); J[5][2] = fP[6]/dl * (1.f - dz*dz/dl2); J[5][3] = dz/dl; + + float_v VJT[4][7]; // V*J^T + for(Int_t i=0; i<4; i++) + { + for(Int_t j=0; j<7; j++) + { + VJT[i][j] = 0.f; + for(Int_t k=0; k<4; k++) + VJT[i][j] += V[IJ(i,k)]*J[j][k]; + } + } + //Calculate the covariance matrix of the particle fC + for( Int_t i=0; i<36; i++ ) fC[i] = 0.f; + + for(Int_t i=0; i<7; ++i) + for(Int_t j=0; j<=i; ++j) + for(Int_t l=0; l<4; l++) + fC[IJ(i,j)]+= J[i][l]*VJT[l][j]; + fC[35] = 1.f; + + fQ = int_v(Vc::Zero); + fNDF = 0; + fChi2 = 0; + + SumDaughterMass = float_v(Vc::Zero); + fMassHypo = float_v(Vc::Zero); +} + +KFParticleSIMD::KFParticleSIMD( const KFPVertex &vertex ): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Copies a vertex in KFPVertex into each element of the vectorised KFParticle + ** \param[in] vertex - vertex to b converted + **/ + + Double_t r[3]; + Double_t C[21]; + + vertex.GetXYZ( r ); + for(Int_t i=0; i<3; i++) + fP[i] = r[i]; + vertex.GetCovarianceMatrix( C ); + for(Int_t i=0; i<21; i++) + fC[i] = C[i]; + fChi2 = vertex.GetChi2(); + fNDF = 2*vertex.GetNContributors() - 3; + fQ = int_v(Vc::Zero); + fAtProductionVertex = 0; + fSFromDecay = 0; +} + +void KFParticleSIMD::SetOneEntry(int iEntry, KFParticleSIMD& part, int iEntryPart) +{ + /** Copies one element of the KFParticleSIMD to one element of another KFParticleSIMD. + ** \param[in] iEntry - index of the element of the current track, where the data will be copied + ** \param[in] part - particle, element of which should be copied to the current particle + ** \param[in] iEntryPart - index of the element of particle part, which should be copied to the current particle + **/ + + for( int i = 0; i < 7; ++i ) + fP[i][iEntry] = part.Parameters()[i][iEntryPart]; + for( int i = 0; i < 36; ++i ) + fC[i][iEntry] = part.CovarianceMatrix()[i][iEntryPart]; + + fQ[iEntry] = part.Q()[iEntryPart]; + fNDF[iEntry] = part.NDF()[iEntryPart]; + fChi2[iEntry] = part.Chi2()[iEntryPart]; + +// fSFromDecay[iEntry] = part.fSFromDecay[iEntryPart]; +// SumDaughterMass[iEntry] = part.SumDaughterMass[iEntryPart]; +// fMassHypo[iEntry] = part.fMassHypo[iEntryPart]; + + fId[iEntry] = part.Id()[iEntryPart]; + + fPDG[iEntry] = part.GetPDG()[iEntryPart]; + + if(iEntry==0) + fDaughterIds.resize( part.NDaughters(), int_v(-1) ); + + for(int iD=0; iD<part.NDaughters(); iD++) + fDaughterIds[iD][iEntry] = part.fDaughterIds[iD][iEntryPart]; + +#ifdef NonhomogeneousField + fField.SetOneEntry( iEntry, part.fField, iEntryPart ); //CHECKME +#endif +} + +KFParticleSIMD::KFParticleSIMD(KFParticle* parts[], const int nPart): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructs a vectoriesd particle from an array of scalar KFParticle objects. + ** \param[in] parts - array of scalar KFParticle objects + ** \param[in] nPart - number of particles in the array + **/ + + { // check + bool ok = 1; + + const int nD = (parts[0])->NDaughters(); + for ( int ie = 1; ie < nPart; ie++ ) { + const KFParticle &part = *(parts[ie]); + ok &= part.NDaughters() == nD; + } + if (!ok) { + std::cout << " void CbmKFParticle_simd::Create(CbmKFParticle *parts[], int N) " << std::endl; + exit(1); + } + } + fDaughterIds.resize( (parts[0])->NDaughters(), int_v(-1) ); + + for ( int iPart = 0; iPart < float_vLen; iPart++ ) { + Int_t iEntry = (iPart < nPart) ? iPart : 0; + KFParticle &part = *(parts[iEntry]); + + fId[iEntry] = part.Id(); + for(int iD=0; iD<part.NDaughters(); iD++) + fDaughterIds[iD][iEntry] = part.DaughterIds()[iD]; + + fPDG[iEntry] = part.GetPDG(); + + for( int i = 0; i < 8; ++i ) + fP[i][iEntry] = part.Parameters()[i]; + for( int i = 0; i < 36; ++i ) + fC[i][iEntry] = part.CovarianceMatrix()[i]; + + fNDF[iEntry] = part.GetNDF(); + fChi2[iEntry] = part.GetChi2(); + fQ[iEntry] = part.GetQ(); + fAtProductionVertex = part.GetAtProductionVertex(); // CHECKME +#ifdef NonhomogeneousField + fField.SetOneEntry( part.GetFieldCoeff(), iEntry); +#endif + } +} + +KFParticleSIMD::KFParticleSIMD( KFParticle &part): KFParticleBaseSIMD() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructs a vectoriesd particle from a single scalar KFParticle object. The same particle is copied to each element. + ** \param[in] part - a scalar particle which should be copied to the current vectorised particle + **/ + + fId = part.Id(); + fNDF = part.GetNDF(); + fChi2 = part.GetChi2(); + fQ = part.GetQ(); + fPDG = part.GetPDG(); + fAtProductionVertex = part.GetAtProductionVertex(); + + SetNDaughters(part.NDaughters()); + for( int i = 0; i < part.NDaughters(); ++i ) { + fDaughterIds.push_back( part.DaughterIds()[i] ); + } + + for( int i = 0; i < 8; ++i ) + fP[i] = part.Parameters()[i]; + for( int i = 0; i < 36; ++i ) + fC[i] = part.CovarianceMatrix()[i]; + +#ifdef NonhomogeneousField + fField = KFParticleFieldRegion(part.GetFieldCoeff()); +#endif +} + +float_m KFParticleSIMD::GetDistanceFromVertexXY( const float_v vtx[], const float_v Cv[], float_v &val, float_v &err ) const +{ + /** Calculates the DCA distance from a vertex together with the error in the XY plane. + ** Returns "true" if calculation is failed, "false" if both value and the error are well defined. + ** + ** \param[in] vtx[2] - { X, Y } coordinates of the vertex + ** \param[in] Cv[3] - lower-triangular part of the covariance matrix of the vertex + ** \param[out] val - the distance in the XY plane to the vertex + ** \param[out] err - the error of the calculated distance, takes into account errors of the particle and vertex + **/ + + float_v mP[8]; + float_v mC[36]; + + float_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + const float_v dS = GetDStoPoint(vtx, dsdr); + Transport( dS, dsdr, mP, mC ); + + float_v dx = mP[0] - vtx[0]; + float_v dy = mP[1] - vtx[1]; + float_v px = mP[3]; + float_v py = mP[4]; + float_v pt = sqrt(px*px + py*py); + float_v ex(Vc::Zero), ey(Vc::Zero); + float_m mask = ( pt < float_v(1.e-4) ); + + pt(mask) = float_v(1.f); + ex(!mask) = (px/pt); + ey(!mask) = (py/pt); + val(mask) = float_v(1.e4); + val(!mask)= dy*ex - dx*ey; + + float_v h0 = -ey; + float_v h1 = ex; + float_v h3 = (dy*ey + dx*ex)*ey/pt; + float_v h4 = -(dy*ey + dx*ex)*ex/pt; + + err = + h0*(h0*GetCovariance(0,0) + h1*GetCovariance(0,1) + h3*GetCovariance(0,3) + h4*GetCovariance(0,4) ) + + h1*(h0*GetCovariance(1,0) + h1*GetCovariance(1,1) + h3*GetCovariance(1,3) + h4*GetCovariance(1,4) ) + + h3*(h0*GetCovariance(3,0) + h1*GetCovariance(3,1) + h3*GetCovariance(3,3) + h4*GetCovariance(3,4) ) + + h4*(h0*GetCovariance(4,0) + h1*GetCovariance(4,1) + h3*GetCovariance(4,3) + h4*GetCovariance(4,4) ); + + if( Cv ){ + err+= h0*(h0*Cv[0] + h1*Cv[1] ) + h1*(h0*Cv[1] + h1*Cv[2] ); + } + + err = sqrt(abs(err)); + + return mask; +} + +float_m KFParticleSIMD::GetDistanceFromVertexXY( const float_v vtx[], float_v &val, float_v &err ) const +{ + /** Calculates the DCA distance from a vertex together with the error in the XY plane. + ** Returns "true" if calculation is failed, "false" if both value and the error are well defined. + ** \param[in] vtx[2] - { X, Y } coordinates of the vertex + ** \param[out] val - the distance in the XY plane to the vertex + ** \param[out] err - the error of the calculated distance, takes into account errors of the particle only + **/ + return GetDistanceFromVertexXY( vtx, 0, val, err ); +} + + +float_m KFParticleSIMD::GetDistanceFromVertexXY( const KFParticleSIMD &Vtx, float_v &val, float_v &err ) const +{ + /** Calculates the DCA distance from a vertex in the KFParticle format together with the error in the XY plane. + ** Returns "true" if calculation is failed, "false" if both value and the error are well defined. + ** \param[in] Vtx - the vertex in the KFParticle format + ** \param[out] val - the distance in the XY plane to the vertex + ** \param[out] err - the error of the calculated distance, takes into account errors of the particle and vertex + **/ + + return GetDistanceFromVertexXY( Vtx.fP, Vtx.fC, val, err ); +} + +#ifdef HomogeneousField +float_m KFParticleSIMD::GetDistanceFromVertexXY( const KFPVertex &Vtx, float_v &val, float_v &err ) const +{ + /** Calculates the DCA distance from a vertex in the KFPVertex format together with the error in the XY plane. + ** Returns "true" if calculation is failed, "false" if both value and the error are well defined. + ** \param[in] Vtx - the vertex in the KFPVertex format + ** \param[out] val - the distance in the XY plane to the vertex + ** \param[out] err - the error of the calculated distance, takes into account errors of the particle and vertex + **/ + + return GetDistanceFromVertexXY( KFParticleSIMD(Vtx), val, err ); +} +#endif + +float_v KFParticleSIMD::GetDistanceFromVertexXY( const float_v vtx[] ) const +{ + /** Returns the DCA distance from a vertex in the XY plane. + ** \param[in] vtx[2] - { X, Y } coordinates of the vertex + **/ + + float_v val, err; + GetDistanceFromVertexXY( vtx, 0, val, err ); + return val; +} + +float_v KFParticleSIMD::GetDistanceFromVertexXY( const KFParticleSIMD &Vtx ) const +{ + /** Returns the DCA distance from a vertex in the KFParticle format in the XY plane. + ** \param[in] Vtx - the vertex in the KFParticle format + **/ + + return GetDistanceFromVertexXY( Vtx.fP ); +} + +#ifdef HomogeneousField +float_v KFParticleSIMD::GetDistanceFromVertexXY( const KFPVertex &Vtx ) const +{ + /** Returns the DCA distance from a vertex in the KFParticle format in the XY plane. + ** \param[in] Vtx - the vertex in the KFPVertex format + **/ + + return GetDistanceFromVertexXY( KFParticleSIMD(Vtx).fP ); +} +#endif + +float_v KFParticleSIMD::GetDistanceFromParticleXY( const KFParticleSIMD &p ) const +{ + /** Returns the DCA distance between the current and the second particles in the XY plane. + ** \param[in] p - the second particle + **/ + + float_v dS[2]; + float_v dsdr[4][6]; + GetDStoParticle( p, dS, dsdr ); + float_v mP[8], mC[36], mP1[8], mC1[36]; + Transport( dS[0], dsdr[0], mP, mC ); + p.Transport( dS[1], dsdr[3], mP1, mC1 ); + float_v dx = mP[0]-mP1[0]; + float_v dy = mP[1]-mP1[1]; + return sqrt(dx*dx+dy*dy); +} + +float_v KFParticleSIMD::GetDeviationFromParticleXY( const KFParticleSIMD &p ) const +{ + /** Returns sqrt(Chi2/ndf) deviation from other particle in the XY plane. + ** \param[in] p - the second particle + **/ + + float_v ds[2] = {0.f,0.f}; + float_v dsdr[4][6]; + float_v F1[36], F2[36], F3[36], F4[36]; + for(int i1=0; i1<36; i1++) + { + F1[i1] = 0; + F2[i1] = 0; + F3[i1] = 0; + F4[i1] = 0; + } + GetDStoParticle( p, ds, dsdr ); + + float_v V0Tmp[36] ; + float_v V1Tmp[36] ; + + + float_v mP1[8], mC1[36]; + float_v mP2[8], mC2[36]; + + Transport(ds[0], dsdr[0], mP1, mC1, dsdr[1], F1, F2); + p.Transport(ds[1], dsdr[3], mP2, mC2, dsdr[2], F4, F3); + + MultQSQt(F2, p.fC, V0Tmp, 6); + MultQSQt(F3, fC, V1Tmp, 6); + + for(int iC=0; iC<3; iC++) + mC1[iC] += V0Tmp[iC] + mC2[iC] + V1Tmp[iC]; + + float_v d[3]={ mP2[0]-mP1[0], mP2[1]-mP1[1], mP2[2]-mP1[2]}; + + return ( ( mC1[0]*d[0] + mC1[1]*d[1])*d[0] + +(mC1[1]*d[0] + mC1[2]*d[1])*d[1] ); +} + + +float_v KFParticleSIMD::GetDeviationFromVertexXY( const float_v vtx[], const float_v Cv[] ) const +{ + /** Returns sqrt(Chi2/ndf) deviation from the vertex in the XY plane. + ** \param[in] vtx[2] - { X, Y } coordinates of the vertex + ** \param[in] Cv[3] - lower-triangular part of the covariance matrix of the vertex + **/ + + float_v mP[8]; + float_v mC[36]; + float_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + const float_v dS = GetDStoPoint(vtx, dsdr); + float_v dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f}; + float_v F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0.f; + F1[i2] = 0.f; + } + Transport( dS, dsdr, mP, mC, dsdp, F, F1 ); + + if(Cv) + { + float_v VFT[3][6]; + for(int i=0; i<3; i++) + for(int j=0; j<6; j++) + { + VFT[i][j] = 0; + for(int k=0; k<3; k++) + { + VFT[i][j] += Cv[IJ(i,k)] * F1[j*6+k]; + } + } + + float_v FVFT[6][6]; + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + { + FVFT[i][j] = 0; + for(int k=0; k<3; k++) + { + FVFT[i][j] += F1[i*6+k] * VFT[k][j]; + } + } + mC[0] += FVFT[0][0] + Cv[0]; + mC[1] += FVFT[1][0] + Cv[1]; + mC[2] += FVFT[1][1] + Cv[2]; + mC[3] += FVFT[2][0] + Cv[3]; + mC[4] += FVFT[2][1] + Cv[4]; + mC[5] += FVFT[2][2] + Cv[5]; + } + + InvertCholetsky3(mC); + + float_v d[3]={ vtx[0]-mP[0], vtx[1]-mP[1], vtx[2]-mP[2]}; + + return ( ( mC[0]*d[0] + mC[1]*d[1] )*d[0] + +(mC[1]*d[0] + mC[2]*d[1] )*d[1] ); +} + + +float_v KFParticleSIMD::GetDeviationFromVertexXY( const KFParticleSIMD &Vtx ) const +{ + /** Returns sqrt(Chi2/ndf) deviation from the vertex in the KFParticle format in the XY plane. + ** \param[in] Vtx - the vertex in the KFParticle format + **/ + + return GetDeviationFromVertexXY( Vtx.fP, Vtx.fC ); +} + +#ifdef HomogeneousField +float_v KFParticleSIMD::GetDeviationFromVertexXY( const KFPVertex &Vtx ) const +{ + /** Returns sqrt(Chi2/ndf) deviation from the vertex in the KFPVertex format in the XY plane. + ** \param[in] Vtx - the vertex in the KFPVertex format + **/ + + KFParticleSIMD v(Vtx); + return GetDeviationFromVertexXY( v.fP, v.fC ); +} +#endif + +float_v KFParticleSIMD::GetAngle ( const KFParticleSIMD &p ) const +{ + /** Returns the opening angle between the current and the second particle in 3D. + ** \param[in] p - the second particle + **/ + + float_v ds[2] = {0.f,0.f}; + float_v dsdr[4][6]; + GetDStoParticle( p, ds, dsdr ); + float_v mP[8], mC[36], mP1[8], mC1[36]; + Transport( ds[0], dsdr[0], mP, mC ); + p.Transport( ds[1], dsdr[3], mP1, mC1 ); + float_v n = sqrt( mP[3]*mP[3] + mP[4]*mP[4] + mP[5]*mP[5] ); + float_v n1= sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] + mP1[5]*mP1[5] ); + n*=n1; + float_v a(Vc::Zero); + float_m mask = (n>(1.e-8f)); + a(mask) = ( mP[3]*mP1[3] + mP[4]*mP1[4] + mP[5]*mP1[5] )/n; + mask = ( abs(a) < float_v(1.f)); + float_m aPos = (a>=float_v(Vc::Zero)); + a(mask) = KFPMath::ACos(a); + a((!mask) && aPos) = float_v(Vc::Zero); + a((!mask) && (!aPos)) = 3.1415926535f; + return a; +} + +float_v KFParticleSIMD::GetAngleXY( const KFParticleSIMD &p ) const +{ + /** Returns the opening angle between the current and the second particle in the XY plane. + ** \param[in] p - the second particle + **/ + + float_v ds[2] = {0.f,0.f}; + float_v dsdr[4][6]; + GetDStoParticle( p, ds, dsdr ); + float_v mP[8], mC[36], mP1[8], mC1[36]; + Transport( ds[0], dsdr[0], mP, mC ); + p.Transport( ds[1], dsdr[3], mP1, mC1 ); + float_v n = sqrt( mP[3]*mP[3] + mP[4]*mP[4] ); + float_v n1= sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] ); + n*=n1; + float_v a(Vc::Zero); + float_m mask = (n>(1.e-8f)); + a = ( mP[3]*mP1[3] + mP[4]*mP1[4] )/n; + a(!mask) = 0.f; + mask = ( abs(a) < float_v(1.f)); + float_m aPos = (a>=float_v(Vc::Zero)); + a(mask) = KFPMath::ACos(a); + a((!mask) && aPos) = float_v(Vc::Zero); + a((!mask) && (!aPos)) = 3.1415926535f; + return a; +} + +float_v KFParticleSIMD::GetAngleRZ( const KFParticleSIMD &p ) const +{ + /** Returns the opening angle between the current and the second particle in the RZ plane, R = sqrt(X*X+Y*Y). + ** \param[in] p - the second particle + **/ + + float_v ds[2] = {0.f,0.f}; + float_v dsdr[4][6]; + GetDStoParticle( p, ds, dsdr ); + float_v mP[8], mC[36], mP1[8], mC1[36]; + Transport( ds[0], dsdr[0], mP, mC ); + p.Transport( ds[1], dsdr[3], mP1, mC1 ); + float_v nr = sqrt( mP[3]*mP[3] + mP[4]*mP[4] ); + float_v n1r= sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] ); + float_v n = sqrt( nr*nr + mP[5]*mP[5] ); + float_v n1= sqrt( n1r*n1r + mP1[5]*mP1[5] ); + n*=n1; + float_v a(Vc::Zero); + float_m mask = (n>(1.e-8f)); + a(mask) = ( nr*n1r +mP[5]*mP1[5])/n; + mask = ( abs(a) < float_v(Vc::Zero)); + float_m aPos = (a>=float_v(Vc::Zero)); + a(mask) = KFPMath::ACos(a); + a((!mask) && aPos) = float_v(Vc::Zero); + a((!mask) && (!aPos)) = 3.1415926535f; + return a; +} + +float_v KFParticleSIMD::GetPseudoProperDecayTime( const KFParticleSIMD &pV, const float_v& mass, float_v* timeErr2 ) const +{ + /** Returns the Pseudo Proper Time of the decay = (r*pt) / |pt| * M/|pt| + ** + ** \param[in] pV - the creation point of the particle + ** \param[in] mass - the mass of the particle + ** \param[out] timeErr2 - error of the returned value, if null pointer is provided - is not calculated + **/ + + const float_v ipt2 = 1/( Px()*Px() + Py()*Py() ); + const float_v mipt2 = mass*ipt2; + const float_v dx = X() - pV.X(); + const float_v dy = Y() - pV.Y(); + + if ( timeErr2 ) { + // -- calculate error = sigma(f(r)) = f'Cf' + // r = {x,y,px,py,x_pV,y_pV} + // df/dr = { px*m/pt^2, + // py*m/pt^2, + // ( x - x_pV )*m*(1/pt^2 - 2(px/pt^2)^2), + // ( y - y_pV )*m*(1/pt^2 - 2(py/pt^2)^2), + // -px*m/pt^2, + // -py*m/pt^2 } + const float_v f0 = Px()*mipt2; + const float_v f1 = Py()*mipt2; + const float_v mipt2derivative = mipt2*(1-2*Px()*Px()*ipt2); + const float_v f2 = dx*mipt2derivative; + const float_v f3 = -dy*mipt2derivative; + const float_v f4 = -f0; + const float_v f5 = -f1; + + const float_v& mC00 = GetCovariance(0,0); + const float_v& mC10 = GetCovariance(0,1); + const float_v& mC11 = GetCovariance(1,1); + const float_v& mC20 = GetCovariance(3,0); + const float_v& mC21 = GetCovariance(3,1); + const float_v& mC22 = GetCovariance(3,3); + const float_v& mC30 = GetCovariance(4,0); + const float_v& mC31 = GetCovariance(4,1); + const float_v& mC32 = GetCovariance(4,3); + const float_v& mC33 = GetCovariance(4,4); + const float_v& mC44 = pV.GetCovariance(0,0); + const float_v& mC54 = pV.GetCovariance(1,0); + const float_v& mC55 = pV.GetCovariance(1,1); + + *timeErr2 = + f5*mC55*f5 + + f5*mC54*f4 + + f4*mC44*f4 + + f3*mC33*f3 + + f3*mC32*f2 + + f3*mC31*f1 + + f3*mC30*f0 + + f2*mC22*f2 + + f2*mC21*f1 + + f2*mC20*f0 + + f1*mC11*f1 + + f1*mC10*f0 + + f0*mC00*f0; + } + return ( dx*Px() + dy*Py() )*mipt2; +} + +void KFParticleSIMD::GetKFParticle(KFParticle &Part, int iPart) +{ + /** Copies an entry "iPart" of the current vectorised particle to the scalar KFParticle object. + ** \param[out] Part - an output scalar particle, where element "iPart" will be copied + ** \param[in] iPart - index of the element to be copied to the scalar particle + **/ + + Part.SetId(static_cast<int>(Id()[iPart])); + + Part.CleanDaughtersId(); + for( unsigned int i = 0; i < DaughterIds().size(); i++ ) + Part.AddDaughterId(static_cast<int>(DaughterIds()[i][iPart])); + + Part.SetPDG( static_cast<int>(GetPDG()[iPart]) ); + + for(int iP=0; iP<8; iP++) + Part.Parameters()[iP] = Parameters()[iP][iPart]; + for(int iC=0; iC<36; iC++) + Part.CovarianceMatrix()[iC] = CovarianceMatrix()[iC][iPart]; + + Part.NDF() = static_cast<int>(GetNDF()[iPart]); + Part.Chi2() = GetChi2()[iPart]; + Part.Q() = GetQ()[iPart]; + Part.SetAtProductionVertex(fAtProductionVertex); +#ifdef NonhomogeneousField + for(int iF=0; iF<10; iF++) + Part.SetFieldCoeff(fField.fField[iF][iPart], iF); +#endif +} + +void KFParticleSIMD::GetKFParticle(KFParticle* Part, int nPart) +{ + /** Copies "nPart" elements of the current vectorised particle to the array of scalar KFParticle objects. + ** \param[out] Part - an output array of scalar particles + ** \param[in] nPart - number of elements to be copied to the array of scalar objects + **/ + + for(int i=0; i<nPart; i++) + GetKFParticle(Part[i],i); +} diff --git a/external/KFParticle/KFParticle/KFParticleSIMD.h b/external/KFParticle/KFParticle/KFParticleSIMD.h new file mode 100644 index 0000000000000000000000000000000000000000..c0db5a0e5a3207a73750028b7842a7a75001238e --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleSIMD.h @@ -0,0 +1,1101 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +//#define NonhomogeneousField +// #define HomogeneousField + +#ifndef KFPARTICLESIMD_H +#define KFPARTICLESIMD_H + +#include "KFParticleBaseSIMD.h" + +#include "KFPTrack.h" +#include "KFPTrackVector.h" +#include "KFPEmcCluster.h" +#include "KFPVertex.h" + +#ifdef NonhomogeneousField +#include "KFParticleField.h" +#endif + +class KFParticle; + +/** @class KFParticleSIMD + ** @brief The main vectorised class of KF Particle pacakge, describes particle objects. + ** @author M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** Vectorised version of the KF Particle class, describes particle objects. + ** The particle is described with the state vector { X, Y, Z, Px, Py, Pz, E } + ** and the corresponding covariance matrix. + ** It contains functionality to create particle-object from track, to construct + ** short-lived particles from other tracks or particles. The mathematics is + ** based on the Kalman filter method. It also allows to subtract particles from + ** the already constructed object, + ** to transport partices, get parameters together with their erros, get distance + ** to other particles and vertices, get deviations from them in terms of errors, etc. + **/ + +class KFParticleSIMD :public KFParticleBaseSIMD +{ + + public: + + void *operator new(size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(float_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new(size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size, void *ptr) { return ::operator new(size, ptr);} ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void operator delete(void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + void operator delete[](void *ptr, size_t) { _mm_free(ptr); } ///< delete operator for the SIMD-alligned dynamic memory release + //* + //* INITIALIZATION + //* + + //* Set magnetic field for all particles +#ifdef HomogeneousField + static void SetField( float_v Bz ); ///< Set Bz field. +#endif +#ifdef NonhomogeneousField + void SetField(const KFParticleFieldRegion &field) + { + /** Set the field approximation along the particle trajectory + ** \param[in] field - approximation of each component of the magnetic field with the parabola alnog the particle trajectory + **/ + fField = field; + } +#endif + //* Constructor (empty) + + KFParticleSIMD():KFParticleBaseSIMD() +#ifdef NonhomogeneousField + , fField() +#endif + { ; } + + //* Destructor (empty) + + ~KFParticleSIMD(){ ; } + + //* Construction of mother particle by its 2-3-4 daughters + + KFParticleSIMD( const KFParticleSIMD &d1, const KFParticleSIMD &d2 ); + KFParticleSIMD( const KFParticleSIMD &d1, const KFParticleSIMD &d2, const KFParticleSIMD &d3 ); + KFParticleSIMD( const KFParticleSIMD &d1, const KFParticleSIMD &d2, const KFParticleSIMD &d3, const KFParticleSIMD &d4 ); + + //* Initialisation from "cartesian" coordinates ( X Y Z Px Py Pz ) + //* Parameters, covariance matrix, charge and PID hypothesis should be provided + + void Create( const float_v Param[], const float_v Cov[], int_v Charge, float_v mass /*Int_t PID*/ ); + + void SetOneEntry(int iEntry, KFParticleSIMD& part, int iEntryPart); + + KFParticleSIMD( const KFPTrack *track, Int_t PID ); + KFParticleSIMD( KFPTrack* Track[], int NTracks, const Int_t *pdg=0 ); + KFParticleSIMD( KFPTrackVector &track, uint_v& index, const int_v& pdg ); + + void Create(KFPTrack* Track[], int NTracks, const Int_t *pdg=0); + void Create(KFPTrackVector &track, uint_v& index, const int_v& pdg); + void Load(KFPTrackVector &track, int index, const int_v& pdg); + void Rotate(); + + KFParticleSIMD(KFPTrack &Track, const Int_t *pdg=0); + KFParticleSIMD(KFPTrackVector &track, int n, const Int_t *pdg=0); + + KFParticleSIMD( KFPEmcCluster &track, uint_v& index, const KFParticleSIMD& vertexGuess ); + KFParticleSIMD( KFPEmcCluster &track, int index, const KFParticleSIMD& vertexGuess ); + void Create( KFPEmcCluster &track, uint_v& index, const KFParticleSIMD& vertexGuess ); + void Load( KFPEmcCluster &track, int index, const KFParticleSIMD& vertexGuess ); + + + //* Initialisation from VVertex + + KFParticleSIMD( const KFPVertex &vertex ); + KFParticleSIMD( KFParticle* part[], const int nPart = 0 ); + KFParticleSIMD( KFParticle &part ); + + //* + //* ACCESSORS + //* + + //* Simple accessors + + float_v GetX () const ; ///< Retruns X coordinate of the particle, fP[0]. + float_v GetY () const ; ///< Retruns Y coordinate of the particle, fP[1]. + float_v GetZ () const ; ///< Retruns Z coordinate of the particle, fP[2]. + float_v GetPx () const ; ///< Retruns X component of the momentum, fP[3]. + float_v GetPy () const ; ///< Retruns Y component of the momentum, fP[4]. + float_v GetPz () const ; ///< Retruns Z component of the momentum, fP[5]. + float_v GetE () const ; ///< Returns energy of the particle, fP[6]. + float_v GetS () const ; ///< Returns dS=l/p, l - decay length, fP[7], defined if production vertex is set. + int_v GetQ () const ; ///< Returns charge of the particle. + float_v GetChi2 () const ; ///< Returns Chi2 of the fit. + int_v GetNDF () const ; ///< Returns number of decrease of freedom. + + Bool_t GetAtProductionVertex() const { return fAtProductionVertex; } ///< Returns a flag which shows if the particle is located at the production point + + const float_v& X () const { return fP[0]; } ///< Retruns X coordinate of the particle, fP[0]. + const float_v& Y () const { return fP[1]; } ///< Retruns Y coordinate of the particle, fP[1]. + const float_v& Z () const { return fP[2]; } ///< Retruns Z coordinate of the particle, fP[2]. + const float_v& Px () const { return fP[3]; } ///< Retruns X component of the momentum, fP[3]. + const float_v& Py () const { return fP[4]; } ///< Retruns Y component of the momentum, fP[4]. + const float_v& Pz () const { return fP[5]; } ///< Retruns Z component of the momentum, fP[5]. + const float_v& E () const { return fP[6]; } ///< Returns energy of the particle, fP[6]. + const float_v& S () const { return fP[7]; } ///< Returns dS=l/p, l - decay length, fP[7], defined if production vertex is set. + const int_v & Q () const { return fQ; } ///< Returns charge of the particle. + const float_v& Chi2 () const { return fChi2; } ///< Returns Chi2 of the fit. + const int_v& NDF () const { return fNDF; } ///< Returns number of decrease of freedom. + + float_v GetParameter ( int i ) const ; ///< Returns P[i] parameter. + float_v GetCovariance( int i ) const ; ///< Returns C[i] element of the covariance matrix in the lower triangular form. + float_v GetCovariance( int i, int j ) const ; ///< Returns C[i,j] element of the covariance matrix. + + //* Accessors with calculations, value returned w/o error flag + + float_v GetP () const; ///< Returns momentum + float_v GetPt () const; ///< Returns transverse momentum + float_v GetEta () const; ///< Returns pseudorapidity + float_v GetPhi () const; ///< Returns the azimuthal angle phi + float_v GetMomentum () const; ///< Returns momentum + float_v GetMass () const; ///< Returns mass + float_v GetDecayLength () const; ///< Returns decay length + float_v GetDecayLengthXY () const; ///< Returns decay length in XY + float_v GetLifeTime () const; ///< Returns life time ctau [cm] + float_v GetR () const; ///< Returns distance to the origin of the coordinate system {0,0,0} + float_v GetRapidity() const { return float_v(0.5f)*log((fP[6] + fP[5])/(fP[6] - fP[5])); } ///< Returns rapidity of the particle + + //* Accessors to estimated errors + + float_v GetErrX () const ; ///< Returns the error of X of current position + float_v GetErrY () const ; ///< Returns the error of Y of current position + float_v GetErrZ () const ; ///< Returns the error of Z of current position + float_v GetErrPx () const ; ///< Returns the error of X-compoment of the particle momentum + float_v GetErrPy () const ; ///< Returns the error of Y-compoment of the particle momentum + float_v GetErrPz () const ; ///< Returns the error of Z-compoment of the particle momentum + float_v GetErrE () const ; ///< Returns the error of energy + float_v GetErrS () const ; ///< Returns the error of decay length / momentum + float_v GetErrP () const ; ///< Returns the error of momentum + float_v GetErrPt () const ; ///< Returns the error of transverse momentum + float_v GetErrEta () const ; ///< Returns the error of pseudorapidity + float_v GetErrPhi () const ; ///< Returns the error of the azimuthal angle phi + float_v GetErrMomentum () const ; ///< Returns the error of momentum + float_v GetErrMass () const ; ///< Returns the error of mass + float_v GetErrDecayLength () const ; ///< Returns the error of decay length + float_v GetErrDecayLengthXY () const ; ///< Returns the error of decay length in XY + float_v GetErrLifeTime () const ; ///< Returns the error of life time + float_v GetErrR () const ; ///< Returns the error of distance to the origin of the coordinate system {0,0,0} + + //* Accessors with calculations( &value, &estimated sigma ) + //* error flag returned (0 means no error during calculations) + + float_m GetP ( float_v &P, float_v &SigmaP ) const ; //* momentum + float_m GetPt ( float_v &Pt, float_v &SigmaPt ) const ; //* transverse momentum + float_m GetEta ( float_v &Eta, float_v &SigmaEta ) const ; //* pseudorapidity + float_m GetPhi ( float_v &Phi, float_v &SigmaPhi ) const ; //* phi + float_m GetMomentum ( float_v &P, float_v &SigmaP ) const ; //* momentum + float_m GetMass ( float_v &M, float_v &SigmaM ) const ; //* mass + float_m GetDecayLength ( float_v &L, float_v &SigmaL ) const ; //* decay length + float_m GetDecayLengthXY ( float_v &L, float_v &SigmaL ) const ; //* decay length in XY + float_m GetLifeTime ( float_v &T, float_v &SigmaT ) const ; //* life time + float_m GetR ( float_v &R, float_v &SigmaR ) const ; //* R + + + //* + //* MODIFIERS + //* + + float_v & X () ; ///< Modifier of X coordinate of the particle, fP[0]. + float_v & Y () ; ///< Modifier of Y coordinate of the particle, fP[1]. + float_v & Z () ; ///< Modifier of Z coordinate of the particle, fP[2]. + float_v & Px () ; ///< Modifier of X component of the momentum, fP[3]. + float_v & Py () ; ///< Modifier of Y component of the momentum, fP[4]. + float_v & Pz () ; ///< Modifier of Z component of the momentum, fP[5]. + float_v & E () ; ///< Modifier of energy of the particle, fP[6]. + float_v & S () ; ///< Modifier of dS=l/p, l - decay length, fP[7], defined if production vertex is set. + int_v & Q () ; ///< Modifier of charge of the particle. + float_v & Chi2 () ; ///< Modifier of Chi2 of the fit. + int_v & NDF () ; ///< Modifier of number of decrease of freedom. + + float_v & Parameter ( int i ) ; ///< Modifier of P[i] parameter. + float_v & Covariance( int i ) ; ///< Modifier of C[i] element of the covariance matrix in the lower triangular form. + float_v & Covariance( int i, int j ) ; ///< Modifier of C[i,j] element of the covariance matrix. + float_v * Parameters () ; ///< Returns pointer to the parameters fP + float_v * CovarianceMatrix() ; ///< Returns pointer to the covariance matrix fC + + void GetKFParticle( KFParticle &Part, int iPart = 0); + void GetKFParticle( KFParticle *Part, int nPart = 0); + + //* + //* CONSTRUCTION OF THE PARTICLE BY ITS DAUGHTERS AND MOTHER + //* USING THE KALMAN FILTER METHOD + //* + + + //* Add daughter to the particle + + void AddDaughter( const KFParticleSIMD &Daughter ); + + //* Add daughter via += operator: ex.{ D0; D0+=Pion; D0+= Kaon; } + + void operator +=( const KFParticleSIMD &Daughter ); + + //* Everything in one go + + void Construct( const KFParticleSIMD *vDaughters[], int nDaughters, + const KFParticleSIMD *ProdVtx=0, Float_t Mass=-1 ); + + //* + //* TRANSPORT + //* + //* ( main transportation parameter is S = SignedPath/Momentum ) + //* ( parameters of decay & production vertices are stored locally ) + //* + + //* Transport the particle close to xyz[] point + + void TransportToPoint( const float_v xyz[] ); + + //* Transport the particle close to VVertex +#ifdef HomogeneousField + void TransportToVertex( const KFPVertex &v ); +#endif + //* Transport the particle close to another particle p + + void TransportToParticle( const KFParticleSIMD &p ); + + //* Get dS to a certain space point + + float_v GetDStoPoint( const float_v xyz[3], float_v dsdr[6] ) const ; + + //* Get dS to other particle p (dSp for particle p also returned) + + void GetDStoParticle( const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] ) const ; + void GetDStoParticleFast( const KFParticleBaseSIMD &p, float_v dS[2] ) const ; + //* + //* OTHER UTILITIES + //* + + //* Calculate distance from another object [cm] in XY-plane + + float_m GetDistanceFromVertexXY( const float_v vtx[], float_v &val, float_v &err ) const ; + float_m GetDistanceFromVertexXY( const float_v vtx[], const float_v Cv[], float_v &val, float_v &err ) const ; + float_m GetDistanceFromVertexXY( const KFParticleSIMD &Vtx, float_v &val, float_v &err ) const ; +#ifdef HomogeneousField + float_m GetDistanceFromVertexXY( const KFPVertex &Vtx, float_v &val, float_v &err ) const ; +#endif + + float_v GetDistanceFromVertexXY( const float_v vtx[] ) const ; + float_v GetDistanceFromVertexXY( const KFParticleSIMD &Vtx ) const ; +#ifdef HomogeneousField + float_v GetDistanceFromVertexXY( const KFPVertex &Vtx ) const ; +#endif + float_v GetDistanceFromParticleXY( const KFParticleSIMD &p ) const ; + + //* Calculate sqrt(Chi2/ndf) deviation from another object in XY plane + //* ( v = [xyz]-vertex, Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix ) + + float_v GetDeviationFromVertexXY( const float_v v[], const float_v Cv[]=0 ) const ; + float_v GetDeviationFromVertexXY( const KFParticleSIMD &Vtx ) const ; +#ifdef HomogeneousField + float_v GetDeviationFromVertexXY( const KFPVertex &Vtx ) const ; +#endif + float_v GetDeviationFromParticleXY( const KFParticleSIMD &p ) const ; + + //* Calculate opennig angle between two particles + + float_v GetAngle ( const KFParticleSIMD &p ) const ; + float_v GetAngleXY( const KFParticleSIMD &p ) const ; + float_v GetAngleRZ( const KFParticleSIMD &p ) const ; + + // * Pseudo Proper Time of decay = (r*pt) / |pt| * M/|pt| + // @primVertex - primary vertex + // @mass - mass of the mother particle (in the case of "Hb -> JPsi" it would be JPsi mass) + // @*timeErr2 - squared error of the decay time. If timeErr2 = 0 it isn't calculated + float_v GetPseudoProperDecayTime( const KFParticleSIMD &primVertex, const float_v& mass, float_v* timeErr2 = 0 ) const; + + void GetFieldValue( const float_v xyz[], float_v B[] ) const ; + + void Transport( float_v dS, const float_v* dsdr, float_v P[], float_v C[], float_v* dsdr1=0, float_v* F=0, float_v* F1=0 ) const ; + void TransportFast( float_v dS, float_v P[] ) const ; + + protected: + + //* + //* INTERNAL STUFF + //* + + //* Method to access ALICE field +#ifdef HomogeneousField + static float_v GetFieldAlice(); +#endif + //* Other methods required by the abstract KFParticleBaseSIMD class + + private: +#ifdef HomogeneousField + static float_v fgBz; ///< Bz compoment of the magnetic field (is defined in case of #ifdef HomogeneousField) +#endif +#ifdef NonhomogeneousField + /** \brief Approximation of the magnetic field along the track trajectory. + ** Each component (Bx, By, Bz) is approximated with the parabola depending on Z coordinate. Is defined in case of #ifdef NonhomogeneousField. + **/ + KFParticleFieldRegion fField; +#endif +}; + + + +//--------------------------------------------------------------------- +// +// Inline implementation of the KFParticleSIMD methods +// +//--------------------------------------------------------------------- + +#ifdef HomogeneousField +inline void KFParticleSIMD::SetField( float_v Bz ) +{ + /** Sets the constant homogemeous one-component magnetic field Bz (is defined in case of #ifdef HomogeneousField). + ** \param[in] Bz - Z-component of the magnetic field + **/ + fgBz = Bz; +} +#endif + +inline KFParticleSIMD::KFParticleSIMD( const KFParticleSIMD &d1, + const KFParticleSIMD &d2, + const KFParticleSIMD &d3 ): KFParticleBaseSIMD() +#ifdef NonhomogeneousField + , fField() +#endif +{ + /** Constructs a particle from three input daughter particles + ** \param[in] d1 - the first daughter particle + ** \param[in] d2 - the second daughter particle + ** \param[in] d3 - the third daughter particle + **/ + + KFParticleSIMD mother; + mother+= d1; + mother+= d2; + mother+= d3; + *this = mother; +} + +inline KFParticleSIMD::KFParticleSIMD( const KFParticleSIMD &d1, + const KFParticleSIMD &d2, + const KFParticleSIMD &d3, + const KFParticleSIMD &d4 ): KFParticleBaseSIMD() +#ifdef NonhomogeneousField + , fField() +#endif +{ + /** Constructs a particle from four input daughter particles + ** \param[in] d1 - the first daughter particle + ** \param[in] d2 - the second daughter particle + ** \param[in] d3 - the third daughter particle + ** \param[in] d4 - the fourth daughter particle + **/ + + KFParticleSIMD mother; + mother+= d1; + mother+= d2; + mother+= d3; + mother+= d4; + *this = mother; +} + +inline float_v KFParticleSIMD::GetX () const +{ + return KFParticleBaseSIMD::GetX(); +} + +inline float_v KFParticleSIMD::GetY () const +{ + return KFParticleBaseSIMD::GetY(); +} + +inline float_v KFParticleSIMD::GetZ () const +{ + return KFParticleBaseSIMD::GetZ(); +} + +inline float_v KFParticleSIMD::GetPx () const +{ + return KFParticleBaseSIMD::GetPx(); +} + +inline float_v KFParticleSIMD::GetPy () const +{ + return KFParticleBaseSIMD::GetPy(); +} + +inline float_v KFParticleSIMD::GetPz () const +{ + return KFParticleBaseSIMD::GetPz(); +} + +inline float_v KFParticleSIMD::GetE () const +{ + return KFParticleBaseSIMD::GetE(); +} + +inline float_v KFParticleSIMD::GetS () const +{ + return KFParticleBaseSIMD::GetS(); +} + +inline int_v KFParticleSIMD::GetQ () const +{ + return KFParticleBaseSIMD::GetQ(); +} + +inline float_v KFParticleSIMD::GetChi2 () const +{ + return KFParticleBaseSIMD::GetChi2(); +} + +inline int_v KFParticleSIMD::GetNDF () const +{ + return KFParticleBaseSIMD::GetNDF(); +} + +inline float_v KFParticleSIMD::GetParameter ( int i ) const +{ + return KFParticleBaseSIMD::GetParameter(i); +} + +inline float_v KFParticleSIMD::GetCovariance( int i ) const +{ + return KFParticleBaseSIMD::GetCovariance(i); +} + +inline float_v KFParticleSIMD::GetCovariance( int i, int j ) const +{ + return KFParticleBaseSIMD::GetCovariance(i,j); +} + + +inline float_v KFParticleSIMD::GetP () const +{ + float_v par, err; + KFParticleBaseSIMD::GetMomentum( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetPt () const +{ + float_v par, err; + KFParticleBaseSIMD::GetPt( par, err ) ; + return par; +} + +inline float_v KFParticleSIMD::GetEta () const +{ + float_v par, err; + KFParticleBaseSIMD::GetEta( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetPhi () const +{ + float_v par, err; + KFParticleSIMD::GetPhi( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetMomentum () const +{ + float_v par, err; + KFParticleSIMD::GetMomentum( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetMass () const +{ + float_v par, err; + KFParticleSIMD::GetMass( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetDecayLength () const +{ + float_v par, err; + KFParticleSIMD::GetDecayLength( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetDecayLengthXY () const +{ + float_v par, err; + KFParticleSIMD::GetDecayLengthXY( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetLifeTime () const +{ + float_v par, err; + KFParticleSIMD::GetLifeTime( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetR () const +{ + float_v par, err; + KFParticleSIMD::GetR( par, err ); + return par; +} + +inline float_v KFParticleSIMD::GetErrX () const +{ + return sqrt(abs( GetCovariance(0,0) )); +} + +inline float_v KFParticleSIMD::GetErrY () const +{ + return sqrt(abs( GetCovariance(1,1) )); +} + +inline float_v KFParticleSIMD::GetErrZ () const +{ + return sqrt(abs( GetCovariance(2,2) )); +} + +inline float_v KFParticleSIMD::GetErrPx () const +{ + return sqrt(abs( GetCovariance(3,3) )); +} + +inline float_v KFParticleSIMD::GetErrPy () const +{ + return sqrt(abs( GetCovariance(4,4) )); +} + +inline float_v KFParticleSIMD::GetErrPz () const +{ + return sqrt(abs( GetCovariance(5,5) )); +} + +inline float_v KFParticleSIMD::GetErrE () const +{ + return sqrt(abs( GetCovariance(6,6) )); +} + +inline float_v KFParticleSIMD::GetErrS () const +{ + return sqrt(abs( GetCovariance(7,7) )); +} + +inline float_v KFParticleSIMD::GetErrP () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetMomentum( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrPt () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetPt( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrEta () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetEta( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrPhi () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetPhi( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrMomentum () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetMomentum( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrMass () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetMass( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrDecayLength () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetDecayLength( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrDecayLengthXY () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetDecayLengthXY( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrLifeTime () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetLifeTime( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + +inline float_v KFParticleSIMD::GetErrR () const +{ + float_v par, err; + float_m mask = KFParticleSIMD::GetR( par, err ); + float_v ret(1.e10f); + ret(!mask) = err; + return ret; +} + + +inline float_m KFParticleSIMD::GetP( float_v &P, float_v &SigmaP ) const +{ + /** Calculates particle momentum and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] P - momentum of the particle + ** \param[out] SigmaP - its error + **/ + return KFParticleBaseSIMD::GetMomentum( P, SigmaP ); +} + +inline float_m KFParticleSIMD::GetPt( float_v &Pt, float_v &SigmaPt ) const +{ + /** Calculates particle transverse momentum and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] Pt - transverse momentum of the particle + ** \param[out] SigmaPt - its error + **/ + return KFParticleBaseSIMD::GetPt( Pt, SigmaPt ); +} + +inline float_m KFParticleSIMD::GetEta( float_v &Eta, float_v &SigmaEta ) const +{ + /** Calculates particle pseudorapidity and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] Eta - pseudorapidity of the particle + ** \param[out] SigmaEta - its error + **/ + return KFParticleBaseSIMD::GetEta( Eta, SigmaEta ); +} + +inline float_m KFParticleSIMD::GetPhi( float_v &Phi, float_v &SigmaPhi ) const +{ + /** Calculates particle polar angle at the current point and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] Phi - polar angle of the particle + ** \param[out] SigmaPhi - its error + **/ + return KFParticleBaseSIMD::GetPhi( Phi, SigmaPhi ); +} + +inline float_m KFParticleSIMD::GetMomentum( float_v &P, float_v &SigmaP ) const +{ + /** Calculates particle momentum and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] P - momentum of the particle + ** \param[out] SigmaP - its error + **/ + return KFParticleBaseSIMD::GetMomentum( P, SigmaP ); +} + +inline float_m KFParticleSIMD::GetMass( float_v &M, float_v &SigmaM ) const +{ + /** Calculates the mass of the particle and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] M - mass of the particle + ** \param[out] SigmaM - its error + **/ + return KFParticleBaseSIMD::GetMass( M, SigmaM ); +} + +inline float_m KFParticleSIMD::GetDecayLength( float_v &L, float_v &SigmaL ) const +{ + /** Calculates the decay length of the particle in the laboratory system and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] L - the decay length + ** \param[out] SigmaL - its error + **/ + return KFParticleBaseSIMD::GetDecayLength( L, SigmaL ); +} + +inline float_m KFParticleSIMD::GetDecayLengthXY( float_v &L, float_v &SigmaL ) const +{ + /** Calculates the projection in the XY plane of the decay length of the particle in the laboratory + ** system and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] L - the decay length + ** \param[out] SigmaL - its error + **/ + return KFParticleBaseSIMD::GetDecayLengthXY( L, SigmaL ); +} + +inline float_m KFParticleSIMD::GetLifeTime( float_v &T, float_v &SigmaT ) const +{ + /** Calculates the lifetime times speed of life (ctau) [cm] of the particle in the + ** center of mass frame and its error. If they are well defined returns 0, otherwise 1. + ** The production point should be set before calling this function. + ** \param[out] T - lifetime of the particle [cm] + ** \param[out] SigmaT - its error + **/ + return KFParticleBaseSIMD::GetLifeTime( T, SigmaT ); +} + +inline float_m KFParticleSIMD::GetR( float_v &R, float_v &SigmaR ) const +{ + /** Calculates the distance to the point {0,0,0} and its error. If they are well defined returns 0, otherwise 1. + ** \param[out] R - polar angle of the particle + ** \param[out] SigmaR - its error + **/ + return KFParticleBaseSIMD::GetR( R, SigmaR ); +} + +inline float_v & KFParticleSIMD::X() +{ + return KFParticleBaseSIMD::X(); +} + +inline float_v & KFParticleSIMD::Y() +{ + return KFParticleBaseSIMD::Y(); +} + +inline float_v & KFParticleSIMD::Z() +{ + return KFParticleBaseSIMD::Z(); +} + +inline float_v & KFParticleSIMD::Px() +{ + return KFParticleBaseSIMD::Px(); +} + +inline float_v & KFParticleSIMD::Py() +{ + return KFParticleBaseSIMD::Py(); +} + +inline float_v & KFParticleSIMD::Pz() +{ + return KFParticleBaseSIMD::Pz(); +} + +inline float_v & KFParticleSIMD::E() +{ + return KFParticleBaseSIMD::E(); +} + +inline float_v & KFParticleSIMD::S() +{ + return KFParticleBaseSIMD::S(); +} + +inline int_v & KFParticleSIMD::Q() +{ + return KFParticleBaseSIMD::Q(); +} + +inline float_v & KFParticleSIMD::Chi2() +{ + return KFParticleBaseSIMD::Chi2(); +} + +inline int_v & KFParticleSIMD::NDF() +{ + return KFParticleBaseSIMD::NDF(); +} + +inline float_v & KFParticleSIMD::Parameter ( int i ) +{ + return KFParticleBaseSIMD::Parameter(i); +} + +inline float_v & KFParticleSIMD::Covariance( int i ) +{ + return KFParticleBaseSIMD::Covariance(i); +} + +inline float_v & KFParticleSIMD::Covariance( int i, int j ) +{ + return KFParticleBaseSIMD::Covariance(i,j); +} + +inline float_v * KFParticleSIMD::Parameters () +{ + return fP; +} + +inline float_v * KFParticleSIMD::CovarianceMatrix() +{ + return fC; +} + + +inline void KFParticleSIMD::operator +=( const KFParticleSIMD &Daughter ) +{ + /** Operator to add daughter to the current particle. Calls AddDaughter() function. + ** \param[in] Daughter - the daughter particle + **/ +#ifdef NonhomogeneousField + fField = Daughter.fField; +#endif + KFParticleBaseSIMD::operator +=( Daughter ); +} + + +inline void KFParticleSIMD::AddDaughter( const KFParticleSIMD &Daughter ) +{ + /** Adds daughter to the current particle. Depending on the selected construction method uses: \n + ** 1) Either simplifyed fast mathematics which consideres momentum and energy as + ** independent variables and thus ignores constraint on the fixed mass (fConstructMethod = 0). + ** In this case the mass of the daughter particle can be corrupted when the constructed vertex + ** is added as the measurement and the mass of the output short-lived particle can become + ** unphysical - smaller then the threshold. Implemented in the + ** AddDaughterWithEnergyFit() function \n + ** 2) Or slower but correct mathematics which requires that the masses of daughter particles + ** stays fixed in the construction process (fConstructMethod = 2). Implemented in the + ** AddDaughterWithEnergyFitMC() function. + ** \param[in] Daughter - the daughter particle + **/ +#ifdef NonhomogeneousField + fField = Daughter.fField; +#endif + KFParticleBaseSIMD::AddDaughter( Daughter ); +} + +inline void KFParticleSIMD::Construct( const KFParticleSIMD *vDaughters[], int nDaughters, + const KFParticleSIMD *ProdVtx, Float_t Mass ) +{ + /** Constructs a short-lived particle from a set of daughter particles:\n + ** 1) all parameters of the "this" objects are initialised;\n + ** 2) daughters are added one after another;\n + ** 3) if Parent pointer is not null, the production vertex is set to it;\n + ** 4) if Mass hypothesis >=0 the mass constraint is set. + ** \param[in] vDaughters - array of daughter particles + ** \param[in] nDaughters - number of daughter particles in the input array + ** \param[in] Parent - optional parrent particle + ** \param[in] Mass - optional mass hypothesis + **/ +#ifdef NonhomogeneousField + fField = vDaughters[0]->fField; +#endif + KFParticleBaseSIMD::Construct( ( const KFParticleBaseSIMD**)vDaughters, nDaughters, + ( const KFParticleBaseSIMD*)ProdVtx, Mass ); +} + +inline void KFParticleSIMD::TransportToPoint( const float_v xyz[] ) +{ + /** Transports particle to the distance of closest approach to the point xyz. + ** \param[in] xyz[3] - point, where particle should be transported + **/ + + float_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + const float_v dS = GetDStoPoint(xyz, dsdr); + TransportToDS( dS, dsdr ); +} +#ifdef HomogeneousField +inline void KFParticleSIMD::TransportToVertex( const KFPVertex &v ) +{ + /** Transports particle to the distance of closest approach to the vertex v. + ** \param[in] v - vertex, where particle should be transported + **/ + TransportToPoint( KFParticleSIMD(v).fP ); +} +#endif +inline void KFParticleSIMD::TransportToParticle( const KFParticleSIMD &p ) +{ + /** Transports particle to the distance of closest approach to the particle p. + ** \param[in] p - particle, to which the current particle should be transported. + **/ + float_v dsdr[4][6]; + float_v dS[2]; + GetDStoParticle( p, dS, dsdr ); + TransportToDS( dS[0], dsdr[0] ); +} + +inline float_v KFParticleSIMD::GetDStoPoint( const float_v xyz[3], float_v dsdr[6] ) const +{ + /** Returns dS = l/p parameter, where \n + ** 1) l - signed distance to the DCA point with the input xyz point;\n + ** 2) p - momentum of the particle; \n + ** Also calculates partial derivatives dsdr of the parameter dS over the state vector of the current particle. + ** If "HomogeneousField" is defined KFParticleBaseSIMD::GetDStoPointBz() is called, + ** if "NonhomogeneousField" is defined - KFParticleBaseSIMD::GetDStoPointCBM() + ** \param[in] xyz[3] - point, to which particle should be transported + ** \param[out] dsdr[6] = ds/dr partial derivatives of the parameter dS over the state vector of the current particle + ** \param[in] param - optional parameter, is used in case if the parameters of the particle are rotated + ** to other coordinate system (see GetDStoPointBy() function), otherwise fP are used + **/ +#ifdef HomogeneousField + return KFParticleBaseSIMD::GetDStoPointBz( GetFieldAlice(), xyz, dsdr ); +#endif +#ifdef NonhomogeneousField + return KFParticleBaseSIMD::GetDStoPointCBM( xyz, dsdr ); +#endif + return 0.; +} + + +#ifdef HomogeneousField +inline float_v KFParticleSIMD::GetFieldAlice() +{ + /** Returns value of the constant homogemeous one-component magnetic field Bz, (is defined in case of #ifdef HomogeneousField). */ + return fgBz; +} +#endif + +#ifdef HomogeneousField +inline void KFParticleSIMD::GetFieldValue( const float_v * /*xyz*/, float_v B[] ) const +{ + /** Calculates the Bx, By, Bz components at the point xyz using approximation of the + ** magnetic field along the particle trajectory. + ** \param[in] xyz[3] - X, Y, Z coordiantes of the point where the magnetic field should be calculated + ** \param[out] B[3] - value of X, Y, Z components of the calculated magnetic field at the given point + **/ + B[0] = B[1] = 0; + B[2] = GetFieldAlice(); +} +#endif + +#ifdef NonhomogeneousField +inline void KFParticleSIMD::GetFieldValue( const float_v xyz[], float_v B[] ) const +{ + /** Calculates the Bx, By, Bz components at the point xyz using approximation of the + ** magnetic field along the particle trajectory. + ** \param[in] xyz[3] - X, Y, Z coordiantes of the point where the magnetic field should be calculated + ** \param[out] B[3] - value of X, Y, Z components of the calculated magnetic field at the given point + **/ + KFParticleFieldValue mB = const_cast<KFParticleFieldRegion&>(fField).Get(xyz[2]); + B[0] = mB.x; + B[1] = mB.y; + B[2] = mB.z; +} +#endif + +inline void KFParticleSIMD::GetDStoParticle( const KFParticleBaseSIMD &p, float_v dS[2], float_v dsdr[4][6] )const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particleСЋ \n + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** Also calculates partial derivatives dsdr of the parameters dS[0] and dS[1] over the state vectors of the particles:\n + ** 1) dsdr[0][6] = d(dS[0])/d(param1);\n + ** 2) dsdr[1][6] = d(dS[0])/d(param2);\n + ** 3) dsdr[2][6] = d(dS[1])/d(param1);\n + ** 4) dsdr[3][6] = d(dS[1])/d(param2);\n + ** where param1 are parameters of the current particle fP and + ** param2 are parameters of the second particle p.fP. If "HomogeneousField" is defined KFParticleBaseSIMD::GetDStoParticleBz() is called, + ** if "NonhomogeneousField" is defined - KFParticleBaseSIMD::GetDStoParticleCBM() + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + ** \param[out] dsdr[4][6] - partial derivatives of the parameters dS[0] and dS[1] over the state vectors of the both particles + **/ +#ifdef HomogeneousField + KFParticleBaseSIMD::GetDStoParticleBz( GetFieldAlice(), p, dS, dsdr ) ; +#endif +#ifdef NonhomogeneousField + KFParticleBaseSIMD::GetDStoParticleCBM( p, dS, dsdr ) ; +#endif +} + +inline void KFParticleSIMD::GetDStoParticleFast( const KFParticleBaseSIMD &p, float_v dS[2] )const +{ + /** Calculates dS = l/p parameters for two particles, where \n + ** 1) l - signed distance to the DCA point with the other particle;\n + ** 2) p - momentum of the particleСЋ \n + ** dS[0] is the transport parameter for the current particle, dS[1] - for the particle "p". + ** If "HomogeneousField" is defined KFParticleBaseSIMD::GetDStoParticleBz() is called, + ** if "NonhomogeneousField" is defined - KFParticleBaseSIMD::GetDStoParticleCBM() + ** \param[in] p - second particle + ** \param[out] dS[2] - transport parameters dS for the current particle (dS[0]) and the second particle "p" (dS[1]) + **/ +#ifdef HomogeneousField + KFParticleBaseSIMD::GetDStoParticleBz( GetFieldAlice(), p, dS ) ; +#endif +#ifdef NonhomogeneousField + KFParticleBaseSIMD::GetDStoParticleCBM( p, dS ) ; +#endif +} + +inline void KFParticleSIMD::Transport( float_v dS, const float_v* dsdr, float_v P[], float_v C[], float_v* dsdr1, float_v* F, float_v* F1 ) const +{ + /** Transports the parameters and their covariance matrix of the current particle + ** on a length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. If "HomogeneousField" is defined KFParticleBaseSIMD::TransportBz() + ** is called, if "NonhomogeneousField" - KFParticleBaseSIMD::TransportCBM(). + ** The obtained parameters and covariance matrix are stored to the arrays P and + ** C respectively. P and C can be set to the parameters fP and covariance matrix fC of the current particle. In this + ** case the particle parameters will be modified. Dependence of the transport parameter dS on the state vector of the + ** current particle is taken into account in the covariance matrix using partial derivatives dsdr = d(dS)/d(fP). If + ** a pointer to F is initialised the transport jacobian F = d(fP new)/d(fP old) is stored. + ** Since dS can depend on the state vector r1 of other particle or vertex, the corelation matrix + ** F1 = d(fP new)/d(r1) can be optionally calculated if a pointer F1 is provided. + * Parameters F and F1 should be either both initialised or both set to null pointer. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[in] dsdr[6] = ds/dr - partial derivatives of the parameter dS over the state vector of the current particle + ** \param[out] P[8] - array, where transported parameters should be stored + ** \param[out] C[36] - array, where transported covariance matrix (8x8) should be stored in the lower triangular form + ** \param[in] dsdr1[6] = ds/dr - partial derivatives of the parameter dS over the state vector of another particle + ** or vertex + ** \param[out] F[36] - optional parameter, transport jacobian, 6x6 matrix F = d(fP new)/d(fP old) + ** \param[out] F1[36] - optional parameter, corelation 6x6 matrix betweeen the current particle and particle or vertex + ** with the state vector r1, to which the current particle is being transported, F1 = d(fP new)/d(r1) + **/ +#ifdef HomogeneousField + KFParticleBaseSIMD::TransportBz( GetFieldAlice(), dS, dsdr, P, C, dsdr1, F, F1 ); +#endif +#ifdef NonhomogeneousField + KFParticleBaseSIMD::TransportCBM( dS, dsdr, P, C, dsdr1, F, F1 ); +#endif +} + +inline void KFParticleSIMD::TransportFast( float_v dS, float_v P[] ) const +{ + /** Transports the parametersof the current particle + ** on a length defined by the transport parameter dS = l/p, where l is the signed distance and p is + ** the momentum of the current particle. If "HomogeneousField" is defined KFParticleBaseSIMD::TransportBz() + ** is called, if "NonhomogeneousField" - KFParticleBaseSIMD::TransportCBM(). + ** The obtained parameters are stored to the array P. + ** P can be set to the parameters fP of the current particle. In this + ** case the particle parameters will be modified. + ** \param[in] dS - transport parameter which defines the distance to which particle should be transported + ** \param[out] P[8] - array, where transported parameters should be stored + **/ +#ifdef HomogeneousField + KFParticleBaseSIMD::TransportBz( GetFieldAlice(), dS, P ); +#endif +#ifdef NonhomogeneousField + KFParticleBaseSIMD::TransportCBM( dS, P ); +#endif +} + +#endif diff --git a/external/KFParticle/KFParticle/KFParticleTopoReconstructor.cxx b/external/KFParticle/KFParticle/KFParticleTopoReconstructor.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0132badc59874d9f2fda0851ce9085b214d56447 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleTopoReconstructor.cxx @@ -0,0 +1,1186 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +#include "KFParticleTopoReconstructor.h" + +#ifdef KFPWITHTRACKER +#include "AliHLTTPCCAGBTracker.h" +#endif + +#include "KFParticleSIMD.h" +#include "KFParticleDatabase.h" + +#include <fstream> +#include <iostream> +#include "string" +using std::string; +using std::ofstream; +using std::vector; + +#include "KFPInputData.h" + +KFParticleTopoReconstructor::~KFParticleTopoReconstructor() +{ + /** The default destructor. Deallocates memory for all pointers if objects exist. **/ + if (fKFParticlePVReconstructor) delete fKFParticlePVReconstructor; + if (fKFParticleFinder) delete fKFParticleFinder; + if(fTracks) delete [] fTracks; +} + +#ifdef HomogeneousField +void KFParticleTopoReconstructor::SetField(double b) +{ + /** Sets constant homogeneous one component magnetic field Bz to "b". */ + KFParticle::SetField(b); + KFParticleSIMD::SetField(float(b)); +} +#endif + +#ifdef KFPWITHTRACKER +void KFParticleTopoReconstructor::Init(AliHLTTPCCAGBTracker* tracker, vector<int>* pdg) +{ + if(!fTracks) + fTracks = new KFPTrackVector[NInputSets]; + + fTracks[0].Resize(0); + fTracks[1].Resize(0); + fTracks[2].Resize(0); + fTracks[3].Resize(0); + fTracks[4].Resize(0); + fTracks[5].Resize(0); + fTracks[6].Resize(0); + fTracks[7].Resize(0); + +#ifdef USE_TIMERS + timer.Start(); +#endif // USE_TIMERS + + KFParticle::SetField( tracker->Slice(0).Param().Bz() ); + KFParticleSIMD::SetField( tracker->Slice(0).Param().Bz() ); + + // create and fill array of tracks to init KFParticleTopoReconstructor + const int nTracks = tracker->NTracks(); + fTracks[1].Resize( int(nTracks/float_vLen+1)*float_vLen ); + fTracks[5].Resize( int(nTracks/float_vLen+1)*float_vLen ); + fParticles.clear(); + int iOTr = 0; // index in out array + + float_v alpha(Vc::Zero); + int nElements=0; + + for ( int iTr = 0; iTr < nTracks; iTr++ ) { + // get track params in local CS + + bool ok = true; + const int q = -(tracker->Tracks()[ iTr ].InnerParam().QPt()>=0 ? 1 : -1); + + for(int iParamSet=0; iParamSet<2; iParamSet++) + { + AliHLTTPCCATrackParam trParam; + int arrayIndex = -1; + if(iParamSet==0) + { + arrayIndex = 1; + trParam = tracker->Tracks()[ iTr ].InnerParam(); + } + if(iParamSet==1) + { + arrayIndex = 5; + trParam = tracker->Tracks()[ iTr ].OuterParam(); + } + + const float x0 = 0; + trParam.TransportToXWithMaterial( x0, tracker->Slice(0).Param().cBz( ) ); + + // -- convert parameters + fTracks[arrayIndex].SetParameter(trParam.X(), 0, iOTr); // X + fTracks[arrayIndex].SetParameter(trParam.Y(), 1, iOTr); // Y + fTracks[arrayIndex].SetParameter(trParam.Z(), 2, iOTr); // Z + + const float pt = CAMath::Abs( 1.f / trParam.QPt() ); +// const int q = -(trParam.QPt()>=0 ? 1 : -1); + // if ( pt < 1 ) continue; // dbg + ok = ok && !( trParam.NDF() < 10+5); //if ( trParam.NDF() < 10+5 ) continue; // at least 15 hits in track + ok = ok && !( trParam.Chi2() > 10*trParam.NDF() ); //if ( trParam.Chi2() > 10*trParam.NDF() ) continue; // dbg + // if ( iOTr >= 4 ) continue; // dbg + + const float cosL = trParam.DzDs(); + fTracks[arrayIndex].SetParameter(pt * trParam.GetCosPhi(), 3, iOTr); // Px + fTracks[arrayIndex].SetParameter(pt * trParam.SinPhi() , 4, iOTr); // Py + fTracks[arrayIndex].SetParameter(pt * cosL , 5, iOTr); // Pz + + // -- convert cov matrix + // get jacobian + float J[6][6]; + for (int i = 0; i < 6; i++) + for (int j = 0; j < 6; j++) + J[i][j] = 0; + J[0][0] = 1; // x -> x + J[1][1] = 1; // y -> y + J[2][2] = 1; // z -> z + J[3][3] = -pt * trParam.SinPhi() / trParam.GetCosPhi(); + J[3][5] = -q * pt * pt * trParam.GetCosPhi(); // q/pt -> px + J[4][3] = pt; // sinPhi -> py + J[4][5] = -q* pt * pt * trParam.SinPhi(); // q/pt -> py + J[5][4] = pt; // dz/ds -> pz + J[5][5] = -q* pt * pt * cosL; // q/pt -> pz + + float CovIn[6][6]; // triangular -> symmetric matrix + { + CovIn[0][0] = .001f*.001f; // dx. From nowhere. TODO + for (int i = 1; i < 6; i++) { + CovIn[i][0] = 0; + CovIn[0][i] = 0; + } + int k = 0; + for (int i = 1; i < 6; i++) { + for (int j = 1; j <= i; j++, k++) { + CovIn[i][j] = trParam.Cov()[k]; + CovIn[j][i] = trParam.Cov()[k]; + } + } + } + + float CovInJ[6][6]; // CovInJ = CovIn * J^t + for (int i = 0; i < 6; i++) + for (int j = 0; j < 6; j++) { + CovInJ[i][j] = 0; + for (int k = 0; k < 6; k++) { + CovInJ[i][j] += CovIn[i][k] * J[j][k]; + } + } + + float CovOut[6][6]; // CovOut = J * CovInJ + for (int i = 0; i < 6; i++) + for (int j = 0; j < 6; j++) { + CovOut[i][j] = 0; + for (int k = 0; k < 6; k++) { + CovOut[i][j] += J[i][k] * CovInJ[k][j]; + } + } + + float KFPCov[21]; // symmetric matrix -> triangular + { + int k = 0; + for (int i = 0; i < 6; i++) { + for (int j = 0; j <= i; j++, k++) { + KFPCov[k] = CovOut[i][j]; + ASSERT( !CAMath::Finite(CovOut[i][j]) || CovOut[i][j] == 0 || fabs( 1. - CovOut[j][i]/CovOut[i][j] ) <= 0.05, + "CovOut[" << i << "][" << j << "] == CovOut[" << j << "][" << i << "] : " << CovOut[i][j] << " == " << CovOut[j][i]); + } + } + } + + if(iParamSet == 0) + { // check cov matrix + int k = 0; + for (int i = 0; i < 6; i++) { + for (int j = 0; j <= i; j++, k++) { + ok &= CAMath::Finite( KFPCov[k] ); + } + ok &= ( KFPCov[k-1] > 0 ); + } + } + + if(ok) + { + int trackPDG = -1; + if(pdg) + trackPDG = (*pdg)[iTr]; + + for(int iC=0; iC<21; iC++) + fTracks[arrayIndex].SetCovariance( KFPCov[iC], iC, iOTr); + fTracks[arrayIndex].SetId(iTr, iOTr); + fTracks[arrayIndex].SetPDG(trackPDG, iOTr); + fTracks[arrayIndex].SetQ(q, iOTr); + fTracks[arrayIndex].SetPVIndex(-1, iOTr); + } + } + if (!ok) continue; + + iOTr++; + + // convert into Global CS. Can't be done erlier because in tracker X hasn't correspondent covMatrix elements. + alpha[nElements] = tracker->Tracks()[ iTr ].Alpha(); + nElements++; + if(nElements == float_vLen) + { + fTracks[1].RotateXY( alpha, iOTr-nElements); + fTracks[5].RotateXY( alpha, iOTr-nElements); + nElements=0; + } + } + if(nElements>0) + { + fTracks[1].RotateXY( alpha, iOTr-nElements); + fTracks[5].RotateXY( alpha, iOTr-nElements); + } + + fTracks[0].Resize(iOTr); + fTracks[0].Set(fTracks[1],iOTr,0); + + fTracks[4].Resize(iOTr); + fTracks[4].Set(fTracks[5],iOTr,0); + + fKFParticlePVReconstructor->Init( &fTracks[0], iOTr ); +#ifdef USE_TIMERS + timer.Stop(); + fStatTime[0] = timer.RealTime(); +#endif // USE_TIMERS +} // void KFParticleTopoReconstructor::Init(AliHLTTPCCAGBTracker* tracker) +#endif + +void KFParticleTopoReconstructor::Init(vector<KFParticle> &particles, vector<int>* pdg, vector<int>* nPixelHits) +{ +#ifdef USE_TIMERS + timer.Start(); +#endif // USE_TIMERS + + if(!fTracks) + fTracks = new KFPTrackVector[NInputSets]; + + fParticles.clear(); + fPV.clear(); + + int nTracks = particles.size(); + fTracks[0].Resize(nTracks); + fTracks[1].Resize(0); + fTracks[2].Resize(0); + fTracks[3].Resize(0); + fTracks[4].Resize(0); + fTracks[5].Resize(0); + fTracks[6].Resize(0); + fTracks[7].Resize(0); + + for(int iTr=0; iTr<nTracks; iTr++) + { + int trackPDG = -1; + if(pdg) + trackPDG = (*pdg)[iTr]; + + int npixelhits = 0; + if(nPixelHits) + npixelhits = nPixelHits->at(iTr); + + for(int iP=0; iP<6; iP++) + fTracks[0].SetParameter(particles[iTr].Parameters()[iP], iP, iTr); + for(int iC=0; iC<21; iC++) + fTracks[0].SetCovariance(particles[iTr].CovarianceMatrix()[iC], iC, iTr); +// fTracks[0].SetId(iTr, iTr); + fTracks[0].SetId(particles[iTr].Id(), iTr); + fTracks[0].SetPDG(trackPDG, iTr); + fTracks[0].SetQ(particles[iTr].Q(), iTr); + fTracks[0].SetPVIndex(-1, iTr); + fTracks[0].SetNPixelHits(npixelhits,iTr); + } + + fKFParticlePVReconstructor->Init( &fTracks[0], nTracks ); + +#ifdef USE_TIMERS + timer.Stop(); + fStatTime[0] = timer.RealTime(); +#endif // USE_TIMERS +} + +void KFParticleTopoReconstructor::Init(KFPTrackVector &tracks, KFPTrackVector &tracksAtLastPoint) +{ +#ifdef USE_TIMERS + timer.Start(); +#endif // USE_TIMERS + + if(!fTracks) + fTracks = new KFPTrackVector[NInputSets]; + + fParticles.clear(); + fPV.clear(); + + int nTracks = tracks.Size(); + fTracks[0].Resize(nTracks); + fTracks[0].Set(tracks, nTracks, 0); + fTracks[1].Resize(0); + fTracks[2].Resize(0); + fTracks[3].Resize(0); + fTracks[4].Resize(tracksAtLastPoint.Size()); + fTracks[4].Set(tracksAtLastPoint, tracksAtLastPoint.Size(), 0); + fTracks[5].Resize(0); + fTracks[6].Resize(0); + fTracks[7].Resize(0); + fKFParticlePVReconstructor->Init( &fTracks[0], nTracks ); + +#ifdef USE_TIMERS + timer.Stop(); + fStatTime[0] = timer.RealTime(); +#endif // USE_TIMERS +} + +void KFParticleTopoReconstructor::Init(const KFPTrackVector *particles, const vector<KFParticle>& pv) +{ +#ifdef USE_TIMERS + timer.Start(); +#endif // USE_TIMERS + fParticles.clear(); + fPV.clear(); + + fTracks = const_cast< KFPTrackVector* >(particles); + fChiToPrimVtx[0].resize(fTracks[0].Size()); + fChiToPrimVtx[1].resize(fTracks[1].Size()); + fPV.resize(pv.size()); + + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + fPV[iPV] = KFParticleSIMD(const_cast<KFParticle&>(pv[iPV])); + +#ifdef USE_TIMERS + timer.Stop(); + fStatTime[0] = timer.RealTime(); +#endif // USE_TIMERS +} + +void KFParticleTopoReconstructor::ReconstructPrimVertex(bool isHeavySystem) +{ + /** Runs reconstruction of primary vertices. If "isHeavySystem" is defined - only the + ** best vertex with the maximum number of tracks-contributors is stored. + **/ +#ifdef USE_TIMERS + timer.Start(); +#endif // USE_TIMERS + fKFParticlePVReconstructor->ReconstructPrimVertex(); + + fPV.clear(); + + int nPrimVtx = NPrimaryVertices(); + int nPV = 0; + if(isHeavySystem) + { + if(NPrimaryVertices() > 1) + { + unsigned int nMax = GetPVTrackIndexArray(0).size(); + for(int i=1; i<NPrimaryVertices(); i++) + if(GetPVTrackIndexArray(i).size() > nMax) + { + nMax = GetPVTrackIndexArray(i).size(); + nPV = i; + } + } + + nPrimVtx = 1; + fPV.resize(nPrimVtx); + fPV[0] = GetPrimVertex(nPV); + } + else + { + fPV.resize(nPrimVtx); + for(int iPV=0; iPV<nPrimVtx; iPV++) + fPV[iPV] = GetPrimVertex(iPV); + } + + for(int iPV=0; iPV<NPrimaryVertices(); iPV++) + { + int pvI = iPV; + + if( isHeavySystem ) + { + if(iPV != nPV) continue; + pvI = 0; //save only one PV + } + + vector<int>& tracks = GetPVTrackIndexArray(iPV); + for(unsigned int iTr=0; iTr<tracks.size(); iTr++) + fTracks[0].SetPVIndex(pvI, tracks[iTr]); + } + + if(isHeavySystem) + { + vector<int> pvTracks = fKFParticlePVReconstructor->GetPVTrackIndexArray(nPV); + KFVertex pv = fKFParticlePVReconstructor->GetPrimKFVertex(nPV); + fKFParticlePVReconstructor->CleanPV(); + fKFParticlePVReconstructor->AddPV(pv, pvTracks); + } + +#ifdef USE_TIMERS + timer.Stop(); + fStatTime[1] = timer.RealTime(); +#endif // USE_TIMERS +} // void KFParticleTopoReconstructor::ReconstructPrimVertex + +void KFParticleTopoReconstructor::SortTracks() +{ + /** Sorts input tracks according to they charge, relation to the primary + ** vertex candidates, PDG hypothesis. The tracks after sorting are divided + ** into several groups: \n + ** 0) secondary positive at the first hit position; \n + ** 1) secondary negative at the first hit position; \n + ** 2) primary positive at the first hit position; \n + ** 3) primary negative at the first hit position; \n + ** 4) secondary positive at the last hit position; \n + ** 5) secondary negative at the last hit position; \n + ** 6) primary positive at the last hit position; \n + ** 7) primary negative at the last hit position. \n + ** In each group they are sorted according to PDG: electrons, muons, pions, + ** tracks without PID, kaons, protons, deuterons, tritons, He3, He4. + **/ +#ifdef USE_TIMERS + timer.Start(); +#endif // USE_TIMERS + + int offset[2] = {0, 4}; + int nSets = 2; + + if(fTracks[4].Size() == 0) + nSets = 1; + + for(int iSet=nSets-1; iSet>=0; iSet--) + { + int Size = fTracks[0].Size(); + + vector<KFPTrackIndex> sortedTracks(Size); + kfvector_uint trackIndex[4]; + for(int iTV=0; iTV<4; iTV++) + trackIndex[iTV].resize(Size); + int nTracks[4] = {0,0,0,0}; + + for(int iTr=0; iTr<Size; iTr++) + { + sortedTracks[iTr].fIndex = iTr; + sortedTracks[iTr].fPdg = fTracks[0].PDG()[iTr]; + } + + std::sort(sortedTracks.begin(), sortedTracks.end(), KFPTrackIndex::Compare); + + for(int iTr=0; iTr<Size; iTr++) + { + int iTrSorted = sortedTracks[iTr].fIndex; + + //int q = fTracks[offset[iSet]].Q()[iTrSorted]; + int q = fTracks[0].Q()[iTrSorted]; //take the charge at the first point to avoid ambiguities in array size + if(fTracks[0].PVIndex()[iTrSorted] < 0) //secondary track + { + + if(q<0) //secondary negative track + { + trackIndex[1][nTracks[1]] = iTrSorted; + nTracks[1]++; + } + else //secondary positive track + { + trackIndex[0][nTracks[0]] = iTrSorted; + nTracks[0]++; + } + } + else //primary track + { + if(q<0) //primary negative track + { + trackIndex[3][nTracks[3]] = iTrSorted; + nTracks[3]++; + } + else //primary positive track + { + trackIndex[2][nTracks[2]] = iTrSorted; + nTracks[2]++; + } + } + } + + for(int iTV=1; iTV<4; iTV++) + fTracks[iTV+offset[iSet]].SetTracks(fTracks[offset[iSet]], trackIndex[iTV], nTracks[iTV]); + + KFPTrackVector positive; + positive.SetTracks(fTracks[offset[iSet]], trackIndex[0], nTracks[0]); + fTracks[offset[iSet]].Resize(nTracks[0]); + fTracks[offset[iSet]].Set(positive,nTracks[0],0); + + for(int iTV=0; iTV<4; iTV++) + fTracks[iTV+offset[iSet]].RecalculateLastIndex(); + + //correct index of tracks in primary clusters with respect to the sorted array + if(iSet == 0) + { + vector<int> newIndex(Size); + int iCurrentTrack=0; + for(int iTC=0; iTC<4; iTC++) + { + for(int iTrackIndex=0; iTrackIndex<fTracks[iTC].Size(); iTrackIndex++) + { + newIndex[trackIndex[iTC][iTrackIndex]] = iCurrentTrack; + iCurrentTrack++; + } + } + + for(int iPV=0; iPV<NPrimaryVertices(); iPV++) + for(unsigned int iTrack=0; iTrack<GetPVTrackIndexArray(iPV).size(); iTrack++) + fKFParticlePVReconstructor->GetPVTrackIndexArray(iPV)[iTrack] = newIndex[GetPVTrackIndexArray(iPV)[iTrack]]; + } + } + + fChiToPrimVtx[0].resize(fTracks[0].Size(), -1); + fChiToPrimVtx[1].resize(fTracks[1].Size(), -1); + +#ifdef USE_TIMERS + timer.Stop(); + fStatTime[2] = timer.RealTime(); +#endif // USE_TIMERS +} + +void KFParticleTopoReconstructor::TransportPVTracksToPrimVertex() +{ + /** Tracks which are considered as primary, i.e. were used in fit of candidates + ** for the primary vertex, are transported to the DCA point to the corresponding + ** primary vertex. + **/ + float_v point[3]; + KFParticleSIMD tmpPart; + + for(int iTV=2; iTV<4; iTV++) + { + unsigned int NTr = fTracks[iTV].Size(); + for(unsigned int iTr=0; iTr < NTr; iTr += float_vLen) + { + const int_v& pdg = reinterpret_cast<const int_v&>(fTracks[iTV].PDG()[iTr]); + const int_v& pvIndex = reinterpret_cast<const int_v&>(fTracks[iTV].PVIndex()[iTr]); + + tmpPart.Load(fTracks[iTV], iTr, pdg); + + for(unsigned int iV=0; iV < (unsigned int)float_vLen; iV++) + { + if(iV+iTr >= NTr) continue; + + int iPV = pvIndex[iV]; + point[0][iV] = fPV[iPV].X()[0]; + point[1][iV] = fPV[iPV].Y()[0]; + point[2][iV] = fPV[iPV].Z()[0]; + } + + tmpPart.TransportToPoint(point); + + for(int iP=0; iP<6; iP++) + fTracks[iTV].SetParameter( tmpPart.GetParameter(iP), iP, iTr ); + for(int iC=0; iC<21; iC++) + fTracks[iTV].SetCovariance( tmpPart.GetCovariance(iC), iC, iTr ); + } + } +} + +void KFParticleTopoReconstructor::GetChiToPrimVertex(KFParticleSIMD* pv, const int nPV) +{ + /** Calculates the chi2-deviation from the primary vertex. If several primary vertices + ** are found the minimum value is stored. + ** \param[in] pv - pointer to the array with primary vertices + ** \param[in] nPV - number of the primary vertices in the array + **/ + KFParticleSIMD tmpPart; + + for(int iTV=0; iTV<2; iTV++) + { + unsigned int NTr = fTracks[iTV].Size(); + for(unsigned int iTr=0; iTr < NTr; iTr += float_vLen) + { + uint_v trackIndex = iTr + uint_v::IndexesFromZero(); + const int_v& pdg = reinterpret_cast<const int_v&>(fTracks[iTV].PDG()[iTr]); + tmpPart.Create(fTracks[iTV],trackIndex, pdg); + + float_v& chi2 = reinterpret_cast<float_v&>(fChiToPrimVtx[iTV][iTr]); + chi2(simd_cast<float_m>(trackIndex<NTr)) = 10000.f; + + for(int iPV=0; iPV<nPV; iPV++) + { + const float_v point[3] = {pv[iPV].X(), pv[iPV].Y(), pv[iPV].Z()}; + tmpPart.TransportToPoint(point); + const float_v& chiVec = tmpPart.GetDeviationFromVertex(pv[iPV]); + chi2( (chi2>chiVec) && simd_cast<float_m>(trackIndex<NTr) ) = chiVec; + } + } + } +} + +/** @class ParticleInfo + ** @brief Helper structure to clean particle spectra by competition of PDG hypothesis. + ** @author I.Kisel, M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The structure contains index of the particle and difference in sigmas between the mass of + ** the particle candidate and the table mass of the corresponding PDG hypothesis. Is used to + ** sort the array with particle candidates according to the smallest difference. Then only + ** the best candidate is stored. + **/ +struct ParticleInfo +{ + ParticleInfo():fParticleIndex(-1),fMassDistance(1.e9f) {}; + /** \brief Constructor with all parameters initialised by user. */ + ParticleInfo(int index, float massDistance):fParticleIndex(index),fMassDistance(massDistance) {}; + + /** \brief Sorting function, returns true if the mass difference of "a" is smaller then of "b". The array is sorted according to the smallest difference.*/ + static bool compare(const ParticleInfo& a, const ParticleInfo& b) { return (a.fMassDistance < b.fMassDistance); } + + int fParticleIndex; ///< Index in the array of the particle candidates. + float fMassDistance; ///< difference between the mass of the candidate and the table mass normalised to the width of the peak. +}; + +bool UseParticleInCompetition(int PDG) +{ + /** Defines if a particle with a given PDG code should be used in the + ** competition between reconstructed particle candidates. + **/ + bool use = (PDG == 310) || //K0 + (PDG == 22) || //gamma + (PDG == 111) || //pi0 + (abs(PDG) == 3122) || //Lambda + (abs(PDG) == 3312) || //Xi + (abs(PDG) == 3334) || //Omega + (abs(PDG) == 3003) || //LambdaN + (abs(PDG) == 3103) || //LambdaNN + (abs(PDG) == 3004) || //H3L + (abs(PDG) == 3005) || //H4L + (abs(PDG) == 3006) || //He4L + (abs(PDG) == 3007) || //He5L + (abs(PDG) == 3203) || //LLn + (abs(PDG) == 3008) || //H4LL + (abs(PDG) == 3009) || //H4LL + (abs(PDG) == 3010) || //H5LL + (abs(PDG) == 3011); //He6LL + return use; +} + +void KFParticleTopoReconstructor::SelectParticleCandidates() +{ + /** Cleans reconstructed short-lived particles: \n + ** 1) primary K0, Lambda, anti-Lambda, gamma, hypernuclei are selected; \n + ** 2) competition between candidates defined by the + ** KFParticleTopoReconstructor::UseParticleInCompetition is run; \n + ** 3) dielectron spectrum is cleaned from gamma-electrons; \n + ** 4) in the dielectron spectrum for low mass vector mesons only those + ** candidates are left, which have both daughters identified as electrons. + **/ + + std::vector<ParticleInfo> particleInfo; + std::vector<bool> isUsed(fParticles.size()); + std::vector<bool> deleteCandidate(fParticles.size()); + std::vector<int> bestMother(fParticles.size()); + + for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) + { + isUsed[iParticle] = false; + deleteCandidate[iParticle] = false; + bestMother[iParticle] = -1; + } + + for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) + { + if(!UseParticleInCompetition(fParticles[iParticle].GetPDG())) continue; + + bool isSecondary = 1; + for(int iPV=0; iPV<NPrimaryVertices(); iPV++) + { + KFParticle tmp = fParticles[iParticle]; + tmp.SetProductionVertex(GetPrimVertex(iPV)); + if(tmp.Chi2()/tmp.NDF()<5) + isSecondary=0; + } + if(isSecondary) + deleteCandidate[iParticle] = true; + } + +// for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) +// { +// if(abs(fParticles[iParticle].GetPDG()) == 431 || abs(fParticles[iParticle].GetPDG()) == 4122) +// { +// vector<int> daughterIds(fParticles[iParticle].NDaughters()); +// for(int iDaughter=0; iDaughter<fParticles[iParticle].NDaughters(); iDaughter++) +// daughterIds[iDaughter] = fParticles[fParticles[iParticle].DaughterIds()[iDaughter]].DaughterIds()[0]; +// std::sort(daughterIds.begin(), daughterIds.end()); +// +// for(unsigned int jParticle=0; jParticle<fParticles.size(); jParticle++) +// { +// if(abs(fParticles[jParticle].GetPDG()) == 411) +// { +// vector<int> daughterIdsDPlus(fParticles[jParticle].NDaughters()); +// for(int iDaughter=0; iDaughter<fParticles[jParticle].NDaughters(); iDaughter++) +// daughterIdsDPlus[iDaughter] = fParticles[fParticles[jParticle].DaughterIds()[iDaughter]].DaughterIds()[0]; +// std::sort(daughterIdsDPlus.begin(), daughterIdsDPlus.end()); +// +// if(daughterIdsDPlus.size() != daughterIds.size()) continue; +// +// bool isSameParticle=1; +// for(unsigned int iDaughter=0; iDaughter<daughterIds.size(); iDaughter++) +// isSameParticle &= daughterIds[iDaughter] == daughterIdsDPlus[iDaughter]; +// if(!isSameParticle) continue; +// +// float mass, massSigma; +// fParticles[jParticle].GetMass(mass, massSigma); +// +// if(fabs(mass - KFParticleDatabase::Instance()->GetDPlusMass()) < 3*KFParticleDatabase::Instance()->GetDPlusMassSigma()) +// { +// deleteCandidate[iParticle] = true; +// break; +// } +// } +// } +// } +// } + + + //clean K0 and Lambda + for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) + { + if(deleteCandidate[iParticle]) continue; + if(!UseParticleInCompetition(fParticles[iParticle].GetPDG())) continue; + + float mass, massSigma; + fParticles[iParticle].GetMass(mass, massSigma); + + float massPDG, massPDGSigma; + KFParticleDatabase::Instance()->GetMotherMass(fParticles[iParticle].GetPDG(), massPDG, massPDGSigma); + + float dm1 = fabs(mass - massPDG)/massPDGSigma; +// if(dm1 > 3.f) continue; + + for(unsigned int jParticle=iParticle+1; jParticle<fParticles.size(); jParticle++) + { + if(deleteCandidate[jParticle]) continue; + if(!UseParticleInCompetition(fParticles[jParticle].GetPDG())) continue; + + fParticles[jParticle].GetMass(mass, massSigma); + KFParticleDatabase::Instance()->GetMotherMass(fParticles[jParticle].GetPDG(), massPDG, massPDGSigma); + + float dm2 = fabs(mass - massPDG)/massPDGSigma; +// if(dm2 > 3.f) continue; + + if(! (fParticles[iParticle].DaughterIds()[0] == fParticles[jParticle].DaughterIds()[0] && + fParticles[iParticle].DaughterIds()[1] == fParticles[jParticle].DaughterIds()[1]) ) continue; + + if(dm1 < 3.f || dm2 < 3.f) + { +// if(dm1 < 3.f && dm2<3.f) +// { +// KFParticle part1 = fParticles[iParticle]; +// KFParticle part2 = fParticles[jParticle]; +// +// if(fParticles[iParticle].GetPDG() == 310) +// { +// deleteCandidate[iParticle] = true; +// break; +// } +// else +// { +// deleteCandidate[jParticle] = true; +// } +// } + + if(dm1 < dm2) + { + deleteCandidate[jParticle] = true; + bestMother[fParticles[iParticle].DaughterIds()[0]] = iParticle; + bestMother[fParticles[iParticle].DaughterIds()[1]] = iParticle; + } + else + { + deleteCandidate[iParticle] = true; + bestMother[fParticles[iParticle].DaughterIds()[0]] = jParticle; + bestMother[fParticles[iParticle].DaughterIds()[1]] = jParticle; + break; + } + } + } + } + +// for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) +// { +// if(!(abs(fParticles[iParticle].GetPDG()) == 22)) continue; +// +// bool bothDaughtersElectrons = 1; +// for(int iDaughter=0; iDaughter<fParticles[iParticle].NDaughters(); iDaughter++) +// { +// const int daughterIndex = fParticles[iParticle].DaughterIds()[iDaughter]; +// bothDaughtersElectrons &= abs(fParticles[daughterIndex].GetPDG()) == 11; +// } +// if(!bothDaughtersElectrons) +// { +// deleteCandidate[iParticle] = true; +// continue; +// } +// } + //clean dielectron spectrum + //at first - both electrons are identified + for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) + { + if(deleteCandidate[iParticle]) continue; + if(!(abs(fParticles[iParticle].GetPDG()) == 22)) continue; + +// bool bothDaughtersElectrons = 1; +// for(int iDaughter=0; iDaughter<fParticles[iParticle].NDaughters(); iDaughter++) +// { +// const int daughterIndex = fParticles[iParticle].DaughterIds()[iDaughter]; +// bothDaughtersElectrons &= abs(fParticles[daughterIndex].GetPDG()) == 11; +// } +// if(!bothDaughtersElectrons) continue; + + float mass, massSigma; + fParticles[iParticle].GetMass(mass, massSigma); + float massPDG, massPDGSigma; + KFParticleDatabase::Instance()->GetMotherMass(fParticles[iParticle].GetPDG(), massPDG, massPDGSigma); + float dm = fabs(mass - massPDG)/massPDGSigma; + + if(dm < 3.f) + particleInfo.push_back(ParticleInfo(iParticle, dm)); + } + + std::sort(particleInfo.begin(), particleInfo.end(), ParticleInfo::compare); + + for(unsigned int iPI=0; iPI<particleInfo.size(); iPI++) + { + const int index = particleInfo[iPI].fParticleIndex; + if(deleteCandidate[index]) continue; + + bool isStore = true; + for(int iDaughter=0; iDaughter<fParticles[index].NDaughters(); iDaughter++) + isStore &= !(isUsed[ fParticles[index].DaughterIds()[iDaughter] ]); + + if(isStore) + { + for(int iDaughter=0; iDaughter<fParticles[index].NDaughters(); iDaughter++) + isUsed[ fParticles[index].DaughterIds()[iDaughter] ] = true; + } + else + deleteCandidate[index] = true; + } + + for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) + { + if(deleteCandidate[iParticle]) continue; + if(!(abs(fParticles[iParticle].GetPDG()) == 22)) continue; + + bool bothDaughtersElectrons = 1; + for(int iDaughter=0; iDaughter<fParticles[iParticle].NDaughters(); iDaughter++) + { + const int daughterIndex = fParticles[iParticle].DaughterIds()[iDaughter]; + bothDaughtersElectrons &= abs(fParticles[daughterIndex].GetPDG()) == 11; + } + + float mass, massSigma; + fParticles[iParticle].GetMass(mass, massSigma); + float massPDG, massPDGSigma; + KFParticleDatabase::Instance()->GetMotherMass(fParticles[iParticle].GetPDG(), massPDG, massPDGSigma); + float dm = fabs(mass - massPDG)/massPDGSigma; + +// if( (bothDaughtersElectrons && dm > 3.f) || !bothDaughtersElectrons) + if( dm > 3.f ) + { + bool isStore = true; + for(int iDaughter=0; iDaughter<fParticles[iParticle].NDaughters(); iDaughter++) + isStore &= !(isUsed[ fParticles[iParticle].DaughterIds()[iDaughter] ]); + if(!isStore) + { + deleteCandidate[iParticle] = true; + } + } + } + + // clean LMVM spectrum + for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) + { + if(!(abs(fParticles[iParticle].GetPDG()) == 100113 || abs(fParticles[iParticle].GetPDG()) == 443)) continue; + + bool bothDaughtersElectrons = 1; + for(int iDaughter=0; iDaughter<fParticles[iParticle].NDaughters(); iDaughter++) + { + const int daughterIndex = fParticles[iParticle].DaughterIds()[iDaughter]; + bothDaughtersElectrons &= abs(fParticles[daughterIndex].GetPDG()) == 11; + } + if(!bothDaughtersElectrons) + { + deleteCandidate[iParticle] = true; + continue; + } + + bool isStore = true; + for(int iDaughter=0; iDaughter<fParticles[iParticle].NDaughters(); iDaughter++) + isStore &= !(isUsed[ fParticles[iParticle].DaughterIds()[iDaughter] ]); + if(!isStore) + { + deleteCandidate[iParticle] = true; + } + } +// for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) +// { +// if(deleteCandidate[iParticle]) continue; +// if(abs(fParticles[iParticle].GetPDG()) == 310 || abs(fParticles[iParticle].GetPDG()) == 3122) +// { +// // float mass, massSigma; +// // fParticles[iParticle].GetMass(mass, massSigma); +// // +// float massPDG, massPDGSigma; +// KFParticleDatabase::Instance()->GetMotherMass(fParticles[iParticle].GetPDG(), massPDG, massPDGSigma); +// // +// // float dm = fabs(mass - massPDG)/massPDGSigma; +// +// KFParticle tmp = fParticles[iParticle]; +// // tmp.SetNonlinearMassConstraint(massPDG); +// +// particleInfo.push_back(ParticleInfo(iParticle, tmp.Chi2())); +// } +// } +// +// std::sort(particleInfo.begin(), particleInfo.end(), ParticleInfo::compare); +// +// for(unsigned int iPI=0; iPI<particleInfo.size(); iPI++) +// { +// const int index = particleInfo[iPI].fParticleIndex; +// if(deleteCandidate[index]) continue; +// +// bool isStore = true; +// for(int iDaughter=0; iDaughter<fParticles[index].NDaughters(); iDaughter++) +// isStore &= !(isUsed[ fParticles[index].DaughterIds()[iDaughter] ]); +// +// if(isStore) +// { +// for(int iDaughter=0; iDaughter<fParticles[index].NDaughters(); iDaughter++) +// isUsed[ fParticles[index].DaughterIds()[iDaughter] ] = true; +// } +// else +// deleteCandidate[index] = true; +// } + + for(int iParticle=0; iParticle<int(fParticles.size()); iParticle++) + { + if(deleteCandidate[iParticle]) continue; + + for(int iDaughter=0; iDaughter<fParticles[iParticle].NDaughters(); iDaughter++) + if(bestMother[fParticles[iParticle].DaughterIds()[iDaughter]] != iParticle && bestMother[fParticles[iParticle].DaughterIds()[iDaughter]] > -1) + { + deleteCandidate[iParticle] = true; + break; + } + } + + for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) + if(deleteCandidate[iParticle]) + fParticles[iParticle].SetPDG(-1); +} + +bool KFParticleTopoReconstructor::ParticleHasRepeatingDaughters(const KFParticle& particle) +{ + /** Checks if the provided particle candidate has two or more daughter tracks + ** with the same index including tracks from the daughter particles in the decay + ** chains. Such candidates should be rejected. + **/ + if(particle.NDaughters() < 2) return 0; + + vector<int> daughters; + GetListOfDaughterTracks(particle, daughters); + std::sort(daughters.begin(), daughters.end()); + bool sameDaughter=0; + for(unsigned int iDaughter=1; iDaughter<daughters.size(); iDaughter++) + { + if(daughters[iDaughter] == daughters[iDaughter-1]) + { + sameDaughter = 1; + break; + } + } + return sameDaughter; +} + +void KFParticleTopoReconstructor::GetListOfDaughterTracks(const KFParticle& particle, vector<int>& daughters) +{ + /** Returns the list of indices of all tracks used for construction of the given particle + ** including tracks from the short-lived daughter particles in the decay chain. + ** \param[in] particle - the particle to be processed + ** \param[out] daughters - a vector with indices of all daughter tracks + **/ + if(particle.NDaughters() == 1) + daughters.push_back( particle.DaughterIds()[0] ); + else + for(int iDaughter=0; iDaughter<particle.NDaughters(); iDaughter++) + GetListOfDaughterTracks( fParticles[ particle.DaughterIds()[iDaughter] ], daughters); +} + +void KFParticleTopoReconstructor::ReconstructParticles() +{ + /** Runs reconstruction of the short-lived particles by KFParticleFinder. + ** At first, primary tracks are transported to the DCA point with the + ** corresponding primary vertices for better precision, + ** chi2-deviation of the secondary tracks to the primary vertex is + ** calculated, and than KFParticleFinder is run. Optionally cleanup of + ** the output array of particle candidates can be run. + **/ +#ifdef USE_TIMERS + timer.Start(); +#endif // USE_TIMERS + + fParticles.clear(); + + if(fPV.size() < 1) return; + + TransportPVTracksToPrimVertex(); + //calculate chi to primary vertex, chi = sqrt(dr C-1 dr) + GetChiToPrimVertex(&(fPV[0]), fPV.size()); + + fKFParticleFinder->FindParticles(fTracks, fChiToPrimVtx, fParticles, fPV, fPV.size()); +// #pragma omp critical +// std::cout << "NPart " << fParticles.size() << " " << fTracks[0].Size() << " "<< fTracks[1].Size() << " " << fTracks[2].Size() << " " << fTracks[3].Size()<< std::endl; + +// for(unsigned int iParticle=0; iParticle<fParticles.size(); iParticle++) +// if(ParticleHasRepeatingDaughters(fParticles[iParticle])) +// fParticles[iParticle].SetPDG(-1); +// +// SelectParticleCandidates(); + +#ifdef USE_TIMERS + timer.Stop(); + fStatTime[3] = timer.RealTime(); +#endif // USE_TIMERS +} // void KFParticleTopoReconstructor::ReconstructPrimVertex + +#ifdef WITHSCIF +void KFParticleTopoReconstructor::SendDataToXeonPhi( int iHLT, scif_epd_t& endpoint, void* buffer, off_t& offsetServer, off_t& offsetSender, float Bz) +{ + //pack the input data + int* data = reinterpret_cast<int*>(buffer); + int dataSize = NInputSets + 1 + 1; //sizes of the track vectors and pv vector, and field + for(int iSet=0; iSet<NInputSets; iSet++) + dataSize += fTracks[iSet].DataSize(); + dataSize += fPV.size() * 9; + + for(int iSet=0; iSet<NInputSets; iSet++) + data[iSet] = fTracks[iSet].Size(); + data[NInputSets] = fPV.size(); + + float& field = reinterpret_cast<float&>(data[NInputSets+1]); + field = Bz; + + int offset = NInputSets+2; + + for(int iSet=0; iSet<NInputSets; iSet++) + fTracks[iSet].SetDataToVector(data, offset); + + for(int iP=0; iP<3; iP++) + { + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + { + float& tmpFloat = reinterpret_cast<float&>(data[offset + iPV]); + tmpFloat = fPV[iPV].Parameter(iP)[0]; + } + offset += fPV.size(); + } + + for(int iC=0; iC<6; iC++) + { + for(unsigned int iPV=0; iPV<fPV.size(); iPV++) + { + float& tmpFloat = reinterpret_cast<float&>(data[offset + iPV]); + tmpFloat = fPV[iPV].Covariance(iC)[0]; + } + offset += fPV.size(); + } + + //send the input data to Xeon Phi + int msgSize = sizeof(int) * dataSize;//1000 * sizeof(int); + + const uint16_t portSenderId = 2000 + iHLT; + + int controlSignal = portSenderId; + scif_send(endpoint, &msgSize, sizeof(int), SCIF_SEND_BLOCK); + scif_recv(endpoint, &controlSignal, sizeof(controlSignal), 1); + if(controlSignal != portSenderId) { std::cout << controlSignal << " " << portSenderId << std::endl; return; } + + int ret = scif_writeto(endpoint, offsetServer, msgSize, offsetSender, 0); + if ( ret == -1 ) std::cout << "Fail sending array to the server. Error: " << errno << std::endl; + + scif_send(endpoint, &controlSignal, sizeof(int), SCIF_SEND_BLOCK); // synchronization +} +#endif + +void KFParticleTopoReconstructor::SaveInputParticles(const string prefix, bool onlySecondary) +{ + /** Stores input tracks to the output file. If the "onlySecondary" flag is set, + ** only secondary particles are stored. As an input function takes the full path + ** to the folder, where output files should be stored. For each event a corresponding + ** file will be created in the provided folder. The name of the file is + ** "event#_KFPTracks.data", where "#" is the number of the event. + ** \param[in] prefix - path to the output folder + ** \param[in] onlySecondary - flag shows if only secondary tracks should be stored + **/ + static int nEvents = 0; + string outFileName = "/event"; + char Result[16]; // string which will contain the number + sprintf ( Result, "%d", nEvents ); + outFileName += string(Result); + outFileName += "_KFPTracks.data"; + + ofstream out((prefix+outFileName).data()); + + //save tracks. tracks are already propagated to the beam + + int nSets = NInputSets; + if(onlySecondary) + nSets = 2; + + float B[3] = {0.f}, r[3] = {0.f}; + KFParticle kfpTmp; + kfpTmp.GetFieldValue(r, B); + out << B[2] << std::endl; + out << nSets << std::endl; + for(int iSet=0; iSet<nSets; iSet++) + { + out << fTracks[iSet].Size() << std::endl; + for(int iP=0; iP<6; iP++) + { + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + out << fTracks[iSet].Parameter(iP)[iTr]<< " "; + out << std::endl; + } + + for(int iC=0; iC<21; iC++) + { + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + out << fTracks[iSet].Covariance(iC)[iTr]<< " "; + out << std::endl; + } + + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + out << fTracks[iSet].Id()[iTr] << " "; + out << std::endl; + + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + out << fTracks[iSet].PDG()[iTr] << " "; + out << std::endl; + + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + out << fTracks[iSet].Q()[iTr] << " "; + out << std::endl; + + for(int iTr=0; iTr<fTracks[iSet].Size(); iTr++) + out << fTracks[iSet].PVIndex()[iTr] << " "; + out << std::endl; + + out << fTracks[iSet].LastElectron() << " " + << fTracks[iSet].LastMuon() << " " + << fTracks[iSet].LastPion() << " " + << fTracks[iSet].LastKaon() << " " + << fTracks[iSet].LastProton() << std::endl; + } + + //Save PVs + out << fPV.size() << std::endl; + for(unsigned int iPV=0; iPV < fPV.size(); iPV++) + { + out << fPV[iPV].X()[0] << " " << fPV[iPV].Y()[0] << " " << fPV[iPV].Z()[0] << " " << std::endl; + + for(int iC=0; iC<6; iC++) + out << fPV[iPV].GetCovariance(iC)[0] << " "; + out << std::endl; + } + out.close(); + + nEvents++; +} + diff --git a/external/KFParticle/KFParticle/KFParticleTopoReconstructor.h b/external/KFParticle/KFParticle/KFParticleTopoReconstructor.h new file mode 100644 index 0000000000000000000000000000000000000000..81df1eca06e4cb111778d6d8addbc262b9263e70 --- /dev/null +++ b/external/KFParticle/KFParticle/KFParticleTopoReconstructor.h @@ -0,0 +1,276 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFParticleTopoReconstructor_H +#define KFParticleTopoReconstructor_H + +#include "KFParticlePVReconstructor.h" +#include "KFParticleFinder.h" + +#include <vector> +#include <string> + +#include "KFPTrackVector.h" +#include "KFParticleSIMD.h" + +#ifdef USE_TIMERS +#ifndef HLTCA_STANDALONE +#include "TStopwatch.h" +typedef TStopwatch Stopwatch; +#else +#include "Stopwatch.h" +#endif +#endif + +#ifdef KFPWITHTRACKER +class AliHLTTPCCAGBTracker; +#endif + +#ifdef WITHSCIF +#include <scif.h> +#endif + +/** @class KFParticleTopoReconstructor + ** @brief Class for reconstruction of the full event topology including primary vertices and short-lived particles. + ** @author I.Kisel, M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class receives as an input tracks from the track finder (both at first and last hit positions) + ** with the PDG hypothesis, reconstructs primary vertex candidates, divides tracks into secondary and + ** primary, each of these groups are subdivided into positive and negative tracks, then they are + ** sorted according to the PDG hypothesis, short-lived particles are constructed, optionally competition + ** between different particle hypothesis is run for the constructed candidates. + **/ + +class KFParticleTopoReconstructor{ + public: + KFParticleTopoReconstructor():fKFParticlePVReconstructor(0),fKFParticleFinder(0),fTracks(0), fParticles(0), fPV(0), fNThreads(1) +#ifdef USE_TIMERS + ,fTime(0.),timer() +#endif + { + /** The default constructor. Allocates memory for all pointers. **/ +#ifdef USE_TIMERS + for ( int i = 0; i < fNTimers; i++ ) fStatTime[i] = 0; +#endif + fKFParticlePVReconstructor = new KFParticlePVReconstructor; + + fKFParticleFinder = new KFParticleFinder; + fKFParticleFinder->SetNThreads(fNThreads); + } + ~KFParticleTopoReconstructor(); + +#ifdef KFPWITHTRACKER + /** Copies tracks from the standalone CA track finder to the vector KFParticleTopoReconstructor::fTracks + ** assuming a given pdg hypothesis for each track. Tracks are rotated to the global coordinate system + ** and checked to have finite parameters. The KFParticleTopoReconstructor::fKFParticlePVReconstructor + ** is initialised with the copied tracks. + ** \param[in] tracker - the standalone CA track finder + ** \param[in] pdg - pointer to the vector with PDG hypothesis for each track, if pointer is not provided + ** "-1" is set as the pdg hypothesis for all tracks + **/ + void Init(AliHLTTPCCAGBTracker* tracker, std::vector<int>* pdg=0); // init array of particles +#endif + /** Copies provided particles to the vector KFParticleTopoReconstructor::fTracks + ** assuming a given PDG hypothesis for each particle. If pointer to pdg-vector is not provided + ** "-1" PDG is assigned to each input particle. If pointer to number of precise measurements + ** is provided then this field of KFPTrackVector is also initialised. + ** Only tracks at the first hit position are initialised by this method. + ** The KFParticleTopoReconstructor::fKFParticlePVReconstructor is initialised with the copied tracks. + ** \param[in] particles - vector with input particles (tracks) + ** \param[in] pdg - pointer to the vector with PDG hypothesis for each track, if pointer is not provided + ** "-1" is set as the pdg hypothesis for all tracks + ** \param[in] nPixelHits - pointer to the vector with number of precise measurement in each track + **/ + void Init(std::vector<KFParticle> &particles, std::vector<int>* pdg=0, std::vector<int>* nPixelHits=0); + /** Initialises the pointer KFParticleTopoReconstructor::fTracks with the external pointer "particles". + ** Primary vertices are assumed to be found and are also provided externally. Only reconstruction + ** of short-lived particles should be run if this initialisation method is used. + ** After reconstruction of short-lived particles the KFParticleTopoReconstructor::DeInit() method + ** should be called, otherwise an external memory will be released that can lead to the memory + ** corruption and segmentation fault. + ** \param[in] particles - pointer to the external vectors with input tracks + ** \param[in] pv - vector with externally reconstructed primary vertex candidates + **/ + void Init(const KFPTrackVector *particles, const std::vector<KFParticle>& pv); + /** Initialises tracks at the first and last hit positions. + ** The KFParticleTopoReconstructor::fKFParticlePVReconstructor is initialised with the copied + ** tracks at the first hit position. + ** \param[in] tracks - vector with the tracks at the first hit position + ** \param[in] tracksAtLastPoint - vector with the tracks at the last hit position + **/ + void Init(KFPTrackVector &tracks, KFPTrackVector &tracksAtLastPoint); + + /** \brief Sets input clusters of the electromagnetic calorimeter to KFParticleFinder. */ + void SetEmcClusters(KFPEmcCluster* clusters) { fKFParticleFinder->SetEmcClusters(clusters); } + void SetMixedEventAnalysis() { fKFParticleFinder->SetMixedEventAnalysis(); } ///< KFParticleFinder is forced to be run in the mixed event analysis mode. + + void DeInit() { fTracks = NULL; } ///< Sets a pointer to the input tracks KFParticleTopoReconstructor::fTracks to NULL. + /** \brief Cleans all candidates for primary vertices and short-lived particles. */ + void Clear() { fParticles.clear(); fPV.clear(); fKFParticlePVReconstructor->CleanPV(); } + + void ReconstructPrimVertex(bool isHeavySystem = 1); // find primary vertex + void SortTracks(); //sort tracks according to the pdg hypothesis and pv index + void ReconstructParticles(); //find short-lived particles + void SelectParticleCandidates(); //clean particle candidates: track can belong to only one particle +#ifdef WITHSCIF + void SendDataToXeonPhi( int iHLT, scif_epd_t& endpoint, void* buffer, off_t& offsetServer, off_t& offsetSender, float Bz); +#endif + int NPrimaryVertices() const { return fKFParticlePVReconstructor->NPrimaryVertices(); } ///< Returns number of the found primary vertex candidates. + KFParticle &GetPrimVertex(int iPV=0) const { return fKFParticlePVReconstructor->GetPrimVertex(iPV); } ///< Return primary vertex candidate with index "iPV". + KFVertex &GetPrimKFVertex(int iPV=0) const { return fKFParticlePVReconstructor->GetPrimKFVertex(iPV); } ///< Return primary vertex candidate with index "iPV". + /** Returns vector with track indices from a cluster with index "iPV". */ + std::vector<int>& GetPVTrackIndexArray(int iPV=0) const { return fKFParticlePVReconstructor->GetPVTrackIndexArray(iPV); } + + std::vector<KFParticle> const &GetParticles() const { return fParticles; } ///< Returns constant reference to the vector with short-lived particle candidates. + /** \brief Logically kills the candidate for short-lived particle with index "iParticle" by setting its PDG hypothesis to "-1". */ + void RemoveParticle(const int iParticle) { if(iParticle>=0 && iParticle<int(fParticles.size())) fParticles[iParticle].SetPDG(-1); } + const KFPTrackVector* GetTracks() const { return fTracks; } ///< Returns a pointer to the arrays with tracks KFParticleTopoReconstructor::fTracks. + const kfvector_float* GetChiPrim() const { return fChiToPrimVtx; } ///<Returns a pointer to the arrays with chi2-deviations KFParticleTopoReconstructor::fChiToPrimVtx. + + KFParticleFinder* GetKFParticleFinder() { return fKFParticleFinder; } ///< Returns a pointer to the KFParticleFinder object. + const KFParticleFinder* GetKFParticleFinder() const { return fKFParticleFinder; } ///< Returns a constant pointer to the KFParticleFinder object. + + void CleanPV() { + /** Cleans vectors with primary vertex candidates and corresponding clusters by calling KFParticlePVReconstructor::CleanPV(). */ + fKFParticlePVReconstructor->CleanPV(); + } + void AddPV(const KFVertex &pv, const std::vector<int> &tracks) { + /** Adds externally found primary vertex to the list together with the cluster of + ** tracks from this vertex. + ** \param[in] pv - external primary vertex + ** \param[in] tracks - vector with indices of tracks associated with the provided primary vertex. + **/ + fKFParticlePVReconstructor->AddPV(pv,tracks); + KFParticle pvPart=pv; + fPV.push_back(pvPart); + fKFParticleFinder->SetNPV(fPV.size()); + } + void AddPV(const KFVertex &pv) { + /** Adds externally found primary vertex to the list. + ** \param[in] pv - external primary vertex + **/ + fKFParticlePVReconstructor->AddPV(pv); + KFParticle pvPart=pv; + fPV.push_back(pvPart); + fKFParticleFinder->SetNPV(fPV.size()); + } + void FillPVIndices() + { + /** Assigns index of the corresponding primary vertex to each input track + ** according to the clusters reconstructed by KFParticlePVReconstructor. */ + if(fTracks) + for(int iPV=0; iPV<NPrimaryVertices(); iPV++) + for(unsigned int iPVTrack=0; iPVTrack<GetPVTrackIndexArray(iPV).size(); iPVTrack++) + fTracks[0].SetPVIndex(iPV,GetPVTrackIndexArray(iPV)[iPVTrack]); + } + /** \brief Adds an external particle candidate to the vector. */ + void AddParticle(const KFParticle& particle) { fParticles.push_back(particle); } + /** \brief Adds an external particle candidate to the vector with primary or secondary candidates of KFParticleFinde. */ + void AddCandidate(const KFParticle& candidate, int iPV = -1) { fKFParticleFinder->AddCandidate(candidate, iPV); } + + void SetBeamLine(KFParticle& p) { fKFParticlePVReconstructor->SetBeamLine(p); } ///< Sets the beam line for precise reconstruction of the primary vertex. +#ifdef HomogeneousField + void SetField(double b); +#endif + + //speed measurements +#ifdef USE_TIMERS + void SetTime(double d) { fTime = d; } ///< Sets the total execution time. + double Time() const { return fTime; } ///< Returns the total execution time. + /** Returns the time of the part of the topology reconstruction according to the index "iTimer":\n + ** 0) initialisation, \n + ** 1) reconstruction of primary vertices, \n + ** 2) sorting of input particles, \n + ** 3) reconstruction of short-lived particles. + **/ + double StatTime( int iTimer ) const { return fStatTime[iTimer]; } + int NTimers() const { return fNTimers; } ///< returns number of the timers to measure performance of different parts of the procedure. +#endif + + void SaveInputParticles(const std::string prefix = "KFPData", bool onlySecondary = 0); + void SetNThreads(short int n) { fNThreads=n; } ///< Sets the number of threads to be run in KFParticleFinder. Currently is not used. + + void SetChi2PrimaryCut(float chi) { + /** Sets the same chi-primary cut to the primary vertex finder and KF Particle Finder. */ + fKFParticlePVReconstructor->SetChi2PrimaryCut(chi); + fKFParticleFinder->SetChiPrimaryCut2D(chi); + } + + void GetListOfDaughterTracks(const KFParticle& particle, std::vector<int>& daughters); + bool ParticleHasRepeatingDaughters(const KFParticle& particle); + + const KFParticleTopoReconstructor &operator=(const KFParticleTopoReconstructor& a) + { + /** Copy operator. All pointers are set to zero, other members are copied. Returns the current object after copying is finished. **/ + fKFParticlePVReconstructor = 0; + fKFParticleFinder = 0; + fTracks = 0; + + fNThreads = a.fNThreads; + + return *this; + } + + /** \brief A copy constructor. All pointers are set to zero, other members are copied. **/ + KFParticleTopoReconstructor(const KFParticleTopoReconstructor& a):fKFParticlePVReconstructor(0),fKFParticleFinder(0),fTracks(0), fParticles(), fPV(), fNThreads(a.fNThreads) +#ifdef USE_TIMERS + ,fTime(0.),timer() +#endif + { + } + + /** Copy cuts from KF Particle Finder of another topology reconstructor object topo. */ + void CopyCuts(const KFParticleTopoReconstructor* topo) { fKFParticleFinder->CopyCuts(topo->fKFParticleFinder); } + private: + + void GetChiToPrimVertex(KFParticleSIMD* pv, const int nPV); + void TransportPVTracksToPrimVertex(); + + KFParticlePVReconstructor* fKFParticlePVReconstructor; ///< Pointer to the KFParticlePVReconstructor. Allocated in the constructor. + KFParticleFinder* fKFParticleFinder; ///< Pointer to the KFParticleFinder object. Allocated in the constructor. + /** Pointer to the array with the input tracks. Memory is allocated by the Init() functions. + ** For reconstruction of primary vertex candidates unsorted tracks are used. For reconstruction of short-lived particles + ** Tracks should be sorted by the KFParticleTopoReconstructor::SortTracks() function. The tracks after sorting are divided + ** into several groups: \n + ** 0) secondary positive at the first hit position; \n + ** 1) secondary negative at the first hit position; \n + ** 2) primary positive at the first hit position; \n + ** 3) primary negative at the first hit position; \n + ** 4) secondary positive at the last hit position; \n + ** 5) secondary negative at the last hit position; \n + ** 6) primary positive at the last hit position; \n + ** 7) primary negative at the last hit position. + **/ + KFPTrackVector *fTracks; + kfvector_float fChiToPrimVtx[2]; ///< Chi2-deviation of the secondary tracks. + std::vector<KFParticle> fParticles; ///< Vector of the reconstructed candidates of short-lived particles. + std::vector<KFParticleSIMD, KFPSimdAllocator<KFParticleSIMD> > fPV; ///< Vector of the reconstructed primary vertices. + + short int fNThreads; ///< Number of threads to be run in KFParticleFinder. Currently is not used. + + //speed measurements +#ifdef USE_TIMERS + double fTime; ///< Total run time. + static const int fNTimers = 4; ///< Number of timers to measure different part of the code. + /** \brief Execution time of different parts of the code: initialisation, reconstruction of primary vertices, + ** sorting of input particles, reconstruction of short-lived particles. */ + double fStatTime[fNTimers]; + Stopwatch timer; ///< Timer. +#endif // USE_TIMERS + +}__attribute__((aligned(sizeof(float_v)))); // class KFParticleTopoReconstructor + + + +#endif // KFParticleTopoReconstructor_H + diff --git a/external/KFParticle/KFParticle/KFVertex.cxx b/external/KFParticle/KFParticle/KFVertex.cxx new file mode 100644 index 0000000000000000000000000000000000000000..40630d225a53dacbd9baeedb8a799aa63e8fd492 --- /dev/null +++ b/external/KFParticle/KFParticle/KFVertex.cxx @@ -0,0 +1,139 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author S.Gorbunov, I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +#include "KFVertex.h" + +#ifndef KFParticleStandalone +ClassImp(KFVertex); +#endif + +KFVertex::KFVertex( const KFPVertex &vertex ): fIsConstrained(0) +{ + /** Constructor from KFPVertex. **/ + + vertex.GetXYZ( fP ); + vertex.GetCovarianceMatrix( fC ); + fChi2 = vertex.GetChi2(); + fNDF = 2*vertex.GetNContributors() - 3; + fQ = 0; + fAtProductionVertex = 0; + fSFromDecay = 0; +} + +void KFVertex::SetBeamConstraint( float x, float y, float z, + float errX, float errY, float errZ ) +{ + /** Sets a soft beam constraint on the vertex position. + ** \param[in] x, y, z - coordinates of the constraint + ** \param[in] errX, errY, errZ - corresponding errors + **/ + fP[0] = x; + fP[1] = y; + fP[2] = z; + fC[0] = errX*errX; + fC[1] = 0; + fC[2] = errY*errY; + fC[3] = 0; + fC[4] = 0; + fC[5] = errZ*errZ; + fIsConstrained = 1; +} + +void KFVertex::SetBeamConstraintOff() +{ + /** Switches off the constraint. Should be called before KFVertex::ConstructPrimaryVertex() **/ + fIsConstrained = 0; +} + +void KFVertex::ConstructPrimaryVertex( const KFParticle *vDaughters[], + int nDaughters, Bool_t vtxFlag[], + float ChiCut ) +{ + /** Reconstructs the primary vertex from a set of particles. Reconstruction is + ** parformed in three steps:\n + ** 1) vertex seed is constructed from all particles; \n + ** 2) if particle deviates more then on the "ChiCut" it is rejected; \n + ** 3) the final vertex is constructed from the set of remaining particles.\n + ** Rejected particles are marked with "false" in the output array of flags. + ** \param[in] vDaughters - input array of pointers to the particles + ** \param[in] nDaughters - number of particles in the input array + ** \param[out] vtxFlag - array of flags showing if particle was used in the + ** vertex fit, if yes - set to "true" + ** \param[in] ChiCut - cut on the chi2-deviation of the particle from the created + ** seed, by default the cut is set to 3.5 + **/ + + if( nDaughters<2 ) return; + float constrP[3]={fP[0], fP[1], fP[2]}; + float constrC[6]={fC[0], fC[1], fC[2], fC[3], fC[4], fC[5]}; + + Construct( vDaughters, nDaughters, 0, -1 ); + +// SetVtxGuess( fVtxGuess[0], fVtxGuess[1], fVtxGuess[2] ); + + for( int i=0; i<nDaughters; i++ ) vtxFlag[i] = 1; + + Int_t nRest = nDaughters; +// while( nRest>2 ) +// { +// float worstChi = 0.; +// Int_t worstDaughter = 0; +// for( Int_t it=0; it<nDaughters; it++ ){ +// if( !vtxFlag[it] ) continue; +// const KFParticle &p = *(vDaughters[it]); +// //KFVertex tmp = *this - p; +// //float chi = p.GetDeviationFromVertex( tmp ); +// float chi = p.GetDeviationFromVertex( *this ); +// if( worstChi < chi ){ +// worstChi = chi; +// worstDaughter = it; +// } +// } +// if( worstChi < ChiCut ) break; +// std::cout <<"worst 1 " << worstDaughter << " " << worstChi << std::endl; +// vtxFlag[worstDaughter] = 0; +// //*this -= *(vDaughters[worstDaughter]); +// nRest--; +// } + + for( Int_t it=0; it<nDaughters; it++ ){ + const KFParticle &p = *(vDaughters[it]); + float chi = p.GetDeviationFromVertex( *this ); + if( chi >= ChiCut ){ + vtxFlag[it] = 0; + nRest--; + } + } + + if( nRest>=2 ) {// final refit +// SetVtxGuess( fP[0], fP[1], fP[2] ); + if( fIsConstrained ){ + fP[0] = constrP[0]; + fP[1] = constrP[1]; + fP[2] = constrP[2]; + for( int i=0; i<6; i++ ) fC[i] = constrC[i]; + } + int nDaughtersNew=0; + const KFParticle **vDaughtersNew=new const KFParticle *[nDaughters]; + for( int i=0; i<nDaughters; i++ ){ + if( vtxFlag[i] ) vDaughtersNew[nDaughtersNew++] = vDaughters[i]; + } + Construct( vDaughtersNew, nDaughtersNew, 0, -1 ); + if (vDaughtersNew) delete[] vDaughtersNew; + } + + if( nRest<=2 && GetChi2() > ChiCut*ChiCut*GetNDF() ) { + for( int i=0; i<nDaughters; i++ ) vtxFlag[i] = 0; + fNDF = -3; + fChi2 = 0; + } +} diff --git a/external/KFParticle/KFParticle/KFVertex.h b/external/KFParticle/KFParticle/KFVertex.h new file mode 100644 index 0000000000000000000000000000000000000000..f12330835c315cc1ddceb9e6a32979cf6db5f8fe --- /dev/null +++ b/external/KFParticle/KFParticle/KFVertex.h @@ -0,0 +1,88 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author S.Gorbunov, I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +#ifndef KFVERTEX_H +#define KFVERTEX_H + +#include "KFParticle.h" +#include "KFPVertex.h" + +/** @class KFVertex + ** @brief Mathematics for reconstruction of primary vertices based on KFParticle. + ** @author S.Gorbunov, I.Kisel, M.Zyzak + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is inherited from KFParticle, adds functionality for reconstruction of + ** primary vertices. + **/ + +class KFVertex : public KFParticle +{ + public: + + KFVertex():KFParticle(),fIsConstrained(0){ } + KFVertex( const KFParticle &particle ): KFParticle(particle), fIsConstrained(0) {} ///< Vertex is constructed from the current position of a given particle. + KFVertex( const KFPVertex &vertex ); + ~KFVertex(){} + + Int_t GetNContributors() const { return fIsConstrained ?fNDF/2:(fNDF+3)/2; } ///< Returns number of particles used for construction of the vertex. + + + void operator +=( const KFParticle &Daughter ); ///< Adds particle to a vertex. + KFVertex operator -( const KFParticle &Daughter ) const; ///< Subtracts particle from a vertex, returns temporary object. Initial vertex stays untouched. + void operator -=( const KFParticle &Daughter ); ///< Subtracts particle from a current vertex. + + void SetBeamConstraint( float X, float Y, float Z, + float ErrX, float ErrY, float ErrZ ); + void SetBeamConstraintOff(); + + void ConstructPrimaryVertex( const KFParticle *vDaughters[], int nDaughters, + Bool_t vtxFlag[], float ChiCut=3.5 ); + + protected: + + Bool_t fIsConstrained; ///< Flag showing if the the beam constraint is set + +#ifndef KFParticleStandalone + ClassDef( KFVertex, 2 ) +#endif +}; + + +//--------------------------------------------------------------------- +// +// Inline implementation of the KFVertex methods +// +//--------------------------------------------------------------------- + + +inline void KFVertex::operator+=( const KFParticle &Daughter ) +{ + KFParticle::operator+=( Daughter ); +} + + +inline void KFVertex::operator-=( const KFParticle &Daughter ) +{ + Daughter.SubtractFromVertex( *this ); +} + +inline KFVertex KFVertex::operator-( const KFParticle &Daughter ) const +{ + KFVertex tmp = *this; + Daughter.SubtractFromVertex( tmp ); + return tmp; +} + + +#endif diff --git a/external/KFParticle/KFParticleLinkDef.h b/external/KFParticle/KFParticleLinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..9591913ae1c185abea19a05e1447093dc766e711 --- /dev/null +++ b/external/KFParticle/KFParticleLinkDef.h @@ -0,0 +1,24 @@ +#if defined(__CINT__) || defined(__CLING__) + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +//KFParticle +#pragma link C++ class KFParticleBase+; +#pragma link C++ class KFParticle+; +#pragma link C++ class KFVertex+; +#pragma link C++ class KFPTrack+; + +//KFParticlePerformance +#pragma link C++ class KFMCParticle+; +#pragma link C++ class KFPartEfficiencies+; + +//#pragma link C++ class KFParticleTest+; + +#endif + + + + + diff --git a/external/KFParticle/KFParticlePerformance/KFMCCounter.h b/external/KFParticle/KFParticlePerformance/KFMCCounter.h new file mode 100644 index 0000000000000000000000000000000000000000..2c8f1ce30fb01dbefd6ef5d5b0219cd19f4ba878 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFMCCounter.h @@ -0,0 +1,119 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFMCCounter_H +#define KFMCCounter_H + +#include <iostream> +#include <fstream> +#include <vector> + +/** @class KFMCCounter + ** @brief A helper structure to store information on the number of reconstructed and Monte Carlo particles for efficiency calculation. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is used to calculate reconstruction efficiency and ratios of a given set of particles. + **/ + +template <typename T> +struct KFMCCounter +{ + int NCounters; ///< Number of counters in the current object. + + std::vector<T> counters; ///< Counters of different set of particles. + + KFMCCounter():NCounters(0),counters(0) { } + KFMCCounter(int nCounters):NCounters(nCounters), counters(nCounters,T(0)) { } ///< Constructs the object with the set of counters "nCounters". + + void AddCounter(){ NCounters++; counters.push_back(T(0)); } ///< Adds a counter to the existing list. + void AddCounters(int nCounters){ NCounters += nCounters; counters.resize( NCounters, T(0)); } ///< Adds several counters to the existing list. + + /** Operator adds all counters from object "a" to the current object. Returns the current object. */ + KFMCCounter& operator+=(KFMCCounter& a){ + if (NCounters != a.NCounters){ + std::cout << " KFMCCounter: Error. Addition of counters of different sizes: " << NCounters << " " << a.NCounters << std::endl; + } + else{ + for (int iC = 0; iC < NCounters; iC++){ + counters[iC] += a.counters[iC]; + } + } + return *this; + }; + /** Operator adds all counters from object "a" to the current object, result is stored to the temporary object. Returns the temporary object. */ + KFMCCounter operator+(KFMCCounter& a){ + KFMCCounter res = *this; + res += a; + return res; + }; + /** Operator divides all counters from the current object to the counters from object "a", result is stored to the temporary object. Returns the temporary object. */ + template <typename T2> + KFMCCounter<double> operator/(KFMCCounter<T2>& a){ + KFMCCounter<double> b(NCounters); + if (NCounters != a.NCounters){ + std::cout << " KFMCCounter: Error. Addition of counters of different sizes: " << NCounters << " " << a.NCounters << std::endl; + } + else{ + for (int iC = 0; iC < NCounters; iC++){ + b.counters[iC] = Div(counters[iC],a.counters[iC]); + } + } + return b; + } + /** Operator divides all counters from the current object to the value "a", result is stored to the temporary object. Returns the temporary object. */ + template <typename T2> + KFMCCounter<T2> operator/(double a){ + KFMCCounter<T2> b(NCounters); + for (int iC = 0; iC < NCounters; iC++){ + b.counters[iC] = (T2)Div(counters[iC],a); + } + return b; + } + /** Operator to write the object "a" to the file "strm".*/ + friend std::fstream & operator<<(std::fstream &strm, const KFMCCounter<T> &a ){ + strm << a.NCounters << " " << a.counters.size() << " "; + for(unsigned int iV=0; iV<a.counters.size(); iV++) + strm << a.counters[iV] << " "; + strm << std::endl; + return strm; + } + /** Operator to write the object "a" to the stream "strm".*/ + friend std::ostream & operator<<(std::ostream &strm, const KFMCCounter<T> &a ){ + strm << a.NCounters << " " << a.counters.size() << " "; + for(unsigned int iV=0; iV<a.counters.size(); iV++) + strm << a.counters[iV] << " "; + strm << std::endl; + return strm; + } + /** Operator to read the object "a" from the file "strm".*/ + friend std::fstream & operator>>(std::fstream &strm, KFMCCounter<T> &a ){ + int tmp; + strm >> tmp; + a.NCounters = tmp; + strm >> tmp; + a.counters.resize(tmp,T(0)); + for(int iV=0; iV<tmp; iV++) + { + T tmp1; + strm >> tmp1; + a.counters[iV] = tmp1; + } + return strm; + } + + private: + /** Divides value "a" on value "b" if b is not zero, otherwise returns "-1". */ + double Div(double a, double b){return (b > 0) ? a/b : -1.;} +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFMCParticle.cxx b/external/KFParticle/KFParticlePerformance/KFMCParticle.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f0c55526f6573b8d2173f5b2072358e5f16e6710 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFMCParticle.cxx @@ -0,0 +1,36 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFMCParticle.h" + +#ifndef KFParticleStandalone +ClassImp(KFMCParticle) +#endif + +KFMCParticle::KFMCParticle() :fDaughterIds(), fMCTrackID(-1), fMotherId(-1), fPDG(0), fInitialParticleId(-1) +{ + for(int i=0; i<3; i++) + { + fIsReconstructable[i] = 0; + fIsV0[i] = 0; + } + fIsReconstructable[3] = 0; + fIsReconstructable[4] = 0; +} + +KFMCParticle::~KFMCParticle() +{ +} + +void KFMCParticle::AddDaughter( int i ) +{ + fDaughterIds.push_back(i); +} diff --git a/external/KFParticle/KFParticlePerformance/KFMCParticle.h b/external/KFParticle/KFParticlePerformance/KFMCParticle.h new file mode 100644 index 0000000000000000000000000000000000000000..a870deb997e78f63e1ad347f1909c893403704d2 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFMCParticle.h @@ -0,0 +1,102 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef _KFMCParticle_h_ +#define _KFMCParticle_h_ + +#include <vector> + +#ifdef HLTCA_STANDALONE +#include "RootTypesDef.h" +#else +#include "TObject.h" +#endif + +/** @class KFMCParticle + ** @brief A class to store relations between mother and daughter Monte Carlo simulated particles. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is used to calculate reconstruction efficiency of all Monte Carlo particles. It is + ** simplifies the procedure for short-lived particles. Contains a vector with unique Ids of all + ** MC daughters, a unique Id of the corresponding MC track, a unique Id of the MC mother particle, + ** the PDG code of the MC particle, flags showing if particle can be reconstructed according + ** to several different definitions, flags showing if particle creates a secondary vertex with + ** two or more daughters, an index of the initial particle Id in case of the K->mu+nu and pi-> mu+nu + ** decays, since GEANT engines do not store neutrinos. + **/ + +class KFMCParticle :public TObject +{ + public: + KFMCParticle(); + ~KFMCParticle(); + + void AddDaughter( int i ); ///< Adds an Id of the new particle to the list with Ids of daughter particles. + int NDaughters() const { return fDaughterIds.size(); } ///< Returns number of daughter particles. + const std::vector<int>& GetDaughterIds() const { return fDaughterIds; } ///< Returns a reference to the vector with Id of daughter particle KFMCParticle::fDaughterIds. + void CleanDaughters() { fDaughterIds.resize(0); } ///< Remove Ids of all daughter particles from the current object. + + void SetPDG(int pdg) {fPDG = pdg;} ///< Set the PDG code of the current particle KFMCParticle::fPDG. + void SetMCTrackID(int id) {fMCTrackID = id;} ///< Sets the Id of the corresponding Monte Carlo track KFMCParticle::fMCTrackID. + void SetMotherId(int id) {fMotherId = id;} ///< Sets the Id of the mother particle or primary vertex KFMCParticle::fMotherId. + + int GetMCTrackID() const {return fMCTrackID;} ///< Returns Id of the corresponding MC track KFMCParticle::fMCTrackID. + int GetMotherId() const {return fMotherId;} ///< Returns Id of the mother particle or primary vertex KFMCParticle::fMotherId. + int GetPDG() const {return fPDG;} ///< Returns PDG code of the current particle KFMCParticle::fPDG. + + bool IsReconstructable(int i) const {return fIsReconstructable[i];} ///< Returns a flag showing if particle can be reconstructed with KFMCParticle::fIsReconstructable index "i". + void SetAsReconstructable(int i) { fIsReconstructable[i] = 1;} ///< Defines the particle as those which should be reconstructed for the efficiency set "i". + + bool IsReconstructableV0(int i) const {return fIsV0[i];} ///< Returns a flag showing if particle is a reconstructable V0. + void SetAsReconstructableV0(int i) { fIsV0[i] = 1;} ///< Defines the particle as V0 which should be reconstructed for the efficiency set "i". + + void SetInitialParticleId(int i) {fInitialParticleId = i;} ///< Sets Id of the Monte Carlo particle, from which the current particle was copied. + int InitialParticleId() const {return fInitialParticleId;} ///< Returns the Id of the Monte Carlo particle, from which the current particle was copied. + private: //data + std::vector<int> fDaughterIds; ///< A vector with Ids of the daughter Monte Carlo particles. + int fMCTrackID; ///< A unique Id of the corresponding Monte Carlo track. + int fMotherId; ///< A unique Id of the mother particle. If the current particle is primary the Id of the primary vertex with a negative sigh is stored. + int fPDG; ///< A PDG code of the current particle. + + /** Flags for calculation of the efficiency, define the denominator in each set of efficiency. + ** Flags 0-2 are used for particles reconstructed by the conventional method, 3 and 4 are used + ** for particles found by the missing mass method: \n + ** [0] - true for all particles, is used for calculation of the efficiency in 4pi;\n + ** [1] - true if the particle is long-lived and can be reconstructed in the detector or + ** if the particle is short-lived and all its daughter particles can be reconstructed; detector-dependent;\n + ** [2] - true if the particle is long-lived and is reconstructed in the detector or + ** if the particle is short-lived and all its daughter particles are reconstructed, + ** is used in calculation of efficiency of the KF Particle Finder method;\n + ** [3] - true if the particle is long-lived and is reconstructed in the detector or + ** if the particle is short-lived, can be reconstructed by the missing mass method + ** and all its daughter particles are reconstructed; \n + ** [4] - true for all particles, which can be found by the missing mass method, + ** is used for calculation of the efficiency in 4pi. + **/ + bool fIsReconstructable[5]; + /** Flags to calculate efficiency of short-lived particles producing a secondary vertex with + ** two or more daughters; similar to KFMCParticle::fIsReconstructable[0-2]. + **/ + bool fIsV0[3]; + + /** For calculation of missing mass method efficiency a copy of the mother particle + ** is created. fInitialParticleId is an Id of the initial mother particle. + **/ + int fInitialParticleId; +#ifndef KFParticleStandalone + ClassDef( KFMCParticle, 1 ) +#endif +}; + +#endif + diff --git a/external/KFParticle/KFParticlePerformance/KFMCTrack.h b/external/KFParticle/KFParticlePerformance/KFMCTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..b7d4fe87f4553ad4ed6e6baaab05e92957939d82 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFMCTrack.h @@ -0,0 +1,82 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFMCTRACK_H +#define KFMCTRACK_H + +#include <cmath> + +/** @class KFMCTrack + ** @brief A class for storage of the Monte Carlo simulated track in the cartesian parametrisation. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** A track is described with the parameters { X, Y, Z, Px, Py, Pz, q/P }. Parameters are stored at + ** the origin position. Class also contains Id of the mother track, PDG code for the current track, + ** number of Monte Carlo points produced by the simulation engine at the detector stations, + ** number of Monte Carlo points produced at the precise detectors (like MVD in CBM, HFT in STAR, + ** ITS in ALICE, etc.). It also has a flag showing if track was found by the reconstruction procedure + ** for efficiency calculation, and a flag showing if track was out of acceptance. + **/ + +class KFMCTrack +{ + public: + KFMCTrack():fMotherId(-1),fPDG(0),fNMCPoints(0), fNMCPixelPoints(0), fIsReconstructed(0),fIsOutOfDetector(0) {}; + + int MotherId() const { return fMotherId; } ///< Returns a uniqueue Id of the mother track or primary vertex KFMCTrack::fMotherId. + int PDG() const { return fPDG;} ///< Returns PDG code of the track KFMCTrack::fPDG. + float Par( int i ) const { return fPar[i]; } ///< Returns value of the parameter KFMCTrack::fPar with index "i". + float X() const { return fPar[0]; } ///< Returns X coordinate of the track at the origin position. + float Y() const { return fPar[1]; } ///< Returns Y coordinate of the track at the origin position. + float Z() const { return fPar[2]; } ///< Returns Y coordinate of the track at the origin position. + float L() const { return sqrt(X()*X() + Y()*Y() + Z()*Z()); } ///< Returns distance from the origin of the track to a point {0,0,0}. + float Px() const { return fPar[3]; } ///< Returns Px momentum component of the track at the origin position. + float Py() const { return fPar[4]; } ///< Returns Py momentum component of the track at the origin position. + float Pz() const { return fPar[5]; } ///< Returns Pz momentum component of the track at the origin position. + float P() const { return sqrt(fPar[3]*fPar[3] + fPar[4]*fPar[4] + fPar[5]*fPar[5]); } ///< Returns momentum of the track. + float Pt() const { return sqrt(fPar[3]*fPar[3] + fPar[4]*fPar[4]); } ///< Returns transverse momentum of the track. + const float *Par() const { return fPar; } ///< Returns a pointer to the array with track parameters KFMCTrack::fPar. + int NMCPoints() const { return fNMCPoints; } ///< Returns number of MC points KFMCTrack::fNMCPoints. + int NMCPixelPoints() const { return fNMCPixelPoints; } ///< Returns number of MC points at the precise detectors KFMCTrack::fNMCPixelPoints. + bool IsReconstructed() const { return fIsReconstructed; } ///< Returns a flag showing if track was found by the reconstruction procedure. + bool IsOutOfDetector() const { return fIsOutOfDetector; } ///< Returns a flag showing if track was out of acceptance. + + void SetPar( int i, float v ) { fPar[i] = v; } ///< Sets a value "v" to the parameter with index "i". + void SetX( float v ) { fPar[0] = v; } ///< Sets X coordinate at the origin position of the track. + void SetY( float v ) { fPar[1] = v; } ///< Sets Y coordinate at the origin position of the track. + void SetZ( float v ) { fPar[2] = v; } ///< Sets Z coordinate at the origin position of the track. + void SetPx( float v ) { fPar[3] = v; } ///< Sets Px momentum component at the origin position of the track. + void SetPy( float v ) { fPar[4] = v; } ///< Sets Py momentum component at the origin position of the track. + void SetPz( float v ) { fPar[5] = v; } ///< Sets Pz momentum component at the origin position of the track. + void SetQP( float v ) { fPar[6] = v; } ///< Sets q/P at the origin position of the track. + void SetMotherId( int v ) { fMotherId = v; } ///< Sets a unique id of the mother track if track is secondary or primary vertex with a negative sign if it is primary. + void SetPDG( int v ) { fPDG = v; } ///< Sets PDG code of the current track. + void SetNMCPoints( int v ) { fNMCPoints = v; } ///< Sets number of MC points produced at the detector planes. + void SetNMCPixelPoints( int v ){ fNMCPixelPoints = v; } ///< Sets number of the MC points produced at the precise detectors. + void SetReconstructed() { fIsReconstructed = 1; } ///< Defines the track as reconstructed. + void SetNotReconstructed() { fIsReconstructed = 0; } ///< Defines the track as not reconstructed. + void SetOutOfDetector() { fIsOutOfDetector = 1; } ///< Defines the track out of acceptance. + + protected: + + int fMotherId; ///< Index of the mother track in tracks array. If track is produced at the primary vertex (PV) negative value with the PV Id is assigned. + int fPDG; ///< The PDG code of the current Monte Carlo track. + float fPar[7]; ///< Parameters of the track: { X, Y, Z, Px, Py, Pz, q/P }, where "q" is its charge. + int fNMCPoints; ///< Total number of Monte Carlo points produced by the simulation engine at the detector stations. + int fNMCPixelPoints; ///< Number of Monte Carlo points produced at the precise detectors (like MVD in CBM, HFT in STAR, ITS in ALICE, etc.). + + bool fIsReconstructed; ///< A flag showing if track was found by the reconstruction procedure. Is required for correct efficiency calculation. + bool fIsOutOfDetector; ///< A flag showing if track was out of acceptance. Is required for correct calculation of the acceptance. +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFMCVertex.cxx b/external/KFParticle/KFParticlePerformance/KFMCVertex.cxx new file mode 100644 index 0000000000000000000000000000000000000000..eab2f904b1309c45f703e6ea89c7680dfc41198a --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFMCVertex.cxx @@ -0,0 +1,38 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFMCVertex.h" + +KFMCVertex::KFMCVertex():fDaughterTracks(0),fIsReconstructable(0),fIsMCReconstructable(0),fIsReconstructed(0),fNReconstructedDaughters(0),fIsTriggerPV(0) +{ + for( int i = 0; i < 3; i++) fPar[i] = 0; +} + +std::ostream& operator<<(std::ostream& out, const KFMCVertex &a) +{ + /** Operator to print coordinates of the MC vertex "a". + ** \param[in] out - stream, where coordinates will be printed + ** \param[in] a - vertex to be printed + **/ + for (int i = 0; i < 3; i++) out << a.fPar[i] << std::endl; + return out; +} + +std::istream& operator>>(std::istream& in, KFMCVertex &a) +{ + /** Operator to read coordinates of the vertex from the input stream. + ** \param[in] in - input stream + ** \param[in] a - vertex, where the coordinates will be read in + **/ + for (int i = 0; i < 3; i++) in >> a.fPar[i]; + return in; +} + diff --git a/external/KFParticle/KFParticlePerformance/KFMCVertex.h b/external/KFParticle/KFParticlePerformance/KFMCVertex.h new file mode 100644 index 0000000000000000000000000000000000000000..ff1ec2d68933ee9c64ccf4a080200943ce4b1c53 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFMCVertex.h @@ -0,0 +1,95 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFMCVERTEX_H +#define KFMCVERTEX_H + +#include <iostream> +#include <vector> + +/** @class KFMCVertex + ** @brief A class to store information about simulated Monte Carlo primary vertices. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class contains coordinates of the vertex, indices of the Monte Carlo tracks produced + ** at this vertex, classification flags, number of the reconstructed Monte Carlo tracks. + **/ + +class KFMCVertex +{ + public: + KFMCVertex(); + + float Par( int i ) const { return fPar[i]; } ///< Returns parameter with index "i" from KFMCVertex::fPar + + float X() const { return fPar[0]; } ///< Returns X coordinate of the vertex. + float Y() const { return fPar[1]; } ///< Returns Y coordinate of the vertex. + float Z() const { return fPar[2]; } ///< Returns Z coordinate of the vertex. + + const float* GetPar() const { return fPar; } ///< Returns pointer to the parameters of the vertex KFMCVertex::fPar + + void SetPar( int i, float v ) { fPar[i] = v; } ///< Sets a value "v" to parameter "i". + + void SetX( float v ) { fPar[0] = v; } ///< Sets value "v" to the X coordinate. + void SetY( float v ) { fPar[1] = v; } ///< Sets value "v" to the Y coordinate. + void SetZ( float v ) { fPar[2] = v; } ///< Sets value "v" to the Z coordinate. + + int NDaughterTracks() const { return fDaughterTracks.size(); } ///< Returns number of Monte Carlo tracks produced at the current vertex. + int NReconstructedDaughterTracks() const { return fNReconstructedDaughters; } ///< Returns number of reconstructed tracks from this vertex. + void AddDaughterTrack( int iTr ) { fDaughterTracks.push_back(iTr); } ///< Adds unique id of the Monte Carlo track produced at the current vertex. + int DaughterTrack( int iTr ) const + { + /** Returns unique id of the Monte Carlo track from this vertex with index "iTr". + ** \param[in] iTr - index of the track. + **/ + if(iTr >= NDaughterTracks()) + { + std::cout << "ERROR!!!! MC PV contains only " << NDaughterTracks() << " tracks" << std::endl; + return -1; + } + return fDaughterTracks[iTr]; + } + + bool IsMCReconstructable() const { return fIsMCReconstructable; } ///< Returns flag showing if the vertex can be found (definition is based on the MC tracks) + bool IsReconstructable() const { return fIsReconstructable; } ///< Returns flag showing if the vertex can be found (definition is based on the reconstructed tracks) + bool IsReconstructed() const { return fIsReconstructed; } ///< Returns flag showing if the vertex was reconstructed + + void SetReconstructable() { fIsReconstructable = 1; } ///< Defines the current vertex as such that can be reconstructed (based on the reconstructed tracks) + void SetUnReconstructable() { fIsReconstructable = 0; } ///< Defines the current vertex as such that can not be reconstructed (based on the reconstructed tracks) + + void SetMCReconstructable() { fIsMCReconstructable = 1; } ///< Defines the current vertex as such that can be reconstructed (based on the MC tracks) + void SetMCUnReconstructable() { fIsMCReconstructable = 0; } ///< Defines the current vertex as such that can not be reconstructed (based on the MC tracks) + + void SetReconstructed() { fIsReconstructed = 1; } ///< Defines the current vertex as such that was reconstructed + void SetUnReconstructed() { fIsReconstructed = 0; } ///< Defines the current vertex as such that was not reconstructed + + void SetNReconstructedDaughters(int n) { fNReconstructedDaughters = n; } ///< Defines number of the reconstructed tracks produced at the current vertex. + + bool IsTriggerPV() const { return fIsTriggerPV; } ///< Returns flag showing if the vertex is considerred as tigger. + void SetTriggerPV() { fIsTriggerPV = 1; } ///< Defines the current vertex as the trigger primary vertex. + + friend std::ostream& operator<<(std::ostream& out, const KFMCVertex &a); + friend std::istream& operator>>(std::istream& in, KFMCVertex &a); + + protected: + + float fPar[3]; ///< Cartesian coordinates of the vertex: { X, Y, Z }. + std::vector<int> fDaughterTracks; ///< Vector with unique ids of the Monte Carlo tracks produced at this vertex. + bool fIsReconstructable; ///< Flag showing if the vertex considered as reconstructable based on the reconstructed tracks. + bool fIsMCReconstructable; ///< Flag showing if the vertex considered as reconstructable based on the Monte Carlo tracks. + bool fIsReconstructed; ///< Flag showing if vertex was reconstructed. + int fNReconstructedDaughters; ///< Number of found tracks, produced at the current vertex. + bool fIsTriggerPV; ///< Flag showing if the vertex was a trigger primary vertex. +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogram.h b/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogram.h new file mode 100644 index 0000000000000000000000000000000000000000..dd82adbe554e1ed25d1593cf3b02c58c20435537 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogram.h @@ -0,0 +1,164 @@ +//---------------------------------------------------------------------------- +// Structures to collect histograms online +// . +// @author M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + + +#ifndef KFPHISTOGRAM +#define KFPHISTOGRAM + +#include "KFPHistogramSet.h" +#include "KFPartEfficiencies.h" +#include "KFParticleTopoReconstructor.h" +#include <map> +#include <iostream> +#include <fstream> + +/** @class KFPHistogram + ** @brief A common object containing histograms for all particle species. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is used to collect histograms in the environment, + ** where ROOT is not available, for example at Intel Xeon Phi cards. + ** Contains a set of histograms for each decay reconstructed by the + ** KF Particle Finder package, allocates the memory for all histograms: + ** This allows faster allocation, faster transfer of the memory, + ** easier access from the Intel Xeon Phi, better performance. + **/ + +class KFPHistogram +{ + public: + KFPHistogram(): fPdgToIndex(), fOutFileName("KFPHistograms.txt"), fMemory(0) + { + KFPartEfficiencies partEff; + fPdgToIndex = partEff.GetPdgToIndexMap(); + + int dataSize = 0; + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + { + fKFPHistogramSet[iParticle] = KFPHistogramSet(iParticle); + dataSize += fKFPHistogramSet[iParticle].DataSize(); + } + + fMemory = new int[dataSize]; + std::memset(fMemory, 0, dataSize); + + int* pointer = fMemory; + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + { + fKFPHistogramSet[iParticle].SetHistogramMemory(pointer); + pointer += fKFPHistogramSet[iParticle].DataSize(); + } + } ///< Default Constructor. Creates histograms, allocates memory for them. + ~KFPHistogram() { if(fMemory) delete [] fMemory; } + + void SetOutFileName(std::string name) { fOutFileName = name; } ///< Set the name of the output file. + + inline void Fill(const KFParticle& particle) + { + std::map<int, int>::iterator it; + it=fPdgToIndex.find(particle.GetPDG()); + if(it != fPdgToIndex.end()) + fKFPHistogramSet[it->second].Fill(particle); + } ///< Fills histograms using parameters of the given particle. + + inline void Fill(const KFParticleTopoReconstructor& topoReconstructor) + { + for(unsigned int iParticle=0; iParticle<topoReconstructor.GetParticles().size(); iParticle++) + Fill(topoReconstructor.GetParticles()[iParticle]); + } ///< Fills histograms for each particle reconstructed by the KFParticleFinder object from the given KFParticleTopoReconstructor. + + KFPHistogramSet GetHistogramSet(int iSet) const { return fKFPHistogramSet[iSet]; } ///< Returns set of histograms for the decay with index iSet. + /** \brief Returns "iHistogram" histogram from the set of histograms for the decay with index "iSet". */ + KFPHistogram1D GetHistogram(int iSet, int iHistogram) const { return fKFPHistogramSet[iSet].GetHistogram1D(iHistogram); } + + friend std::fstream & operator<<(std::fstream &strm, KFPHistogram &histograms) + { + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++ ) + { + strm << iParticle << std::endl; + const int& nHistograms = histograms.fKFPHistogramSet[iParticle].GetNHisto1D(); + for(int iHistogram = 0; iHistogram<nHistograms; iHistogram++) + { + const KFPHistogram1D& histogram = histograms.fKFPHistogramSet[iParticle].GetHistogram1D(iHistogram); + strm << histogram.Name() << " " << histogram.MinBin() << " " << histogram.MaxBin() << " " << histogram.NBins() << std::endl; + for(int iBin=0; iBin<histogram.NBins()+2; iBin++) + strm << histogram.GetHistogram()[iBin] << " "; + strm << std::endl; + } + } + + return strm; + } ///< Stores all histograms to the output file. + + void Save() + { + std::fstream file(fOutFileName.data(),std::fstream::out); + file << (*this); + file.close(); + } ///< Stores all histograms to the file with the name defined in KFPHistogram::fOutFileName. + + bool FillFromFile( std::string prefix ) + { + std::fstream ifile(prefix.data(),std::fstream::in); + if ( !ifile.is_open() ) return 0; + + int iSet = 0; + + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++ ) + { + ifile >> iSet; + const int& nHistograms = fKFPHistogramSet[iParticle].GetNHisto1D(); + for(int iHistogram = 0; iHistogram<nHistograms; iHistogram++) + { + std::string name; + float minBin = 0.f, maxBin = 0.f; + int nBins = 0; + ifile >> name >> minBin >> maxBin >> nBins; + if(nBins != fKFPHistogramSet[iParticle].GetHistogram1D(iHistogram).NBins() || + minBin != fKFPHistogramSet[iParticle].GetHistogram1D(iHistogram).MinBin() || + maxBin != fKFPHistogramSet[iParticle].GetHistogram1D(iHistogram).MaxBin() ) + { + std::cout << "Fatal error: size of the histograms is not in an agreement with the current version." << std::endl; + exit(1); + } + + int binContent = 0; + for(int iBin=0; iBin<nBins+2; iBin++) + { + ifile >> binContent; + fKFPHistogramSet[iParticle].SetHisto1DBinContent(iHistogram, iBin, binContent); + } + } + } + + ifile.close(); + return 1; + } ///< Reads object from the file with the name defined by "prefix". + + inline void operator += ( const KFPHistogram &h ) + { + for(int i=0; i<KFPartEfficiencies::nParticles; i++) + fKFPHistogramSet[i] += h.fKFPHistogramSet[i]; + }///< Adds all histograms from object "h" to the current object. + + private: + std::map<int, int> fPdgToIndex; ///< A map between PDG code and index of the decay in the KF Particle Finder scheme. A copy of an object from KFPartEfficiencies. + std::string fOutFileName; ///< The name of the output file, where histograms will be stored. + KFPHistogramSet fKFPHistogramSet[KFPartEfficiencies::nParticles]; ///< A set of histograms for all decays reconstructed by KF Particle Finder. + int* fMemory; ///< A pointer to the memory for all histograms. + + KFPHistogram(const KFPHistogram&); ///< Does not allow copying of the objects of this class. + KFPHistogram& operator=(const KFPHistogram&); ///< Does not allow copying of the objects of this class. +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogram1D.h b/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogram1D.h new file mode 100644 index 0000000000000000000000000000000000000000..dba6e858727264eb12a01b295ed67f1303a683c6 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogram1D.h @@ -0,0 +1,109 @@ +//---------------------------------------------------------------------------- +// Structures to collect histograms online +// . +// @author M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPHISTOGRAM1D +#define KFPHISTOGRAM1D + +#include <vector> +#include <string> +#include <cmath> +#include <iostream> +#include <cstdlib> + +/** @class KFPHistogram1D + ** @brief One-dimensional histogram. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is used to collect one-dimensional histograms in the environment, + ** where ROOT is not available, for example at Intel Xeon Phi cards. + ** It contains the histogram itself, number of bins, its name, + ** minimum and maximum value of the axis. The histogram memory is allocated externally + ** (by KFPHistogram) for better performance. + **/ + +class KFPHistogram1D +{ + public: + + KFPHistogram1D(): fHistogram(0), fSize(0), fName(""), fMinBin(0), fMaxBin(0) {} + KFPHistogram1D(std::string name, int nBins, float minX, float maxX): + fHistogram(0), fSize(nBins+2), fName(name), fMinBin(minX), fMaxBin(maxX) {} ///< Constructor with user-defined parameters. + ~KFPHistogram1D() {} + + int* GetHistogram() const { return fHistogram; } ///< Returns a pointer to the histogram data. + std::string Name() const { return fName; } ///< Returns name of the histogram. + float MinBin() const { return fMinBin; } ///< returns minimum of the X axis. + float MaxBin() const { return fMaxBin; } ///< Returns maximum of the X axis. + int NBins() const { return (fSize-2); } ///< Returns number of bins. + int DataSize() const { return fSize; } ///< Returns number of bins plus underflow and overflow bins. + int Size() const { return fSize; } ///< Returns number of bins plus underflow and overflow bins. + + inline void SetBinContent(int iBin, int value) { fHistogram[iBin] = value; } ///< Sets the value of the bin "iBin". + inline void SetHistogramMemory(int* pointer) { fHistogram = pointer; } ///< Sets the pointer to the memory with the histogram. + + /** Adds "value" to the histogram: calculates the corresponding bin and adds one there. */ + void Fill(float value) + { + int iBin = floor(float(value - fMinBin)/float(fMaxBin - fMinBin) * float(fSize-2)) + 1; + + if(iBin > fSize-1) + iBin = fSize-1; + if(iBin < 1) + iBin = 0; + + if( !(iBin==iBin) || !(std::isfinite(iBin)) ) iBin = 0; + + fHistogram[iBin]++; + } + + /** Adds histogram "h" to the current histogram bin-by-bin. */ + inline void operator += ( const KFPHistogram1D &h ) + { + if( fSize != h.fSize ) + { + std::cout << "Size of 1D histogram " << fName << " is incorrect. Stop the program." << std::endl; + } + else + { + for(int i=0; i<fSize; i++) + fHistogram[i] += h.fHistogram[i]; + } + } + + /** The copy-constructor. Memory for the fHistogram is not allocated, only the pointer is copied.*/ + KFPHistogram1D(const KFPHistogram1D& h): fHistogram(h.fHistogram), fSize(h.fSize), fName(h.fName), fMinBin(h.fMinBin), fMaxBin(h.fMaxBin) + { + } + + /** Copies object "h" to the current object. Memory for the fHistogram is not allocated, only the pointer is copied. Returns the current object. */ + const KFPHistogram1D& operator=(const KFPHistogram1D& h) + { + fHistogram = h.fHistogram; + fSize = h.fSize; + fName = h.fName; + fMinBin = h.fMinBin; + fMaxBin = h.fMaxBin; + + return *this; + } + + private: + int* fHistogram; ///< Pointer to the array with the values of the histogram. + int fSize; ///< Number of bins +2, additional two bins are reserved for the underflow and overflow. + + std::string fName; ///< Name of the histogram. + float fMinBin; ///< Minimum value at the X axis. + float fMaxBin; ///< Maximum value at the X axis. +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogramSet.cxx b/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogramSet.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2ec0aed5311f70a688931ef15d8586637c1acb57 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogramSet.cxx @@ -0,0 +1,168 @@ +//---------------------------------------------------------------------------- +// Structures to collect histograms online +// . +// @author M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFPHistogramSet.h" +#include "KFPartEfficiencies.h" + +KFPHistogramSet::KFPHistogramSet(int iPart) +{ + /** Creates a set of histograms for the given particle specie. + ** \param[in] iPart - number of the particle specie in the KF Particle Finder scheme + ** \see KFPartEfficiencies for the definition of "iPart". + **/ + KFPartEfficiencies fParteff; + std::string parName[NHisto1D] = {"M","p","p_{t}","y","DecayL","c#tau","chi2ndf","prob","#theta","phi","X","Y","Z","R", "L", "l/dl","Multiplicity"}; +#ifdef CBM + int nBins[NHisto1D] = {1000, // M + 100, // p + 100, // pt + 100, // y + 100, // DecayL + 100, // ctau + 100, // chi2/ndf + 100, // prob + 100, // theta + 100, // phi + 200, // X + 200, // Y + 360, // Z + 200, // R + 200, // L + 200, // L/dL + fParteff.partMaxMult[iPart]+1}; + float xMin[NHisto1D] = { fParteff.partMHistoMin[iPart], // M + 0.f, // p + 0.f, // pt + 0.f, // y + -5.f, // DecayL + 0.f, // ctau + 0.f, // chi2/ndf + 0.f, // prob + -2.f, // theta + -2.f, // phi + -50.f, // X + -50.f, // Y + -10.f, // Z + 0.f, // R + 0.f, // L + -1.f, // L/dL + -0.5f }; + float xMax[NHisto1D] = { fParteff.partMHistoMax[iPart], // M + 10.f, // p + 3.f, // pt + 6.f, // y + 55.f, // DecayL + 30.f, // ctau + 20.f, // chi2/ndf + 1.f, // prob + 2.f, // theta + 2.f, // phi + 50.f, // X + 50.f, // Y + 80.f, // Z + 50.f, // R + 100.f, // L + 35.f, // L/dL + float(fParteff.partMaxMult[iPart])+0.5f}; +#else + int nBins[NHisto1D] = {1000, // M + 100, // p + 100, // pt + 100, // y + 100, // DecayL + 100, // ctau + 100, // chi2/ndf + 100, // prob + 100, // theta + 100, // phi + 100, // X + 1000, // Y + 1000, // Z + 1000, // R + 1000, // L + 1000, // L/dL + fParteff.partMaxMult[iPart]+1}; + float xMin[NHisto1D] = { fParteff.partMHistoMin[iPart], // M + 0.f, // p + 0.f, // pt + -6.f, // y + -5.f, // DecayL + 0.f, // ctau + 0.f, // chi2/ndf + 0.f, // prob + -2.f, // theta + -2.f, // phi + -200.f, // X + -200.f, // Y + -200.f, // Z + 0.f, // R + 0.f, // L + -1.f, // L/dL + -0.5f }; + float xMax[NHisto1D] = { fParteff.partMHistoMax[iPart], // M + 10.f, // p + 3.f, // pt + 6.f, // y + 55.f, // DecayL + 30.f, // ctau + 20.f, // chi2/ndf + 1.f, // prob + 2.f, // theta + 2.f, // phi + 200.f, // X + 200.f, // Y + 200.f, // Z + 200.f, // R + 400.f, // L + 35.f, // L/dL + float(fParteff.partMaxMult[iPart])+0.5f}; +#endif + for(int iHisto=0; iHisto<NHisto1D; iHisto++) + fKFPHistogram1D[iHisto] = KFPHistogram1D(parName[iHisto], nBins[iHisto], xMin[iHisto], xMax[iHisto]); +} + +void KFPHistogramSet::SetHistogramMemory(int* pointer) +{ + /** Sets a pointer to the memory allocated externally for the current set of histograms. + ** \param[in] pointer - pointer to the memory + **/ + for(int i=0; i<NHisto1D; i++) + { + fKFPHistogram1D[i].SetHistogramMemory(pointer); + pointer += fKFPHistogram1D[i].DataSize(); + } +} + +void KFPHistogramSet::Fill(const KFParticle& particle) +{ + /** Fill all possible histograms using parameters of the provided KFParticle object. + ** \param[in] particle - KFParticle object + **/ + float mass = 0, p=0, pt=0, err = 0; + particle.GetMass(mass, err); + particle.GetMomentum(p, err); + particle.GetPt(pt, err); + float rapidity = particle.GetRapidity(); + float chi2ndf = particle.GetChi2()/float(particle.GetNDF()); + float r = sqrt(particle.X()*particle.X() + particle.Y()*particle.Y()); + float l = sqrt(particle.X()*particle.X() + particle.Y()*particle.Y() + particle.Z()*particle.Z()); + + fKFPHistogram1D[0].Fill(mass); + fKFPHistogram1D[1].Fill(p); + fKFPHistogram1D[2].Fill(pt); + fKFPHistogram1D[3].Fill(rapidity); + fKFPHistogram1D[6].Fill(chi2ndf); + fKFPHistogram1D[10].Fill(particle.X()); + fKFPHistogram1D[11].Fill(particle.Y()); + fKFPHistogram1D[12].Fill(particle.Z()); + fKFPHistogram1D[13].Fill(r); + fKFPHistogram1D[14].Fill(l); +} diff --git a/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogramSet.h b/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogramSet.h new file mode 100644 index 0000000000000000000000000000000000000000..032c22125a71cf39d74597bc7547cd13eeb1fba5 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFPHistogram/KFPHistogramSet.h @@ -0,0 +1,68 @@ +//---------------------------------------------------------------------------- +// Structures to collect histograms online +// . +// @author M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPHISTOGRAMSET +#define KFPHISTOGRAMSET + +#include "KFPHistogram1D.h" +#include "KFParticle.h" + +/** @class KFPHistogramSet + ** @brief A set of histograms collected at the external devise. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class defines a set of histograms to be collect in the environment, + ** where ROOT is not available, for example at Intel Xeon Phi cards. + ** It contains a set of one-dimensional histograms. + ** Also,Calculates the needed amount of memory to be allocated + **/ + +class KFPHistogramSet +{ + public: + KFPHistogramSet(int iPart=0); + ~KFPHistogramSet() {} + + void Fill(const KFParticle& particle); + + inline int GetNHisto1D() const { return NHisto1D; } ///< Returns a number of one dimensional histograms in the set. + inline int DataSize() const + { + int dataSize = 0; + for(int i=0; i<NHisto1D; i++) + dataSize += fKFPHistogram1D[i].DataSize(); + return dataSize; + } ///< Returns the size of the memory in blocks of integer (or 4 bytes, or 32 bits) to be allocated for the histogram set. \see KFPHistogram, where memory is allocated. + KFPHistogram1D GetHistogram1D(int iHistogram) const { return fKFPHistogram1D[iHistogram]; } ///< Returns one dimensional histogram with index "iHistogram". + + /**Sets bin content of the histogram "iHisto" to a given value. + ** \param[in] iHisto - index of the histogram in the set + ** \param[in] iBin - number of the bin + ** \param[in] value - value to be set + **/ + inline void SetHisto1DBinContent(int iHisto, int iBin, int value) { fKFPHistogram1D[iHisto].SetBinContent(iBin,value); } + + inline void operator += ( const KFPHistogramSet &h ) + { + for(int i=0; i<NHisto1D; i++) + fKFPHistogram1D[i] += h.fKFPHistogram1D[i]; + } ///< Adds all histograms bin-by-bin from the histogram set "h" to the current set. + + void SetHistogramMemory(int* pointer); + + private: + static const int NHisto1D = 17; ///< Number of histogram per each particle specie. + KFPHistogram1D fKFPHistogram1D[NHisto1D]; ///< A set of the one dimensional histograms. +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFPVEfficiencies.h b/external/KFParticle/KFParticlePerformance/KFPVEfficiencies.h new file mode 100644 index 0000000000000000000000000000000000000000..5efb4ada1109a516c65fbd5c8fa22f6391bd83be --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFPVEfficiencies.h @@ -0,0 +1,220 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPVEfficiencies_H +#define KFPVEfficiencies_H + +#ifndef HLTCA_STANDALONE +#include "TNamed.h" +#endif + +#include <map> +#include <iomanip> +#include "KFMCCounter.h" + +/** @class KFPVEfficiencies + ** @brief Class to calculate efficiency of KF Particle Finder. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class calculates reconstruction efficiency of the primary vertices.\n + ** Definitions:\n + ** background - physics background, when daughter particle come from the secondary vertex;\n + ** ghost - combinatorial background, tracks do not form a real vertex;\n + ** clone - a vertex is reconstructed several times, for example, half of tracks form one group and + ** another half form second group. + **/ + +class KFPVEfficiencies: public TNamed +{ + public: + + KFPVEfficiencies(): + names(), + indices(), + ratio_reco(), + mc(), + reco(), + ratio_ghost(), + ratio_bg(), + ratio_clone(), + ghost(), + bg(), + clone() + { + AddCounter(Form("%s","PV"), Form("%-*s",12,"PV")); + AddCounter(Form("%s","PVtrigger"), Form("%-*s",12,"PV trigger")); + AddCounter(Form("%s","PVpileup"), Form("%-*s",12,"PV pileup ")); + } + + virtual ~KFPVEfficiencies(){}; + + virtual void AddCounter(TString shortname, TString name) + { + /** Adds a counter with the name defined by "name" to all counter + ** objects. For easiness of operation with counters, a shortname is assigned + ** to each of them and the corresponding entry in the map indices is done. + ** \param[in] shortname - a short name of the counter for fast and easy access to its index + ** \param[in] name - name of the counter which is added to each counter object. + **/ + indices[shortname] = names.size(); + names.push_back(name); + + ratio_reco.AddCounter(); + mc.AddCounter(); + reco.AddCounter(); + + ratio_ghost.AddCounter(); + ratio_bg.AddCounter(); + ratio_clone.AddCounter(); + ghost.AddCounter(); + bg.AddCounter(); + clone.AddCounter(); + }; + + /** \brief Operator to add efficiency table from object "a" to the current object. Returns the current object after addition. */ + KFPVEfficiencies& operator+=(KFPVEfficiencies& a){ + mc += a.mc; reco += a.reco; + ghost += a.ghost; bg += a.bg; clone += a.clone; + return *this; + }; + + /** \brief Function to calculate efficiency after all counters are set. If the counters are modified the function should be called again. */ + void CalcEff(){ + ratio_reco = reco/mc; + + KFMCCounter<int> allReco = reco + ghost + bg; + ratio_ghost = ghost/allReco; + ratio_bg = bg/allReco; + ratio_clone = clone/allReco; + }; + + + void Inc(bool isReco, int nClones, TString name) + { + /** Increases counters by one, if the corresponding boolean variable is "true". + ** MC counter is increased in any case. + ** \param[in] isReco - "true" if vertex is reconstructed + ** \param[in] nClones - number of double reconstructed vertices for the given MC vertex, + ** will be added to the "clone" counters + ** \param[in] name - "shortname" of the set of counters, which should be increased + **/ + const int index = indices[name]; + + mc.counters[index]++; + if (isReco) reco.counters[index]++; + if(nClones > 0) + clone.counters[index] += nClones; + }; + + void IncReco(bool isGhost, bool isBg, TString name) + { + /** Increases counters by one, if the corresponding boolean variable is "true". + ** \param[in] isGhost - "true" if ghost is added + ** \param[in] isBg - "true" if physics background is added + ** \param[in] name - "shortname" of the set of counters, which should be increased + **/ + const int index = indices[name]; + + if (isGhost) ghost.counters[index]++; + if (isBg) bg.counters[index]++; + }; + + /** \brief Prints the efficiency table on the screen. */ + void PrintEff(){ + std::ios_base::fmtflags original_flags = std::cout.flags(); + std::cout.setf(std::ios::fixed); + std::cout.setf(std::ios::showpoint); + std::cout.precision(3); + std::cout << " : " + << " Eff " + <<" / "<< " Ghost " + <<" / "<< "BackGr " + <<" / "<< "Clone " + <<" / "<< "N Ghost" + <<" / "<< "N BackGr" + <<" / "<< "N Reco " + <<" / "<< "N Clone " + <<" | "<< " N MC " << std::endl; + + int NCounters = mc.NCounters; + for (int iC = 0; iC < NCounters; iC++){ + std::cout << names[iC] + << " : " << std::setw(6) << ratio_reco.counters[iC] + << " / " << std::setw(6) << ratio_ghost.counters[iC] // particles w\o MCParticle + << " / " << std::setw(6) << ratio_bg.counters[iC] // particles with incorrect MCParticle + << " / " << std::setw(6) << ratio_clone.counters[iC] // particles with incorrect MCParticle + << " / " << std::setw(6) << ghost.counters[iC] + << " / " << std::setw(7) << bg.counters[iC] + << " / " << std::setw(6) << reco.counters[iC] + << " / " << std::setw(7) << clone.counters[iC] + << " | " << std::setw(6) << mc.counters[iC] << std::endl; + } + std::cout.flags(original_flags); + }; + + /** \brief Operator to write efficiencies to file. */ + friend std::fstream & operator<<(std::fstream &strm, KFPVEfficiencies &a) { + + strm << a.ratio_reco; + strm << a.mc; + strm << a.reco; + strm << a.ratio_ghost; + strm << a.ratio_bg; + strm << a.ratio_clone; + strm << a.ghost; + strm << a.bg; + strm << a.clone; + + return strm; + } + /** \brief Operator to read efficiencies from file. */ + friend std::fstream & operator>>(std::fstream &strm, KFPVEfficiencies &a){ + + strm >> a.ratio_reco; + strm >> a.mc; + strm >> a.reco; + strm >> a.ratio_ghost; + strm >> a.ratio_bg; + strm >> a.ratio_clone; + strm >> a.ghost; + strm >> a.bg; + strm >> a.clone; + + return strm; + } + /** \brief Adds efficiency from the file with the name defined by "fileName" to the current objects. */ + void AddFromFile(TString fileName) + { + std::fstream file(fileName.Data(),std::fstream::in); + file >> *this; + } + + private: + std::vector<TString> names; ///< Names of the counters. The same for all counters objects. + std::map<TString, int> indices; ///< Map between the counter index and its short name. + + KFMCCounter<double> ratio_reco; ///< Efficiency. + + KFMCCounter<int> mc; ///< Counters of the Monte Carlo vertices. + KFMCCounter<int> reco; ///< Counters of the reconstructed vertices. + + KFMCCounter<double> ratio_ghost; ///< Ratio of the ghost candidates to the total number of candidates. + KFMCCounter<double> ratio_bg; ///< Ratio of the physics background candidates to the total number of candidates. + KFMCCounter<double> ratio_clone; ///< Ratio of double reconstructed vertices to the total number of signal candidates. + + KFMCCounter<int> ghost; ///< Counters of the ghost candidates. + KFMCCounter<int> bg; ///< Counters of the physics background candidates. + KFMCCounter<int> clone; ///< Counters of the double reconstructed vertices. +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFPartEfficiencies.cxx b/external/KFParticle/KFParticlePerformance/KFPartEfficiencies.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4b86a8f6d2a72e04275a4dc8b37e695830298128 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFPartEfficiencies.cxx @@ -0,0 +1,16 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#include "KFPartEfficiencies.h" + +#ifndef KFParticleStandalone +ClassImp(KFPartEfficiencies) +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFPartEfficiencies.h b/external/KFParticle/KFParticlePerformance/KFPartEfficiencies.h new file mode 100644 index 0000000000000000000000000000000000000000..0cae660c3a79be623abc1279345a843dc2d571a1 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFPartEfficiencies.h @@ -0,0 +1,1327 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPartEfficiencies_H +#define KFPartEfficiencies_H + +#include <map> +#include <iomanip> +#include "KFMCCounter.h" + +#ifdef HLTCA_STANDALONE +#include "RootTypesDef.h" +#else +#include "TObject.h" +#endif + +/** @class KFEfficiencyParticleInfo + ** @brief A helper class to define parameters of the decay list in KFPartEfficiencies. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + **/ + +class KFEfficiencyParticleInfo +{ + public: + KFEfficiencyParticleInfo():fName("null"),fTitle("null"),fPDG(0),fHistoMin(0.f),fHistoMax(0.f),fMass(0.f),fLifeTime(0.f),fCharge(0), fMassSigma(0.001) {}; + /** \brief Constructor with all parameters set in. There is no other way to define the parameters other then use this constructor.*/ + KFEfficiencyParticleInfo(std::string name, std::string title, int pdg, float histoMin, float histoMax, float mass, float lifeTime, int charge, float massSigma ): + fName(name), fTitle(title), fPDG(pdg), fHistoMin(histoMin), fHistoMax(histoMax), fMass(mass), fLifeTime(lifeTime), fCharge(charge), fMassSigma(massSigma) {}; + ~KFEfficiencyParticleInfo() {}; + + //accessors + std::string Name() const { return fName; } ///< Returns name of the decay in the file with histograms. + std::string Title() const { return fTitle; } ///< Returns name of the decay in the output table with efficiency. + int PDG() const { return fPDG; } ///< Returns the assigned PDG code. + float HistoMin() const { return fHistoMin; } ///< Returns lower boundary in the mass histogram for the current decay. + float HistoMax() const { return fHistoMax; } ///< Returns upper boundary in the mass histogram for the current decay. + float Mass() const { return fMass; } ///< Returns table mass of the particle. + float LifeTime() const { return fLifeTime; } ///< Returns lifetime of the particle. + int Charge() const { return fCharge; } ///< Returns charge of the particle in units of the elementary charge. + float MassSigma() const { return fMassSigma; } ///< Returns expected width of the mass peak, used in the side bands method. + + private: + std::string fName; ///< Name of the decay in the file with histograms. + std::string fTitle; ///< Name of the decay in the output table with efficiency. + int fPDG; ///< PDG code assigned to the current decay in the scheme of KF Particle Finder. + float fHistoMin; ///< Lower boundary in the mass histogram for the current decay. + float fHistoMax; ///< Upper boundary in the mass histogram for the current decay. + float fMass; ///< Table mass of the particle. + float fLifeTime; ///< Lifetime of the particle in seconds. + int fCharge; ///< Charge in units of the elementary charge. + float fMassSigma; ///< Expected width of the decay, determines peak sigma for the side bands method. +}; + +/** @class KFPartEfficiencies + ** @brief Class to calculate efficiency of KF Particle Finder. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class has two main purposes:\n + ** 1) Defines the list of decays to be analysed: a unique code of the decay, its mass, lifetime, + ** a list of daughter particles, etc. See KFPartEfficiencies::KFPartEfficiencies() for more details.\n + ** 2) It calculates reconstruction efficiency of the decays from the KF Particle Finder scheme.\n + ** Definitions:\n + ** background - physics background, when daughter particle come from the real particle, but the pdg + ** hypothesis is incorrect, for example, Lambda->p pi will create a physics background for + ** K0s if the proton is misidentified;\n + ** ghost - combinatorial background, tracks do not form a real vertex;\n + ** clone - a particle is reconstructed several times, for example, particle track is split into + ** to parts due to the multiple scattering. + **/ + +class KFPartEfficiencies :public TObject +{ + public: + + /** \brief The default constructor. Defines the list of decays to be analysed and their properties. Please, see the code for indexing scheme. */ + KFPartEfficiencies(): + partDaughterPdg(0), + names(), + indices(), + fPdgToIndex(), + ratio_reco1(), + ratio_reco2(), + ratio_reco3(), + mc1(), + mc2(), + mc3(), + reco(), + ratio_ghost(), + ratio_bg(), + ratio_clone(), + ghost(), + bg(), + clone() + { + KFEfficiencyParticleInfo particleInfo[nParticles] = + { + // name title PDG code min max mass lifetime Q +#ifdef CBM + KFEfficiencyParticleInfo("Ks", "KShort ", 310, 0.3f, 1.3f, 0.497614 , 8.954e-11, 0, 0.0045), //0 +#else + KFEfficiencyParticleInfo("Ks", "KShort ", 310, 0.3f, 1.3f, 0.497614 , 8.954e-11, 0, 0.0057), //0 +#endif + KFEfficiencyParticleInfo("Lambda", "Lambda ", 3122, 1.0f, 2.0f, 1.115683 , 2.632e-10, 0, 0.0020), //1 + KFEfficiencyParticleInfo("Lambdab", "Lambda b ", -3122, 1.0f, 2.0f, 1.115683 , 2.632e-10, 0, 0.0020), //2 + KFEfficiencyParticleInfo("Xi-", "Xi- ", 3312, 1.0f, 3.0f, 1.32171 , 1.639e-10, -1, 0.0022), //3 + KFEfficiencyParticleInfo("Xi+", "Xi+ ", -3312, 1.0f, 3.0f, 1.32171 , 1.639e-10, 1, 0.0022), //4 + KFEfficiencyParticleInfo("Xi0", "Xi0 ", 3322, 1.0f, 3.0f, 1.31486 , 2.9e-10, 0, 0.0030), //5 + KFEfficiencyParticleInfo("Xi0b", "Xi0 b ", -3322, 1.0f, 3.0f, 1.31486 , 2.9e-10, 0, 0.0030), //6 + KFEfficiencyParticleInfo("Omega-", "Omega- ", 3334, 1.0f, 3.0f, 1.67245 , 0.821e-10, -1, 0.0022), //7 + KFEfficiencyParticleInfo("Omega+", "Omega+ ", -3334, 1.0f, 3.0f, 1.67245 , 0.821e-10, 1, 0.0022), //8 + KFEfficiencyParticleInfo("Sigma^0", "Sigma0 ", 3212, 1.0f, 3.0f, 1.192642 , 7.4e-20, 0, 0.0030), //9 + KFEfficiencyParticleInfo("Sigma^0b", "Sigma0 b ", -3212, 1.0f, 3.0f, 1.192642 , 7.4e-20, 0, 0.0030), //10 + KFEfficiencyParticleInfo("Sigma^+", "Sigma+ ", 3222, 1.0f, 3.0f, 1.18937 , 0.8018e-10, 1, 0.0030), //11 + KFEfficiencyParticleInfo("Sigma^-b", "Sigma- b ", -3222, 1.0f, 3.0f, 1.18937 , 0.8018e-10,-1, 0.0030), //12 + KFEfficiencyParticleInfo("K*0", "K*0 ", 313, 0.6f, 2.6f, 0.8958 , 1.38e-23, 0, 0.0300), //13 + KFEfficiencyParticleInfo("K*0b", "K*0 b ", -313, 0.6f, 2.6f, 0.8958 , 1.38e-23, 0, 0.0300), //14 + KFEfficiencyParticleInfo("K*+", "K*+ ", 323, 0.6f, 2.6f, 0.89166 , 1.30e-23, 1, 0.0300), //15 + KFEfficiencyParticleInfo("K*-", "K*- ", -323, 0.6f, 2.6f, 0.89166 , 1.30e-23, -1, 0.0300), //16 + KFEfficiencyParticleInfo("K*0_K0,pi0", "K*0_K0pi0 ", 100313, 0.6f, 2.6f, 0.8958 , 1.38e-23, 0, 0.0030), //17 + KFEfficiencyParticleInfo("K*+_K+,pi0", "K*+_K+pi0 ", 100323, 0.6f, 2.6f, 0.89166 , 1.30e-23, 1, 0.0030), //18 + KFEfficiencyParticleInfo("K*-_K-,pi0", "K*-_K-pi0 ", -100323, 0.6f, 2.6f, 0.89166 , 1.30e-23, -1, 0.0030), //19 + KFEfficiencyParticleInfo("Sigma*+", "Sigma*+ ", 3224, 1.0f, 3.0f, 1.3828 , 1.83e-23, 1, 0.0100), //20 + KFEfficiencyParticleInfo("Sigma*-", "Sigma*- ", 3114, 1.0f, 3.0f, 1.3872 , 1.67e-23, -1, 0.0100), //21 + KFEfficiencyParticleInfo("Sigma*+b", "Sigma*+ b ", -3114, 1.0f, 3.0f, 1.3828 , 1.83e-23, -1, 0.0100), //22 + KFEfficiencyParticleInfo("Sigma*-b", "Sigma*- b ", -3224, 1.0f, 3.0f, 1.3872 , 1.67e-23, 1, 0.0100), //23 + KFEfficiencyParticleInfo("Sigma*0", "Sigma*0 ", 3214, 1.0f, 3.0f, 1.3837 , 1.83e-23, 0, 0.0030), //24 + KFEfficiencyParticleInfo("Sigma*0b", "Sigma*0 b ", -3214, 1.0f, 3.0f, 1.3837 , 1.83e-23, 0, 0.0030), //25 + KFEfficiencyParticleInfo("Lambda*", "Lambda* ", 3124, 1.4f, 3.4f, 1.5195 , 4.22e-23, 0, 0.0100), //26 + KFEfficiencyParticleInfo("Lambda*b", "Lambda* b ", -3124, 1.4f, 3.4f, 1.5195 , 4.22e-23, 0, 0.0100), //27 + KFEfficiencyParticleInfo("Xi*0", "Xi*0 ", 3324, 1.4f, 3.4f, 1.53180 , 7.23e-23, 0, 0.0100), //28 + KFEfficiencyParticleInfo("Xi*0b", "Xi*0 b ", -3324, 1.4f, 3.4f, 1.53180 , 7.23e-23, 0, 0.0100), //29 + KFEfficiencyParticleInfo("Xi*-_LK", "Xi*-_lk ", 1003314, 1.4f, 3.4f, 1.823 , 2.74e-23, -1, 0.0030), //30 + KFEfficiencyParticleInfo("Xi*+_LK", "Xi*+_lk ", -1003314, 1.4f, 3.4f, 1.823 , 2.74e-23, 1, 0.0030), //31 + KFEfficiencyParticleInfo("Xi*-_xi-,pi0", "Xi*-_XiPi ", 3314, 1.4f, 3.4f, 1.535 , 6.65e-23, -1, 0.0030), //32 + KFEfficiencyParticleInfo("Xi*+_xi+,pi0", "Xi*+_XiPi ", -3314, 1.4f, 3.4f, 1.535 , 6.65e-23, 1, 0.0030), //33 + KFEfficiencyParticleInfo("Omega*-", "Omega*- ", 1003334, 1.8f, 3.8f, 2.252 , 1.2e-23, -1, 0.0030), //34 + KFEfficiencyParticleInfo("Omega*+", "Omega*+ ", -1003334, 1.8f, 3.8f, 2.252 , 1.2e-23, 1, 0.0030), //35 + KFEfficiencyParticleInfo("H0_LL", "H0_LL ", 3000, 1.5f, 3.5f, 2.21 , 1.32e-10, 0, 0.0030), //36 + KFEfficiencyParticleInfo("phi_KK", "phi_KK ", 333, 0.8f, 2.8f, 1.019455 , 1.55e-22, 0, 0.0030), //37 + KFEfficiencyParticleInfo("rho_pipi", "rho_pipi ", 113, 0.0f, 2.0f, 0.77526 , 4.45e-24, 0, 0.0030), //38 + KFEfficiencyParticleInfo("rho_ee", "rho_ee ", 100113, 0.0f, 2.0f, 0.77526 , 4.45e-24, 0, 0.0030), //39 + KFEfficiencyParticleInfo("rho_mm", "rho_mm ", 200113, 0.0f, 2.0f, 0.77526 , 4.45e-24, 0, 0.0030), //40 + KFEfficiencyParticleInfo("gamma", "gamma ", 22, 0.0f, 3.0f, 0. , 1.e20, 0, 0.0030), //41 + KFEfficiencyParticleInfo("pi0", "pi0 ", 111, 0.0f, 3.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //42 + KFEfficiencyParticleInfo("eta", "eta ", 221, 0.0f, 3.0f, 0.547862 , 5.0e-19, 0, 0.0030), //43 +//Delta and N resonances + KFEfficiencyParticleInfo("Delta0", "Delta0 ", 2114, 1.0f, 3.0f, 1.232 , 5.63e-24, 0, 0.0030), //44 + KFEfficiencyParticleInfo("Delta0 b", "Delta0 b ", -2114, 1.0f, 3.0f, 1.232 , 5.63e-24, 0, 0.0030), //45 + KFEfficiencyParticleInfo("Delta++", "Delta++ ", 2224, 1.0f, 3.0f, 1.232 , 5.63e-24, 2, 0.0030), //46 + KFEfficiencyParticleInfo("Delta-- b", "Delta-- b ", -2224, 1.0f, 3.0f, 1.232 , 5.63e-24, -2, 0.0030), //47 +//charmonium + KFEfficiencyParticleInfo("JPsi_ee", "JPsi_ee ", 443, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //48 + KFEfficiencyParticleInfo("JPsi_mumu", "JPsi_mm ", 100443, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //49 + KFEfficiencyParticleInfo("JPsi_pp", "JPsi_pp ", 200443, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //50 + KFEfficiencyParticleInfo("JPsi_LL", "JPsi_LL ", 300443, 2.0f, 5.0f, 3.096916 , 7.1e-21, 0, 0.0030), //51 + KFEfficiencyParticleInfo("JPsi_XiXi", "JPsi_XiXi ", 400443, 2.0f, 5.0f, 3.096916 , 7.1e-21, 0, 0.0030), //52 + KFEfficiencyParticleInfo("Psi_OO", "Psi_OO ", 500443, 3.0f, 6.0f, 3.686109 , 2.1e-22, 0, 0.0030), //53 +//open charm + KFEfficiencyParticleInfo("D0", "D0 ", 421, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //54 + KFEfficiencyParticleInfo("D0b", "D0b ", -421, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //55 + KFEfficiencyParticleInfo("D0_4", "D0_4 ", 429, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0100), //56 + KFEfficiencyParticleInfo("D0b_4", "D0b_4 ", -429, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0100), //57 + KFEfficiencyParticleInfo("D0_pipi", "D0_pipi ", 420, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //58 + KFEfficiencyParticleInfo("D0_2pi2pi", "D0_2pi2pi ", 470, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //59 + KFEfficiencyParticleInfo("D0_K0pipi", "D0_K0pipi ", 425, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0150), //60 + KFEfficiencyParticleInfo("D0_KK", "D0_KK ", 426, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0130), //61 + KFEfficiencyParticleInfo("D0_KKK0", "D0_KKK0 ", 427, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //62 + KFEfficiencyParticleInfo("D0_pi0", "D0_#pi0 ", 428, 1.0f, 3.0f, 1.86486 , 4.1e-13, 0, 0.0030), //63 + KFEfficiencyParticleInfo("D+", "D+ ", 411, 1.0f, 3.0f, 1.86962 , 1.04e-13, 1, 0.0114), //64 + KFEfficiencyParticleInfo("D-", "D- ", -411, 1.0f, 3.0f, 1.86962 , 1.04e-13, -1, 0.0114), //65 + KFEfficiencyParticleInfo("D+_K0pi+", "D+_K0pi+ ", 100411, 0.6f, 4.6f, 1.86962 , 1.04e-13, 1, 0.0030), //66 + KFEfficiencyParticleInfo("D-_K0pi-", "D-_K0pi- ", -100411, 0.6f, 4.6f, 1.86962 , 1.04e-13, -1, 0.0030), //67 + KFEfficiencyParticleInfo("D+_K03pi", "D+_K03pi ", 200411, 0.6f, 4.6f, 1.86962 , 1.04e-13, 1, 0.0030), //68 + KFEfficiencyParticleInfo("D-_K03pi", "D-_K03pi ", -200411, 0.6f, 4.6f, 1.86962 , 1.04e-13, -1, 0.0030), //69 + KFEfficiencyParticleInfo("D+_3pi", "D+_3pi ", 300411, 0.6f, 4.6f, 1.86962 , 1.04e-13, 1, 0.0030), //70 + KFEfficiencyParticleInfo("D-_3pi", "D-_3pi ", -300411, 0.6f, 4.6f, 1.86962 , 1.04e-13, -1, 0.0030), //71 + KFEfficiencyParticleInfo("Ds+", "Ds+ ", 431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0110), //72 + KFEfficiencyParticleInfo("Ds-", "Ds- ", -431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0110), //73 + KFEfficiencyParticleInfo("Ds+_K0K+", "Ds+_K0K+ ", 100431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0030), //74 + KFEfficiencyParticleInfo("Ds-_K0K-", "Ds-_K0K- ", -100431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0030), //75 + KFEfficiencyParticleInfo("Ds+_K0K0pi+", "Ds+_K0K0pi+ ", 200431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0030), //76 + KFEfficiencyParticleInfo("Ds-_K0K0pi-", "Ds-_K0K0pi- ", -200431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0030), //77 + KFEfficiencyParticleInfo("Ds+_K0K+pipi", "Ds+_K0K+pipi ", 300431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0030), //78 + KFEfficiencyParticleInfo("Ds-_K0K-pipi", "Ds-_K0K-pipi ", -300431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0030), //79 + KFEfficiencyParticleInfo("Ds+_K+pipi", "Ds+_K+pipi ", 400431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0030), //80 + KFEfficiencyParticleInfo("Ds-_K-pipi", "Ds-_K-pipi ", -400431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0030), //81 + KFEfficiencyParticleInfo("Lc", "Lambdac ", 4122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0110), //82 + KFEfficiencyParticleInfo("Lcb", "Lambdac b ", -4122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0110), //83 + KFEfficiencyParticleInfo("Lc_{pK0}", "Lc {pK0} ", 104122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //84 + KFEfficiencyParticleInfo("Lcb_{pK0}", "Lc b {pK0} ", -104122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //85 + KFEfficiencyParticleInfo("Lc_{pK02pi}", "Lc {pK02pi} ", 204122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //86 + KFEfficiencyParticleInfo("Lcb_{pK02pi}", "Lc b {pK02pi} ", -204122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //87 + KFEfficiencyParticleInfo("Lc_{Lpi}", "Lc {Lpi} ", 304122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //88 + KFEfficiencyParticleInfo("Lcb_{Lpi}", "Lc b {Lpi} ", -304122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //89 + KFEfficiencyParticleInfo("Lc_{L3pi}", "Lc {L3pi} ", 404122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //90 + KFEfficiencyParticleInfo("Lcb_{L3pi}", "Lc b {L3pi} ", -404122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //91 + KFEfficiencyParticleInfo("Lc_{p2pi}", "Lc {p2pi} ", 504122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //92 + KFEfficiencyParticleInfo("Lcb_{p2pi}", "Lc b {p2pi} ", -504122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //93 + KFEfficiencyParticleInfo("Xic0", "Xic0 ", 4132, 2.1f, 4.1f, 2.47087 , 1.0e-13, 0, 0.0030), //94 + KFEfficiencyParticleInfo("Xic0b", "Xic0b ", -4132, 2.1f, 4.1f, 2.47087 , 1.0e-13, 0, 0.0030), //95 + KFEfficiencyParticleInfo("D*0", "D*0 ", 10421, 1.8f, 3.8f, 2.00699 , 3.0e-22, 0, 0.0030), //96 + KFEfficiencyParticleInfo("D*0b", "D*0 b ", -10421, 1.8f, 3.8f, 2.00699 , 3.0e-22, 0, 0.0030), //97 + KFEfficiencyParticleInfo("D*+", "D*+ ", 10411, 1.8f, 3.8f, 2.01029 , 6.86e-21, 1, 0.0030), //98 + KFEfficiencyParticleInfo("D*-", "D*- ", -10411, 1.8f, 3.8f, 2.01029 , 6.86e-21, -1, 0.0030), //99 + KFEfficiencyParticleInfo("D*+_4", "D*+_4 ", 20411, 1.8f, 3.8f, 2.01029 , 6.86e-21, 1, 0.0030), //100 + KFEfficiencyParticleInfo("D*-_4", "D*-_4 ", -20411, 1.8f, 3.8f, 2.01029 , 6.86e-21, -1, 0.0030), //101 + KFEfficiencyParticleInfo("D0*_pi0", "D0*_#pi0 ", 10428, 1.8f, 3.8f, 2.00699 , 6.86e-21, 0, 0.0030), //102 +//B mesons + KFEfficiencyParticleInfo("B_Jpsi_ee", "B_Jpsi_ee ", 500, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //103 + KFEfficiencyParticleInfo("B_Jpsi_mm", "B_Jpsi_mm ", 501, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //104 + KFEfficiencyParticleInfo("B+_D0bPi+", "B+ {D0bPi+} ", 521, 3.0f, 7.0f, 5.27931 , 1.638e-12, 0, 0.0030), //105 + KFEfficiencyParticleInfo("B-_D0Pi-", "B- {D0Pi-} ", -521, 3.0f, 7.0f, 5.27931 , 1.638e-12, 0, 0.0030), //106 + KFEfficiencyParticleInfo("B+_D0bK+", "B+ {D0bK+} ", 529, 3.0f, 7.0f, 5.27931 , 1.638e-12, 0, 0.0030), //107 + KFEfficiencyParticleInfo("B-_D0K-", "B- {D0K+} ", -529, 3.0f, 7.0f, 5.27931 , 1.638e-12, 0, 0.0030), //108 + KFEfficiencyParticleInfo("B0_D-Pi+", "B0 {D-Pi+} ", 511, 3.0f, 7.0f, 5.27962 , 1.520e-12, 0, 0.0030), //109 + KFEfficiencyParticleInfo("B0b_D+Pi-", "B0b {D+Pi-} ", -511, 3.0f, 7.0f, 5.27962 , 1.520e-12, 0, 0.0030), //110 + KFEfficiencyParticleInfo("B0_D-K+", "B0 {D-K+} ", 519, 3.0f, 7.0f, 5.27962 , 1.520e-12, 0, 0.0030), //111 + KFEfficiencyParticleInfo("B0b_D+K-", "B0b {D+K-} ", -519, 3.0f, 7.0f, 5.27962 , 1.520e-12, 0, 0.0030), //112 + KFEfficiencyParticleInfo("H0_{Lppi}", "H0 ", 3001, 2.0f, 4.0f, 2.21 , 1.32e-10, 0, 0.0030), //113 +//hypernuclei + KFEfficiencyParticleInfo("LambdaN", "LambdaN ", 3003, 1.0f, 3.0f, 2.05395 , 1.00e-10, 0, 0.0030), //114 + KFEfficiencyParticleInfo("LambdaNb", "LambdaN b ", -3003, 1.0f, 3.0f, 2.05395 , 1.00e-10, 0, 0.0030), //115 + KFEfficiencyParticleInfo("LambdaNN", "LambdaNN ", 3103, 2.0f, 4.0f, 2.99352 , 1.00e-10, 0, 0.0030), //116 + KFEfficiencyParticleInfo("LambdaNNb", "LambdaNN b ", -3103, 2.0f, 4.0f, 2.99352 , 1.00e-10, 0, 0.0030), //117 + KFEfficiencyParticleInfo("H3L", "H3L ", 3004, 2.0f, 4.0f, 2.99339 , 1.85e-10, 1, 0.0030), //118 + KFEfficiencyParticleInfo("H3Lb", "H3L b ", -3004, 2.0f, 4.0f, 2.99339 , 1.85e-10, -1, 0.0030), //119 + KFEfficiencyParticleInfo("H4L", "H4L ", 3005, 3.0f, 5.0f, 3.92975 , 1.80e-10, 1, 0.0030), //120 + KFEfficiencyParticleInfo("H4Lb", "H4L b ", -3005, 3.0f, 5.0f, 3.92975 , 1.80e-10, -1, 0.0030), //121 + KFEfficiencyParticleInfo("He4L", "He4L ", 3006, 3.0f, 5.0f, 3.93070 , 1.50e-10, 2, 0.0030), //122 + KFEfficiencyParticleInfo("He4Lb", "He4L b ", -3006, 3.0f, 5.0f, 3.93070 , 1.50e-10, -2, 0.0030), //123 + KFEfficiencyParticleInfo("He5L", "He5L ", 3007, 4.0f, 6.0f, 4.86824 , 1.40e-10, 2, 0.0030), //124 + KFEfficiencyParticleInfo("He5Lb", "He5L b ", -3007, 4.0f, 6.0f, 4.86824 , 1.40e-10, -2, 0.0030), //125 + KFEfficiencyParticleInfo("LLn", "LLn ", 3203, 3.0f, 5.0f, 3.16964 , 1.00e-10, 0, 0.0030), //126 + KFEfficiencyParticleInfo("H4LL_{He4Lpi-}", "H4LL_{He4Lpi-}", 3008, 3.0f, 5.0f, 4.10791 , 1.0e-10, 1, 0.0030), //127 + KFEfficiencyParticleInfo("H4LL_{H3Lppi-}", "H4LL_{H3Lppi-}", 3009, 3.0f, 5.0f, 4.10791 , 1.0e-10, 1, 0.0030), //128 + KFEfficiencyParticleInfo("H5LL_{He5Lpi-}", "H5LL_{He5Lpi-}", 3010, 4.0f, 6.0f, 5.04748 , 1.0e-10, 1, 0.0030), //129 + KFEfficiencyParticleInfo("He6LL", "He6LL ", 3011, 5.0f, 7.0f, 5.98575 , 1.0e-10, 2, 0.0030), //130 +//missing mass method + KFEfficiencyParticleInfo("pi-_{mu,nu}", "pi-_{mnu} ", -7000211,-1.0f, 1.0f, 0.139570 , 2.6e-8, -1, 0.0030), //131 + KFEfficiencyParticleInfo("nu_{pi-}", "nu_{mupi-} b ", -7000014,-1.0f, 1.0f, 0. , 1.0e20, 0, 0.0030), //132 + KFEfficiencyParticleInfo("pi+_{mu,nu}", "pi+_{mnu} ", 7000211,-1.0f, 1.0f, 0.139570 , 2.6e-8, 1, 0.0030), //133 + KFEfficiencyParticleInfo("nu_{pi+}", "nu_{mupi+} ", 7000014,-1.0f, 1.0f, 0. , 1.0e20, 0, 0.0030), //134 + KFEfficiencyParticleInfo("K-_{mu,nu}", "K-_{mnu} ", -7000321,-1.0f, 1.0f, 0.493677 , 1.238e-8, -1, 0.0030), //135 + KFEfficiencyParticleInfo("nu_{K-}", "nu_{K-} b ", -8000014,-1.0f, 1.0f, 0. , 1.0e20, 0, 0.0030), //136 + KFEfficiencyParticleInfo("K+_{mu,nu}", "K+_{mnu} ", 7000321,-1.0f, 1.0f, 0.493677 , 1.238e-8, 1, 0.0030), //137 + KFEfficiencyParticleInfo("nu_{K+}", "nu_{K+} ", 8000014,-1.0f, 1.0f, 0. , 1.0e20, 0, 0.0030), //138 + KFEfficiencyParticleInfo("Sigma-_{pi-,n}", "Sigma-_{pi-n} ", 7003112, 0.0f, 3.0f, 1.192642 , 1.479e-10, -1, 0.0100), //139 + KFEfficiencyParticleInfo("n_{Sigma-}", "n_{Sigma-} ", 7002112, 0.0f, 1.5f, 0.9395654 , 880, 0, 0.0030), //140 + KFEfficiencyParticleInfo("Sigma+_{pi+n}b", "Sigma+{pi+n} b", -7003112, 0.0f, 3.0f, 1.192642 , 1.479e-10, -1, 0.0030), //141 + KFEfficiencyParticleInfo("n_{Sigma+} b", "n_{Sigma+b} b ", -7002112, 0.0f, 1.5f, 0.9395654 , 880, 0, 0.0030), //142 + KFEfficiencyParticleInfo("Sigma-_{pi-n}b", "Sigma+{pi-n} b", -7003222, 0.0f, 3.0f, 1.18937 , 0.8018e-10, 1, 0.0030), //143 + KFEfficiencyParticleInfo("n_{Sigma-} b", "n_{Sigma-_b} b", -8002112, 0.0f, 1.5f, 0.9395654 , 0.93956541, 0, 0.0030), //144 + KFEfficiencyParticleInfo("Sigma+_{pi+n}", "Sigma+_{pi+n} ", 7003222, 0.0f, 3.0f, 1.18937 , 0.8018e-10, 1, 0.0100), //145 + KFEfficiencyParticleInfo("n_{Sigma+}", "n_{Sigma+} ", 8002112, 0.0f, 1.5f, 0.9395654 , 880, 0, 0.0030), //146 + KFEfficiencyParticleInfo("Xi-_{pi-L}", "Xi-_{pi-L} ", 7003312, 0.0f, 3.0f, 1.32171 , 1.639e-10, -1, 0.0030), //147 + KFEfficiencyParticleInfo("Lambda_{Xi-}", "Lambda_{Xi-} ", 7003122, 0.0f, 2.0f, 1.115683 , 2.632e-10, 0, 0.0030), //148 + KFEfficiencyParticleInfo("Xi+_{pi+L_b}", "Xi+_{pi+L_b} ", -7003312, 0.0f, 3.0f, 1.32171 , 1.639e-10, 1, 0.0030), //149 + KFEfficiencyParticleInfo("Lambda_{Xi+} b", "Lambda_{Xi+} b", -7003122, 0.0f, 2.0f, 1.115683 , 2.632e-10, 0, 0.0030), //150 + KFEfficiencyParticleInfo("Omega-_{Xi-pi0}", "Omega-{pi-Xi0}", 7003334, 0.0f, 3.0f, 1.67245 , 0.821e-10, -1, 0.0030), //151 + KFEfficiencyParticleInfo("Xi0_{Omega-}", "Xi0_{Omega-} ", 7003322, 0.0f, 3.0f, 1.31486 , 2.9e-10, 0, 0.0030), //152 + KFEfficiencyParticleInfo("Omega+_{Xi+pi0}", "Omega+_{Xipi0}", -7003334, 0.0f, 3.0f, 1.67245 , 0.821e-10, 1, 0.0030), //153 + KFEfficiencyParticleInfo("Xi0_{Omega+} b", "Xi0_{Omega+} b", -7003322, 0.0f, 3.0f, 1.31486 , 2.9e-10, 0, 0.0030), //154 + KFEfficiencyParticleInfo("K-_{pi-pi0}", "K-_{pi-pi0} ", -9000321, 0.0f, 3.0f, 0.493677 , 1.24e-8, -1, 0.0030), //155 + KFEfficiencyParticleInfo("pi0_{K-}", "pi0_{K-} ", -9000111, 0.0f, 3.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //156 + KFEfficiencyParticleInfo("K+_{pi+pi0}", "K+_{pi+pi0} ", 9000321, 0.0f, 3.0f, 0.493677 , 1.24e-8, 1, 0.0030), //157 + KFEfficiencyParticleInfo("pi0_{K+}", "pi0_{K+} ", 9000111, 0.0f, 3.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //158 + KFEfficiencyParticleInfo("Omega-{K-L}", "Omega-_{K-L} ", 8003334, 0.0f, 3.0f, 1.67245 , 0.821e-10, -1, 0.0030), //159 + KFEfficiencyParticleInfo("Lambda_{Omega-}", "Lambda_{O-} ", 8003122, 0.0f, 3.0f, 1.115683 , 2.632e-10, 0, 0.0030), //160 + KFEfficiencyParticleInfo("Omega+_{K+L_b}", "Omega+_{K+Lb} ", -8003334, 0.0f, 3.0f, 1.67245 , 0.821e-10, 1, 0.0030), //161 + KFEfficiencyParticleInfo("Lamda_{Omega+} b", "Lambda_{O+} b ", -8003122, 0.0f, 3.0f, 1.115683 , 2.632e-10, 0, 0.0030), //162 + KFEfficiencyParticleInfo("Sigma-{p_b pi0} b","Sigma-{ppi0} b", -8003222, 0.0f, 3.0f, 1.18937 , 0.8018e-10, 1, 0.0030), //163 + KFEfficiencyParticleInfo("pi0_{Sigma-b}", "pi0_{Sigma-_b}", -8000111, 0.0f, 3.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //164 + KFEfficiencyParticleInfo("Sigma+_{p pi0}", "Sigma+_{ppi0} ", 8003222, 0.0f, 3.0f, 1.18937 , 0.8018e-10, 1, 0.0250), //165 + KFEfficiencyParticleInfo("pi0_{Sigma+}", "pi0_{Sigma+} ", 8000111, 0.0f, 3.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //166 +//tracks + KFEfficiencyParticleInfo("e-", "e- ", 11, 0.0f,0.01f, 5.485799e-4, 1.0e20, -1, 0.0030), //167 + KFEfficiencyParticleInfo("e+", "e+ ", -11, 0.0f,0.01f, 5.485799e-4, 1.0e20, 1, 0.0030), //168 + KFEfficiencyParticleInfo("mu-", "mu- ", 13, 0.0f, 1.0f, 0.105658 , 2.2e-6, -1, 0.0030), //169 + KFEfficiencyParticleInfo("mu+", "mu+ ", -13, 0.0f, 1.0f, 0.105658 , 2.2e-6, 1, 0.0030), //170 + KFEfficiencyParticleInfo("pi+", "pi+ ", 211, 0.0f, 1.0f, 0.139570 , 2.6e-8, 1, 0.0030), //171 + KFEfficiencyParticleInfo("pi-", "pi- ", -211, 0.0f, 1.0f, 0.139570 , 2.6e-8, -1, 0.0030), //172 + KFEfficiencyParticleInfo("K+", "K+ ", 321, 0.0f, 1.0f, 0.493677 , 1.238e-8, 1, 0.0030), //173 + KFEfficiencyParticleInfo("K-", "K- ", -321, 0.0f, 1.0f, 0.493677 , 1.238e-8, -1, 0.0030), //174 + KFEfficiencyParticleInfo("p+", "p+ ", 2212, 0.0f, 1.5f, 0.938272 , 1.0e20, 1, 0.0030), //175 + KFEfficiencyParticleInfo("p-", "p- ", -2212, 0.0f, 1.5f, 0.938272 , 1.0e20, -1, 0.0030), //176 + KFEfficiencyParticleInfo("d+", "d+ ", 1000010020, 0.0f, 2.5f, 1.876124 , 1.0e20, 1, 0.0030), //177 + KFEfficiencyParticleInfo("d-", "d- ",-1000010020, 0.0f, 2.5f, 1.876124 , 1.0e20, -1, 0.0030), //178 + KFEfficiencyParticleInfo("t+", "t+ ", 1000010030, 0.0f, 3.5f, 2.809432 , 1.0e20, 1, 0.0030), //179 + KFEfficiencyParticleInfo("t-", "t- ",-1000010030, 0.0f, 3.5f, 2.809432 , 1.0e20, -1, 0.0030), //180 + KFEfficiencyParticleInfo("He3+", "He3+ ", 1000020030, 0.0f, 3.5f, 2.809413 , 1.0e20, 2, 0.0030), //181 + KFEfficiencyParticleInfo("He3-", "He3- ",-1000020030, 0.0f, 3.5f, 2.809413 , 1.0e20, -2, 0.0030), //182 + KFEfficiencyParticleInfo("He4+", "He4+ ", 1000020040, 0.0f, 4.5f, 3.728400 , 1.0e20, 2, 0.0030), //183 + KFEfficiencyParticleInfo("He4-", "He4- ",-1000020040, 0.0f, 4.5f, 3.728400 , 1.0e20, -2, 0.0030), //184 +//background for subtraction + KFEfficiencyParticleInfo("pi+pi+", "pi+pi+ ", 9001, 0.0f, 2.0f, 0 , 1.0e20, 0, 0.0030), //185 + KFEfficiencyParticleInfo("pi+K+", "pi+K+ ", 9002, 0.6f, 5.6f, 0 , 1.0e20, 0, 0.0030), //186 + KFEfficiencyParticleInfo("K+K+", "K+K+ ", 9003, 0.8f, 3.8f, 0 , 1.0e20, 0, 0.0030), //187 + KFEfficiencyParticleInfo("K+p+", "K+p+ ", 9004, 1.4f, 5.4f, 0 , 1.0e20, 0, 0.0030), //188 + KFEfficiencyParticleInfo("pi-pi-", "pi-pi- ", -9001, 0.0f, 2.0f, 0 , 1.0e20, 0, 0.0030), //189 + KFEfficiencyParticleInfo("pi-K-", "pi-K- ", -9002, 0.6f, 5.6f, 0 , 1.0e20, 0, 0.0030), //190 + KFEfficiencyParticleInfo("K-K-", "K-K- ", -9003, 0.8f, 3.8f, 0 , 1.0e20, 0, 0.0030), //191 + KFEfficiencyParticleInfo("K-p-", "K-p- ", -9004, 1.4f, 5.4f, 0 , 1.0e20, 0, 0.0030), //192 +//V0 + KFEfficiencyParticleInfo("V0", "V0 ", 123456789, 0.3f, 1.3f, 0 , 0, 0, 0.0030) //193 + }; + + int mPartMaxMult[nParticles]; + for(int i=0; i<nParticles; i++) + mPartMaxMult[i] = 20; + mPartMaxMult[fFirstStableParticleIndex + 4] = 500; + mPartMaxMult[fFirstStableParticleIndex + 5] = 500; + mPartMaxMult[fFirstStableParticleIndex + 6] = 50; + mPartMaxMult[fFirstStableParticleIndex + 7] = 50; + mPartMaxMult[fFirstStableParticleIndex + 8] = 500; + + //set decay mode + partDaughterPdg.resize(nParticles); + + int curPart = 0; + + partDaughterPdg[curPart].push_back( 211); //K0s -> pi+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //Lambda -> p pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //Lambda_bar -> p- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Xi- -> Lambda pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Xi+ -> Lambda_bar pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Xi0 -> Lambda Pi0 + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Xi0_bar -> Lambda_bar Pi0 + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Omega- -> Lambda K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Omega+ -> Lambda_bar K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 22); //Sigma0 -> Lambda Gamma + partDaughterPdg[curPart].push_back( 3122); + curPart++; + + partDaughterPdg[curPart].push_back( 22); //Sigma0_bar -> Lambda_bar Gamma + partDaughterPdg[curPart].push_back(-3122); + curPart++; + + partDaughterPdg[curPart].push_back( 111); //Sigma+ -> p Pi0 + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 111); //Sigma+_bar -> p- Pi0 + partDaughterPdg[curPart].push_back(-2212); + curPart++; + + partDaughterPdg[curPart].push_back( 321); //K*0 -> K+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( -321); //K*0_bar -> K- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //K*+ -> K0s pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //K*- -> K0s pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //K*0 -> K0 pi0 + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back( 111); //K*+ -> K+ pi0 + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 111); //K*- -> K- pi0 + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Sigma+ -> Lambda pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Sigma- -> Lambda pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Sigma+_bar -> Lambda_bar pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Sigma-_bar -> Lambda_bar pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Sigma*0 -> Lambda pi0 + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Sigma*0_bar -> Lambda_bar pi0 + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //Lambda* -> p K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //Lambda*_bar -> p- K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 3312); //Xi*0 -> Xi- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back(-3312); //Xi*0_bar -> Xi+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Xi*- -> Lambda K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Xi*+ -> Lambda_bar K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 3312); //Xi*- -> Xi- pi0 + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back(-3312); //Xi*+ -> Xi+ pi0 + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back( 3312); //Omega*- -> Xi- pi+ K- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back(-3312); //Omega*- -> Xi+ pi- K+ + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //H-dibar -> Lambda Lambda + partDaughterPdg[curPart].push_back( 3122); + curPart++; + + partDaughterPdg[curPart].push_back( 321); //phi -> K+ K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //rho, omega, phi -> pi+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 11); //rho, omega, phi -> e+ e- + partDaughterPdg[curPart].push_back( -11); + curPart++; + + partDaughterPdg[curPart].push_back( 13); //rho, omega, phi -> mu+ mu- + partDaughterPdg[curPart].push_back( -13); + curPart++; + + partDaughterPdg[curPart].push_back( 11); //gamma -> e+ e- + partDaughterPdg[curPart].push_back( -11); + curPart++; + + partDaughterPdg[curPart].push_back( 22); //pi0 -> gamma gamma + partDaughterPdg[curPart].push_back( 22); + curPart++; + + partDaughterPdg[curPart].push_back( 111); //eta -> pi0 pi0 + partDaughterPdg[curPart].push_back( 111); + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //Delta0 -> p pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //Delta0_bar -> p- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //Delta++ -> p pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //Delta--_bar -> p- pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 11); //JPsi -> e+ e- + partDaughterPdg[curPart].push_back( -11); + curPart++; + + partDaughterPdg[curPart].push_back( 13); //JPsi -> mu+ mu- + partDaughterPdg[curPart].push_back( -13); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //JPsi -> p p- + partDaughterPdg[curPart].push_back( -2212); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //JPsi -> Lambda Lambda_bar + partDaughterPdg[curPart].push_back( -3122); + curPart++; + + partDaughterPdg[curPart].push_back( 3312); //JPsi -> Xi- Xi+ + partDaughterPdg[curPart].push_back( -3312); + curPart++; + + partDaughterPdg[curPart].push_back( 3334); //Psi -> Omega- Omega+ + partDaughterPdg[curPart].push_back( -3334); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //D0 -> pi+ K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( -211); //D0_bar -> K+ pi- + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //D0 -> pi+ pi+ pi- K- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( -211); //D0_bar -> pi- pi- pi+ K+ + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //D0 -> pi+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //D0 -> 2pi+ 2pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //D0_bar -> K0 pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 321); //D0_bar -> K+ K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 321); //D0_bar -> K+ K- K0 + partDaughterPdg[curPart].push_back( -321); + partDaughterPdg[curPart].push_back( 310); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //D0_bar -> K0 pi+ pi- pi0 + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back( -321); //D+ -> K- pi+ pi+ + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 321); //D- -> K+ pi- pi- + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //D+ -> K0 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //D- -> K0 pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //D+ -> K0 pi+ pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //D- -> K0 pi+ pi- pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //D+ -> pi+ pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //D- -> pi+ pi- pi- + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( -321); //Ds+ -> K- K+ pi+ + partDaughterPdg[curPart].push_back( 321); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 321); //Ds- -> K+ K- pi- + partDaughterPdg[curPart].push_back( -321); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //Ds+ -> K0 K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //Ds- -> K0 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //Ds+ -> K0 K0 pi+ + partDaughterPdg[curPart].push_back( 310); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //Ds- -> K0 K0 pi- + partDaughterPdg[curPart].push_back( 310); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //Ds+ -> K0 K+ pi+ pi- + partDaughterPdg[curPart].push_back( 321); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 310); //Ds- -> K0 K- pi+ pi- + partDaughterPdg[curPart].push_back( -321); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 321); //Ds+ -> K+ pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( -321); //Ds- -> K- pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + + partDaughterPdg[curPart].push_back( 211); //Lambdac -> pi+ K- p + partDaughterPdg[curPart].push_back( -321); + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( -211); //Lambdac_bar -> pi- K+ p- + partDaughterPdg[curPart].push_back( 321); + partDaughterPdg[curPart].push_back(-2212); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //Lambdac -> p K0s + partDaughterPdg[curPart].push_back( 310); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //Lambdac_bar -> p_bar K0s + partDaughterPdg[curPart].push_back( 310); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //Lambdac -> p K0s pi+ pi- + partDaughterPdg[curPart].push_back( 310); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //Lambdac_bar -> p_bar K0s pi+ pi- + partDaughterPdg[curPart].push_back( 310); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Lambdac -> Lambda pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Lambdac_bar -> Lambda_bar pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //Lambdac -> Lambda 2pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-3122); //Lambdac_bar -> Lambda_bar 2pi- pi+ + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3312); //Xic0 -> Xi- 2pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-3312); //Xic0_bar -> Xi+ 2pi- pi+ + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //Lambdac -> p pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //Lambdac_bar -> p_bar pi+ pi- + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + + partDaughterPdg[curPart].push_back( 411); //D*0 -> D+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( -411); //D*0_bar -> D- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 421); //D*+ -> D0 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( -421); //D*- -> D0_bar pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 429); //D*+ -> D04 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( -429); //D*- -> D04_bar pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 428); //D*0 -> D04 pi0 + partDaughterPdg[curPart].push_back( 111); + curPart++; + + partDaughterPdg[curPart].push_back( 11); //B -> e+ e- + partDaughterPdg[curPart].push_back( -11); + curPart++; + + partDaughterPdg[curPart].push_back( 13); //B -> mu+ mu- + partDaughterPdg[curPart].push_back( -13); + curPart++; + + partDaughterPdg[curPart].push_back( -421); //B+ -> D0_bar pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 421); //B- -> D0 pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( -421); //B+ -> D0_bar K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 421); //B- -> D0 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( -411); //B0 -> D- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 411); //B0_bar -> D+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( -411); //B0 -> D0_bar K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 411); //B0_bar -> D0 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 3122); //H0-> Lambda pi- p + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010020); //LambdaN -> d+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010020); //LambdaN_bar-> d- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //LambdaNN -> t+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010030); //LambdaNN_bar -> t- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //H3Lambda -> He3+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020030); //H3Lambda_bar -> He3- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //H4Lambda -> He4+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020040); //H4Lambda_bar -> He4- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //He4Lambda -> He3+ p+ pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020030); //He4Lambda_bar -> He3- p- pi+ + partDaughterPdg[curPart].push_back(-2212); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He5Lambda -> He4+ p+ pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020040); //He5Lambda_bar -> He4- p- pi+ + partDaughterPdg[curPart].push_back(-2212); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 3004); //LLn -> H3Lambda pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3006); //H4LL -> He4Lambda pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3004); //H4LL -> H3Lambda p pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3007); //H5LL -> He5Lambda pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3007); //He6LL -> He5Lambda p pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 13); // pi- -> mu- + nu_mu_bar + partDaughterPdg[curPart].push_back(-7000014); // + curPart++; + + partDaughterPdg[curPart].push_back( -211); // nu_mu_bar <- pi- - mu- + partDaughterPdg[curPart].push_back( 13); // + curPart++; + + partDaughterPdg[curPart].push_back( -13); // pi+ -> mu+ + nu_mu + partDaughterPdg[curPart].push_back( 7000014); // + curPart++; + + partDaughterPdg[curPart].push_back( 211); // nu_mu <- pi+ - mu+ + partDaughterPdg[curPart].push_back( -13); // + curPart++; + + partDaughterPdg[curPart].push_back( 13); // K- -> mu- + nu_mu_bar + partDaughterPdg[curPart].push_back(-8000014); // + curPart++; + + partDaughterPdg[curPart].push_back( -321); // nu_mu_bar <- K- - mu- + partDaughterPdg[curPart].push_back( 13); // + curPart++; + + partDaughterPdg[curPart].push_back( -13); // K+ -> mu+ + nu_mu + partDaughterPdg[curPart].push_back( 8000014); // + curPart++; + + partDaughterPdg[curPart].push_back( 321); // nu_mu <- K+ - mu+ + partDaughterPdg[curPart].push_back( -13); // + curPart++; + + partDaughterPdg[curPart].push_back( -211); // Sigma- -> pi- + n + partDaughterPdg[curPart].push_back( 7002112); // + curPart++; + + partDaughterPdg[curPart].push_back( 3112); // n <- Sigma- - pi- + partDaughterPdg[curPart].push_back( -211); // + curPart++; + + partDaughterPdg[curPart].push_back( 211); // Sigma-b -> pi+ + nb + partDaughterPdg[curPart].push_back( -7002112); // + curPart++; + + partDaughterPdg[curPart].push_back( -3112); // nb <- Sigma-b - pi+ + partDaughterPdg[curPart].push_back( 211); // + curPart++; + + partDaughterPdg[curPart].push_back( -211); // Sigma+b -> pi- + nb + partDaughterPdg[curPart].push_back( -8002112); // + curPart++; + + partDaughterPdg[curPart].push_back( -3222); // nb <- Sigma+b - pi- + partDaughterPdg[curPart].push_back( -211); // + curPart++; + + partDaughterPdg[curPart].push_back( 211); // Sigma+ -> pi+ + n + partDaughterPdg[curPart].push_back( 8002112); // + curPart++; + + partDaughterPdg[curPart].push_back( 3222); // n <- Sigma+ - pi+ + partDaughterPdg[curPart].push_back( 211); // + curPart++; + + partDaughterPdg[curPart].push_back( -211); // Xi- -> pi- + lam + partDaughterPdg[curPart].push_back( 7003122); // + curPart++; + + partDaughterPdg[curPart].push_back( 3312); // lam <- Xi- - pi- + partDaughterPdg[curPart].push_back( -211); // + curPart++; + + partDaughterPdg[curPart].push_back( 211); // Xi-b -> pi+ + lam_b + partDaughterPdg[curPart].push_back( -7003122); // + curPart++; + + partDaughterPdg[curPart].push_back( -3312); // lam_b <- Xi-b - pi+ + partDaughterPdg[curPart].push_back( 211); // + curPart++; + + partDaughterPdg[curPart].push_back( -211); // Om- -> pi- + Xi0 + partDaughterPdg[curPart].push_back( 7003322); // + curPart++; + + partDaughterPdg[curPart].push_back( 3334); // Xi0 <- Om- - pi- + partDaughterPdg[curPart].push_back( -211); // + curPart++; + + partDaughterPdg[curPart].push_back( 211); // Om-b -> pi+ + Xi0_b + partDaughterPdg[curPart].push_back( -7003322); // + curPart++; + + partDaughterPdg[curPart].push_back( -3334); // Xi0_b <- Om-b - pi+ + partDaughterPdg[curPart].push_back( 211); // + curPart++; + + partDaughterPdg[curPart].push_back( -211); // K- -> pi- + Pi0_b + partDaughterPdg[curPart].push_back( -9000111); // + curPart++; + + partDaughterPdg[curPart].push_back( -321); // Pi0_b <- K- - pi- + partDaughterPdg[curPart].push_back( -211); // + curPart++; + + partDaughterPdg[curPart].push_back( 211); // K+ -> pi+ + Pi0 + partDaughterPdg[curPart].push_back( 9000111); // + curPart++; + + partDaughterPdg[curPart].push_back( 321); // Pi0 <- K+ - pi+ + partDaughterPdg[curPart].push_back( 211); // + curPart++; + + partDaughterPdg[curPart].push_back( -321); // Om- -> K- + Lam + partDaughterPdg[curPart].push_back( 8003122); // + curPart++; + + partDaughterPdg[curPart].push_back( 3334); // Lam <- Om- - K- + partDaughterPdg[curPart].push_back( -321); // + curPart++; + + partDaughterPdg[curPart].push_back( 321); // Om+ -> K+ + Lam_b + partDaughterPdg[curPart].push_back( -8003122); // + curPart++; + + partDaughterPdg[curPart].push_back( -3334); // Lam_b <- Om+ - K+ + partDaughterPdg[curPart].push_back( 321); // + curPart++; + + partDaughterPdg[curPart].push_back( -2212); // Si+b -> p_b + Pi0 + partDaughterPdg[curPart].push_back( -8000111); // + curPart++; + + partDaughterPdg[curPart].push_back( -3222); // Pi0 <- Si+b - p_b + partDaughterPdg[curPart].push_back( -2212); // + curPart++; + + partDaughterPdg[curPart].push_back( 2212); // Si+ -> p + Pi0 + partDaughterPdg[curPart].push_back( 8000111); // + curPart++; + + partDaughterPdg[curPart].push_back( 3222); // Pi0 <- Si+ - p + partDaughterPdg[curPart].push_back( 2212); // + curPart++; + + for(int iP=0; iP<nParticles; iP++) + { + partPDG[iP] = particleInfo[iP].PDG(); + partName[iP] = particleInfo[iP].Name(); + partTitle[iP] = particleInfo[iP].Title(); + partMHistoMin[iP] = particleInfo[iP].HistoMin(); + partMHistoMax[iP] = particleInfo[iP].HistoMax(); + partMaxMult[iP] = mPartMaxMult[iP]; + partMass[iP] = particleInfo[iP].Mass(); + partLifeTime[iP] = particleInfo[iP].LifeTime(); + partCharge[iP] = particleInfo[iP].Charge(); + partMassSigma[iP] = particleInfo[iP].MassSigma(); + } + + for(int iP=0; iP<nParticles; iP++) + { + AddCounter(partName[iP], partTitle[iP] + " "); + AddCounter(partName[iP] + "_prim", partTitle[iP] + " Prim"); + AddCounter(partName[iP] + "_sec", partTitle[iP] + " Sec "); + } + + for(int iP=0; iP<nParticles; iP++) + fPdgToIndex[particleInfo[iP].PDG()] = iP; + } + + virtual ~KFPartEfficiencies(){}; + + /** \brief Returns index of the decay with a given PDG code in the scheme of the KF Particle Finder. If it is not present there - returns "-1". */ + int GetParticleIndex(int pdg) + { + std::map<int, int>::iterator it; + it=fPdgToIndex.find(pdg); + if(it != fPdgToIndex.end()) return it->second; + else return -1; + } + + /** \brief Returns the map between PDG codes and index of the decay in the scheme of the KF Particle Finder. */ + std::map<int,int> GetPdgToIndexMap() const { return fPdgToIndex; } + + virtual void AddCounter(std::string shortname, std::string name) + { + /** Adds a counter with the name defined by "name" to all counter + ** objects. For easiness of operation with counters, a shortname is assigned + ** to each of them and the corresponding entry in the map indices is done. + ** \param[in] shortname - a short name of the counter for fast and easy access to its index + ** \param[in] name - name of the counter which is added to each counter object. + **/ + indices[shortname] = names.size(); + names.push_back(name); + + ratio_reco1.AddCounter(); + ratio_reco2.AddCounter(); + ratio_reco3.AddCounter(); + + mc1.AddCounter(); + mc2.AddCounter(); + mc3.AddCounter(); + + reco.AddCounter(); + + ratio_ghost.AddCounter(); + ratio_bg.AddCounter(); + ratio_clone.AddCounter(); + ghost.AddCounter(); + bg.AddCounter(); + clone.AddCounter(); + }; + + /** \brief Operator to add efficiency table from object "a" to the current object. Returns the current object after addition. */ + KFPartEfficiencies& operator+=(KFPartEfficiencies& a){ + mc1 += a.mc1; mc2 += a.mc2; mc3 += a.mc3; reco += a.reco; + ghost += a.ghost; bg += a.bg; clone += a.clone; + return *this; + }; + + /** \brief Function to calculate efficiency after all counters are set. If the counters are modified the function should be called again. */ + void CalcEff(){ + ratio_reco1 = reco/mc1; + ratio_reco2 = reco/mc2; + ratio_reco3 = reco/mc3; + + KFMCCounter<int> allReco = reco + ghost + bg; + ratio_ghost = ghost/allReco; + ratio_bg = bg/allReco; + ratio_clone = clone/allReco; + }; + + void Inc(bool isReco, int nClones, bool isMC1, bool isMC2, bool isMC3, std::string name) + { + /** Increases counters by one, if the corresponding boolean variable is "true". + ** \param[in] isReco - "true" if particle is reconstructed + ** \param[in] nClones - number of double reconstructed particles for the given MC particle, + ** will be added to the "clone" counters + ** \param[in] isMC1 - "true" if particle is reconstructable in 4pi, mc1 is increased + ** \param[in] isMC2 - "true" if all daughters are reconstructable, mc2 is increased + ** \param[in] isMC3 - "true" if all daughters are reconstructed, mc3 is increased + ** \param[in] name - "shortname" of the set of counters, which should be increased + **/ + const int index = indices[name]; + + if(isMC1) mc1.counters[index]++; + if(isMC2) mc2.counters[index]++; + if(isMC3) mc3.counters[index]++; + + if(isReco) reco.counters[index]++; + if(nClones > 0) + clone.counters[index] += nClones; + }; + + void IncReco(bool isGhost, bool isBg, std::string name) + { + /** Increases counters by one, if the corresponding boolean variable is "true". + ** \param[in] isGhost - "true" if ghost is added + ** \param[in] isBg - "true" if physics background is added + ** \param[in] name - "shortname" of the set of counters, which should be increased + **/ + const int index = indices[name]; + + if (isGhost) ghost. counters[index]++; + if (isBg) bg.counters[index]++; + }; + + /** \brief Prints the efficiency table on the screen. */ + void PrintEff(){ + std::ios_base::fmtflags original_flags = std::cout.flags(); + std::cout.setf(std::ios::fixed); + std::cout.setf(std::ios::showpoint); + std::cout.precision(3); + std::cout << "Particle : " + << " Eff 4pi " + <<" / "<< " Eff accept" + <<" / "<< " Eff KFPF " + <<" / "<< " Ghost " + <<" / "<< " BackGr " + <<" / "<< " N Ghost " + <<" / "<< " N BackGr " + <<" / "<< " N Reco " + <<" / "<< " N Clone " + <<" | "<< " N MC 4pi " + <<" | "<< "N MC accept" + <<" | "<< " N MC KFPF " << std::endl; + + int NCounters = mc1.NCounters; + for (int iC = 0; iC < NCounters; iC++){ + std::cout << names[iC] + << " : " << std::setw(10) << ratio_reco1.counters[iC] + << " / " << std::setw(10) << ratio_reco2.counters[iC] + << " / " << std::setw(10) << ratio_reco3.counters[iC] + << " / " << std::setw(10) << ratio_ghost.counters[iC] // particles w\o MCParticle + << " / " << std::setw(10) << ratio_bg.counters[iC] // particles with incorrect MCParticle + << " / " << std::setw(10) << ghost.counters[iC] + << " / " << std::setw(10) << bg.counters[iC] + << " / " << std::setw(10) << reco.counters[iC] + << " / " << std::setw(10) << clone.counters[iC] + << " | " << std::setw(10) << mc1.counters[iC] + << " | " << std::setw(10) << mc2.counters[iC] + << " | " << std::setw(10) << mc3.counters[iC] << std::endl; + } + std::cout.flags(original_flags); + }; + + float GetTotal4piEfficiency(int iDecay) { return ratio_reco1.counters[3*iDecay]; } ///< Returns efficiency in 4pi for decay "iDecay". + float GetTotalKFPEfficiency(int iDecay) { return ratio_reco3.counters[3*iDecay]; } ///< Returns efficiency of KF Particle Finder method (cuts) for decay "iDecay". + float GetPrimary4piEfficiency(int iDecay) { return ratio_reco1.counters[3*iDecay+1]; } ///< Returns efficiency in 4pi for decay "iDecay" for primary particles. + float GetPrimaryKFPEfficiency(int iDecay) { return ratio_reco3.counters[3*iDecay+1]; } ///< Returns efficiency of KF Particle Finder method (cuts) for decay "iDecay" for primary particles. + float GetSecondary4piEfficiency(int iDecay) { return ratio_reco1.counters[3*iDecay+2]; } ///< Returns efficiency in 4pi for decay "iDecay" for secondary particles. + float GetSecondaryKFPEfficiency(int iDecay) { return ratio_reco3.counters[3*iDecay+2]; } ///< Returns efficiency of KF Particle Finder method (cuts) for decay "iDecay" for secondary particles. + + /** \brief Operator to write efficiencies to file. */ + friend std::fstream & operator<<(std::fstream &strm, KFPartEfficiencies &a) + { + strm << a.ratio_reco1; + strm << a.ratio_reco2; + strm << a.ratio_reco3; + strm << a.mc1; + strm << a.mc2; + strm << a.mc3; + strm << a.reco; + strm << a.ratio_ghost; + strm << a.ratio_bg; + strm << a.ratio_clone; + strm << a.ghost; + strm << a.bg; + strm << a.clone; + + return strm; + } + /** \brief Operator to read efficiencies from file. */ + friend std::fstream & operator>>(std::fstream &strm, KFPartEfficiencies &a) + { + strm >> a.ratio_reco1; + strm >> a.ratio_reco2; + strm >> a.ratio_reco3; + strm >> a.mc1; + strm >> a.mc2; + strm >> a.mc3; + strm >> a.reco; + strm >> a.ratio_ghost; + strm >> a.ratio_bg; + strm >> a.ratio_clone; + strm >> a.ghost; + strm >> a.bg; + strm >> a.clone; + + return strm; + } + /** \brief Adds efficiency from the file with the name defined by "fileName" to the current objects. */ + void AddFromFile(std::string fileName) + { + std::fstream file(fileName.data(),std::fstream::in); + file >> *this; + } + + int GetNDaughters(int iParticle) const { return partDaughterPdg[iParticle].size(); } ///< Returns number of daughter particles for the decay with index "iParticle". + /** \brief Returns the PDG code of the daughter "iDaughter" from the decay with index "iParticle". */ + int GetDaughterPDG(int iParticle, int iDaughter) const { return partDaughterPdg[iParticle][iDaughter]; } + + float GetMass(int iParticle) const { return partMass[iParticle]; } ///< Returns the table mass of the decay with index "iParticle". + float GetMassSigma(int iParticle) const { return partMassSigma[iParticle]; } ///< Returns expected width of the mass peak of the decay with index "iParticle". + + static const int nParticles = 194; ///< Number of particles. + static const int fFirstHypernucleusIndex = 114; ///< Index of the first hypernuclei in the list. + static const int fLastHypernucleusIndex = 130; ///< Index of the last hypernuclei in the list. + static const int fFirstMissingMassParticleIndex = 131; ///< Index of the first decay reconstructed by the missing mass method. + static const int fLastMissingMassParticleIndex = 166; ///< Index of the last decay reconstructed by the missing mass method. + static const int fFirstStableParticleIndex = 167; ///< Index of the first stable particle in the list. + static const int fLastStableParticleIndex = 184; ///< Index of the last stable particle in the list. + + int partPDG[nParticles]; ///< Array of PDG codes assigned to the decays. + std::string partName[nParticles]; ///< Array of names of the decay in the file with histograms. + std::string partTitle[nParticles]; ///< Array of names of the decay in the output table with efficiency. + std::vector<std::vector<int> > partDaughterPdg; ///< Array with vectors of daughter particles for each decay. + float partMHistoMin[nParticles]; ///< Array with lower boundary in the mass histograms for each decay. + float partMHistoMax[nParticles]; ///< Array with upper boundary in the mass histograms for each decay. + int partMaxMult[nParticles]; ///< Array with upper boundary in the multiplicity histograms of each decay. + float partMass[nParticles]; ///< Array with table masses of each decay. + float partLifeTime[nParticles]; ///< Array with lifetimes in seconds of each decay. + int partCharge[nParticles]; ///< Array with charge of each particle specie in units of the elementary charge. + float partMassSigma[nParticles]; ///< Array with expected width of mass peaks used for the side band method. + + + private: + std::vector<std::string> names; ///< Names of the counters. The same for all counters objects. + std::map<std::string, int> indices; ///< Map between the counter index and its short name. + + std::map<int, int> fPdgToIndex; ///< The map between PDG code assigned to the decay and index in the decay list. + + KFMCCounter<double> ratio_reco1; ///< Efficiency in 4 pi for all decays. + KFMCCounter<double> ratio_reco2; ///< Efficiency normalised on the particles with all daughters reconstructable for all decays. + KFMCCounter<double> ratio_reco3; ///< Efficiency normalised on the particles with all daughters reconstructed for all decays. + + KFMCCounter<int> mc1; ///< Counters of the Monte Carlo particles of all species. + KFMCCounter<int> mc2; ///< Counters of the Monte Carlo particles with all daughters reconstructable for all species. + KFMCCounter<int> mc3; ///< Counters of the Monte Carlo particles with all daughters found for all species. + + KFMCCounter<int> reco; ///< Counters of the reconstructed particles for all species. + + KFMCCounter<double> ratio_ghost; ///< Ratio of the ghost candidates to the total number of candidates for all species. + KFMCCounter<double> ratio_bg; ///< Ratio of the physics background candidates to the total number of candidates for all species. + KFMCCounter<double> ratio_clone; ///< Ratio of double reconstructed particles to the total number of signal candidates for all species. + + KFMCCounter<int> ghost; ///< Counters of the ghost candidates for all species. + KFMCCounter<int> bg; ///< Counters of the physics background candidates for all species. + KFMCCounter<int> clone; ///< Counters of the double reconstructed particles for all species. + +#ifndef KFParticleStandalone + ClassDef( KFPartEfficiencies, 1 ) +#endif +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFPartMatch.h b/external/KFParticle/KFParticlePerformance/KFPartMatch.h new file mode 100644 index 0000000000000000000000000000000000000000..5c1c8e8ee6e04cc2d1b89a6d0f39954151bbc95f --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFPartMatch.h @@ -0,0 +1,48 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifndef KFPartMatch_H +#define KFPartMatch_H + +#include <vector> + + +/** @class KFPartMatch + ** @brief A structure to store matching information between simulated Monte Carlo and reconstructed particles. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class is used in both directions: to store links from Monte Carlo to reconstructed particles and vise versa. + ** It contains two kind of links: 1) PDG hypothesis of the reconstructed and Monte Carlo particles should be the same; + ** 2) PDG code differs. + **/ + +struct KFPartMatch // used for Reco to MC match as well as for MC to Reco +{ + KFPartMatch():ids(),idsMI() {} + + bool IsMatched() const { return ids.size() != 0 || idsMI.size() != 0; } ///< Returns true if at least one link exists independently of the PDG hypothesis. + bool IsMatchedWithPdg() const { return ids.size() != 0; } ///< Returns true is at least one link with the correct PDG exists. + int GetBestMatch() const { + if (ids.size() != 0) return ids[0]; + else if (idsMI.size() != 0) return idsMI[0]; + else return -1; + } ///< Returns first link with correct PDG if exists, otherwise first link with incorrect PDG. If no link exists returns "-1". + int GetBestMatchWithPdg() const { + if (ids.size() != 0) return ids[0]; + else return -1; + } ///< Returns first link with correct PDG if exists, otherwise returns "-1". + std::vector<int> ids; ///< Vector of links, PDG hypothesis of the reconstructed particle is required to be the same as the PDG code of the Monte Carlo particle. + std::vector<int> idsMI; ///< Vector of links, PDG hypothesis of the reconstructed particle differs from the Monte Carlo particle. +}; + +#endif diff --git a/external/KFParticle/KFParticlePerformance/KFParticlePerformanceBase.cxx b/external/KFParticle/KFParticlePerformance/KFParticlePerformanceBase.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e3ca1e24fcace602a24ab9f4e8b7e1cfb64c11d5 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFParticlePerformanceBase.cxx @@ -0,0 +1,1072 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifdef DO_TPCCATRACKER_EFF_PERFORMANCE + +#include "KFParticlePerformanceBase.h" + +#include "TDirectory.h" +#include "TH1.h" +#include "TH2.h" +#include "TH3.h" +#include "TProfile.h" +#include "TProfile2D.h" + + +KFParticlePerformanceBase::KFParticlePerformanceBase(): + fParteff(), fPVeff(), fPVeffMCReconstructable(), outfileName(), histodir(0), fNEvents(0), fStoreMCHistograms(1), + fStorePrimSecHistograms(1), fStoreZRHistograms(1),fHistoDir(0) +{ + /** The default constructor. Initialises all pointers to nullptr. **/ + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + { + for(int iFitQA=0; iFitQA<nFitQA; iFitQA++) + { + hFitDaughtersQA [iParticle][iFitQA] = nullptr; + hFitQA [iParticle][iFitQA] = nullptr; + hFitQANoConstraint [iParticle][iFitQA] = nullptr; + hFitQAMassConstraint [iParticle][iFitQA] = nullptr; + hFitQATopoConstraint [iParticle][iFitQA] = nullptr; + hFitQATopoMassConstraint[iParticle][iFitQA] = nullptr; + } + } + + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + for(int iQA=0; iQA<nDSToParticleQA; iQA++) + hDSToParticleQA[iParticle][iQA] = nullptr; + + for(int iParameterSet=0; iParameterSet<nParametersSet; iParameterSet++) + { + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + { + for(int iHisto=0; iHisto<nHistoPartParam; iHisto++) + { + hPartParam [iParameterSet][iParticle][iHisto] = nullptr; + hPartParamPrimary [iParameterSet][iParticle][iHisto] = nullptr; + hPartParamPrimaryMass [iParameterSet][iParticle][iHisto] = nullptr; + hPartParamPrimaryTopo [iParameterSet][iParticle][iHisto] = nullptr; + hPartParamPrimaryTopoMass[iParameterSet][iParticle][iHisto] = nullptr; + hPartParamSecondary [iParameterSet][iParticle][iHisto] = nullptr; + hPartParamSecondaryMass [iParameterSet][iParticle][iHisto] = nullptr; + } + } + } + + for(int iParameterSet=0; iParameterSet<nParametersSet; iParameterSet++) + { + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + { + for(int iHisto=0; iHisto<nHistoPartParam2D; iHisto++) + { + hPartParam2D [iParameterSet][iParticle][iHisto] = nullptr; + hPartParam2DPrimary [iParameterSet][iParticle][iHisto] = nullptr; + hPartParam2DPrimaryMass [iParameterSet][iParticle][iHisto] = nullptr; + hPartParam2DPrimaryTopo [iParameterSet][iParticle][iHisto] = nullptr; + hPartParam2DPrimaryTopoMass[iParameterSet][iParticle][iHisto] = nullptr; + hPartParam2DSecondary [iParameterSet][iParticle][iHisto] = nullptr; + hPartParam2DSecondaryMass [iParameterSet][iParticle][iHisto] = nullptr; + } + } + } + + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + for(int iHisto=0; iHisto<nHistoPartParam3D; iHisto++) + hPartParam3D[0][iParticle][iHisto] = nullptr; + + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + for(int iEffSet=0; iEffSet<3; iEffSet++) + for(int iEff=0; iEff<nPartEfficiency; iEff++) + hPartEfficiency[iParticle][iEffSet][iEff] = nullptr; + + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + for(int iEffSet=0; iEffSet<3; iEffSet++) + for(int iEff=0; iEff<nPartEfficiency2D; iEff++) + hPartEfficiency2D[iParticle][iEffSet][iEff] = nullptr; + + for(int iEffSet=0; iEffSet<2; iEffSet++) + for(int iHistoPV=0; iHistoPV<nHistosPV; iHistoPV++) + hPVFitQa[iEffSet][iHistoPV] = nullptr; + + for(int iEffSet1=0; iEffSet1<2; iEffSet1++) + for(int iEffSet2=0; iEffSet2<2; iEffSet2++) + for(int iHistoPV=0; iHistoPV<nHistosPV-1; iHistoPV++) + hPVFitQa2D[iEffSet1][iEffSet2][iHistoPV] = nullptr; + + for(int iParam=0; iParam<nHistosPVParam; iParam++) + { + hPVParam [iParam] = nullptr; + hPVParamGhost [iParam] = nullptr; + hPVParamSignal[iParam] = nullptr; + hPVParamPileup[iParam] = nullptr; + hPVParamBG [iParam] = nullptr; + } + + for(int iParam=0; iParam<nHistosPVParam2D; iParam++) + hPVParam2D[iParam] = nullptr; + + for(int iFitQA=0; iFitQA<nFitPVTracksQA; iFitQA++) + hFitPVTracksQA[iFitQA] = nullptr; + + for(int iTP=0; iTP<nHistosTP; iTP++) + hTrackParameters[iTP] = nullptr; + + for(int iEffSet=0; iEffSet<4; iEffSet++) + for(int iEff=0; iEff<nPVefficiency; iEff++) + hPVefficiency[iEffSet][iEff] = nullptr; +} + +void KFParticlePerformanceBase::CreateHistos(std::string histoDir, TDirectory* outFile, std::map<int,bool> decays) +{ + /** Creates all histograms. If "outFile" is provided - creates a new ROOT directory and stores all + ** histograms there. Otherwise histograms are stored in TDirectory::CurrentDirectory(). + ** \param[in] histoDir - name of the ROOT directory with histograms + ** \param[in] outFile - pointer to the external ROOT directory or file, where histograms should be stored + ** \param[in] decays - a list of decays, for which histograms are created, if empty - histograms are + ** created for all decay channels from the KF Particle Finder reconstruction scheme + **/ + TDirectory *curdir = gDirectory; + if (outFile) { + outFile->cd(); + fHistoDir = outFile; + if (histoDir != "") { + fHistoDir = outFile->mkdir( TString(histoDir) ); + fHistoDir->cd(); + } + } else { + fHistoDir = TDirectory::CurrentDirectory(); + } + { + gDirectory->mkdir("KFParticlesFinder"); + gDirectory->cd("KFParticlesFinder"); + histodir = gDirectory; + gDirectory->mkdir("Particles"); + gDirectory->cd("Particles"); + for(int iPart=0; iPart<fParteff.nParticles; ++iPart) + { + if(!(decays.empty()) && (iPart < fParteff.fFirstStableParticleIndex || iPart > fParteff.fLastStableParticleIndex)) + if(decays.find(fParteff.partPDG[iPart]) == decays.end()) continue; + + gDirectory->mkdir(fParteff.partName[iPart].data()); + gDirectory->cd(fParteff.partName[iPart].data()); + { + if(fStoreMCHistograms) + { + TString res = "res"; + TString pull = "pull"; + + gDirectory->mkdir("DaughtersQA"); + gDirectory->cd("DaughtersQA"); + { + TString parName[nFitQA/2] = {"X","Y","Z","Px","Py","Pz","E","M"}; + int nBins = 100; + float xMax[nFitQA/2] = {0.15,0.15,0.03,0.01,0.01,0.06,0.06,0.01}; + // float xMax[nFitQA/2] = {2.,2.,5.,0.3,0.3,0.3,0.03,0.03}; + + for( int iH=0; iH<nFitQA/2; iH++ ){ + hFitDaughtersQA[iPart][iH] = new TH1F((res+parName[iH]).Data(), + (GetDirectoryPath()+res+parName[iH]).Data(), + nBins, -xMax[iH],xMax[iH]); + hFitDaughtersQA[iPart][iH+8] = new TH1F((pull+parName[iH]).Data(), + (GetDirectoryPath()+pull+parName[iH]).Data(), + nBins, -6,6); + } + } + gDirectory->cd(".."); //particle directory + + gDirectory->mkdir("DSToParticleQA"); + gDirectory->cd("DSToParticleQA"); + { + TString parName[3] = {"X","Y","Z"}; + int nBins = 100; + float xMax[3] = {0.5, 0.5, 2.}; + + for( int iH=0; iH<3; iH++ ){ + hDSToParticleQA[iPart][iH] = new TH1F((res+parName[iH]).Data(), + (GetDirectoryPath()+res+parName[iH]).Data(), + nBins, -xMax[iH],xMax[iH]); + hDSToParticleQA[iPart][iH+3] = new TH1F((pull+parName[iH]).Data(), + (GetDirectoryPath()+pull+parName[iH]).Data(), + nBins, -6,6); + } + + hDSToParticleQA[iPart][6] = new TH1F("r", (GetDirectoryPath()+TString("r")).Data(), 1000, 0.0, 20.0); + } + gDirectory->cd(".."); //particle directory + + CreateFitHistograms(hFitQA[iPart], iPart); + CreateEfficiencyHistograms(hPartEfficiency[iPart],hPartEfficiency2D[iPart]); + } + gDirectory->mkdir("Parameters"); + gDirectory->cd("Parameters"); + { + const bool drawZR = IsCollectZRHistogram(iPart); + CreateParameterHistograms(hPartParam[0], hPartParam2D[0], hPartParam3D[0], iPart, drawZR); + + if(IsCollect3DHistogram(iPart)) + { + gDirectory->mkdir("SignalReco"); + gDirectory->cd("SignalReco"); + { + CreateParameterHistograms(hPartParam[4], hPartParam2D[4], 0, iPart, drawZR); + } + gDirectory->cd(".."); // Parameters + gDirectory->mkdir("BGReco"); + gDirectory->cd("BGReco"); + { + CreateParameterHistograms(hPartParam[5], hPartParam2D[5], 0, iPart, drawZR); + } + gDirectory->cd(".."); // Parameters + } + + if(fStoreMCHistograms) + { + gDirectory->mkdir("Signal"); + gDirectory->cd("Signal"); + { + CreateParameterHistograms(hPartParam[1], hPartParam2D[1], 0, iPart, drawZR); + } + gDirectory->cd(".."); // particle directory / Parameters + gDirectory->mkdir("Background"); + gDirectory->cd("Background"); + { + CreateParameterHistograms(hPartParam[2], hPartParam2D[2], 0, iPart, drawZR); + } + gDirectory->cd(".."); // particle directory + gDirectory->mkdir("Ghost"); + gDirectory->cd("Ghost"); + { + CreateParameterHistograms(hPartParam[3], hPartParam2D[3], 0, iPart, drawZR); + } + gDirectory->cd(".."); // Parameters + gDirectory->mkdir("MCSignal"); + gDirectory->cd("MCSignal"); + { + CreateParameterHistograms(hPartParam[6], hPartParam2D[6], 0, iPart, drawZR); + } + gDirectory->cd(".."); // Parameters + + + bool plotPrimaryHistograms = abs(fParteff.partPDG[iPart]) == 310 || + abs(fParteff.partPDG[iPart]) == 3122 || + abs(fParteff.partPDG[iPart]) == 22 || + abs(fParteff.partPDG[iPart]) == 111 || + abs(fParteff.partPDG[iPart]) == 3312 || + abs(fParteff.partPDG[iPart]) == 3334; + + bool plotSecondaryHistograms = abs(fParteff.partPDG[iPart]) == 310 || + abs(fParteff.partPDG[iPart]) == 3122 || + abs(fParteff.partPDG[iPart]) == 22 || + abs(fParteff.partPDG[iPart]) == 111; + + if(fStorePrimSecHistograms && plotPrimaryHistograms) + { + gDirectory->mkdir("Primary"); + gDirectory->cd("Primary"); + { + CreateParameterSubfolder("NoConstraint (1C-Fit)", hPartParamPrimary, hPartParam2DPrimary, hFitQANoConstraint, iPart, true); + CreateParameterSubfolder("MassConstraint (2C-Fit)", hPartParamPrimaryMass, hPartParam2DPrimaryMass, hFitQAMassConstraint, iPart, true); + CreateParameterSubfolder("PVConstraint (3C-Fit)", hPartParamPrimaryTopo, hPartParam2DPrimaryTopo, hFitQATopoConstraint, iPart, true); + CreateParameterSubfolder("PVMassConstraint (4C-Fit)", hPartParamPrimaryTopoMass, hPartParam2DPrimaryTopoMass, hFitQATopoMassConstraint, iPart, true); + } + gDirectory->cd(".."); // particle directory / Parameters + } + + if(fStorePrimSecHistograms && plotSecondaryHistograms) + { + gDirectory->mkdir("Secondary"); + gDirectory->cd("Secondary"); + { + CreateParameterSubfolder("NoConstraint (1C-Fit)", hPartParamSecondary, hPartParam2DSecondary, 0, iPart, true); + CreateParameterSubfolder("MassConstraint (2C-Fit)", hPartParamSecondaryMass, hPartParam2DSecondaryMass, 0, iPart, true); + } + gDirectory->cd(".."); // particle directory / Parameters + } + } + } + gDirectory->cd(".."); //particle directory + } + gDirectory->cd(".."); //Particles + } + gDirectory->cd(".."); //main + gDirectory->mkdir("PrimaryVertexQA"); + gDirectory->cd("PrimaryVertexQA"); + { + struct { + TString name; + TString title; + Int_t n; + Double_t l,r; + } Table[nHistosPV]= + { + {"PVResX", "x_{rec}-x_{mc}, cm", 100, -0.1f, 0.1f}, + {"PVResY", "y_{rec}-y_{mc}, cm", 100, -0.1f, 0.1f}, + {"PVResZ", "z_{rec}-z_{mc}, cm", 100, -1.f, 1.f}, + {"PVPullX", "Pull X", 100, -6.f, 6.f}, + {"PVPullY", "Pull Y", 100, -6.f, 6.f}, + {"PVPullZ", "Pull Z", 100, -6.f, 6.f}, + {"Lost", "Lost tracks", 102, -0.01f, 1.01f} + }; + + TString parName[nHistosPVParam] = {"x","y","z","r","Ntracks","Chi2","NDF","Chi2NDF","prob", "PVpurity", + "ghostTr", "triggerTr", "pileupTr", "bgTr", "dzSamePV"}; + TString parAxisName[nHistosPVParam] = {"x [cm]","y [cm]","z [cm]","r [cm]","N tracks","Chi2","NDF","Chi2NDF","prob","purity", + "ghost tracks [%]", "trigger tracks [%]", "pileup tracks [%]", "bg tracks [%]", "dz [cm]"}; + int nBins[nHistosPVParam] = {1000,1000,1000,1000,1001,10000,1001,10000,100,102,102,102,102,102,1000}; + float xMin[nHistosPVParam] = {-1., -1., -10., 0, -0.5, 0., -0.5, 0., 0., -0.01, -0.01, -0.01, -0.01, -0.01, 0.}; + float xMax[nHistosPVParam] = { 1., 1., 10., 10, 1000.5, 1000., 1000.5, 1000., 1., 1.01, 1.01, 1.01, 1.01, 1.01, 100.}; + + TString parName2D[nHistosPVParam2D] = {"xy"}; + TString parXAxisName2D[nHistosPVParam2D] = {"x [cm]"}; + TString parYAxisName2D[nHistosPVParam2D] = {"y [cm]"}; + int nBinsX2D[nHistosPVParam2D] = {1000}; + float xMin2D[nHistosPVParam2D] = {-1.}; + float xMax2D[nHistosPVParam2D] = { 1.}; + int nBinsY2D[nHistosPVParam2D] = {1000}; + float yMin2D[nHistosPVParam2D] = {-1.}; + float yMax2D[nHistosPVParam2D] = { 1.}; + + for(int iH=0; iH<nHistosPVParam; iH++) + { + hPVParam[iH] = new TH1F(parName[iH].Data(),(GetDirectoryPath()+parName[iH]).Data(), + nBins[iH],xMin[iH],xMax[iH]); + hPVParam[iH]->GetXaxis()->SetTitle(parAxisName[iH].Data()); + } + + for(int iH=0; iH<nHistosPVParam2D; iH++) + { + hPVParam2D[iH] = new TH2F(parName2D[iH].Data(),(GetDirectoryPath()+parName2D[iH]).Data(), + nBinsX2D[iH],xMin2D[iH],xMax2D[iH], + nBinsY2D[iH],yMin2D[iH],yMax2D[iH]); + hPVParam2D[iH]->GetXaxis()->SetTitle(parXAxisName2D[iH].Data()); + hPVParam2D[iH]->GetYaxis()->SetTitle(parYAxisName2D[iH].Data()); + hPVParam2D[iH]->GetYaxis()->SetTitleOffset(1.0); + } + + gDirectory->mkdir("Efficiency"); + gDirectory->cd("Efficiency"); + { + TString effName[nPVefficiency] = {"effVsNMCPVTracks","effVsNMCPV","effVsNMCTracks","effVsNPVTracks","effVsNPV","effVsNTracks"}; + int nBinsEff[nPVefficiency] = { 100 , 100 , 100 , 100 , 100 , 1000 }; + float xMinEff[nPVefficiency] = { 0., 0., 0., 0., 0., 0.}; + float xMaxEff[nPVefficiency] = { 100., 100., 1000., 100., 100., 1000.}; + + gDirectory->mkdir("Signal"); + gDirectory->cd("Signal"); + { + for( int iH=0; iH<nPVefficiency; iH++ ){ + hPVefficiency[0][iH] = new TProfile( effName[iH].Data(), (GetDirectoryPath()+effName[iH]).Data(), nBinsEff[iH], xMinEff[iH], xMaxEff[iH]); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Pileup"); + gDirectory->cd("Pileup"); + { + for( int iH=0; iH<nPVefficiency; iH++ ){ + hPVefficiency[1][iH] = new TProfile( effName[iH].Data(), (GetDirectoryPath()+effName[iH].Data()), nBinsEff[iH], xMinEff[iH], xMaxEff[iH]); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Signal_MCReconstructable"); + gDirectory->cd("Signal_MCReconstructable"); + { + for( int iH=0; iH<nPVefficiency; iH++ ){ + hPVefficiency[2][iH] = new TProfile( effName[iH].Data(), (GetDirectoryPath()+effName[iH].Data()), nBinsEff[iH], xMinEff[iH], xMaxEff[iH]); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Pileup_MCReconstructable"); + gDirectory->cd("Pileup_MCReconstructable"); + { + for( int iH=0; iH<nPVefficiency; iH++ ){ + hPVefficiency[3][iH] = new TProfile( effName[iH].Data(), (GetDirectoryPath()+effName[iH].Data()), nBinsEff[iH], xMinEff[iH], xMaxEff[iH]); + } + } + gDirectory->cd(".."); //L1 + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("PVTracksQA"); + gDirectory->cd("PVTracksQA"); + { + TString resTrPV = "resTrPV"; + TString pullTrPV = "pullTrPV"; + TString parNameTrPV[nFitPVTracksQA/2] = {"X","Y","Z","Px","Py","Pz"}; + int nBinsTrPV = 100; + float xMaxTrPV[nFitPVTracksQA/2] = {0.5,0.5,0.5,0.05,0.05,0.05}; + + for( int iH=0; iH<nFitPVTracksQA/2; iH++ ){ + hFitPVTracksQA[iH] = new TH1F((resTrPV+parNameTrPV[iH]).Data(), + (GetDirectoryPath()+resTrPV+parNameTrPV[iH]).Data(), + nBinsTrPV, -xMaxTrPV[iH],xMaxTrPV[iH]); + hFitPVTracksQA[iH+nFitPVTracksQA/2] = new TH1F((pullTrPV+parNameTrPV[iH]).Data(), + (GetDirectoryPath()+pullTrPV+parNameTrPV[iH]).Data(), + nBinsTrPV, -6,6); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Signal"); + gDirectory->cd("Signal"); + { + gDirectory->mkdir("FitQA"); + gDirectory->cd("FitQA"); + { + gDirectory->mkdir("FitQAvcNMCPVTracks"); + gDirectory->cd("FitQAvcNMCPVTracks"); + { + for(int iHPV=0; iHPV<nHistosPV-1; ++iHPV){ + hPVFitQa2D[0][0][iHPV] = new TH2F(Table[iHPV].name.Data(),(GetDirectoryPath()+Table[iHPV].title).Data(), + 500, 0., 5000., + Table[iHPV].n, Table[iHPV].l, Table[iHPV].r); + } + } + gDirectory->cd(".."); //FitQA + + gDirectory->mkdir("FitQAvcNPVTracks"); + gDirectory->cd("FitQAvcNPVTracks"); + { + for(int iHPV=0; iHPV<nHistosPV-1; ++iHPV){ + hPVFitQa2D[0][1][iHPV] = new TH2F(Table[iHPV].name.Data(),(GetDirectoryPath()+Table[iHPV].title).Data(), + 500, 0., 5000., + Table[iHPV].n, Table[iHPV].l, Table[iHPV].r); + } + } + gDirectory->cd(".."); //FitQA + + for(int iHPV=0; iHPV<nHistosPV; ++iHPV){ + hPVFitQa[0][iHPV] = new TH1F(Table[iHPV].name.Data(),(GetDirectoryPath()+Table[iHPV].title).Data(), + Table[iHPV].n, Table[iHPV].l, Table[iHPV].r); + } + } + gDirectory->cd(".."); //Signal + + for(int iH=0; iH<nHistosPVParam; iH++) + { + hPVParamSignal[iH] = new TH1F((parName[iH]).Data(),(GetDirectoryPath()+parName[iH]).Data(), + nBins[iH],xMin[iH],xMax[iH]); + hPVParamSignal[iH]->GetXaxis()->SetTitle(parAxisName[iH].Data()); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Pileup"); + gDirectory->cd("Pileup"); + { + gDirectory->mkdir("FitQA"); + gDirectory->cd("FitQA"); + { + gDirectory->mkdir("FitQAvcNMCPVTracks"); + gDirectory->cd("FitQAvcNMCPVTracks"); + { + for(int iHPV=0; iHPV<nHistosPV-1; ++iHPV){ + hPVFitQa2D[1][0][iHPV] = new TH2F(Table[iHPV].name.Data(),(GetDirectoryPath()+Table[iHPV].title).Data(), + 500, 0., 5000., + Table[iHPV].n, Table[iHPV].l, Table[iHPV].r); + } + } + gDirectory->cd(".."); //FitQA + + gDirectory->mkdir("FitQAvcNPVTracks"); + gDirectory->cd("FitQAvcNPVTracks"); + { + for(int iHPV=0; iHPV<nHistosPV-1; ++iHPV){ + hPVFitQa2D[1][1][iHPV] = new TH2F(Table[iHPV].name.Data(),(GetDirectoryPath()+Table[iHPV].title).Data(), + 500, 0., 5000., + Table[iHPV].n, Table[iHPV].l, Table[iHPV].r); + } + } + gDirectory->cd(".."); //FitQA + + for(int iHPV=0; iHPV<nHistosPV; ++iHPV){ + hPVFitQa[1][iHPV] = new TH1F(Table[iHPV].name.Data(),(GetDirectoryPath()+Table[iHPV].title).Data(), + Table[iHPV].n, Table[iHPV].l, Table[iHPV].r); + } + } + gDirectory->cd(".."); //Signal + + for(int iH=0; iH<nHistosPVParam; iH++) + { + hPVParamPileup[iH] = new TH1F((parName[iH]).Data(),(GetDirectoryPath()+parName[iH]).Data(), + nBins[iH],xMin[iH],xMax[iH]); + hPVParamPileup[iH]->GetXaxis()->SetTitle(parAxisName[iH].Data()); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Background"); + gDirectory->cd("Background"); + { + for(int iH=0; iH<nHistosPVParam; iH++) + { + hPVParamBG[iH] = new TH1F((parName[iH]).Data(),(GetDirectoryPath()+parName[iH]).Data(), + nBins[iH],xMin[iH],xMax[iH]); + hPVParamBG[iH]->GetXaxis()->SetTitle(parAxisName[iH].Data()); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Ghost"); + gDirectory->cd("Ghost"); + { + for(int iH=0; iH<nHistosPVParam; iH++) + { + hPVParamGhost[iH] = new TH1F((parName[iH]).Data(),(GetDirectoryPath()+parName[iH]).Data(), + nBins[iH],xMin[iH],xMax[iH]); + hPVParamGhost[iH]->GetXaxis()->SetTitle(parAxisName[iH].Data()); + } + } + gDirectory->cd(".."); //L1 + } + gDirectory->cd(".."); //L1 + gDirectory->mkdir("TrackParameters"); + gDirectory->cd("TrackParameters"); + { + TString chi2Name = "Chi2Prim"; + for(int iPart=0; iPart < KFPartEfficiencies::nParticles; iPart++) + { + TString chi2NamePart = "Chi2Prim"; + chi2NamePart += "_"; + chi2NamePart += fParteff.partName[iPart].data(); + hTrackParameters[iPart] = new TH1F(chi2NamePart.Data(), (GetDirectoryPath()+chi2NamePart).Data(), 1000, 0, 100); + + } + hTrackParameters[KFPartEfficiencies::nParticles ] = new TH1F("Chi2Prim_total", (GetDirectoryPath()+TString("Chi2Prim_total")), 1000, 0, 100); + hTrackParameters[KFPartEfficiencies::nParticles+1] = new TH1F("Chi2Prim_prim", (GetDirectoryPath()+TString("Chi2Prim_prim")), 1000, 0, 100); + hTrackParameters[KFPartEfficiencies::nParticles+2] = new TH1F("Chi2Prim_sec", (GetDirectoryPath()+TString("Chi2Prim_sec")), 1000, 0, 100); + hTrackParameters[KFPartEfficiencies::nParticles+3] = new TH1F("Chi2Prim_ghost", (GetDirectoryPath()+TString("Chi2Prim_ghost")), 1000, 0, 100); + + hTrackParameters[KFPartEfficiencies::nParticles+4] = new TH1F("ProbPrim_total", (GetDirectoryPath()+TString("ProbPrim_total")), 10000, 0, 1); + hTrackParameters[KFPartEfficiencies::nParticles+5] = new TH1F("ProbPrim_prim", (GetDirectoryPath()+TString("ProbPrim_prim")), 10000, 0, 1); + hTrackParameters[KFPartEfficiencies::nParticles+6] = new TH1F("ProbPrim_sec", (GetDirectoryPath()+TString("ProbPrim_sec")), 10000, 0, 1); + hTrackParameters[KFPartEfficiencies::nParticles+7] = new TH1F("ProbPrim_ghost", (GetDirectoryPath()+TString("ProbPrim_ghost")), 10000, 0, 1); + } + gDirectory->cd(".."); //particle directory + curdir->cd(); + } +} + +void KFParticlePerformanceBase::CreateFitHistograms(TH1F* histo[nFitQA], int iPart) +{ + /** Creates 1D histograms with fit QA for decay with "iPart" number. + ** \param[in,out] histo - array with pointers, for which the memory is allocated + ** \param[in] iPart - number of the decay in the KF Particle Finder reconstruction scheme + **/ + TString res = "res"; + TString pull = "pull"; + + TString AxisNameResidual[nFitQA/2]; + TString AxisNamePull[nFitQA/2]; + + AxisNameResidual[0] = "Residual (x^{reco} - x^{mc}) [cm]"; + AxisNameResidual[1] = "Residual (y^{reco} - y^{mc}) [cm]"; + AxisNameResidual[2] = "Residual (z^{reco} - z^{mc}) [cm]"; + AxisNameResidual[3] = "Residual (P_{x}^{reco} - P_{x}^{mc}) [GeV/c]"; + AxisNameResidual[4] = "Residual (P_{y}^{reco} - P_{y}^{mc}) [GeV/c]"; + AxisNameResidual[5] = "Residual (P_{z}^{reco} - P_{z}^{mc}) [GeV/c]"; + AxisNameResidual[6] = "Residual (E^{reco} - E^{mc}) [GeV/c^{2}]"; + AxisNameResidual[7] = "Residual (M^{reco} - M^{mc}) [GeV/c^{2}]"; + + AxisNamePull[0] = "Pull x"; + AxisNamePull[1] = "Pull y"; + AxisNamePull[2] = "Pull z"; + AxisNamePull[3] = "Pull P_{x}"; + AxisNamePull[4] = "Pull P_{y}"; + AxisNamePull[5] = "Pull P_{z}"; + AxisNamePull[6] = "Pull E"; + AxisNamePull[7] = "Pull M"; + + gDirectory->mkdir("FitQA"); + gDirectory->cd("FitQA"); + { + TString parName[nFitQA/2] = {"X","Y","Z","Px","Py","Pz","E","M"}; + int nBins = 50; + float xMax[nFitQA/2] = {0.15,0.15,1.2,0.02,0.02,0.15,0.15,0.006}; + float mult[nFitQA/2]={1.f,1.f,1.f,1.f,1.f,1.f,1.f,1.f}; + if(iPart>63 && iPart<75) + for(int iMult=3; iMult<nFitQA/2; iMult++) + mult[iMult] = 3; + if(iPart>45 && iPart<64) + { +#ifdef CBM + for(int iMult=0; iMult<3; iMult++) + mult[iMult] = 0.03; + for(int iMult=3; iMult<nFitQA/2; iMult++) + mult[iMult] = 3; +#else + mult[2] = 0.1; + for(int iMult=3; iMult<nFitQA/2; iMult++) + mult[iMult] = 10; + mult[5] = 2; + mult[6] = 2; +#endif + } + if(iPart==44 || iPart==45) + { + mult[0] = 0.25; + mult[1] = 0.5; + mult[2] = 0.15; + for(int iMult=3; iMult<nFitQA/2; iMult++) + mult[iMult] = 4; + } + + for( int iH=0; iH<nFitQA/2; iH++ ) + { + histo[iH] = new TH1F((res+parName[iH]).Data(), + (GetDirectoryPath()+res+parName[iH]).Data(), + nBins, -mult[iH]*xMax[iH],mult[iH]*xMax[iH]); + histo[iH]->GetXaxis()->SetTitle(AxisNameResidual[iH].Data()); + histo[iH+8] = new TH1F((pull+parName[iH]).Data(), + (GetDirectoryPath()+pull+parName[iH]).Data(), + nBins, -6,6); + histo[iH+8]->GetXaxis()->SetTitle(AxisNamePull[iH+8].Data()); + } + } + gDirectory->cd(".."); +} + +void KFParticlePerformanceBase::CreateEfficiencyHistograms(TProfile* histo[3][nPartEfficiency], TProfile2D* histo2[3][nPartEfficiency2D]) +{ + /** Creates efficiency plots in the current ROOT folder. + ** \param[in,out] histo - 1D efficiency plots + ** \param[in,out] histo2 - 2D efficiency plots + **/ + gDirectory->mkdir("Efficiency"); + gDirectory->cd("Efficiency"); + {//vs p, pt, y, z, c*tau, decay length, l, r + TString partNameEff[nPartEfficiency] = {"EffVsP","EffVsPt","EffVsY","EffVsZ","EffVsCT","EffVsDL","EffVsL","EffVsR","EffVsMt" }; + TString partAxisNameEff[nPartEfficiency] = {"p [GeV/c]","p_{t} [GeV/c]", + "y", "z [cm]", "Life time c#tau [cm]", "Decay length [cm]", + "L [cm]", "Rxy [cm]", "m_{t} [GeV/c^{2}]"}; +#ifdef CBM + int nBinsEff[nPartEfficiency] = { 100 , 100 , 100 , 360 , 100 , 100 , 200 , 200 , 100 }; + float xMinEff[nPartEfficiency] = { 0., 0., 0., -10., 0., 0., 0., 0. , 0.}; + float xMaxEff[nPartEfficiency] = { 20., 5., 6., 80., 100., 100., 100., 50. , 4.}; +#else + int nBinsEff[nPartEfficiency] = { 100 , 100 , 30 , 100 , 100 , 100 , 100 , 100 , 100 }; + float xMinEff[nPartEfficiency] = { 0., 0., -1.5, -10., 0., 0., 0., 0., 0. }; + float xMaxEff[nPartEfficiency] = { 10., 10., 1.5, 10., 30., 5., 1., 1., 10. }; +#endif + TString effTypeName[3] = {"All particles", + "Reconstructable daughters", + "Reconstructed daughters"}; + + for(int iEff=0; iEff<3; iEff++) + { + gDirectory->mkdir(effTypeName[iEff].Data()); + gDirectory->cd(effTypeName[iEff].Data()); + { + for(int iH=0; iH<nPartEfficiency; iH++) + { + histo[iEff][iH] = new TProfile( partNameEff[iH].Data(), (GetDirectoryPath()+partAxisNameEff[iH]).Data(), nBinsEff[iH], xMinEff[iH], xMaxEff[iH]); + histo[iEff][iH]->GetYaxis()->SetTitle("Efficiency"); + histo[iEff][iH]->GetYaxis()->SetTitleOffset(1.0); + histo[iEff][iH]->GetXaxis()->SetTitle(partAxisNameEff[iH].Data()); + } + + histo2[iEff][0] = new TProfile2D( "EffVsPtVsY", (GetDirectoryPath()+partAxisNameEff[2]+partAxisNameEff[1]).Data(), + nBinsEff[2], xMinEff[2], xMaxEff[2], nBinsEff[1], xMinEff[1], xMaxEff[1]); + histo2[iEff][0]->GetZaxis()->SetTitle("Efficiency"); + histo2[iEff][0]->GetXaxis()->SetTitle(partAxisNameEff[2].Data()); + histo2[iEff][0]->GetYaxis()->SetTitle(partAxisNameEff[1].Data()); + histo2[iEff][0]->GetYaxis()->SetTitleOffset(1.0); + + histo2[iEff][1] = new TProfile2D( "EffVsMtVsY", (GetDirectoryPath()+partAxisNameEff[2]+partAxisNameEff[8]).Data(), + nBinsEff[2], xMinEff[2], xMaxEff[2], nBinsEff[8], xMinEff[8], xMaxEff[8]); + histo2[iEff][1]->GetZaxis()->SetTitle("Efficiency"); + histo2[iEff][1]->GetXaxis()->SetTitle(partAxisNameEff[2].Data()); + histo2[iEff][1]->GetYaxis()->SetTitle(partAxisNameEff[8].Data()); + histo2[iEff][1]->GetYaxis()->SetTitleOffset(1.0); + } + gDirectory->cd("..");// particle directory / Efficiency + } + } + gDirectory->cd("..");// particle directory +} + +void KFParticlePerformanceBase::CreateParameterHistograms(TH1F* histoParameters[KFPartEfficiencies::nParticles][nHistoPartParam], + TH2F *histoParameters2D[KFPartEfficiencies::nParticles][nHistoPartParam2D], + TH3F *histoParameters3D[KFPartEfficiencies::nParticles][nHistoPartParam3D], + int iPart, bool drawZR) +{ + /** Creates histograms with parameter distributions for decay with "iPart" number. + ** \param[in,out] histoParameters - 1D histograms + ** \param[in,out] histoParameters2D - 2D histograms + ** \param[in,out] histoParameters3D - 3D histograms + ** \param[in] iPart - number of the decay in the KF Particle Finder reconstruction scheme + ** \param[in] drawZR - flag showing if Z-R histogram should be created + **/ + TString parName[nHistoPartParam] = {"M","p","p_{t}","y","DecayL","c#tau","chi2ndf","prob","#theta","phi","X","Y","Z","R", "L", "l/dl","m_{t}","Multiplicity"}; + TString parTitle[nHistoPartParam]; + TString parName2D[nHistoPartParam2D] = {"y-p_{t}", "Z-R", "Armenteros", "y-m_{t}"}; + TString parTitle2D[nHistoPartParam2D]; + TString parName3D[nHistoPartParam3D] = {"y-p_{t}-M", "y-m_{t}-M", "centrality-pt-M", "centrality-y-M", "centrality-mt-M", "ct-pt-M"}; + TString parTitle3D[nHistoPartParam3D]; + for(int iParam=0; iParam<nHistoPartParam; iParam++) + { + TString path = GetDirectoryPath(); + parTitle[iParam] = path + parName[iParam]; + if(iParam<nHistoPartParam2D) + parTitle2D[iParam] = path + parName2D[iParam]; + if(iParam<nHistoPartParam3D) + parTitle3D[iParam] = path + parName3D[iParam]; + } + + TString parAxisName[nHistoPartParam] = {"m [GeV/c^{2}]","p [GeV/c]","p_{t} [GeV/c]", + "y","Decay length [cm]","Life time c#tau [cm]", + "chi2/ndf","prob","#theta [rad]", + "phi [rad]","x [cm]","y [cm]","z [cm]","Rxy [cm]", "L [cm]", "L/dL","m_{t} [GeV/c^{2}]","Multiplicity"}; +#ifdef CBM + int nBins[nHistoPartParam] = {1000, // M + 100, // p + 100, // pt + 40, // y + 60, // DecayL + 60, // ctau + 100, // chi2/ndf + 100, // prob + 100, // theta + 100, // phi + 200, // X + 200, // Y + 360, // Z + 60, // R + 140, // L + 200, // L/dL + 100, // Mt + fParteff.partMaxMult[iPart]+1}; + float xMin[nHistoPartParam] = { fParteff.partMHistoMin[iPart], // M + 0.f, // p + 0.f, // pt + 0.f, // y + -10.f, // DecayL + -10.f, // ctau + 0.f, // chi2/ndf + 0.f, // prob + -2.f, // theta + -2.f, // phi + -50.f, // X + -50.f, // Y + -10.f, // Z + 0.f, // R + 0.f, // L + -1.f, // L/dL + 0.f, // Mt + -0.5f }; + float xMax[nHistoPartParam] = { fParteff.partMHistoMax[iPart], // M + 20.f, // p + 5.f, // pt + 4.f, // y + 50.f, // DecayL + 50.f, // ctau + 20.f, // chi2/ndf + 1.f, // prob + 2.f, // theta + 2.f, // phi + 50.f, // X + 50.f, // Y + 80.f, // Z + 30.f, // R + 70.f, // L + 35.f, // L/dL + 4.f, // Mt + float(fParteff.partMaxMult[iPart])+0.5f}; +#else + int nBins[nHistoPartParam] = {1000, // M + 100, // p + 100, // pt + 30, // y + 60, // DecayL + 60, // ctau + 100, // chi2/ndf + 100, // prob + 100, // theta + 100, // phi + 100, // X + 100, // Y + 100, // Z + 100, // R + 100, // L + 1000, // L/dL + 100, // Mt + fParteff.partMaxMult[iPart]+1}; + float xMin[nHistoPartParam] = { fParteff.partMHistoMin[iPart], // M + 0.f, // p + 0.f, // pt + -1.5f, // y + -10.f, // DecayL + -10.f, // ctau + 0.f, // chi2/ndf + 0.f, // prob + 0.f, // theta + -3.1416f, // phi + -10.f, // X + -10.f, // Y + -30.f, // Z + 0.f, // R + 0.f, // L + -1.f, // L/dL + 0.f, // Mt + -0.5f }; + float xMax[nHistoPartParam] = { fParteff.partMHistoMax[iPart], // M + 10.f, // p + 10.f, // pt + 1.5f, // y + 50.f, // DecayL + 50.f, // ctau + 20.f, // chi2/ndf + 1.f, // prob + 3.1416f, // theta + 3.1416f, // phi + 10.f, // X + 10.f, // Y + 30.f, // Z + 50.f, // R + 50.f, // L + 35.f, // L/dL + 10.f, // Mt + float(fParteff.partMaxMult[iPart])+0.5f}; + if(iPart < 9) + { + xMin[10] =-50; xMin[11] =-50; xMin[12] =-100; + xMax[10] = 50; xMax[11] = 50; xMax[12] = 100; xMax[13] = 50; xMax[14] = 50; + } +#endif + for(int iH=0; iH<nHistoPartParam; iH++) + { + histoParameters[iPart][iH] = new TH1F(parName[iH].Data(),parTitle[iH].Data(), + nBins[iH],xMin[iH],xMax[iH]); + histoParameters[iPart][iH]->GetXaxis()->SetTitle(parAxisName[iH].Data()); + } + + histoParameters2D[iPart][0] = new TH2F(parName2D[0].Data(),parTitle2D[0].Data(), + nBins[3],xMin[3],xMax[3], + nBins[2],xMin[2],xMax[2]); + histoParameters2D[iPart][0]->GetXaxis()->SetTitle("y"); + histoParameters2D[iPart][0]->GetYaxis()->SetTitle("p_{t} [GeV/c]"); + histoParameters2D[iPart][0]->GetYaxis()->SetTitleOffset(1.0); + + if(drawZR) + { + histoParameters2D[iPart][1] = new TH2F(parName2D[1].Data(),parTitle2D[1].Data(), + nBins[12],xMin[12],xMax[12], + nBins[13],xMin[13],xMax[13]); + histoParameters2D[iPart][1]->GetXaxis()->SetTitle("Z [cm]"); + histoParameters2D[iPart][1]->GetYaxis()->SetTitle("R [cm]"); + histoParameters2D[iPart][1]->GetYaxis()->SetTitleOffset(1.0); + } + else + histoParameters2D[iPart][1] = NULL; + + //create armenteros plot + if(IsCollectArmenteros(iPart)) + { + histoParameters2D[iPart][2] = new TH2F(parName2D[2].Data(),parTitle2D[2].Data(), + 50, -1.f, 1.f, + 150, 0.f, 1.f); + histoParameters2D[iPart][2]->GetXaxis()->SetTitle("#alpha (p_{L}^{+}-p_{L}^{-})/(p_{L}^{+}+p_{L}^{-})"); + histoParameters2D[iPart][2]->GetYaxis()->SetTitle("q_{t} [GeV/c]"); + histoParameters2D[iPart][2]->GetYaxis()->SetTitleOffset(1.0); + } + else + histoParameters2D[iPart][2] = NULL; + //create y-mt plot + histoParameters2D[iPart][3] = new TH2F(parName2D[3].Data(),parTitle2D[3].Data(), + nBins[3],xMin[3], xMax[3], //y + nBins[16],xMin[16],xMax[16]); //Mt + histoParameters2D[iPart][3]->GetXaxis()->SetTitle("y"); + histoParameters2D[iPart][3]->GetYaxis()->SetTitle("m_{t} [GeV/c]"); + histoParameters2D[iPart][3]->GetYaxis()->SetTitleOffset(1.0); + + + if( histoParameters3D && IsCollect3DHistogram(iPart) ) + { + histoParameters3D[iPart][0] = new TH3F(parName3D[0].Data(),parTitle3D[0].Data(), + nBins[3],xMin[3],xMax[3], + nBins[2],xMin[2],xMax[2], + nBins[0],xMin[0],xMax[0]); + histoParameters3D[iPart][0]->GetXaxis()->SetTitle("y"); + histoParameters3D[iPart][0]->GetYaxis()->SetTitle("p_{t} [GeV/c]"); + histoParameters3D[iPart][0]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][0]->GetZaxis()->SetTitle("M"); + + histoParameters3D[iPart][1] = new TH3F(parName3D[1].Data(),parTitle3D[1].Data(), + nBins[3],xMin[3],xMax[3], + nBins[16],xMin[16],xMax[16], + nBins[0],xMin[0],xMax[0]); + histoParameters3D[iPart][1]->GetXaxis()->SetTitle("y"); + histoParameters3D[iPart][1]->GetYaxis()->SetTitle("m_{t} [GeV/c]"); + histoParameters3D[iPart][1]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][1]->GetZaxis()->SetTitle("M"); + + int centralityHisto[3] = {2,3,16}; + for(int iCH = 0; iCH<3; iCH++) + { + histoParameters3D[iPart][2+iCH] = new TH3F(parName3D[2+iCH].Data(),parTitle3D[2+iCH].Data(), + 10,0.,10., + nBins[centralityHisto[iCH]],xMin[centralityHisto[iCH]],xMax[centralityHisto[iCH]], + nBins[0],xMin[0],xMax[0]); + histoParameters3D[iPart][2+iCH]->GetXaxis()->SetTitle("centrality bin"); + histoParameters3D[iPart][2+iCH]->GetYaxis()->SetTitle(parAxisName[centralityHisto[iCH]]); + histoParameters3D[iPart][2+iCH]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][2+iCH]->GetZaxis()->SetTitle("M"); + } + + histoParameters3D[iPart][5] = new TH3F(parName3D[5].Data(),parTitle3D[5].Data(), + nBins[5],xMin[5],xMax[5], + nBins[2],xMin[2],xMax[2], + nBins[0],xMin[0],xMax[0]); + histoParameters3D[iPart][5]->GetXaxis()->SetTitle("c#tau [cm]"); + histoParameters3D[iPart][5]->GetYaxis()->SetTitle("p_{t} [GeV/c]"); + histoParameters3D[iPart][5]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][5]->GetZaxis()->SetTitle("M"); + } + else if(histoParameters3D) + { + histoParameters3D[iPart][0] = NULL; + histoParameters3D[iPart][1] = NULL; + for(int iCH = 0; iCH<3; iCH++) + histoParameters3D[iPart][2+iCH] = NULL; + histoParameters3D[iPart][5] = NULL; + } +} + +bool KFParticlePerformanceBase::IsCollectZRHistogram(int iParticle) const +{ + /** Checks if Z-R histogram for decay "iParticle" should be created. */ + return (abs(fParteff.partPDG[iParticle]) == 310 || + abs(fParteff.partPDG[iParticle]) == 3122 || + abs(fParteff.partPDG[iParticle]) == 3312 || + abs(fParteff.partPDG[iParticle]) == 3334 || + abs(fParteff.partPDG[iParticle]) == 22) && fStoreMCHistograms && fStoreZRHistograms; +} + +bool KFParticlePerformanceBase::IsCollect3DHistogram(int iParticle) const +{ + /** Checks if 3D histograms for decay "iParticle" should be created. */ + return abs(fParteff.partPDG[iParticle]) == 310 || + abs(fParteff.partPDG[iParticle]) == 3122 || + abs(fParteff.partPDG[iParticle]) == 3312 || + abs(fParteff.partPDG[iParticle]) == 3334 || + abs(fParteff.partPDG[iParticle]) == 3003 || + abs(fParteff.partPDG[iParticle]) == 3103 || + abs(fParteff.partPDG[iParticle]) == 3004 || + abs(fParteff.partPDG[iParticle]) == 3005 || +#ifdef CBM + abs(fParteff.partPDG[iParticle]) == 7003112 || + abs(fParteff.partPDG[iParticle]) == 7003222 || + abs(fParteff.partPDG[iParticle]) == 7003312 || + abs(fParteff.partPDG[iParticle]) == 8003222 || + abs(fParteff.partPDG[iParticle]) == 9000321; +#else + abs(fParteff.partPDG[iParticle]) == 421 || + abs(fParteff.partPDG[iParticle]) == 429 || + abs(fParteff.partPDG[iParticle]) == 426 || + abs(fParteff.partPDG[iParticle]) == 411 || + abs(fParteff.partPDG[iParticle]) == 431 || + abs(fParteff.partPDG[iParticle]) == 4122 || + abs(fParteff.partPDG[iParticle]) == 521 || + abs(fParteff.partPDG[iParticle]) == 511; +#endif +} + +bool KFParticlePerformanceBase::IsCollectArmenteros(int iParticle) const +{ + /** Checks if Armenteros-Podoliansky plot for decay "iParticle" should be created. */ + return abs(fParteff.partPDG[iParticle]) == 310 || + abs(fParteff.partPDG[iParticle]) == 3122 || + abs(fParteff.partPDG[iParticle]) == 3312 || + abs(fParteff.partPDG[iParticle]) == 3334 || + abs(fParteff.partPDG[iParticle]) == 22 || + abs(fParteff.partPDG[iParticle]) == 111 || + abs(fParteff.partPDG[iParticle]) == 3003 || + abs(fParteff.partPDG[iParticle]) == 3103 || + abs(fParteff.partPDG[iParticle]) == 3004 || + abs(fParteff.partPDG[iParticle]) == 3005 || + abs(fParteff.partPDG[iParticle]) == 3203 || + abs(fParteff.partPDG[iParticle]) == 3008 || + abs(fParteff.partPDG[iParticle]) == 3000 || + abs(fParteff.partPDG[iParticle]) == 333 || +#ifdef CBM + abs(fParteff.partPDG[iParticle]) == 7003112 || + abs(fParteff.partPDG[iParticle]) == 7003222 || + abs(fParteff.partPDG[iParticle]) == 7003312 || + abs(fParteff.partPDG[iParticle]) == 8003222 || + abs(fParteff.partPDG[iParticle]) == 9000321; +#else + abs(fParteff.partPDG[iParticle]) == 421 || + abs(fParteff.partPDG[iParticle]) == 420 || + abs(fParteff.partPDG[iParticle]) == 426 || + abs(fParteff.partPDG[iParticle]) == 521 || + abs(fParteff.partPDG[iParticle]) == 511; +#endif +} + +void KFParticlePerformanceBase::CreateParameterSubfolder(TString folderName, + TH1F* histoParameters[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam], + TH2F* histoParameters2D[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D], + TH1F* histoFit[KFPartEfficiencies::nParticles][nFitQA], int iPart, bool withWrongPVHypothesis) +{ + /** Creates all subfolders in the current ROOT directory for the current decay channel. */ + gDirectory->mkdir(folderName.Data()); + gDirectory->cd(folderName.Data()); + { + gDirectory->mkdir("Signal"); + gDirectory->cd("Signal"); + { + CreateParameterHistograms(histoParameters[1], histoParameters2D[1], 0, iPart); + } + gDirectory->cd(".."); + if(withWrongPVHypothesis) + { + gDirectory->mkdir("WrongPVHypothesis"); + gDirectory->cd("WrongPVHypothesis"); + { + CreateParameterHistograms(histoParameters[4], histoParameters2D[4], 0, iPart); + } + gDirectory->cd(".."); + } + gDirectory->mkdir("Background"); + gDirectory->cd("Background"); + { + CreateParameterHistograms(histoParameters[2], histoParameters2D[2], 0, iPart); + } + gDirectory->cd(".."); + gDirectory->mkdir("Ghost"); + gDirectory->cd("Ghost"); + { + CreateParameterHistograms(histoParameters[3], histoParameters2D[3], 0, iPart); + } + gDirectory->cd(".."); + + CreateParameterHistograms(histoParameters[0], histoParameters2D[0], 0, iPart); + if(histoFit!=0) + CreateFitHistograms(histoFit[iPart], iPart); + } + gDirectory->cd(".."); +} + +TString KFParticlePerformanceBase::GetDirectoryPath() +{ + /** Returns the path to the current folder. It is used as an addition to the histogram name. */ + TString path = gDirectory->GetPath(); + int fileNamePosition = path.Index("Finder/"); + path.Remove(0, fileNamePosition+7); + path.ReplaceAll("Particles/", ""); + path.ReplaceAll("/Parameters", ""); + path+=" "; + return path; +} + +#endif //DO_TPCCATRACKER_EFF_PERFORMANCE + diff --git a/external/KFParticle/KFParticlePerformance/KFParticlePerformanceBase.h b/external/KFParticle/KFParticlePerformance/KFParticlePerformanceBase.h new file mode 100644 index 0000000000000000000000000000000000000000..47fe48dc4e5b2b5f1d65521aadafef6887537a03 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFParticlePerformanceBase.h @@ -0,0 +1,195 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifdef DO_TPCCATRACKER_EFF_PERFORMANCE + +#ifndef KFParticlePERFORMANCEBASE_H +#define KFParticlePERFORMANCEBASE_H + +#ifdef KFPWITHTRACKER +#include "AliHLTTPCCounters.h" + +#include "AliHLTTPCPerformanceBase.h" + +#include "AliHLTTPCCADef.h" +#include "AliHLTArray.h" +#include "AliHLTTPCCAMCTrack.h" +#include "AliHLTTPCCAMCPoint.h" +#endif + +#include "KFPartEfficiencies.h" +#include "KFPVEfficiencies.h" + +#include <map> +#include <string> + +class TDirectory; +class TH1F; +class TH2F; +class TH3F; + +class KFParticle; +class TProfile; +class TProfile2D; + +/** @class KFParticlePerformanceBase + ** @brief The base class for KFTopoPerformance. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class contains a set of histograms, allocates memory for them, sets names and axis names. + ** For each particle from the KF Particle Reconstruction scheme histograms with parameter distribution, + ** efficiencies, fit QA, fit QA of daughters, histograms for the side bands method and histograms for + ** multi-differential extraction of spectra are collected. Also, a set of histograms for quality of + ** the reconstructed parameters of primary vertices is created: distribution of parameters; fit QA; + ** fit QA of primary tracks; contamination of ghost, secondary (background) tracks and tracks from + ** another primary vertex; efficiency. + **/ + +class KFParticlePerformanceBase +#ifdef KFPWITHTRACKER +: public AliHLTTPCPerformanceBase +#endif +{ + public: + + KFParticlePerformanceBase(); + virtual ~KFParticlePerformanceBase(){}; + + /// Histograms + virtual void CreateHistos(std::string histoDir = "", TDirectory* outFile = 0, std::map<int,bool> decays = std::map<int,bool>()); + TDirectory* GetHistosDirectory() { return fHistoDir; } ///< Returns pointer to the ROOT directory with created histograms. + + /** Switch off collection of histograms requiring Monte Carlo information. Not to allocate memory should be called + ** before KFParticlePerformanceBase::CreateHistos(). **/ + void DoNotStoreMCHistograms() { fStoreMCHistograms = 0; } + /** Switch off collection of histograms for primary and secondary candidates. Not to allocate memory should be called + ** before KFParticlePerformanceBase::CreateHistos(). **/ + void DoNotStorePrimSecHistograms() { fStorePrimSecHistograms = 0; } + /** Switch off collection of Z-R histograms. Not to allocate memory should be called + ** before KFParticlePerformanceBase::CreateHistos(). **/ + void DoNotStoreZRHistograms() { fStoreZRHistograms = 0; } + + /** Returns residual histogram with "iParameter" parameter for decay with "iDecay" number. */ + const TH1F* GetDecayResidual(const int iDecay, const int iParameter) const { return hFitQA[iDecay][iParameter]; } + /** Returns pull histogram with "iParameter" parameter for decay with "iDecay" number. */ + const TH1F* GetDecayPull(const int iDecay, const int iParameter) const { return hFitQA[iDecay][iParameter+nFitQA/2]; } + +// efficiencies + KFPartEfficiencies fParteff; ///< Object with reconstruction efficiency of short-lived particles. + KFPVEfficiencies fPVeff; ///< Object with reconstruction efficiency of primary vertices defined by the reconstructed tracks. + KFPVEfficiencies fPVeffMCReconstructable; ///< Object with reconstruction efficiency of primary vertices defined by the Monte Carlo tracks. + + protected: + TString outfileName; ///< Name of the output file, where histograms will be stored. + TDirectory* histodir; ///< Pointer to the ROOT directory, where histograms are created. + + int fNEvents; ///< Number of processed events. + bool fStoreMCHistograms; ///< Flag showing if histograms requiring Monte Carlo information should be created and collected. "True" by default. + bool fStorePrimSecHistograms; ///< Flag showing if histograms for primary and secondary candidates should be created and collected. "True" by default. + bool fStoreZRHistograms; ///< Flag showing if Z-R histograms should be created and collected. "True" by default. + +//histos + static const int nFitQA = 16; ///< Number of fit QA histograms: residuals and pulls in X, Y, Z, Px, Py, Pz, E, M. + TH1F *hFitDaughtersQA[KFPartEfficiencies::nParticles][nFitQA]; ///< Residuals and pulls of daughter particles at production point. + TH1F *hFitQA[KFPartEfficiencies::nParticles][nFitQA]; ///< Residuals and pulls of the reconstructed particle: X, Y, Z at decay point, P, E, M - at production point + TH1F *hFitQANoConstraint[KFPartEfficiencies::nParticles][nFitQA]; ///< Residuals and pulls of the particle with no constraints set. + TH1F *hFitQAMassConstraint[KFPartEfficiencies::nParticles][nFitQA]; ///< Residuals and pulls of the particle with the mass constraint. + TH1F *hFitQATopoConstraint[KFPartEfficiencies::nParticles][nFitQA]; ///< Residuals and pulls of the particle with the production point constraint. + TH1F *hFitQATopoMassConstraint[KFPartEfficiencies::nParticles][nFitQA]; ///< Residuals and pulls of the particle with the mass and production point constraints. + + static const int nDSToParticleQA = 7; ///< Number of histograms to evaluate GetDStoParticle function: residuals and pulls in X, Y, Z; distance between DCA points. + TH1F *hDSToParticleQA[KFPartEfficiencies::nParticles][nDSToParticleQA]; ///< Histograms to evaluate KFParticleSIMD::GetDStoParticle() function + + /** \brief Number of histograms with parameter distributions: mass, p, pt, rapidity, decay length, c*tau, + ** chi/ndf, prob, theta, phi, X, Y, Z, R, L, L/dL, Mt, multiplicity. **/ + static const int nHistoPartParam = 18; + /** Number of sets of histograms with parameter distributions: 0 - all candidates, 1 - reconstructed signal, 2 - physics background from other decays, 3 - combinatorial + ** background (ghost), 4 - reconstructed signal for side bands method, 5- reconstructed background for side bands method, 6 - MC signal. **/ + static const int nParametersSet = 7; + TH1F *hPartParam[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam]; ///< Parameters of all candidates. + TH1F *hPartParamPrimary[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam]; ///< Parameters of primary candidates. + TH1F *hPartParamPrimaryMass[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam]; ///< Parameters of primary candidates with mass constraint. + TH1F *hPartParamPrimaryTopo[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam]; ///< Parameters of primary candidates with vertex constraint. + TH1F *hPartParamPrimaryTopoMass[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam]; ///< Parameters of primary candidates with mass and vertex constraint. + TH1F *hPartParamSecondary[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam]; ///< Parameters of secondary candidates. + TH1F *hPartParamSecondaryMass[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam]; ///< Parameters of secondary candidates with mass constraint. + + static const int nHistoPartParam2D = 4; ///< Number of 2D histograms: 0 - y-pt, 1 - z-r, 2 - armenteros, 3- y-mt. + TH2F *hPartParam2D[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D]; ///< 2D histograms for all candidates. + TH2F *hPartParam2DPrimary[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D]; ///< 2D for primary candidates. + TH2F *hPartParam2DPrimaryMass[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D]; ///< 2D for primary candidates with mass constraint. + TH2F *hPartParam2DPrimaryTopo[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D]; ///< 2D for primary candidates with vertex constraint. + TH2F *hPartParam2DPrimaryTopoMass[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D]; ///< 2D with mass and vertex constraints. + TH2F *hPartParam2DSecondary[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D]; ///< 2D for secondary candidates. + TH2F *hPartParam2DSecondaryMass[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D]; ///< 2D for secondary candidates with mass constraint. + + static const int nHistoPartParam3D = 6; ///< Number of 3D histograms: y-pt-M, y-mt-M, b-pt-M, b-y-M, b-mt-M, ct-pt-M + TH3F *hPartParam3D[1][KFPartEfficiencies::nParticles][nHistoPartParam3D]; ///< 3D histograms. + + static const int nPartEfficiency = 9; ///< Number of efficiency plots for each decay: vs p, pt, y, z, c*tau, decay length, l, r, Mt. + TProfile* hPartEfficiency[KFPartEfficiencies::nParticles][3][nPartEfficiency]; ///< Efficiency plots. + static const int nPartEfficiency2D = 2; ///< Number of 2D efficiency plots for each decay: y-pt, y-mt. + TProfile2D* hPartEfficiency2D[KFPartEfficiencies::nParticles][3][nPartEfficiency2D]; ///< 2D efficiency plots. + + static const int nHistosPV = 7; ///< Number of QA histograms for primary vertices: residuals, pulls, number of lost tracks. + TH1F *hPVFitQa[2][nHistosPV]; ///< Fit QA of primary vertices, 1D histograms. + TH2F *hPVFitQa2D[2][2][nHistosPV-1]; ///< Fit QA of primary vertices, 2D histograms. + + /** Number of histograms with parameter distributions: x, y, z, r, Ntracks, Chi2, NDF, Chi2/NDF, prob, purity, part of ghost tracks, + ** part of tracks from the current vertex, number of tracks from merged vertices, number of background tracks from decays, distance in Z between clones. **/ + static const int nHistosPVParam = 15; ///< + TH1F *hPVParam[nHistosPVParam]; ///< Histograms for all vertex candidates. + TH1F *hPVParamGhost[nHistosPVParam]; ///< Histograms for ghost (combinatorial background) vertex candidates. + TH1F *hPVParamSignal[nHistosPVParam]; ///< Histograms for signal vertex candidates. + TH1F *hPVParamPileup[nHistosPVParam]; ///< Histograms for pileup vertex candidates. + TH1F *hPVParamBG[nHistosPVParam]; ///< Histograms for physics background (decays, secondary vertices) vertex candidates. + static const int nHistosPVParam2D = 1; ///< Number of 2D histograms for primary vertex. + TH2F *hPVParam2D[nHistosPVParam2D]; ///< x-y histogram. + + static const int nFitPVTracksQA = 12; ///< Number of fit QA histograms for primary tracks: residuals and pulls in X, Y, Z, Px, Py, Pz. + TH1F *hFitPVTracksQA[nFitPVTracksQA]; ///< Residuals and pulls of primary tracks at the primary vertex position. + + static const int nHistosTP = KFPartEfficiencies::nParticles + 8; ///< Number of histograms with chi2 primary distributions for daughter tracks. + /** Histograms with chi2 primary distributions for daughter tracks of each decays plus 4 distributions of chi2 and 4 prob for primary, secondary, + ** ghost and all particles. **/ + TH1F *hTrackParameters[nHistosTP]; + + static const int nPVefficiency = 6; ///< Number of Efficiency plots for primary vertices for each category. + TProfile* hPVefficiency[4][nPVefficiency]; ///< Efficiency plots for primary vertices. + + TDirectory *fHistoDir; ///< ROOT directory with histograms. + + bool IsCollectZRHistogram(int iParticle) const; + bool IsCollect3DHistogram(int iParticle) const; + bool IsCollectArmenteros(int iParticle) const; + + private: + const KFParticlePerformanceBase& operator = (const KFParticlePerformanceBase&); ///< Copying of objects of this class is forbidden. + KFParticlePerformanceBase(const KFParticlePerformanceBase&); ///< Copying of objects of this class is forbidden. + + void CreateFitHistograms(TH1F* histo[nFitQA], int iPart); + void CreateEfficiencyHistograms(TProfile* histo[3][nPartEfficiency], TProfile2D* histo2[3][nPartEfficiency2D]); + void CreateParameterHistograms(TH1F* histoParameters[KFPartEfficiencies::nParticles][nHistoPartParam], + TH2F *histoParameters2D[KFPartEfficiencies::nParticles][nHistoPartParam2D], + TH3F *histoParameters3D[KFPartEfficiencies::nParticles][nHistoPartParam3D], + int iPart, bool drawZR = 0); + void CreateParameterSubfolder(TString folderName, + TH1F* histoParameters[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam], + TH2F* histoParameters2D[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D], + TH1F* histoFit[KFPartEfficiencies::nParticles][nFitQA], int iPart, bool withWrongPVHypothesis = 0); + + TString GetDirectoryPath(); +}; + +#endif +#endif //DO_TPCCATRACKER_EFF_PERFORMANCE diff --git a/external/KFParticle/KFParticlePerformance/KFTopoPerformance.cxx b/external/KFParticle/KFParticlePerformance/KFTopoPerformance.cxx new file mode 100644 index 0000000000000000000000000000000000000000..21d387949c86d8d8d897137f57af4815496e84bd --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFTopoPerformance.cxx @@ -0,0 +1,2179 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifdef DO_TPCCATRACKER_EFF_PERFORMANCE + +#include "KFTopoPerformance.h" + +#ifdef KFPWITHTRACKER +#ifdef MAIN_DRAW +#include "AliHLTTPCCADisplay.h" +#endif //DRAW +#include "AliHLTTPCCATracker.h" +#include "AliHLTTPCCAPerformance.h" +#endif + +#include "KFParticleTopoReconstructor.h" +#include "KFParticleSIMD.h" +#include "KFPHistogram/KFPHistogram.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" + +#include "TMath.h" +#include "TH1.h" +#include "TH2.h" +#include "TH3.h" +#include "TProfile.h" +#include "TProfile2D.h" + +#include <map> +#include <algorithm> +using std::sort; +using std::vector; + +KFTopoPerformance::KFTopoPerformance():KFParticlePerformanceBase(),fTopoReconstructor(0),fPrimVertices(0), fMCTrackToMCPVMatch(0), + fPVPurity(0), fNCorrectPVTracks(0), fTrackMatch(0), vMCTracks(0), vMCParticles(0), fNeutralIndex(0), MCtoRParticleId(0), RtoMCParticleId(0), + MCtoRPVId(0), RtoMCPVId(0), fPrintEffFrequency(1), fCentralityBin(-1), fCentralityWeight(0.f) +{ +} + +KFTopoPerformance::~KFTopoPerformance() +{ +} + +#ifdef KFPWITHTRACKER +void KFTopoPerformance::SetNewEvent( + const AliHLTTPCCAGBTracker * const tracker, + AliHLTResizableArray<AliHLTTPCCAHitLabel> *hitLabels, + AliHLTResizableArray<AliHLTTPCCAMCTrack> *mcTracks, + AliHLTResizableArray<AliHLTTPCCALocalMCPoint> *localMCPoints) +{ + vMCTracks.resize(mcTracks->Size()); + for(int iTr=0; iTr<vMCTracks.size(); iTr++) + { + for(int iP=0; iP<3; iP++) + vMCTracks[iTr].SetPar(iP, (*mcTracks)[iTr].Par(iP)); + for(int iP=3; iP<6; iP++) + vMCTracks[iTr].SetPar(iP, (*mcTracks)[iTr].Par(iP) * (*mcTracks)[iTr].P()); + vMCTracks[iTr].SetPar(6, (*mcTracks)[iTr].Par(6)); + + vMCTracks[iTr].SetPDG( (*mcTracks)[iTr].PDG() ); + vMCTracks[iTr].SetMotherId( (*mcTracks)[iTr].MotherId() ); + vMCTracks[iTr].SetNMCPoints( (*mcTracks)[iTr].NMCPoints() ); + } +} // void KFTopoPerformance::SetNewEvent +#endif + +void KFTopoPerformance::SetTopoReconstructor( const KFParticleTopoReconstructor * const TopoReconstructor) +{ + /** Sets a pointer to the external KFParticleTopoReconstructor object. */ + fTopoReconstructor = TopoReconstructor; +} // void KFTopoPerformance::SetTopoReconstructor + +void KFTopoPerformance::CheckMCTracks() +{ + /** Cleans Monte Carlo information on primary vertices, and refill it with the current event. */ + fMCTrackToMCPVMatch.clear(); + fPrimVertices.clear(); + + // find prim vertex + if (vMCTracks.size() <= 0) return; + + fMCTrackToMCPVMatch.resize(vMCTracks.size(),-1); + + vector<int> pvIndex; + for(unsigned int iTr=0; iTr<vMCTracks.size(); iTr++) + { + KFMCTrack &mctr = vMCTracks[iTr]; + int motherID = mctr.MotherId(); + if(motherID <0 ) + { + bool newPV = 1; + for(unsigned int iPV=0; iPV<pvIndex.size(); iPV++) + { + if(motherID == pvIndex[iPV]) + { + fPrimVertices[iPV].AddDaughterTrack(iTr); + fMCTrackToMCPVMatch[iTr] = iPV; + newPV = 0; + } + } + if(newPV) + { + KFMCVertex primVertex; + primVertex.SetX( mctr.X() ); + primVertex.SetY( mctr.Y() ); + primVertex.SetZ( mctr.Z() ); + primVertex.AddDaughterTrack(iTr); + if(motherID == -1) + primVertex.SetTriggerPV(); + fPrimVertices.push_back(primVertex); + fMCTrackToMCPVMatch[iTr] = pvIndex.size(); + pvIndex.push_back(motherID); + } + } + } +} // void KFTopoPerformance::CheckMCTracks() + +void KFTopoPerformance::GetMCParticles() +{ + /** Fills information on relations between Monte Carlo particles. */ + + vMCParticles.clear(); + vMCParticles.reserve(vMCTracks.size()); + // all MC tracks are copied into KF MC Particles + for(unsigned int iMC=0; iMC < vMCTracks.size(); iMC++) + { + KFMCTrack &mtra = vMCTracks[iMC]; + KFMCParticle part; + part.SetMCTrackID( iMC ); + part.SetMotherId ( mtra.MotherId() ); + part.SetPDG ( mtra.PDG() ); + vMCParticles.push_back( part ); + } + // find relations between mother and daughter MC particles + const int nMCParticles = vMCParticles.size(); + for (int iP = 0; iP < nMCParticles; iP++ ) { + KFMCParticle &part = vMCParticles[iP]; + int motherId = part.GetMotherId(); + if(motherId < 0) continue; + if(motherId >= nMCParticles) + { + std::cout << "ERROR!!!!! KF Particle Performance: MC track mother Id is out of range." << std::endl; + exit(1); + } + KFMCParticle &motherPart = vMCParticles[motherId]; + motherPart.AddDaughter(iP); + } + + fNeutralIndex.clear(); + fNeutralIndex.resize(nMCParticles, -1); + + for(unsigned int iMC=0; iMC < vMCParticles.size(); iMC++) + { + KFMCParticle &part = vMCParticles[iMC]; + part.SetMCTrackID( iMC ); + } + + const int NmmPDG = 7; + vector<int> mmMotherPDG(NmmPDG); //PDG for particles found by the missing mass method + vector<int> mmChargedDaughterPDG(NmmPDG); + vector<int> mmNeutralDaughterPDG(NmmPDG); + vector<int> newMotherPDG(NmmPDG); + vector<int> newNeutralPDG(NmmPDG); + + mmMotherPDG[ 0] = 3112; mmChargedDaughterPDG[ 0] = 211; mmNeutralDaughterPDG[ 0] = 2112; + mmMotherPDG[ 1] = 3222; mmChargedDaughterPDG[ 1] = 211; mmNeutralDaughterPDG[ 1] = 2112; + mmMotherPDG[ 2] = 3312; mmChargedDaughterPDG[ 2] = 211; mmNeutralDaughterPDG[ 2] = 3122; + mmMotherPDG[ 3] = 3334; mmChargedDaughterPDG[ 3] = 211; mmNeutralDaughterPDG[ 3] = 3322; + mmMotherPDG[ 4] = 321; mmChargedDaughterPDG[ 4] = 211; mmNeutralDaughterPDG[ 4] = 111; + mmMotherPDG[ 5] = 3334; mmChargedDaughterPDG[ 5] = 321; mmNeutralDaughterPDG[ 5] = 3122; + mmMotherPDG[ 6] = 3222; mmChargedDaughterPDG[ 6] = 2212; mmNeutralDaughterPDG[ 6] = 111; + + newMotherPDG[ 0] = 7003112; newNeutralPDG[ 0] = 7002112; + newMotherPDG[ 1] = 7003222; newNeutralPDG[ 1] = 8002112; + newMotherPDG[ 2] = 7003312; newNeutralPDG[ 2] = 7003122; + newMotherPDG[ 3] = 7003334; newNeutralPDG[ 3] = 7003322; + newMotherPDG[ 4] = 9000321; newNeutralPDG[ 4] = 9000111; + newMotherPDG[ 5] = 8003334; newNeutralPDG[ 5] = 8003122; + newMotherPDG[ 6] = 8003222; newNeutralPDG[ 6] = 8000111; + + //add neutrinos, if they are not saved + for(int iMC=0; iMC<nMCParticles; iMC++) + { + if( abs(vMCParticles[iMC].GetPDG()) == 211 || abs(vMCParticles[iMC].GetPDG()) == 321 ) + { + int muonIndex = -1; + for(int iD=0; iD<vMCParticles[iMC].NDaughters(); iD++) + if( abs(vMCParticles[vMCParticles[iMC].GetDaughterIds()[iD]].GetPDG()) == 13 ) + muonIndex = vMCParticles[iMC].GetDaughterIds()[iD]; + + if(muonIndex > -1) + { + int newPDG = 0; + if(vMCParticles[iMC].GetPDG() >0) + newPDG = vMCParticles[iMC].GetPDG() + 7000000; + else + newPDG = vMCParticles[iMC].GetPDG() - 7000000; + KFMCParticle motherPart = vMCParticles[iMC]; + KFMCTrack motherTrack = vMCTracks[motherPart.GetMCTrackID()]; + motherTrack.SetPDG(newPDG); + motherTrack.SetNotReconstructed(); + int newMotherIndex = vMCTracks.size(); + motherPart.SetPDG(newPDG); + motherPart.SetMCTrackID(newMotherIndex); + + const KFMCParticle& daughterPart = vMCParticles[muonIndex]; + const KFMCTrack& daughterTrack = vMCTracks[daughterPart.GetMCTrackID()]; + + int neutrinoPDG = 7000014; + if(vMCParticles[iMC].GetPDG() == -211) neutrinoPDG = -7000014; + if(vMCParticles[iMC].GetPDG() == 321) neutrinoPDG = 8000014; + if(vMCParticles[iMC].GetPDG() == -321) neutrinoPDG = -8000014; + + int neutrinoIndex = vMCTracks.size()+1; + vMCParticles[iMC].AddDaughter(neutrinoIndex); + + fNeutralIndex[iMC] = neutrinoIndex; + + KFMCParticle neutrinoPart; + KFMCTrack neutrinoTrack; + neutrinoTrack.SetX(daughterTrack.X()); + neutrinoTrack.SetY(daughterTrack.Y()); + neutrinoTrack.SetZ(daughterTrack.Z()); + neutrinoTrack.SetPx(motherTrack.Px() - daughterTrack.Px()); + neutrinoTrack.SetPy(motherTrack.Py() - daughterTrack.Py()); + neutrinoTrack.SetPz(motherTrack.Pz() - daughterTrack.Pz()); + neutrinoTrack.SetQP(0); + neutrinoTrack.SetMotherId(newMotherIndex); + neutrinoTrack.SetPDG(neutrinoPDG); + + motherPart.CleanDaughters(); + motherPart.AddDaughter(muonIndex); + motherPart.AddDaughter(neutrinoIndex); + motherPart.SetInitialParticleId(iMC); + vMCTracks.push_back(motherTrack); + vMCParticles.push_back(motherPart); + fNeutralIndex.push_back(-1); + + neutrinoPart.SetMCTrackID(neutrinoIndex); + neutrinoPart.SetMotherId(newMotherIndex); + neutrinoPart.SetPDG(neutrinoPDG); + neutrinoPart.AddDaughter(iMC); + neutrinoPart.AddDaughter(muonIndex); + vMCTracks.push_back(neutrinoTrack); + vMCParticles.push_back(neutrinoPart); + fNeutralIndex.push_back(-1); + + vMCParticles[iMC].SetAsReconstructable(4); + vMCParticles[muonIndex].SetAsReconstructable(4); + } + } + // add sigmas, omegas, xis ... + if( vMCParticles[iMC].NDaughters() >= 2 && + (abs(vMCParticles[iMC].GetPDG()) == 3112 || + abs(vMCParticles[iMC].GetPDG()) == 3222 || + abs(vMCParticles[iMC].GetPDG()) == 3312 || + abs(vMCParticles[iMC].GetPDG()) == 3334 || + abs(vMCParticles[iMC].GetPDG()) == 321) ) + { + int neutralDaughterId = -1, chargedDaughterId = -1; + + int newPDG = 0; + int neutralPDG = 0; + + for(int iPDG=0; iPDG<NmmPDG; iPDG++) + { + if(abs(vMCParticles[iMC].GetPDG()) == mmMotherPDG[iPDG]) + { + bool isDaughter[2] = {0,0}; + + vector<float> xDaughter; + vector<float> yDaughter; + vector<float> zDaughter; + vector< vector<int> > nDaughtersAtPoint; + + for(int iMCDaughter=0; iMCDaughter<vMCParticles[iMC].NDaughters(); iMCDaughter++) + { + bool isNewDecayPoint = 1; + + for(unsigned int iPoint=0; iPoint<xDaughter.size(); iPoint++) + { + float dx = fabs(vMCTracks[vMCParticles[iMC].GetDaughterIds()[iMCDaughter]].X() - xDaughter[iPoint]); + float dy = fabs(vMCTracks[vMCParticles[iMC].GetDaughterIds()[iMCDaughter]].Y() - yDaughter[iPoint]); + float dz = fabs(vMCTracks[vMCParticles[iMC].GetDaughterIds()[iMCDaughter]].Z() - zDaughter[iPoint]); + + bool isSamePoint = (dx < 1.e-5 && dy < 1.e-5 && dz < 1.e-5); + if(isSamePoint) + nDaughtersAtPoint[iPoint].push_back(iMCDaughter); + + isNewDecayPoint &= !isSamePoint; + } + + if(isNewDecayPoint) + { + xDaughter.push_back(vMCTracks[vMCParticles[iMC].GetDaughterIds()[iMCDaughter]].X()); + yDaughter.push_back(vMCTracks[vMCParticles[iMC].GetDaughterIds()[iMCDaughter]].Y()); + zDaughter.push_back(vMCTracks[vMCParticles[iMC].GetDaughterIds()[iMCDaughter]].Z()); + vector<int> newPointIndex; + newPointIndex.push_back(iMCDaughter); + nDaughtersAtPoint.push_back(newPointIndex); + } + } + + for(unsigned int iPoint = 0; iPoint<nDaughtersAtPoint.size(); iPoint++) + { + if(nDaughtersAtPoint[iPoint].size() == 2) + { + for(unsigned int iDaughter=0; iDaughter<nDaughtersAtPoint[iPoint].size(); iDaughter++) + { + int iMCDaughter = nDaughtersAtPoint[iPoint][iDaughter]; + if(abs(vMCParticles[vMCParticles[iMC].GetDaughterIds()[iMCDaughter]].GetPDG()) == mmChargedDaughterPDG[iPDG]) + { + isDaughter[0] = 1; + chargedDaughterId = vMCParticles[iMC].GetDaughterIds()[iMCDaughter]; + } + if(abs(vMCParticles[vMCParticles[iMC].GetDaughterIds()[iMCDaughter]].GetPDG()) == mmNeutralDaughterPDG[iPDG]) + { + isDaughter[1] = 1; + neutralDaughterId = vMCParticles[iMC].GetDaughterIds()[iMCDaughter]; + } + } + + if(isDaughter[0] && isDaughter[1]) + { + int signPDG = vMCParticles[iMC].GetPDG()/abs(vMCParticles[iMC].GetPDG()); + newPDG = signPDG * newMotherPDG[iPDG]; + neutralPDG = signPDG * newNeutralPDG[iPDG]; + } + } + } + } + } + + if(newPDG != 0) + { + KFMCParticle motherPart = vMCParticles[iMC]; + KFMCTrack motherTrack = vMCTracks[motherPart.GetMCTrackID()]; + motherTrack.SetPDG(newPDG); + motherTrack.SetNotReconstructed(); + int newMotherIndex = vMCTracks.size(); + motherPart.SetPDG(newPDG); + motherPart.SetMCTrackID(newMotherIndex); + + int neutrinoIndex = vMCTracks.size()+1; + fNeutralIndex[iMC] = neutrinoIndex; + + KFMCTrack neutralTrack = vMCTracks[neutralDaughterId]; + neutralTrack.SetMotherId(newMotherIndex); + neutralTrack.SetPDG(neutralPDG); + + motherPart.CleanDaughters(); + motherPart.AddDaughter(chargedDaughterId); + motherPart.AddDaughter(neutrinoIndex); + motherPart.SetInitialParticleId(iMC); + vMCTracks.push_back(motherTrack); + vMCParticles.push_back(motherPart); + fNeutralIndex.push_back(-1); + + KFMCParticle neutralPart; + neutralPart.SetMCTrackID(neutrinoIndex); + neutralPart.SetMotherId(newMotherIndex); + neutralPart.SetPDG(neutralPDG); + neutralPart.AddDaughter(iMC); + neutralPart.AddDaughter(chargedDaughterId); + vMCTracks.push_back(neutralTrack); + vMCParticles.push_back(neutralPart); + fNeutralIndex.push_back(-1); + + vMCParticles[iMC].SetAsReconstructable(4); + vMCParticles[chargedDaughterId].SetAsReconstructable(4); + } + } + } + + //clean Lambda c daughters + for(unsigned int iMC=0; iMC < vMCParticles.size(); iMC++) + { + KFMCParticle &part = vMCParticles[iMC]; + +// if(abs(part.GetPDG()) == 4122) + { + //add daughters into one pool + vector<int> newDaughters; + for(unsigned int iD=0; iD<part.GetDaughterIds().size(); iD++) + { + KFMCParticle &d = vMCParticles[part.GetDaughterIds()[iD]]; + if( abs(d.GetPDG())==3224 || + abs(d.GetPDG())==3114 || + abs(d.GetPDG())==113 || + abs(d.GetPDG())==313 || + abs(d.GetPDG())==323 || + abs(d.GetPDG())==2224 || + abs(d.GetPDG())==2214 || + abs(d.GetPDG())==2114 || + abs(d.GetPDG())==1114 + ) + { + for(unsigned int iDaughter=0; iDaughter<d.GetDaughterIds().size(); iDaughter++) + { + newDaughters.push_back(d.GetDaughterIds()[iDaughter]); + vMCParticles[d.GetDaughterIds()[iDaughter]].SetMotherId(iMC); + } + } + else +// if(d.GetDaughterIds().size() == 0 || abs(d.GetPDG())==310 || abs(d.GetPDG())==3122) + newDaughters.push_back(part.GetDaughterIds()[iD]); + } + part.CleanDaughters(); + for(unsigned int iDaughter=0; iDaughter<newDaughters.size(); iDaughter++) + part.AddDaughter(newDaughters[iDaughter]); + + //change PDG to separate channels + int indexPDG = fParteff.GetParticleIndex(part.GetPDG()); + for(int iPDG=indexPDG; iPDG<indexPDG+10; iPDG++) + { + const int nDaughters = part.GetDaughterIds().size(); + + if(int(fParteff.partDaughterPdg[iPDG].size()) != nDaughters) + continue; + + vector<bool> isDaughterFound(nDaughters); + vector<bool> isDaughterUsed(nDaughters); + for(int iDMC=0; iDMC<nDaughters; iDMC++) + { + isDaughterFound[iDMC] = 0; + isDaughterUsed[iDMC] = 0; + } + + bool isCorrectPDG = 1; + for(int iDMC=0; iDMC<nDaughters; iDMC++) + for(int iD=0; iD<nDaughters; iD++) + { + if(isDaughterUsed[iD]) continue; + if(vMCParticles[part.GetDaughterIds()[iD]].GetPDG() == fParteff.partDaughterPdg[iPDG][iDMC]) + { + isDaughterUsed[iD] = 1; + isDaughterFound[iDMC] = 1; + break; + } + } + + for(int iDMC=0; iDMC<nDaughters; iDMC++) + isCorrectPDG &= isDaughterFound[iDMC]; + + if(isCorrectPDG) + { + part.SetPDG(fParteff.partPDG[iPDG]); + break; + } + } + } + } +} + +void KFTopoPerformance::FindReconstructableMCParticles() +{ + /** Check each Monte Carlo particle if it can be reconstructed. */ + const unsigned int nMCParticles = vMCParticles.size(); + + for ( unsigned int iP = 0; iP < nMCParticles; iP++ ) { + KFMCParticle &part = vMCParticles[iP]; + CheckMCParticleIsReconstructable(part); + } +} + +void KFTopoPerformance::CheckMCParticleIsReconstructable(KFMCParticle &part) +{ + /** Checks if the given Monte Carlo particle can be reconstructed. */ + if ( part.IsReconstructable(0) ) return; + if ( vMCTracks[part.GetMCTrackID()].IsOutOfDetector() ) return; + + if( abs(part.GetPDG()) == 211 || + abs(part.GetPDG()) == 2212 || + abs(part.GetPDG()) == 321 || + abs(part.GetPDG()) == 13 || + abs(part.GetPDG()) == 3112 || + abs(part.GetPDG()) == 3222 || + abs(part.GetPDG()) == 3312 || + abs(part.GetPDG()) == 3334 ) + { + int iMCTrack = part.GetMCTrackID(); + KFMCTrack &mcTrack = vMCTracks[iMCTrack]; + + // reconstructable in 4pi is defined in GetMCParticles, when decay is found + if(mcTrack.IsReconstructed()) + part.SetAsReconstructable(3); + } + // tracks + if ( abs(part.GetPDG()) == 211 || + abs(part.GetPDG()) == 2212 || + abs(part.GetPDG()) == 321 || + abs(part.GetPDG()) == 11 || + abs(part.GetPDG()) == 13 || + abs(part.GetPDG()) == 1000010020 || + abs(part.GetPDG()) == 1000010030 || + abs(part.GetPDG()) == 1000020030 || + abs(part.GetPDG()) == 1000020040 || + ( (part.GetPDG() == 22) && (vMCTracks[part.GetMCTrackID()].IsReconstructed()) ) ) + { + int iMCTrack = part.GetMCTrackID(); + KFMCTrack &mcTrack = vMCTracks[iMCTrack]; + + part.SetAsReconstructable(0); + + if(mcTrack.NMCPoints() >= 15) + part.SetAsReconstructable(1); +// if(mc.IsReconstructable()) +// part.SetAsReconstructable2(); + + if(mcTrack.IsReconstructed()) + part.SetAsReconstructable(2); + } + // mother particles + else + { + //Check if the particle is V0 + + if(part.NDaughters() >= 2) + { + bool isPositiveDaughter[5] = {0,0,0,0,0}; + bool isNegativeDaughter[5] = {0,0,0,0,0}; + + int nRecoDaughters[5] = {0,0,0,0,0}; + + for(int iD=0; iD < part.NDaughters(); iD++) + { + KFMCParticle &daughter = vMCParticles[part.GetDaughterIds()[iD]]; + CheckMCParticleIsReconstructable(daughter); + + TParticlePDG* particlePDG = TDatabasePDG::Instance()->GetParticle(daughter.GetPDG()); + Double_t charge = (particlePDG) ? particlePDG->Charge()/3 : 0; + + for(int iEff=0; iEff<5; iEff++) + { + if(charge > 0) + isPositiveDaughter[iEff] |= daughter.IsReconstructable(iEff); + else + isNegativeDaughter[iEff] |= daughter.IsReconstructable(iEff); + + if(daughter.IsReconstructable(iEff)) + nRecoDaughters[iEff]++; + } + } + +// for(int iEff=0; iEff<3; iEff++) +// if(isPositiveDaughter[iEff] && isNegativeDaughter[iEff]) +// part.SetAsReconstructableV0(iEff); + for(int iEff=0; iEff<3; iEff++) + if(nRecoDaughters[iEff] > 1) + part.SetAsReconstructableV0(iEff); + } + + for(int iPart=0; iPart<fParteff.nParticles; iPart++) + { + if(part.GetPDG() == fParteff.partPDG[iPart]) + { + const unsigned int nDaughters = fParteff.partDaughterPdg[iPart].size(); + if( part.GetDaughterIds().size() != nDaughters ) return; + vector<int> pdg(nDaughters); + + for(unsigned int iD=0; iD<nDaughters; iD++) + pdg[iD] = vMCParticles[part.GetDaughterIds()[iD]].GetPDG(); + + vector<bool> isDaughterFound(nDaughters); + for(unsigned int iDMC=0; iDMC<nDaughters; iDMC++) + isDaughterFound[iDMC] = 0; + + bool isReco = 1; + for(unsigned int iDMC=0; iDMC<nDaughters; iDMC++) + for(unsigned int iD=0; iD<nDaughters; iD++) + if(pdg[iD] == fParteff.partDaughterPdg[iPart][iDMC]) isDaughterFound[iDMC] = 1; + + for(unsigned int iDMC=0; iDMC<nDaughters; iDMC++) + isReco = isReco && isDaughterFound[iDMC]; + + if(!isReco) return; + } + } + + const vector<int>& dIds = part.GetDaughterIds(); + const unsigned int nD = dIds.size(); + if(nD == 0) return; //TODO optimize for all species + + bool reco1 = 1; + bool reco2 = 1; + bool reco3 = 1; + bool reco4 = 1; + bool reco5 = 1; + + for ( unsigned int iD = 0; iD < nD && (reco1 || reco2 || reco3 || reco4 || reco5); iD++ ) { + KFMCParticle &dp = vMCParticles[dIds[iD]]; + CheckMCParticleIsReconstructable(dp); + reco1 &= dp.IsReconstructable(0); + reco2 &= dp.IsReconstructable(1); + reco3 &= dp.IsReconstructable(2); + reco4 &= dp.IsReconstructable(3); + reco5 &= dp.IsReconstructable(4); + } + + if (reco1) part.SetAsReconstructable(0); + if (reco2) part.SetAsReconstructable(1); + if (reco3) part.SetAsReconstructable(2); + int iParticle = fParteff.GetParticleIndex(part.GetPDG()); + if (reco4 && iParticle>=KFPartEfficiencies::fFirstMissingMassParticleIndex && + iParticle<=KFPartEfficiencies::fLastMissingMassParticleIndex ) part.SetAsReconstructable(3); + if (reco5 && iParticle>=KFPartEfficiencies::fFirstMissingMassParticleIndex && + iParticle<=KFPartEfficiencies::fLastMissingMassParticleIndex ) part.SetAsReconstructable(4); + } +} + + +void KFTopoPerformance::FindReconstructableMCVertices() +{ + /** Checks which Monte Carlo primary vertices can be reconstructed. */ + const unsigned int nMCVertices = fPrimVertices.size(); + + for ( unsigned int iV = 0; iV < nMCVertices; iV++ ) { + KFMCVertex &vert = fPrimVertices[iV]; + + int nReconstructableDaughters = 0; + int nMCReconstructableDaughters = 0; + + for(int iP=0; iP<vert.NDaughterTracks(); iP++) + { + int idDaughter = vert.DaughterTrack(iP); + KFMCParticle &part = vMCParticles[idDaughter]; + + if(part.IsReconstructable(2)) nReconstructableDaughters++; + if(part.IsReconstructable(1)) nMCReconstructableDaughters++; + } + + if(nReconstructableDaughters >= 2) vert.SetReconstructable(); + else vert.SetUnReconstructable(); + + if(nMCReconstructableDaughters >= 2) vert.SetMCReconstructable(); + else vert.SetMCUnReconstructable(); + } +} + +void KFTopoPerformance::MatchParticles() +{ + /** Matches Monte Carlo and reconstructed particles. */ + MCtoRParticleId.clear(); + RtoMCParticleId.clear(); + MCtoRParticleId.resize(vMCParticles.size()); + RtoMCParticleId.resize(fTopoReconstructor->GetParticles().size() ); + + // match tracks ( particles which are direct copies of tracks ) + for( unsigned int iRP = 0; iRP < fTopoReconstructor->GetParticles().size(); iRP++ ) + { + const KFParticle &rPart = fTopoReconstructor->GetParticles()[iRP]; + + if (rPart.NDaughters() != 1) continue; + + const int rTrackId = rPart.DaughterIds()[0]; + const int mcTrackId = fTrackMatch[rTrackId]; + + if(mcTrackId < 0) continue; + + KFMCParticle &mPart = vMCParticles[mcTrackId]; + if( mPart.GetPDG() == rPart.GetPDG() ) + { + MCtoRParticleId[mcTrackId].ids.push_back(iRP); + RtoMCParticleId[iRP].ids.push_back(mcTrackId); + } + else { + MCtoRParticleId[mcTrackId].idsMI.push_back(iRP); + RtoMCParticleId[iRP].idsMI.push_back(mcTrackId); + } + } + + // match created mother particles + for( unsigned int iRP = 0; iRP < fTopoReconstructor->GetParticles().size(); iRP++ ) { + const KFParticle &rPart = fTopoReconstructor->GetParticles()[iRP]; + const unsigned int NRDaughters = rPart.NDaughters(); + + if (NRDaughters < 2) continue; + + bool isMissingMass = ((abs(rPart.GetPDG()) == 7000211)||(abs(rPart.GetPDG()) == 7000321)||(abs(rPart.GetPDG()) == 7003112) || (abs(rPart.GetPDG()) == 7003222)|| (abs(rPart.GetPDG()) == 7003312)|| (abs(rPart.GetPDG()) == 7003334)|| (abs(rPart.GetPDG()) == 9000321)|| (abs(rPart.GetPDG()) == 8003334)||(abs(rPart.GetPDG()) == 8003222)); + + //missing mass method + if ( (abs(rPart.GetPDG()) == 7000014 ) || (abs(rPart.GetPDG()) == 8000014 ) || (abs(rPart.GetPDG()) == 7002112 ) || + (abs(rPart.GetPDG()) == 8002112 ) || (abs(rPart.GetPDG()) == 7003122 ) || (abs(rPart.GetPDG()) == 7003322 ) || + (abs(rPart.GetPDG()) == 9000111 ) || (abs(rPart.GetPDG()) == 8003122 ) || (abs(rPart.GetPDG()) == 8000111 ) ) + { + //During the reconstruction 1st daughter - mother particle, 2nd daughter - charged daughter + + int mcNeutralDaughterId = -1; + const int recoMotherId = rPart.DaughterIds()[0]; + if ( !RtoMCParticleId[recoMotherId].IsMatched() ) continue; + + const int mcMotherId = RtoMCParticleId[recoMotherId].GetBestMatch(); + + const int recoChargedDaughterId = rPart.DaughterIds()[1]; + if ( !RtoMCParticleId[recoChargedDaughterId].IsMatched() ) continue; + + const int mcChargedDaughterId = RtoMCParticleId[recoChargedDaughterId].GetBestMatch(); + const KFMCParticle& chargedDaughter = vMCParticles[mcChargedDaughterId]; + + if(chargedDaughter.GetMotherId() != mcMotherId) continue; + const KFMCParticle& mother = vMCParticles[mcMotherId]; + + if(fNeutralIndex[mcMotherId] > -1) + mcNeutralDaughterId = fNeutralIndex[mcMotherId]; + + if(mcNeutralDaughterId > -1) + { + KFMCParticle &neutralDaughter = vMCParticles[mcNeutralDaughterId]; + + int iParticle = fParteff.GetParticleIndex(rPart.GetPDG()); + + bool allCorrectDaughters = mother.GetPDG() == fParteff.partDaughterPdg[iParticle][0] && + chargedDaughter.GetPDG() == fParteff.partDaughterPdg[iParticle][1]; + + if( neutralDaughter.GetPDG() == rPart.GetPDG() && + neutralDaughter.NDaughters() == rPart.NDaughters() && + allCorrectDaughters) { + MCtoRParticleId[mcNeutralDaughterId].ids.push_back(iRP); + RtoMCParticleId[iRP].ids.push_back(mcNeutralDaughterId); + } + else { + MCtoRParticleId[mcNeutralDaughterId].idsMI.push_back(iRP); + RtoMCParticleId[iRP].idsMI.push_back(mcNeutralDaughterId); + } + } + } + + + + //normal decays + else + { + unsigned int iD = 0; + vector<int> mcDaughterIds; + int mmId = -2; // MC id for rPart + { + const int rdId = rPart.DaughterIds()[iD]; + if ( !RtoMCParticleId[rdId].IsMatched() ) continue; + const int mdId = RtoMCParticleId[rdId].GetBestMatch(); + mcDaughterIds.push_back(mdId); + mmId = vMCParticles[mdId].GetMotherId(); + } + + iD++; + for ( ; iD < NRDaughters; iD++ ) { + const int rdId = rPart.DaughterIds()[iD]; + if ( !RtoMCParticleId[rdId].IsMatched() ) break; + const int mdId = RtoMCParticleId[rdId].GetBestMatch(); + mcDaughterIds.push_back(mdId); + + if(isMissingMass) + { + const KFMCParticle &neutralDaughter = vMCParticles[mdId]; + if(mmId != vMCParticles[neutralDaughter.GetMotherId()].InitialParticleId()) break; + mmId = neutralDaughter.GetMotherId(); + } + + if( !(isMissingMass) && (vMCParticles[mdId].GetMotherId() != mmId) ) break; + } + + int nClones = 0; + sort(mcDaughterIds.begin(), mcDaughterIds.end()); + for(unsigned int ie=1; ie<mcDaughterIds.size(); ie++) + { + if(mcDaughterIds[ie] == mcDaughterIds[ie-1]) + nClones++; + } + + if(nClones > 0) continue; + + if ( iD == NRDaughters && mmId > -1 ) { // match is found and it is not primary vertex + KFMCParticle &mmPart = vMCParticles[mmId]; + + if( mmPart.GetPDG() == rPart.GetPDG() && + mmPart.NDaughters() == rPart.NDaughters() ) { + MCtoRParticleId[mmId].ids.push_back(iRP); + RtoMCParticleId[iRP].ids.push_back(mmId); + } + else { + MCtoRParticleId[mmId].idsMI.push_back(iRP); + RtoMCParticleId[iRP].idsMI.push_back(mmId); + } + } + } + } +} + +void KFTopoPerformance::MatchPV() +{ + /** Matches Monte Carlo and reconstructed primary vertices. */ + MCtoRPVId.clear(); + RtoMCPVId.clear(); + MCtoRPVId.resize(fPrimVertices.size()); + RtoMCPVId.resize(fTopoReconstructor->NPrimaryVertices() ); + + fPVPurity.clear(); + fPVPurity.resize(fTopoReconstructor->NPrimaryVertices(), 0.); + fNCorrectPVTracks.clear(); + fNCorrectPVTracks.resize(fTopoReconstructor->NPrimaryVertices(), 0); + + for(int iE = 0; iE<4; iE++) + { + fPVTracksRate[iE].clear(); + fPVTracksRate[iE].resize(fTopoReconstructor->NPrimaryVertices(),0); + } + + for( unsigned int iMCPV=0; iMCPV<fPrimVertices.size(); iMCPV++) + { + KFMCVertex &mcPV = fPrimVertices[iMCPV]; + int nReconstructedDaughters = 0; + for(int iD=0; iD<mcPV.NDaughterTracks(); iD++) + if(MCtoRParticleId[ mcPV.DaughterTrack(iD) ].IsMatched()) + nReconstructedDaughters++; + + mcPV.SetNReconstructedDaughters(nReconstructedDaughters); + } + + for( int iPV = 0; iPV < fTopoReconstructor->NPrimaryVertices(); iPV++ ) { + + vector<int> &tracks = fTopoReconstructor->GetPVTrackIndexArray(iPV); + + int nPVTracks = tracks.size()>0 ? tracks.size() : -1;//tracks.size(); + + vector<short int> nTracksFromMCPV(fPrimVertices.size() + vMCParticles.size(), 0); + vector< vector<int> > mcIDs(fPrimVertices.size() + vMCParticles.size()); + + int nGhostTracks = 0; + int nTriggerTracks = 0; + int nPileupTracks = 0; + int nBGTracks = 0; + + for(int iRP=0; iRP < nPVTracks; iRP++) + { + const int rTrackId = tracks[iRP]; + if ( !RtoMCParticleId[rTrackId].IsMatched() ) + { + nGhostTracks++; + continue; + } + + int iMCPart = RtoMCParticleId[rTrackId].GetBestMatch(); + KFMCParticle &mcPart = vMCParticles[iMCPart]; + int iMCTrack = mcPart.GetMCTrackID(); + KFMCTrack &mcTrack = vMCTracks[iMCTrack]; + + int motherId = mcTrack.MotherId(); + + if(motherId < 0) //real PV + { + if(motherId == -1) + nTriggerTracks++; + if(motherId < -1) + nPileupTracks++; + + int iMCPV = fMCTrackToMCPVMatch[iMCTrack]; + if(iMCPV < 0) + { + std::cout << "Error!!! iMCPV < 0" << std::endl; + continue; + } + + nTracksFromMCPV[iMCPV]++; + mcIDs[iMCPV].push_back(iMCTrack); + } + else // pchysics background + { + if(motherId >-1) + { + nBGTracks++; + + int iMCPV = motherId + fPrimVertices.size(); + + nTracksFromMCPV[iMCPV]++; + mcIDs[iMCPV].push_back(iMCTrack); + } + } + } + + + + for(unsigned int iMCPV=0; iMCPV<nTracksFromMCPV.size(); iMCPV++) + { + int nClones = 0; + sort(mcIDs[iMCPV].begin(), mcIDs[iMCPV].end()); + for(unsigned int ie=1; ie<mcIDs[iMCPV].size(); ie++) + { + if(mcIDs[iMCPV][ie] == mcIDs[iMCPV][ie-1]) + nClones++; + } + nTracksFromMCPV[iMCPV] = nTracksFromMCPV[iMCPV] - nClones; + nPVTracks -= nClones; + } + + // calculate rate of each type of tracks in reconstructed PV + fPVTracksRate[0][iPV] = double(nGhostTracks)/double(nPVTracks); + fPVTracksRate[1][iPV] = double(nTriggerTracks)/double(nPVTracks); + fPVTracksRate[2][iPV] = double(nPileupTracks)/double(nPVTracks); + fPVTracksRate[3][iPV] = double(nBGTracks)/double(nPVTracks); + + int iBestMCPV=-1; + int nTracksBestMCPV = 1; + for(unsigned int iMCPV=0; iMCPV<nTracksFromMCPV.size(); iMCPV++ ) + { + if(nTracksFromMCPV[iMCPV] > nTracksBestMCPV ) + { + nTracksBestMCPV = nTracksFromMCPV[iMCPV]; + iBestMCPV = iMCPV; + } + } + + if( (iBestMCPV > -1) && (iBestMCPV<int(fPrimVertices.size())) ) + { + fNCorrectPVTracks[iPV] = nTracksFromMCPV[iBestMCPV]; + } + else + fNCorrectPVTracks[iPV] = 0; + + double purity = double(nTracksBestMCPV)/double(nPVTracks); + + fPVPurity[iPV] = purity; +// if(purity < 0.7) continue; + + if(iBestMCPV < 0) continue; + + if(iBestMCPV < int(fPrimVertices.size())) + { + fPrimVertices[iBestMCPV].SetReconstructed(); + + MCtoRPVId[iBestMCPV].ids.push_back(iPV); + RtoMCPVId[iPV].ids.push_back(iBestMCPV); + } + else + { + RtoMCPVId[iPV].idsMI.push_back(iBestMCPV); + } + } +} + +void KFTopoPerformance::MatchTracks() +{ + /** Runs reading of Monte Carlo particles and vertices, their matching, calculation of efficiency. */ +#ifdef KFPWITHTRACKER + for(int iTr=0; iTr<vMCTracks.size(); iTr++) + { + if( (AliHLTTPCCAPerformance::Instance().GetSubPerformance("Global Performance")->GetMCData())[iTr].IsReconstructed() ) + vMCTracks[iTr].SetReconstructed(); + } + fTrackMatch.resize(AliHLTTPCCAPerformance::Instance().GetSubPerformance("Global Performance")->GetRecoData().size()); + for(int iTr=0; iTr<fTrackMatch.size(); iTr++) + { + const AliHLTTPCCAPerformanceRecoTrackData& matchInfo = (AliHLTTPCCAPerformance::Instance().GetSubPerformance("Global Performance")->GetRecoData())[iTr]; + if( matchInfo.IsGhost(PParameters::MinTrackPurity) || matchInfo.GetMCTrackId()<0 ) + fTrackMatch[iTr] = -1; + else + fTrackMatch[iTr] = matchInfo.GetMCTrackId(); + } +#endif + + GetMCParticles(); + FindReconstructableMCParticles(); + MatchParticles(); + CalculateEfficiency(); + + FindReconstructableMCVertices(); + MatchPV(); + CalculatePVEfficiency(); +} // void KFTopoPerformance::MatchTracks() + +void KFTopoPerformance::CalculateEfficiency() +{ + /** Calculates reconstruction efficiency of short-lived particles. */ + KFPartEfficiencies partEff; // efficiencies for current event + + const int NRP = fTopoReconstructor->GetParticles().size(); + for ( int iP = 0; iP < NRP; ++iP ) { +// const CbmKFParticle &part = fPF->GetParticles()[iP]; + const KFParticle &part = fTopoReconstructor->GetParticles()[iP]; + const int pdg = part.GetPDG(); + + const bool isBG = RtoMCParticleId[iP].idsMI.size() != 0; + const bool isGhost = !RtoMCParticleId[iP].IsMatched(); + + for(int iPart=0; iPart<fParteff.nParticles; iPart++) + if ( pdg == fParteff.partPDG[iPart] ) + partEff.IncReco(isGhost, isBG, fParteff.partName[iPart].data()); + + // Calculate the gost level for V0 + if(abs(pdg) == 310 /*|| + CAMath::Abs(pdg) == 3122 || + CAMath::Abs(pdg) == 421 || + CAMath::Abs(pdg) == 22 */) + { + partEff.IncReco(isGhost, 0, fParteff.partName[fParteff.nParticles - 1].data()); + } + } + + const int NMP = vMCParticles.size(); + for ( int iP = 0; iP < NMP; ++iP ) { + const KFMCParticle &part = vMCParticles[iP]; + const int pdg = part.GetPDG(); + const int mId = part.GetMotherId(); + + vector<bool> isReco; + vector<int> nClones; + + vector<int> iParticle; + iParticle.push_back(fParteff.GetParticleIndex(pdg)); + vector< vector<bool> > isReconstructable; + vector<bool> isRecPart; + + const std::map<int,bool>& decays = fTopoReconstructor->GetKFParticleFinder()->GetReconstructionList(); + if(!(decays.empty()) && (iParticle[0] < fParteff.fFirstStableParticleIndex || iParticle[0] > fParteff.fLastStableParticleIndex)) + if(decays.find(pdg) == decays.end()) continue; + + if( fParteff.GetParticleIndex(pdg)>=KFPartEfficiencies::fFirstMissingMassParticleIndex && + fParteff.GetParticleIndex(pdg)<=KFPartEfficiencies::fLastMissingMassParticleIndex ) + { + isRecPart.push_back(part.IsReconstructable(4)); + isRecPart.push_back(part.IsReconstructable(1)); + isRecPart.push_back(part.IsReconstructable(3)); + } + else + for(int iEff = 0; iEff < 3; iEff++) + isRecPart.push_back(part.IsReconstructable(iEff)); + + isReconstructable.push_back(isRecPart); + isReco.push_back( MCtoRParticleId[iP].ids.size() != 0 ); + nClones.push_back( MCtoRParticleId[iP].ids.size() - 1 ); + + if(decays.empty() && (part.IsReconstructableV0(0) || part.IsReconstructableV0(1) || part.IsReconstructableV0(2)) ) + { + iParticle.push_back(fParteff.nParticles - 1); + vector<bool> isRecV0; + for(int iEff = 0; iEff < 3; iEff++) + isRecV0.push_back(part.IsReconstructableV0(iEff)); + isReconstructable.push_back(isRecV0); + isReco.push_back( (MCtoRParticleId[iP].ids.size() != 0) || (MCtoRParticleId[iP].idsMI.size() != 0) ); + + int nClonesV0 = MCtoRParticleId[iP].ids.size() + MCtoRParticleId[iP].idsMI.size() - 1; + nClones.push_back( nClonesV0 ); + } + + { + for(unsigned int iPType=0; iPType<iParticle.size(); iPType++) + { + int iPart = iParticle[iPType]; + if(iPart<0) continue; + + partEff.Inc(isReco[iPType], nClones[iPType], isReconstructable[iPType][0], isReconstructable[iPType][1], isReconstructable[iPType][2], fParteff.partName[iPart].data()); + if ( mId == -1 ) + partEff.Inc(isReco[iPType], nClones[iPType], isReconstructable[iPType][0], isReconstructable[iPType][1], isReconstructable[iPType][2], (fParteff.partName[iPart]+"_prim").data()); + else + partEff.Inc(isReco[iPType], nClones[iPType], isReconstructable[iPType][0], isReconstructable[iPType][1], isReconstructable[iPType][2], (fParteff.partName[iPart]+"_sec").data()); + + for(int iEff=0; iEff<3; iEff++) + { + if(!isReconstructable[iPType][iEff]) continue; + + int iMCTrack = part.GetMCTrackID(); + KFMCTrack &mcTrack = vMCTracks[iMCTrack]; + + Double_t massMC = fParteff.partMass[iPart]; + Double_t E = sqrt(mcTrack.P()*mcTrack.P() + massMC*massMC); + Double_t Y = 0.5*log((E + mcTrack.Pz())/(E - mcTrack.Pz())); + Double_t Z = mcTrack.Z(); + Double_t R = -1, L=-1; + Double_t Mt_mc = sqrt(mcTrack.Pt()*mcTrack.Pt()+massMC*massMC)-massMC; + Double_t cT = -1.e10; + Double_t decayLength = -1.e10; + + if(part.NDaughters() > 0) + { + int mcDaughterId = part.GetDaughterIds()[0]; + KFMCTrack &mcDaughter = vMCTracks[mcDaughterId]; + R = sqrt(mcDaughter.X()*mcDaughter.X() + mcDaughter.Y()*mcDaughter.Y()); + L = sqrt(mcDaughter.X()*mcDaughter.X() + mcDaughter.Y()*mcDaughter.Y()); + Z = mcDaughter.Z(); + + if(mcTrack.MotherId() < 0) + { + KFParticle motherKFParticle; + float decayPoint[3] = { mcDaughter.X(), mcDaughter.Y(), mcDaughter.Z() }; + for(int iP=0; iP<6; iP++) + motherKFParticle.Parameter(iP) = mcTrack.Par()[iP]; + + float dsdr[6]; + double s = motherKFParticle.GetDStoPoint(decayPoint, dsdr); + int jParticlePDG = fParteff.GetParticleIndex(mcTrack.PDG()); + Double_t massMC = (jParticlePDG>=0) ? fParteff.partMass[jParticlePDG] :0.13957; + + cT = s*massMC; + decayLength = s*mcTrack.P(); + } + } + + if(fStoreMCHistograms) + { + hPartEfficiency[iPart][iEff][0]->Fill( mcTrack.P(), isReco[iPType] ); + hPartEfficiency[iPart][iEff][1]->Fill( mcTrack.Pt(), isReco[iPType] ); + hPartEfficiency[iPart][iEff][2]->Fill( Y, isReco[iPType] ); + hPartEfficiency[iPart][iEff][3]->Fill( Z, isReco[iPType] ); + if(cT > -1.e10) hPartEfficiency[iPart][iEff][4]->Fill( cT, isReco[iPType] ); + if(decayLength > -1.e10) hPartEfficiency[iPart][iEff][5]->Fill( decayLength, isReco[iPType] ); + hPartEfficiency[iPart][iEff][3]->Fill( Z, isReco[iPType] ); + hPartEfficiency[iPart][iEff][6]->Fill( L, isReco[iPType] ); + hPartEfficiency[iPart][iEff][7]->Fill( R, isReco[iPType] ); + hPartEfficiency[iPart][iEff][8]->Fill( Mt_mc, isReco[iPType] ); + + hPartEfficiency2D[iPart][iEff][0]->Fill( Y, mcTrack.Pt(), isReco[iPType] ); + hPartEfficiency2D[iPart][iEff][1]->Fill( Y, Mt_mc, isReco[iPType] ); + } + } + } + } + } + + fNEvents++; + + fParteff += partEff; + + partEff.CalcEff(); + fParteff.CalcEff(); + + if(fNEvents%fPrintEffFrequency == 0) + { + std::cout << " ---- KF Particle finder --- " << std::endl; + std::cout << "ACCUMULATED STAT : " << fNEvents << " EVENTS " << std::endl << std::endl; + fParteff.PrintEff(); + std::cout<<std::endl; + } +} + +void KFTopoPerformance::CalculatePVEfficiency() +{ + /** Calculates reconstruction efficiency of primary vertices. */ + KFPVEfficiencies pvEff; // efficiencies for current event + KFPVEfficiencies pvEffMCReconstructable; + int nTracks = 0; + //calculate N reco tracks + for( unsigned int iRP = 0; iRP < fTopoReconstructor->GetParticles().size(); iRP++ ) { +// CbmKFParticle &rPart = fTopoReconstructor->GetParticles()[iRP]; + const KFParticle &rPart = fTopoReconstructor->GetParticles()[iRP]; + + if (rPart.NDaughters() != 1) continue; + + nTracks++; + } + + const int NRecoPV = fTopoReconstructor->NPrimaryVertices(); + for ( int iP = 0; iP < NRecoPV; ++iP ) { + + const bool isBG = RtoMCPVId[iP].idsMI.size() != 0; + const bool isGhost = !RtoMCPVId[iP].IsMatched(); + + pvEff.IncReco(isGhost, isBG, "PV"); + pvEffMCReconstructable.IncReco(isGhost, isBG, "PV"); + } + + const int NMCPV = fPrimVertices.size(); + for ( int iV = 0; iV < NMCPV; ++iV ) { + const KFMCVertex &pvMC = fPrimVertices[iV]; + if ( pvMC.IsReconstructable() ) + { + const bool isReco = pvMC.IsReconstructed(); + const int nClones = MCtoRPVId[iV].ids.size() - 1; + + + pvEff.Inc(isReco, nClones, "PV"); + if ( pvMC.IsTriggerPV() ) + { + pvEff.Inc(isReco, nClones, "PVtrigger"); + hPVefficiency[0][0]->Fill( pvMC.NDaughterTracks(), isReco ); + hPVefficiency[0][1]->Fill( NMCPV, isReco ); + hPVefficiency[0][2]->Fill( vMCTracks.size(), isReco ); + hPVefficiency[0][3]->Fill( pvMC.NReconstructedDaughterTracks(), isReco ); + hPVefficiency[0][4]->Fill( NRecoPV, isReco ); + hPVefficiency[0][5]->Fill( nTracks, isReco ); + } + else + { + pvEff.Inc(isReco, nClones, "PVpileup"); + hPVefficiency[1][0]->Fill( pvMC.NDaughterTracks(), isReco ); + hPVefficiency[1][1]->Fill( NMCPV, isReco ); + hPVefficiency[1][2]->Fill( vMCTracks.size(), isReco ); + hPVefficiency[1][3]->Fill( pvMC.NReconstructedDaughterTracks(), isReco ); + hPVefficiency[1][4]->Fill( NRecoPV, isReco ); + hPVefficiency[1][5]->Fill( nTracks, isReco ); + } + } + if ( pvMC.IsMCReconstructable() ) + { + const bool isReco = pvMC.IsReconstructed(); + const int nClones = MCtoRPVId[iV].ids.size() - 1; + + + pvEffMCReconstructable.Inc(isReco, nClones, "PV"); + if ( pvMC.IsTriggerPV() ) + { + pvEffMCReconstructable.Inc(isReco, nClones, "PVtrigger"); + hPVefficiency[2][0]->Fill( pvMC.NDaughterTracks(), isReco ); + hPVefficiency[2][1]->Fill( NMCPV, isReco ); + hPVefficiency[2][2]->Fill( vMCTracks.size(), isReco ); + hPVefficiency[2][3]->Fill( pvMC.NReconstructedDaughterTracks(), isReco ); + hPVefficiency[2][4]->Fill( NRecoPV, isReco ); + hPVefficiency[2][5]->Fill( nTracks, isReco ); + } + else + { + pvEffMCReconstructable.Inc(isReco, nClones, "PVpileup"); + hPVefficiency[3][0]->Fill( pvMC.NDaughterTracks(), isReco ); + hPVefficiency[3][1]->Fill( NMCPV, isReco ); + hPVefficiency[3][2]->Fill( vMCTracks.size(), isReco ); + hPVefficiency[3][3]->Fill( pvMC.NReconstructedDaughterTracks(), isReco ); + hPVefficiency[3][4]->Fill( NRecoPV, isReco ); + hPVefficiency[3][5]->Fill( nTracks, isReco ); + } + } + } + + fPVeff += pvEff; + + pvEff.CalcEff(); + fPVeff.CalcEff(); + + fPVeffMCReconstructable += pvEffMCReconstructable; + pvEffMCReconstructable.CalcEff(); + fPVeffMCReconstructable.CalcEff(); + + if(fNEvents%fPrintEffFrequency == 0) + { + std::cout << " ---- KF PV finder --- " << std::endl; + std::cout << "ACCUMULATED STAT : " << fNEvents << " EVENTS " << std::endl << std::endl; + std::cout << "PV with at least 2 reconstructed tracks is reconstructable:" << std::endl; + fPVeff.PrintEff(); + std::cout << std::endl; + std::cout << "PV with at least 2 MC tracks with 15 MC points is reconstructable:" << std::endl; + fPVeffMCReconstructable.PrintEff(); + + std::cout<<std::endl; + } +} + +void KFTopoPerformance::FillParticleParameters(KFParticle& TempPart, + int iParticle, + int iP, + int iPV, + TH1F* histoParameters[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam], + TH2F* histoParameters2D[nParametersSet][KFPartEfficiencies::nParticles][nHistoPartParam2D], + TH3F* histoParameters3D[1][KFPartEfficiencies::nParticles][nHistoPartParam3D], + TH1F* histoFit[KFPartEfficiencies::nParticles][nFitQA], + TH1F* histoFitDaughtersQA[KFPartEfficiencies::nParticles][nFitQA], + TH1F* histoDSToParticleQA[KFPartEfficiencies::nParticles][nDSToParticleQA], + vector<int>* multiplicities) +{ + /** Fills provided histograms with the parameters of the given particle. */ + + const std::map<int,bool>& decays = fTopoReconstructor->GetKFParticleFinder()->GetReconstructionList(); + if(!(decays.empty()) && (iParticle < fParteff.fFirstStableParticleIndex || iParticle > fParteff.fLastStableParticleIndex)) + if(decays.find(TempPart.GetPDG()) == decays.end()) return; + + float M, M_t, ErrM; + float dL, ErrdL; // decay length + float cT, ErrcT; // c*tau + float P, ErrP; + float Pt; + float Rapidity; + float Theta; + float Phi; + float X,Y,Z,R; + float QtAlpha[2]; + + TempPart.GetMass(M,ErrM); + TempPart.GetMomentum(P,ErrP); + Pt = TempPart.GetPt(); + Rapidity = TempPart.GetRapidity(); + + KFParticle TempPartTopo = TempPart; + TempPartTopo.SetProductionVertex(fTopoReconstructor->GetPrimVertex(0)); + TempPartTopo.GetDecayLength(dL,ErrdL); + TempPartTopo.GetLifeTime(cT,ErrcT); + + float chi2 = TempPart.GetChi2(); + Int_t ndf = TempPart.GetNDF(); + float prob = TMath::Prob(chi2, ndf);//(TDHelper<float>::Chi2IProbability( ndf, chi2 )); + Theta = TempPart.GetTheta(); + Phi = TempPart.GetPhi(); + X = TempPart.GetX(); + Y = TempPart.GetY(); + Z = TempPart.GetZ(); +#ifdef CBM + if(Z>=1. && iParticle>=54 && iParticle<=64) return; +#endif + R = sqrt(X*X+Y*Y); + M_t = sqrt(Pt*Pt+fParteff.GetMass(iParticle)*fParteff.GetMass(iParticle))-fParteff.GetMass(iParticle); + + KFParticleSIMD tempSIMDPart(TempPart); + float_v l,dl; + KFParticleSIMD pv(fTopoReconstructor->GetPrimVertex(iPV)); + tempSIMDPart.GetDistanceToVertexLine(pv, l, dl); +#ifdef __ROOT__ + if( (l[0] > 0.2f || Pt < 0.f) && (abs( TempPart.GetPDG() ) == 4122 || + abs( TempPart.GetPDG() ) == 104122 || + abs( TempPart.GetPDG() ) == 204122 || + abs( TempPart.GetPDG() ) == 304122 || + abs( TempPart.GetPDG() ) == 404122 || + abs( TempPart.GetPDG() ) == 504122 ) ) return; + if( (l[0] > 0.2f || Pt < 0.f) && (abs( TempPart.GetPDG() ) == 421 || + abs( TempPart.GetPDG() ) == 420 || + abs( TempPart.GetPDG() ) == 425 || + abs( TempPart.GetPDG() ) == 426 || + abs( TempPart.GetPDG() ) == 427 || + abs( TempPart.GetPDG() ) == 429) ) return; + if( (l[0] > 0.4f || Pt < 0.f) && (abs( TempPart.GetPDG() ) == 411 || + abs( TempPart.GetPDG() ) == 100411 || + abs( TempPart.GetPDG() ) == 200411 || + abs( TempPart.GetPDG() ) == 300411) ) return; + if( (l[0] > 0.2f || Pt < 0.f) && (abs( TempPart.GetPDG() ) == 431 || + abs( TempPart.GetPDG() ) == 100431 || + abs( TempPart.GetPDG() ) == 200431 || + abs( TempPart.GetPDG() ) == 300431 || + abs( TempPart.GetPDG() ) == 400431) ) return; + +// if(Pt < 2. && (abs( TempPart.GetPDG() ) == 443 || +// abs( TempPart.GetPDG() ) == 100443 || +// abs( TempPart.GetPDG() ) == 200443 || +// abs( TempPart.GetPDG() ) == 300443 || +// abs( TempPart.GetPDG() ) == 400443 || +// abs( TempPart.GetPDG() ) == 500443) ) return; + + if(Pt < 0.5f && (abs( TempPart.GetPDG() ) == 3000 || + abs( TempPart.GetPDG() ) == 3001) ) return; +#endif + float parameters[17] = {M, P, Pt, Rapidity, dL, cT, chi2/ndf, prob, Theta, Phi, X, Y, Z, R, l[0], l[0]/dl[0], M_t }; + + //for all particle-candidates + for(int iParam=0; iParam<17; iParam++) + histoParameters[0][iParticle][iParam]->Fill(parameters[iParam]); + + if(multiplicities) + multiplicities[0][iParticle]++; + + histoParameters2D[0][iParticle][0]->Fill(Rapidity,Pt,1); + histoParameters2D[0][iParticle][3]->Fill(Rapidity,M_t,1); + + const bool drawZR = IsCollectZRHistogram(iParticle); + if(histoParameters2D[0][iParticle][1] && drawZR) + { + histoParameters2D[0][iParticle][1]->Fill(Z,R,1); + } + + if(TempPart.NDaughters() == 2 && IsCollectArmenteros(iParticle)) + { + int index1 = TempPart.DaughterIds()[0]; + int index2 = TempPart.DaughterIds()[1]; + if(index1 >= int(fTopoReconstructor->GetParticles().size()) || + index2 >= int(fTopoReconstructor->GetParticles().size()) || + index1 < 0 || index2 < 0 ) + return; + + KFParticle posDaughter, negDaughter; + if(int(fTopoReconstructor->GetParticles()[index1].Q()) > 0) + { + posDaughter = fTopoReconstructor->GetParticles()[index1]; + negDaughter = fTopoReconstructor->GetParticles()[index2]; + } + else + { + negDaughter = fTopoReconstructor->GetParticles()[index1]; + posDaughter = fTopoReconstructor->GetParticles()[index2]; + } + float vertex[3] = {TempPart.GetX(), TempPart.GetY(), TempPart.GetZ()}; + posDaughter.TransportToPoint(vertex); + negDaughter.TransportToPoint(vertex); + KFParticle::GetArmenterosPodolanski(posDaughter, negDaughter, QtAlpha ); + + histoParameters2D[0][iParticle][2]->Fill(QtAlpha[1],QtAlpha[0],1); + } + + //Fill 3D histograms for multi differential analysis + if( histoParameters3D && IsCollect3DHistogram(iParticle)) + { + histoParameters3D[0][iParticle][0]->Fill(Rapidity,Pt,M,1); + histoParameters3D[0][iParticle][1]->Fill(Rapidity,M_t,M,1); + if(fCentralityBin>=0) + { + histoParameters3D[0][iParticle][2]->Fill(fCentralityBin, Pt, M, fCentralityWeight); + histoParameters3D[0][iParticle][3]->Fill(fCentralityBin, Rapidity, M, fCentralityWeight); + histoParameters3D[0][iParticle][4]->Fill(fCentralityBin, M_t, M, fCentralityWeight); + } + histoParameters3D[0][iParticle][5]->Fill(cT, Pt, M, 1); + } + + //Fill histograms for the side bands analysis + if(histoDSToParticleQA && IsCollect3DHistogram(iParticle)) + { + if(fabs(fParteff.GetMass(iParticle)-M) < 3.f*fParteff.GetMassSigma(iParticle))//SignalReco + { + for(int iParam=0; iParam<17; iParam++) + histoParameters[4][iParticle][iParam]->Fill(parameters[iParam]); + + if(multiplicities) + multiplicities[4][iParticle]++; + + histoParameters2D[4][iParticle][0]->Fill(Rapidity,Pt,1); + histoParameters2D[4][iParticle][3]->Fill(Rapidity,M_t,1); + + if(drawZR) + { + if(histoParameters2D[4][iParticle][1]) + histoParameters2D[4][iParticle][1]->Fill(Z,R,1); + if(histoParameters2D[4][iParticle][2]) + histoParameters2D[4][iParticle][2]->Fill(QtAlpha[1],QtAlpha[0],1); + } + } + + if( fabs(fParteff.GetMass(iParticle)-M) > 3.f*fParteff.GetMassSigma(iParticle) && + fabs(fParteff.GetMass(iParticle)-M) <= 6.f*fParteff.GetMassSigma(iParticle) )//BGReco + { + for(int iParam=0; iParam<17; iParam++) + histoParameters[5][iParticle][iParam]->Fill(parameters[iParam]); + + if(multiplicities) + multiplicities[5][iParticle]++; + + histoParameters2D[5][iParticle][0]->Fill(Rapidity,Pt,1); + histoParameters2D[5][iParticle][3]->Fill(Rapidity,M_t,1); + + if(drawZR) + { + if(histoParameters2D[5][iParticle][1]) + histoParameters2D[5][iParticle][1]->Fill(Z,R,1); + if(histoParameters2D[5][iParticle][2]) + histoParameters2D[5][iParticle][2]->Fill(QtAlpha[1],QtAlpha[0],1); + } + } + } + + if(!fStoreMCHistograms) return; + + int iSet = 1; + if(!RtoMCParticleId[iP].IsMatchedWithPdg()) //background + { + if(!RtoMCParticleId[iP].IsMatched()) iSet = 3; // for ghost particles - combinatorial background + else iSet = 2; // for physical background + } + + //Check if PV association is correct + if(!histoDSToParticleQA && iSet == 1) + { + int iMCPart = RtoMCParticleId[iP].GetBestMatchWithPdg(); + KFMCParticle &mcPart = vMCParticles[iMCPart]; + int iMCTrack = mcPart.GetMCTrackID(); + KFMCTrack &mcTrack = vMCTracks[iMCTrack]; + int motherId = mcTrack.MotherId(); + bool isSecondaryParticle = motherId >= 0; + + if(iPV >=0) + { + if(isSecondaryParticle) + iSet = 4; + else + { + int iMCPV = -1; + if(RtoMCPVId[iPV].IsMatchedWithPdg()) + iMCPV = RtoMCPVId[iPV].GetBestMatch(); + + int iMCPVFromParticle = fMCTrackToMCPVMatch[iMCTrack]; + if(iMCPV != iMCPVFromParticle) + iSet = 4; + } + } + else + { + if(!isSecondaryParticle) + iSet = 4; + } + } + + //for signal particles + for(int iParam=0; iParam<17; iParam++) + histoParameters[iSet][iParticle][iParam]->Fill(parameters[iParam]); + + if(multiplicities) + multiplicities[iSet][iParticle]++; + + histoParameters2D[iSet][iParticle][0]->Fill(Rapidity,Pt,1); + if(drawZR) + { + if(histoParameters2D[iSet][iParticle][1]) + histoParameters2D[iSet][iParticle][1]->Fill(Z,R,1); + if(histoParameters2D[iSet][iParticle][2]) + histoParameters2D[iSet][iParticle][2]->Fill(QtAlpha[1],QtAlpha[0],1); + } + histoParameters2D[iSet][iParticle][3]->Fill(Rapidity,M_t,1); + + if(iSet != 1) return; + + int iMCPart = RtoMCParticleId[iP].GetBestMatchWithPdg(); + KFMCParticle &mcPart = vMCParticles[iMCPart]; + // Fit quality of the mother particle + if(histoFit) + { + int iMCTrack = mcPart.GetMCTrackID(); + KFMCTrack &mcTrack = vMCTracks[iMCTrack]; + int mcDaughterId = -1; + if(iParticle >= fParteff.fFirstStableParticleIndex && iParticle <= fParteff.fLastStableParticleIndex) + mcDaughterId = iMCTrack; + else if(mcTrack.PDG() == 22 && TempPart.NDaughters() == 1) + mcDaughterId = iMCTrack; + else if(iParticle >= fParteff.fFirstMissingMassParticleIndex && iParticle <= fParteff.fLastMissingMassParticleIndex) + mcDaughterId = mcPart.GetDaughterIds()[1]; //the charged daughter + else + mcDaughterId = mcPart.GetDaughterIds()[0]; + + KFMCTrack &mcDaughter = vMCTracks[mcDaughterId]; + + float mcX = mcTrack.X(); + float mcY = mcTrack.Y(); + float mcZ = mcTrack.Z(); + if(histoDSToParticleQA || hPartParamPrimary == histoParameters) + { + mcX = mcDaughter.X(); + mcY = mcDaughter.Y(); + mcZ = mcDaughter.Z(); + } + const float mcPx = mcTrack.Par(3); + const float mcPy = mcTrack.Par(4); + const float mcPz = mcTrack.Par(5); + + float decayVtx[3] = { mcTrack.X(), mcTrack.Y(), mcTrack.Z() }; + float recParam[8] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; + float errParam[8] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; + + for(int iPar=0; iPar<3; iPar++) + { + recParam[iPar] = TempPart.GetParameter(iPar); + Double_t error = TempPart.GetCovariance(iPar,iPar); + if(error < 0.) { error = 1.e20;} + errParam[iPar] = TMath::Sqrt(error); + } + TempPart.TransportToPoint(decayVtx); + for(int iPar=3; iPar<7; iPar++) + { + recParam[iPar] = TempPart.GetParameter(iPar); + Double_t error = TempPart.GetCovariance(iPar,iPar); + if(error < 0.) { error = 1.e20;} + errParam[iPar] = TMath::Sqrt(error); + } + + int jParticlePDG = fParteff.GetParticleIndex(mcTrack.PDG()); + Double_t massMC = (jParticlePDG>=0) ? fParteff.partMass[jParticlePDG] :0.13957; + + Double_t Emc = sqrt(mcTrack.P()*mcTrack.P() + massMC*massMC); + Double_t res[8] = {0}, + pull[8] = {0}, + mcParam[8] = { mcX, mcY, mcZ, + mcPx, mcPy, mcPz, Emc, massMC }; + for(int iPar=0; iPar < 7; iPar++ ) + { + res[iPar] = recParam[iPar] - mcParam[iPar]; + if(fabs(errParam[iPar]) > 1.e-20) pull[iPar] = res[iPar]/errParam[iPar]; + } + + res[7] = M - mcParam[7]; + if(fabs(ErrM) > 1.e-20) pull[7] = res[7]/ErrM; + + for(int iPar=0; iPar < 8; iPar++ ) + { + histoFit[iParticle][iPar]->Fill(res[iPar]); + histoFit[iParticle][iPar+8]->Fill(pull[iPar]); + } + } + // Fit quality of daughters + int daughterIndex[2] = {-1, -1}; + + if(histoFitDaughtersQA) + { + for(int iD=0; iD<mcPart.NDaughters(); ++iD) + { + int mcDaughterId = mcPart.GetDaughterIds()[iD]; + // if(!MCtoRParticleId[mcDaughterId].IsMatchedWithPdg()) continue; + if(!MCtoRParticleId[mcDaughterId].IsMatched()) continue; + KFMCTrack &mcTrack = vMCTracks[mcDaughterId]; + // int recDaughterId = MCtoRParticleId[mcDaughterId].GetBestMatchWithPdg(); + int recDaughterId = MCtoRParticleId[mcDaughterId].GetBestMatch(); + KFParticle Daughter = fTopoReconstructor->GetParticles()[recDaughterId]; + Daughter.GetMass(M,ErrM); + + const float mcX = mcTrack.X(); + const float mcY = mcTrack.Y(); + const float mcZ = mcTrack.Z(); + const float mcPx = mcTrack.Px(); + const float mcPy = mcTrack.Py(); + const float mcPz = mcTrack.Pz(); + + float_v decayVtx[3] = {mcX, mcY, mcZ}; + + KFParticleSIMD DaughterSIMD(Daughter); + DaughterSIMD.TransportToPoint(decayVtx); + + int jParticlePDG = fParteff.GetParticleIndex(mcTrack.PDG()); + Double_t massMC = (jParticlePDG>=0) ? fParteff.partMass[jParticlePDG] :0.13957; + Double_t Emc = sqrt(mcTrack.P()*mcTrack.P() + massMC*massMC); + + Double_t res[8] = {0}, + pull[8] = {0}, + mcParam[8] = { mcX, mcY, mcZ, + mcPx, mcPy, mcPz, Emc, massMC }; + for(int iPar=0; iPar < 7; iPar++ ) + { + Double_t error = DaughterSIMD.GetCovariance(iPar,iPar)[0]; + if(error < 0.) { error = 1.e20;} + error = TMath::Sqrt(error); + Double_t recoPar = DaughterSIMD.GetParameter(iPar)[0]; + res[iPar] = recoPar - mcParam[iPar]; + if(fabs(error) > 1.e-20) pull[iPar] = res[iPar]/error; + } + res[7] = M - mcParam[7]; + if(fabs(ErrM) > 1.e-20) pull[7] = res[7]/ErrM; + + for(int iPar=0; iPar < 8; iPar++ ) + { + histoFitDaughtersQA[iParticle][iPar]->Fill(res[iPar]); + histoFitDaughtersQA[iParticle][iPar+8]->Fill(pull[iPar]); + } + + //fill Histos for GetDStoParticle + if(iD == 0) + daughterIndex[0] = recDaughterId; + if(iD == 1 && daughterIndex[0] > -1 && histoDSToParticleQA) + { + daughterIndex[1] = recDaughterId; + KFParticle d1 = fTopoReconstructor->GetParticles()[daughterIndex[0]]; + KFParticle d2 = fTopoReconstructor->GetParticles()[daughterIndex[1]]; + + KFParticleSIMD daughters[2] = {d2, d1}; + + float_v dS[2] = {0.f, 0.f}; + float_v dsdr[4][6]; + for(int i1=0; i1<4; i1++) + for(int i2=0; i2<6; i2++) + dsdr[i1][i2] = 0.f; + + daughters[0].GetDStoParticle(daughters[1], dS, dsdr); + float_v pD[2][8], cD[2][36], corrPD[2][36], corrCD[2][36]; + + for(int iDR=0; iDR<2; iDR++) + { + for(int iPD = 0; iPD<8; iPD++) + { + pD[iDR][iPD] = 0; + corrPD[iDR][iPD] = 0; + } + for(int iCD=0; iCD<36; iCD++) + { + cD[iDR][iCD] = 0; + corrCD[iDR][iCD] = 0; + } + } + + float_v F[4][36]; + { + for(int i1=0; i1<4; i1++) + for(int i2=0; i2<36; i2++) + F[i1][i2] = 0; + } + daughters[0].Transport(dS[0], dsdr[0], pD[0], cD[0], dsdr[1], F[0], F[1]); + daughters[1].Transport(dS[1], dsdr[3], pD[1], cD[1], dsdr[2], F[3], F[2]); + + daughters[0].MultQSQt( F[1], daughters[1].CovarianceMatrix(), corrCD[0], 6); + daughters[0].MultQSQt( F[2], daughters[0].CovarianceMatrix(), corrCD[1], 6); + for(int iDR=0; iDR<2; iDR++) + for(int iC=0; iC<6; iC++) + cD[iDR][iC] += corrCD[iDR][iC]; + + for(int iDR=0; iDR<2; iDR++) + { + cD[iDR][1] = cD[iDR][2]; + cD[iDR][2] = cD[iDR][5]; + for(int iPar=0; iPar<3; iPar++) + { + res[iPar] = pD[iDR][iPar][0] - decayVtx[iPar][0]; + + Double_t error = cD[iDR][iPar][0]; + if(error < 0.) { error = 1.e20;} + error = sqrt(error); + + pull[iPar] = res[iPar] / error; + + histoDSToParticleQA[iParticle][iPar]->Fill(res[iPar]); + histoDSToParticleQA[iParticle][iPar+3]->Fill(pull[iPar]); + } + } + + Double_t dXds = pD[0][0][0] - pD[1][0][0]; + Double_t dYds = pD[0][1][0] - pD[1][1][0]; + Double_t dZds = pD[0][2][0] - pD[1][2][0]; + + Double_t dRds = sqrt(dXds*dXds + dYds*dYds + dZds*dZds); + histoDSToParticleQA[iParticle][6]->Fill(dRds); + } + } + } +} + +void KFTopoPerformance::FillHistos() +{ + /** Fills histograms with parameter distributions and fit quality for all particle and primary vertex candidates. */ + vector<int> multiplicities[6]; + for(int iV=0; iV<6; iV++) + multiplicities[iV].resize(KFPartEfficiencies::nParticles, 0); + + //fill histograms for found short-lived particles + for(unsigned int iP=0; iP<fTopoReconstructor->GetParticles().size(); iP++) + { + int iParticle = fParteff.GetParticleIndex(fTopoReconstructor->GetParticles()[iP].GetPDG()); + if(iParticle < 0) continue; + KFParticle TempPart = fTopoReconstructor->GetParticles()[iP]; + + FillParticleParameters(TempPart,iParticle, iP, 0, hPartParam, hPartParam2D, hPartParam3D, + hFitQA, hFitDaughtersQA, hDSToParticleQA, multiplicities); + } + + if(fStoreMCHistograms) + { + for(int iSet=0; iSet<KFParticleFinder::GetNSecondarySets(); iSet++) + { + const std::vector<KFParticle>& SecondaryCandidates = fTopoReconstructor->GetKFParticleFinder()->GetSecondaryCandidates()[iSet]; + for(unsigned int iP=0; iP<SecondaryCandidates.size(); iP++) + { + KFParticle TempPart = SecondaryCandidates[iP]; + int iParticle = fParteff.GetParticleIndex(TempPart.GetPDG()); + if(iParticle < 0) continue; + + const int id = TempPart.Id(); + FillParticleParameters(TempPart, iParticle, id, 0, hPartParamSecondaryMass, hPartParam2DSecondaryMass, 0); + + TempPart = fTopoReconstructor->GetParticles()[id]; + FillParticleParameters(TempPart, iParticle, id, 0, hPartParamSecondary, hPartParam2DSecondary, 0); + } + } + + for(int iSet=0; iSet<KFParticleFinder::GetNPrimarySets(); iSet++) + { + for(int iPV=0; iPV<fTopoReconstructor->NPrimaryVertices(); iPV++) + { + const std::vector<KFParticle>& PrimaryCandidates = fTopoReconstructor->GetKFParticleFinder()->GetPrimaryCandidates()[iSet][iPV]; + for(unsigned int iP=0; iP<PrimaryCandidates.size(); iP++) + { + KFParticle TempPart = PrimaryCandidates[iP]; + int iParticle = fParteff.GetParticleIndex(TempPart.GetPDG()); + if(iParticle < 0) continue; + + const int id = TempPart.Id(); + FillParticleParameters(TempPart,iParticle, id, iPV, hPartParamPrimaryMass, hPartParam2DPrimaryMass, 0, hFitQAMassConstraint); + + TempPart = fTopoReconstructor->GetParticles()[id]; + FillParticleParameters(TempPart,iParticle, id, iPV, hPartParamPrimary, hPartParam2DPrimary, 0, hFitQANoConstraint); + } + + const std::vector<KFParticle>& PrimaryCandidatesTopo = fTopoReconstructor->GetKFParticleFinder()->GetPrimaryTopoCandidates()[iSet][iPV]; + for(unsigned int iP=0; iP<PrimaryCandidatesTopo.size(); iP++) + { + KFParticle TempPart = PrimaryCandidatesTopo[iP]; + int iParticle = fParteff.GetParticleIndex(TempPart.GetPDG()); + if(iParticle < 0) continue; + + FillParticleParameters(TempPart,iParticle, TempPart.Id(), iPV, hPartParamPrimaryTopo, hPartParam2DPrimaryTopo, 0, hFitQATopoConstraint); + } + + const std::vector<KFParticle>& PrimaryCandidatesTopoMass = fTopoReconstructor->GetKFParticleFinder()->GetPrimaryTopoMassCandidates()[iSet][iPV]; + for(unsigned int iP=0; iP<PrimaryCandidatesTopoMass.size(); iP++) + { + KFParticle TempPart = PrimaryCandidatesTopoMass[iP]; + int iParticle = fParteff.GetParticleIndex(TempPart.GetPDG()); + if(iParticle < 0) continue; + + FillParticleParameters(TempPart,iParticle, TempPart.Id(), iPV, hPartParamPrimaryTopoMass, hPartParam2DPrimaryTopoMass, 0, hFitQATopoMassConstraint); + } + } + } + } + //fill histograms with ChiPrim for every particle + for(unsigned int iP=0; iP<fTopoReconstructor->GetParticles().size(); iP++) + { + KFParticle TempPart = fTopoReconstructor->GetParticles()[iP]; + KFParticle vtx = fTopoReconstructor->GetPrimVertex(0); + + if(RtoMCParticleId[iP].IsMatched()) + { + int iMCPV = vMCParticles[RtoMCParticleId[iP].GetBestMatch()].GetMotherId(); + if(iMCPV<0.) + { + iMCPV = -iMCPV - 1; + if(MCtoRPVId[iMCPV].IsMatched()) + { + vtx = fTopoReconstructor->GetPrimVertex(MCtoRPVId[iMCPV].GetBestMatch()); + } + } + } +// else +// KFParticle & vtx = fTopoReconstructor->GetPrimVertex(0); + + + float chi2 = TempPart.GetDeviationFromVertex(vtx); + int ndf = 2; + + hTrackParameters[KFPartEfficiencies::nParticles]->Fill(chi2); + hTrackParameters[KFPartEfficiencies::nParticles+4]->Fill(TMath::Prob(chi2, ndf)); + + if(!RtoMCParticleId[iP].IsMatched()) + { + hTrackParameters[KFPartEfficiencies::nParticles+3]->Fill(chi2); + hTrackParameters[KFPartEfficiencies::nParticles+7]->Fill(TMath::Prob(chi2, ndf)); + continue; + } + + int iMCPart = RtoMCParticleId[iP].GetBestMatch(); + KFMCParticle &mcPart = vMCParticles[iMCPart]; + if(mcPart.GetMotherId() < 0) + { + hTrackParameters[KFPartEfficiencies::nParticles+1]->Fill(chi2 ); + hTrackParameters[KFPartEfficiencies::nParticles+5]->Fill(TMath::Prob(chi2, ndf)); + } + else + { + hTrackParameters[KFPartEfficiencies::nParticles+2]->Fill(chi2 ); + hTrackParameters[KFPartEfficiencies::nParticles+6]->Fill(TMath::Prob(chi2, ndf)); + } + int iParticle = fParteff.GetParticleIndex(fTopoReconstructor->GetParticles()[iP].GetPDG()); + if(iParticle > -1 && iParticle<KFPartEfficiencies::nParticles) + hTrackParameters[iParticle]->Fill(chi2 ); + + } + + + //fill histograms of the primary vertex quality + for(int iPV = 0; iPV<fTopoReconstructor->NPrimaryVertices(); iPV++) + { + KFParticle & vtx = fTopoReconstructor->GetPrimVertex(iPV); + vector<int> &tracks = fTopoReconstructor->GetPVTrackIndexArray(iPV); + + Double_t probPV = TMath::Prob(vtx.Chi2(), vtx.NDF());//(TDHelper<float>::Chi2IProbability( ndf, chi2 )); + vector<Double_t> dzPV; + if(RtoMCPVId[iPV].IsMatched()) + { + int iCurrMCPV = RtoMCPVId[iPV].GetBestMatch(); + for(int iPV2 = iPV+1; iPV2 < fTopoReconstructor->NPrimaryVertices(); iPV2++) + { + if(!RtoMCPVId[iPV2].IsMatched()) continue; + int iCurrMCPV2 = RtoMCPVId[iPV2].GetBestMatch(); + if(iCurrMCPV != iCurrMCPV2) continue; + KFParticle & vtx2 = fTopoReconstructor->GetPrimVertex(iPV2); + + dzPV.push_back(fabs(vtx.Z() - vtx2.Z())); + } + } + + hPVParam[ 0]->Fill(vtx.X()); + hPVParam[ 1]->Fill(vtx.Y()); + hPVParam[ 2]->Fill(vtx.Z()); + hPVParam[ 3]->Fill(sqrt(vtx.X()*vtx.X() + vtx.Y()*vtx.Y())); + hPVParam[ 4]->Fill(tracks.size()); + hPVParam[ 5]->Fill(vtx.Chi2()); + hPVParam[ 6]->Fill(vtx.NDF()); + hPVParam[ 7]->Fill(vtx.Chi2()/vtx.NDF()); + hPVParam[ 8]->Fill(probPV); + hPVParam[ 9]->Fill(fPVPurity[iPV]); + hPVParam[10]->Fill(fPVTracksRate[0][iPV]); + hPVParam[11]->Fill(fPVTracksRate[1][iPV]); + hPVParam[12]->Fill(fPVTracksRate[2][iPV]); + hPVParam[13]->Fill(fPVTracksRate[3][iPV]); + for(unsigned int iZ=0; iZ<dzPV.size(); iZ++) + hPVParam[14]->Fill(dzPV[iZ]); + + hPVParam2D[0]->Fill(vtx.X(),vtx.Y()); + + + if(!RtoMCPVId[iPV].IsMatchedWithPdg()) + { + if(!RtoMCPVId[iPV].IsMatched()) + { + hPVParamGhost[ 0]->Fill(vtx.X()); + hPVParamGhost[ 1]->Fill(vtx.Y()); + hPVParamGhost[ 2]->Fill(vtx.Z()); + hPVParamGhost[ 3]->Fill(sqrt(vtx.X()*vtx.X() + vtx.Y()*vtx.Y())); + hPVParamGhost[ 4]->Fill(tracks.size()); + hPVParamGhost[ 5]->Fill(vtx.Chi2()); + hPVParamGhost[ 6]->Fill(vtx.NDF()); + hPVParamGhost[ 7]->Fill(vtx.Chi2()/vtx.NDF()); + hPVParamGhost[ 8]->Fill(probPV); + hPVParamGhost[ 9]->Fill(fPVPurity[iPV]); + hPVParamGhost[10]->Fill(fPVTracksRate[0][iPV]); + hPVParamGhost[11]->Fill(fPVTracksRate[1][iPV]); + hPVParamGhost[12]->Fill(fPVTracksRate[2][iPV]); + hPVParamGhost[13]->Fill(fPVTracksRate[3][iPV]); + for(unsigned int iZ=0; iZ<dzPV.size(); iZ++) + hPVParamGhost[14]->Fill(dzPV[iZ]); + } + else + { + hPVParamBG[ 0]->Fill(vtx.X()); + hPVParamBG[ 1]->Fill(vtx.Y()); + hPVParamBG[ 2]->Fill(vtx.Z()); + hPVParamBG[ 3]->Fill(sqrt(vtx.X()*vtx.X() + vtx.Y()*vtx.Y())); + hPVParamBG[ 4]->Fill(tracks.size()); + hPVParamBG[ 5]->Fill(vtx.Chi2()); + hPVParamBG[ 6]->Fill(vtx.NDF()); + hPVParamBG[ 7]->Fill(vtx.Chi2()/vtx.NDF()); + hPVParamBG[ 8]->Fill(probPV); + hPVParamBG[ 9]->Fill(fPVPurity[iPV]); + hPVParamBG[10]->Fill(fPVTracksRate[0][iPV]); + hPVParamBG[11]->Fill(fPVTracksRate[1][iPV]); + hPVParamBG[12]->Fill(fPVTracksRate[2][iPV]); + hPVParamBG[13]->Fill(fPVTracksRate[3][iPV]); + for(unsigned int iZ=0; iZ<dzPV.size(); iZ++) + hPVParamBG[14]->Fill(dzPV[iZ]); + } + continue; + } + + int iMCPV = RtoMCPVId[iPV].GetBestMatch(); + KFMCVertex &mcPV = fPrimVertices[iMCPV]; // primary vertex positions (currently only one vertex is implemented) + + int iPVType = 0; + if(mcPV.IsTriggerPV()) + { + hPVParamSignal[ 0]->Fill(vtx.X()); + hPVParamSignal[ 1]->Fill(vtx.Y()); + hPVParamSignal[ 2]->Fill(vtx.Z()); + hPVParamSignal[ 3]->Fill(sqrt(vtx.X()*vtx.X() + vtx.Y()*vtx.Y())); + hPVParamSignal[ 4]->Fill(tracks.size()); + hPVParamSignal[ 5]->Fill(vtx.Chi2()); + hPVParamSignal[ 6]->Fill(vtx.NDF()); + hPVParamSignal[ 7]->Fill(vtx.Chi2()/vtx.NDF()); + hPVParamSignal[ 8]->Fill(probPV); + hPVParamSignal[ 9]->Fill(fPVPurity[iPV]); + hPVParamSignal[10]->Fill(fPVTracksRate[0][iPV]); + hPVParamSignal[11]->Fill(fPVTracksRate[1][iPV]); + hPVParamSignal[12]->Fill(fPVTracksRate[2][iPV]); + hPVParamSignal[13]->Fill(fPVTracksRate[3][iPV]); + for(unsigned int iZ=0; iZ<dzPV.size(); iZ++) + hPVParamSignal[14]->Fill(dzPV[iZ]); + } + else + { + hPVParamPileup[ 0]->Fill(vtx.X()); + hPVParamPileup[ 1]->Fill(vtx.Y()); + hPVParamPileup[ 2]->Fill(vtx.Z()); + hPVParamPileup[ 3]->Fill(sqrt(vtx.X()*vtx.X() + vtx.Y()*vtx.Y())); + hPVParamPileup[ 4]->Fill(tracks.size()); + hPVParamPileup[ 5]->Fill(vtx.Chi2()); + hPVParamPileup[ 6]->Fill(vtx.NDF()); + hPVParamPileup[ 7]->Fill(vtx.Chi2()/vtx.NDF()); + hPVParamPileup[ 8]->Fill(probPV); + hPVParamPileup[ 9]->Fill(fPVPurity[iPV]); + hPVParamPileup[10]->Fill(fPVTracksRate[0][iPV]); + hPVParamPileup[11]->Fill(fPVTracksRate[1][iPV]); + hPVParamPileup[12]->Fill(fPVTracksRate[2][iPV]); + hPVParamPileup[13]->Fill(fPVTracksRate[3][iPV]); + for(unsigned int iZ=0; iZ<dzPV.size(); iZ++) + hPVParamPileup[14]->Fill(dzPV[iZ]); + iPVType = 1; + } + //Find MC parameters of the primary vertex + float mcPVx[3]={mcPV.X(), mcPV.Y(), mcPV.Z()}; + + float errPV[3] = {vtx.CovarianceMatrix()[0], vtx.CovarianceMatrix()[2], vtx.CovarianceMatrix()[5]}; + for(int iErr=0; iErr<3; iErr++) + if(fabs(errPV[iErr]) < 1.e-8f) errPV[iErr] = 1.e8; + + float dRPVr[3] = {vtx.X()-mcPVx[0], + vtx.Y()-mcPVx[1], + vtx.Z()-mcPVx[2]}; + float dRPVp[3] = {static_cast<float>(dRPVr[0]/sqrt(errPV[0])), + static_cast<float>(dRPVr[1]/sqrt(errPV[1])), + static_cast<float>(dRPVr[2]/sqrt(errPV[2]))}; + + for(unsigned int iHPV=0; iHPV<3; ++iHPV) + hPVFitQa[iPVType][iHPV]->Fill(dRPVr[iHPV]); + for(unsigned int iHPV=3; iHPV<6; ++iHPV) + hPVFitQa[iPVType][iHPV]->Fill(dRPVp[iHPV-3]); + + for(unsigned int iHPV=0; iHPV<3; ++iHPV) + hPVFitQa2D[iPVType][1][iHPV]->Fill(fNCorrectPVTracks[iPV],dRPVr[iHPV]); + for(unsigned int iHPV=3; iHPV<6; ++iHPV) + hPVFitQa2D[iPVType][1][iHPV]->Fill(fNCorrectPVTracks[iPV],dRPVp[iHPV-3]); + + for(unsigned int iHPV=0; iHPV<3; ++iHPV) + hPVFitQa2D[iPVType][0][iHPV]->Fill(mcPV.NReconstructedDaughterTracks(),dRPVr[iHPV]); + for(unsigned int iHPV=3; iHPV<6; ++iHPV) + hPVFitQa2D[iPVType][0][iHPV]->Fill(mcPV.NReconstructedDaughterTracks(),dRPVp[iHPV-3]); + + hPVFitQa[iPVType][6]->Fill( double(mcPV.NReconstructedDaughterTracks() - fNCorrectPVTracks[iPV])/double(mcPV.NReconstructedDaughterTracks()) ); + } + + //fill histograms with quality of input tracks from PV + for(unsigned int iP=0; iP<fTopoReconstructor->GetParticles().size(); iP++) + { + KFParticle TempPart = fTopoReconstructor->GetParticles()[iP]; + int nDaughters = TempPart.NDaughters(); + if(nDaughters > 1) continue; //use only tracks, not short lived particles + + if(!RtoMCParticleId[iP].IsMatchedWithPdg()) continue; //ghost + + int iMCPart = RtoMCParticleId[iP].GetBestMatchWithPdg(); + KFMCParticle &mcPart = vMCParticles[iMCPart]; + + int iMCTrack = mcPart.GetMCTrackID(); + KFMCTrack &mcTrack = vMCTracks[iMCTrack]; + + if( mcTrack.MotherId() > -1 ) continue; // select only PV tracks + + const float mcX = mcTrack.X(); + const float mcY = mcTrack.Y(); + const float mcZ = mcTrack.Z(); + const float mcPx = mcTrack.Px(); + const float mcPy = mcTrack.Py(); + const float mcPz = mcTrack.Pz(); + + float decayVtx[3] = {mcX, mcY, mcZ}; + TempPart.TransportToPoint(decayVtx); + + + Double_t res[6] = {0}, + pull[6] = {0}, + mcParam[6] = { mcX, mcY, mcZ, + mcPx, mcPy, mcPz }; + for(int iPar=0; iPar < 6; iPar++ ) + { + Double_t error = TempPart.GetCovariance(iPar,iPar); + if(error < 0.) { error = 1.e20;} + error = TMath::Sqrt(error); + res[iPar] = TempPart.GetParameter(iPar) - mcParam[iPar]; + if(fabs(error) > 1.e-20) pull[iPar] = res[iPar]/error; + + hFitPVTracksQA[iPar]->Fill(res[iPar]); + hFitPVTracksQA[iPar+6]->Fill(pull[iPar]); + } + } + + if(fStoreMCHistograms) + { + for(int iV=0; iV<6; iV++) + for(int iP=0; iP < KFPartEfficiencies::nParticles; iP++) + if(hPartParam[iV][iP][17]) + hPartParam[iV][iP][17]->Fill(multiplicities[iV][iP]); + FillMCHistos(); + } + else + for(int iP=0; iP < KFPartEfficiencies::nParticles; iP++) + if(hPartParam[0][iP][17]) + hPartParam[0][iP][17]->Fill(multiplicities[0][iP]); +} // void KFTopoPerformance::FillHistos() + +void KFTopoPerformance::FillMCHistos() +{ + /** Fills histograms of Monte Carlo particles. */ + for(unsigned int iMCTrack=0; iMCTrack<vMCTracks.size(); iMCTrack++) + { + int iPDG = fParteff.GetParticleIndex(vMCTracks[iMCTrack].PDG()); + if(iPDG < 0) continue; + + if(vMCTracks[iMCTrack].MotherId()>=0) continue; + KFMCParticle &part = vMCParticles[iMCTrack]; + + float M = fParteff.partMass[iPDG]; + float P = vMCTracks[iMCTrack].P(); + float Pt = vMCTracks[iMCTrack].Pt(); + float E = sqrt(M*M+P*P); + float Rapidity = 0.5*log((E+vMCTracks[iMCTrack].Pz())/(E-vMCTracks[iMCTrack].Pz())); + float M_t = sqrt(Pt*Pt+M*M)-M; + + float X; + float Y; + float Z; + float R; + + if (part.NDaughters()>0) + { + X = vMCTracks[part.GetDaughterIds()[0]].X(); + Y = vMCTracks[part.GetDaughterIds()[0]].Y(); + Z = vMCTracks[part.GetDaughterIds()[0]].Z(); + } + else + { + X = vMCTracks[iMCTrack].X(); + Y = vMCTracks[iMCTrack].Y(); + Z = vMCTracks[iMCTrack].Z(); + } + R = sqrt(X*X+Y*Y); + + + float parameters[17] = {M, P, Pt, Rapidity, 0, 0, 0, 0, 0, 0, X, Y, Z, R, 0, 0, M_t}; + //for all particle-candidates + for(int iParam=0; iParam<17; iParam++) + if(hPartParam[6][iPDG][iParam]) hPartParam[6][iPDG][iParam]->Fill(parameters[iParam]); + + if(hPartParam2D[6][iPDG][0]) hPartParam2D[6][iPDG][0]->Fill(Rapidity,Pt,1); + if(hPartParam2D[6][iPDG][3]) hPartParam2D[6][iPDG][3]->Fill(Rapidity,M_t,1); + + if(IsCollectZRHistogram(iPDG)) + if(hPartParam2D[6][iPDG][1]) hPartParam2D[6][iPDG][1]->Fill(Z,R,1); + + if( part.IsReconstructable(2) && IsCollectArmenteros(iPDG)) + { + int index1 = part.GetDaughterIds()[0]; + int index2 = part.GetDaughterIds()[1]; + KFMCTrack positive, negative; + if(vMCTracks[index1].Par(6) > 0) + { + positive = vMCTracks[index1]; + negative = vMCTracks[index2]; + } + else + { + negative = vMCTracks[index1]; + positive = vMCTracks[index2]; + } + + float alpha = 0., qt = 0.; + float spx = positive.Px() + negative.Px(); + float spy = positive.Py() + negative.Py(); + float spz = positive.Pz() + negative.Pz(); + float sp = sqrt(spx*spx + spy*spy + spz*spz); + float pn, pln, plp; + pn = sqrt(negative.Px()*negative.Px() + negative.Py()*negative.Py() + negative.Pz()*negative.Pz()); + pln = (negative.Px()*spx+negative.Py()*spy+negative.Pz()*spz)/sp; + plp = (positive.Px()*spx+positive.Py()*spy+positive.Pz()*spz)/sp; + float ptm = (1.-((pln/pn)*(pln/pn))); + qt= (ptm>=0.)? pn*sqrt(ptm) :0; + alpha = (plp-pln)/(plp+pln); + + if(hPartParam2D[6][iPDG][2]) hPartParam2D[6][iPDG][2]->Fill(alpha,qt,1); + } + } +} + +void KFTopoPerformance::AddV0Histos() +{ + /** Copies histograms of K0s candidates to V0 folder. */ + int iV0 = fParteff.nParticles - 1; + int iK0 = fParteff.GetParticleIndex(310); + + for(int iH=0; iH<nFitQA; iH++) + { + hFitDaughtersQA[iV0][iH]->Add(hFitDaughtersQA[iK0][iH]); + hFitQA[iV0][iH]->Add(hFitQA[iK0][iH]); + } + + for(int iV=0; iV<4; iV++) + for(int iH=0; iH<nHistoPartParam; iH++) + hPartParam[iV][iV0][iH]->Add(hPartParam[iV][iK0][iH]); +} + +void KFTopoPerformance::FillHistos(const KFPHistogram* histograms) +{ + /** Fill histograms with the histograms from the provided KFPHistogram object. */ + for(int iParticle=0; iParticle<KFPartEfficiencies::nParticles; iParticle++) + { + const int& nHistograms = histograms->GetHistogramSet(0).GetNHisto1D(); + for(int iHistogram=0; iHistogram<nHistograms; iHistogram++) + { + const KFPHistogram1D& histogram = histograms->GetHistogram(iParticle,iHistogram); + for(int iBin=0; iBin<histogram.Size(); iBin++) + hPartParam[0][iParticle][iHistogram]->SetBinContent( iBin, histogram.GetHistogram()[iBin] ); + } + } +} + +#endif //DO_TPCCATRACKER_EFF_PERFORMANCE diff --git a/external/KFParticle/KFParticlePerformance/KFTopoPerformance.h b/external/KFParticle/KFParticlePerformance/KFTopoPerformance.h new file mode 100644 index 0000000000000000000000000000000000000000..e86346ce9f9ca4202b6fee22ebe38f7890ccbc32 --- /dev/null +++ b/external/KFParticle/KFParticlePerformance/KFTopoPerformance.h @@ -0,0 +1,159 @@ +//---------------------------------------------------------------------------- +// Implementation of the KFParticle class +// . +// @author I.Kisel, I.Kulakov, M.Zyzak +// @version 1.0 +// @since 20.08.13 +// +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//____________________________________________________________________________ + +#ifdef DO_TPCCATRACKER_EFF_PERFORMANCE + +#ifndef KFTOPOPERFORMANCE_H +#define KFTOPOPERFORMANCE_H + + +#include "KFParticlePerformanceBase.h" + +#include "KFMCVertex.h" +#include "KFMCTrack.h" +#include <cstdio> +#include <map> + +#include "KFPartMatch.h" +#include "KFMCParticle.h" + +class AliHLTTPCCAGBTracker; + +class KFParticleTopoReconstructor; +class KFPHistogram; + +/** @class KFTopoPerformance + ** @brief The class to collect histograms. + ** @author M.Zyzak, I.Kisel + ** @date 05.02.2019 + ** @version 1.0 + ** + ** The class collects a set of histograms. + ** For each particle from the KF Particle Reconstruction scheme histograms with parameter distribution, + ** efficiencies, fit QA, fit QA of daughters, histograms for the side bands method and histograms for + ** multi-differential extraction of spectra are collected. Also, a set of histograms for quality of + ** the reconstructed parameters of primary vertices is created: distribution of parameters; fit QA; + ** fit QA of primary tracks; contamination of ghost, secondary (background) tracks and tracks from + ** another primary vertex; efficiency. + **/ + +class KFTopoPerformance: public KFParticlePerformanceBase +{ + public: + + KFTopoPerformance(); + virtual ~KFTopoPerformance(); +#ifdef KFPWITHTRACKER + virtual void SetNewEvent( + const AliHLTTPCCAGBTracker * const Tracker, + AliHLTResizableArray<AliHLTTPCCAHitLabel> *hitLabels, + AliHLTResizableArray<AliHLTTPCCAMCTrack> *mcTracks, + AliHLTResizableArray<AliHLTTPCCALocalMCPoint> *localMCPoints); +#endif + void SetTopoReconstructor( const KFParticleTopoReconstructor * const TopoReconstructor ); + const KFParticleTopoReconstructor * GetTopoReconstructor() const { return fTopoReconstructor; } ///< Returns pointer to the KFParticleTopoReconstructor object. + + // Check if MC track is reconstructable. Calculate set of MC track. Etc. + virtual void CheckMCTracks(); // fill mcData. + // Find reco-MCTracks correspondence + virtual void MatchTracks(); // fill recoData. + // Calculate efficiencies + + /// Histograms + void FillHistos(); + void FillHistos(const KFPHistogram* histograms); + void FillMCHistos(); + + void AddV0Histos(); + + void SetTrackMatch(const std::vector<int>& trackMatch) { fTrackMatch = trackMatch;} ///< Fill matching between Monte Carlo and reconstructed tracks. + void SetMCTracks(const std::vector<KFMCTrack>& mcTracks) { vMCTracks = mcTracks; } ///< Fill Monte Carlo tracks. + + const KFPartEfficiencies GetEfficiency() const { return fParteff; } ///< Returns KFPartEfficiencies object with calculated efficiency. + void SetPrintEffFrequency(int n) { fPrintEffFrequency = n;} ///< Sets frequency in events for efficiency table to be printed on the screen. + + const std::vector<KFMCVertex> GetPrimVertices() { return fPrimVertices; } ///< Returns Monte Carlo primary vertices in the current event. + const std::vector<KFMCParticle>& MCParticles() { return vMCParticles; } ///< Returns Monte Carlo particles in the current event. + const std::vector<KFPartMatch>& ParticlesMatch() { return RtoMCParticleId; } ///< Returns matching between reconstructed and Monte Carlo particles. + const std::vector<KFPartMatch>& GetMCtoRPVId() { return MCtoRPVId; } ///< Returns matching between Monte Carlo and reconstructed primary vertices. + const std::vector<KFPartMatch>& GetRtoMCPVId() { return RtoMCPVId; } ///< Returns matching between reconstructed and Monte Carlo primary vertices. + const KFMCTrack& GetMCTrack(const int iRecoTrack) + { + /** Returns Monte Carlo track matched with the reconstructed track with index "iRecoTrack". */ + int iMCTrack = 0; + if(RtoMCParticleId[iRecoTrack].IsMatched()) + iMCTrack = RtoMCParticleId[iRecoTrack].GetBestMatch(); + return vMCTracks[iMCTrack]; + } + + void SetCentralityBin(const int iBin) { fCentralityBin = iBin; } ///< Sets centrality bin of the current event. + void SetCentralityWeight(const float weight) { fCentralityWeight = weight; } ///< Sets weight of the centrality bin of the current event. + + private: + + const KFTopoPerformance& operator = (const KFTopoPerformance&); ///< Copying of objects of this class is forbidden. + KFTopoPerformance(const KFTopoPerformance&); ///< Copying of objects of this class is forbidden. + + void GetMCParticles(); + void MatchParticles(); + void MatchPV(); + void CalculateEfficiency(); + void CalculatePVEfficiency(); + void FindReconstructableMCParticles(); + void CheckMCParticleIsReconstructable(KFMCParticle &part); + void FindReconstructableMCVertices(); + void FillParticleParameters(KFParticle& TempPart, + int iParticle, + int iP, + int iPV, + TH1F* histoParameters[4][KFPartEfficiencies::nParticles][nHistoPartParam], + TH2F* histoParameters2D[4][KFPartEfficiencies::nParticles][nHistoPartParam2D], + TH3F* histoParameters3D[1][KFPartEfficiencies::nParticles][nHistoPartParam3D], + TH1F* histoFit[KFPartEfficiencies::nParticles][nFitQA] = 0, + TH1F* histoFitDaughtersQA[KFPartEfficiencies::nParticles][nFitQA] = 0, + TH1F* histoDSToParticleQA[KFPartEfficiencies::nParticles][nDSToParticleQA] = 0, + std::vector<int>* multiplicities = 0); + + const KFParticleTopoReconstructor *fTopoReconstructor; ///< Pointer to the KFParticleTopoReconstructor object with particles and vertices to be analysed. + + std::vector<KFMCVertex> fPrimVertices; ///< Monte Carlo primary vertices. + std::vector<int> fMCTrackToMCPVMatch; ///< Matching of Monte Carlo tracks and corresponding primary vertex + std::vector<double> fPVPurity; ///< Purity of the primary vertices. + std::vector<double> fPVTracksRate[4]; ///< Ratio in the primary vertices of: 0 - ghost tracks, 1 - from trigger PV, 2 - from pileup, 3 - from physics background. + std::vector<int> fNCorrectPVTracks; ///< Number of correctly attached tracks in the corresponding reconstructed primary vertex. + + std::vector<int> fTrackMatch; ///< Matching between reconstructed tracks and + std::vector<KFMCTrack> vMCTracks; ///< Monte Carlo tracks (parameters of the particle trajectories at the production point). + std::vector<KFMCParticle> vMCParticles; ///< Monte Carlo particles. + std::vector<int> fNeutralIndex; ///< Index of the created neutral daughters for missing mass method in vMCTracks for the Monte Carlo track with given index. + + /** Matching between Monte Carlo and reconstructed particles. MCtoRParticleId[i] provides index of the reconstructed particle in the + ** fTopoReconstructor->GetParticles() array for the Monte Carlo particle (or track) with index "i". **/ + std::vector<KFPartMatch> MCtoRParticleId; + /** Matching between reconstructed and Monte Carlo particles. RtoMCParticleId[i] provides index of the Monte Carlo particle in the + ** vMCTracks and vMCParticles arrays for the reconstructed particle with index "i" from fTopoReconstructor->GetParticles(). **/ + std::vector<KFPartMatch> RtoMCParticleId; + + /** Matching between Monte Carlo and reconstructed primary vertices. MCtoRPVId[i] provides index of the reconstructed vertex in the + ** fTopoReconstructor->GetPrimVertex() array for the Monte Carlo vertex with index "i". **/ + std::vector<KFPartMatch> MCtoRPVId; + /** Matching between reconstructed and Monte Carlo primary vertices. RtoMCPVId[i] provides index of the Monte Carlo vertex in the + ** fPrimVertices array for the reconstructed vertex with index "i" from fTopoReconstructor->GetPrimVertex(). **/ + std::vector<KFPartMatch> RtoMCPVId; + + int fPrintEffFrequency; ///< Frequency in events with which efficiency table is printed on the screen. + + int fCentralityBin; ///< Centrality bin for the current event. + float fCentralityWeight; ///< Centrality weight for the current event. +}; + +#endif +#endif //DO_TPCCATRACKER_EFF_PERFORMANCE diff --git a/field/CMakeLists.txt b/field/CMakeLists.txt index 2dbd15ccfcfac07249660da43696c3ae67f0069e..6f3244cfb5d1b7543d4aabc195a9a343c99dcde1 100644 --- a/field/CMakeLists.txt +++ b/field/CMakeLists.txt @@ -31,9 +31,24 @@ SpdMultiField.cxx SpdFieldCreator.cxx SpdFieldMap.cxx SpdFieldMapData.cxx +SpdAxialFieldMap.cxx +SpdAxialFieldMapData.cxx SpdFieldContFact.cxx ) +set(HEADERS +SpdAxialFieldMapData.h +SpdAxialFieldMap.h +SpdConstField.h +SpdFieldContFact.h +SpdFieldCreator.h +SpdField.h +SpdFieldMapData.h +SpdFieldMap.h +SpdMultiField.h +SpdRadialField.h +) + set(LINKDEF FieldLinkDef.h) Set(LIBRARY_NAME SpdField) Set(DEPENDENCIES Base SpdData SpdCommon) diff --git a/field/FieldLinkDef.h b/field/FieldLinkDef.h index 1ce2c16945a0912feb6e201623e9f25f525a5457..0ac76d5a1ac785c3231aaeaad5c3a9f8f281f54f 100644 --- a/field/FieldLinkDef.h +++ b/field/FieldLinkDef.h @@ -12,6 +12,8 @@ #pragma link C++ class SpdMultiField+; #pragma link C++ class SpdFieldMap+; #pragma link C++ class SpdFieldMapData+; +#pragma link C++ class SpdAxialFieldMap+; +#pragma link C++ class SpdAxialFieldMapData+; #pragma link C++ class SpdFieldCreator+; #pragma link C++ class SpdFieldContFact+; diff --git a/field/SpdAxialFieldMap.cxx b/field/SpdAxialFieldMap.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ce6fe873c1e6111a5fd2900dbd858a46dde03787 --- /dev/null +++ b/field/SpdAxialFieldMap.cxx @@ -0,0 +1,507 @@ +//_____________________________________________________________________________ +// +// SpdAxialFieldMap +//_____________________________________________________________________________ + +#include "SpdAxialFieldMap.h" +#include "SpdFieldPar.h" +#include <TSystem.h> +#include <TMath.h> + +#include <iostream> +#include <iomanip> + +using std::cout; +using std::endl; + +using TMath::Abs; + +#define RTOLERANCE 1.e-12 + +ClassImp(SpdAxialFieldMap) + +//_____________________________________________________________________________ +SpdAxialFieldMap::SpdAxialFieldMap(): +SpdField("SpdAxialFieldMap"),SpdAxialFieldMapData("SpdAxialFieldMapData"), +fApproxMethod(0) +{ + fType = 3; + SetTitle("Map"); + SetNFieldParameters(2); +} + +//_____________________________________________________________________________ +SpdAxialFieldMap::SpdAxialFieldMap(const Char_t* name, const Char_t* type): +SpdField(name),SpdAxialFieldMapData(name,type), +fApproxMethod(0) +{ + fType = 3; + SetTitle("AxialMap"); + SetNFieldParameters(2); +} + +//_____________________________________________________________________________ +SpdAxialFieldMap::SpdAxialFieldMap(SpdFieldPar* fieldPar, const Char_t* name): +SpdField(name),SpdAxialFieldMapData(name), +fApproxMethod(0) +{ + fType = 3; + SetTitle("AxialMap"); + + if (!fieldPar) { + cout << "-E- <SpdField::SpdAxialFieldMap> Empty parameter container " << endl; + SetNFieldParameters(2); + return; + } + + GetFieldParameters(fieldPar); + GetRegionParameters(fieldPar); + + InitData(fFileName); + + if (Abs(fParams[0]-1.) > 1e-9 || + Abs(fParams[1]-1.) > 1e-9) + { + SpdAxialFieldMapData::MultiplyField(fParams[0],fParams[1]); + } +} + +//_____________________________________________________________________________ +void SpdAxialFieldMap::Clear() +{ + SpdAxialFieldMapData::Clear(); +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::InitData(TString fileName, TString path) +{ + TString pathToData; + Bool_t found = false; + + while (true) + { + // if absolute path to magnetic field map + if (path.BeginsWith("/") ) { + if (!gSystem->AccessPathName(path.Data())) { + pathToData = path; + found = true; + cout << "-I- <SpdAxialFieldMap::InitData> Path to the field map: " << pathToData << endl; + break; + } + } + + // if MAGFPATH (path to magnetic field map) is set + path = getenv("MAGFPATH"); + path.ReplaceAll("//","/"); + if (!path.IsNull() ) { + if (!gSystem->AccessPathName(path.Data())) { + pathToData = path; + found = true; + cout << "-I- <SpdAxialFieldMap::InitData> Path to the field map ($MAGFPATH): " << pathToData << endl; + break; + } + } + + // if file was not found look it in the standard path + path = TString(getenv("VMCWORKDIR")); + path.ReplaceAll("//","/"); + if (!path.IsNull() ) { + (path.EndsWith("/")) ? path += "input/" : path += "/input/"; + if (!gSystem->AccessPathName(path.Data())) { + pathToData = path; + cout << "-I- <SpdAxialFieldMap::InitData> Path to the field map ($VMCWORKDIR/input): " << pathToData << endl; + found = true; + break; + } + } + + break; + } + + if (!found) cout << "-I- <SpdAxialFieldMap::InitData> Search for the field map in a current directory: " << endl; + + return SpdAxialFieldMapData::InitData(fileName,pathToData); +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::InitData() // protected +{ + cout <<"-I- <SpdAxialFieldMap::InitData> " << endl; + + fRmin = GetRmin(); + fZmin = SpdAxialFieldMapData::GetZmin(); + + fRstep = GetRstep(); + fZstep = GetZstep(); + + fRevCellSize = fRstep*fZstep; + fRevCellSize = 1./fRevCellSize; + + fFr = fBr->GetArray(); + fFz = fBz->GetArray(); + + fInitLevel = 2; + + return kTRUE; +} + +//_____________________________________________________________________________ +void SpdAxialFieldMap::MultiplyField(Double_t v) +{ + MultiplyField(v,v); +} + +//_____________________________________________________________________________ +void SpdAxialFieldMap::MultiplyField(Double_t vr, Double_t vz) +{ + fParams[0] *= vr; + fParams[1] *= vz; + + SpdAxialFieldMapData::MultiplyField(vr,vz); +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::IsInsideRegion(Double_t x, Double_t y, Double_t z) +{ + z = Abs(z); + if (!IsInsideMapRegion(x,y,z)) return kFALSE; + if (!fFieldRegion) return kTRUE; + return (fSwitchFieldRegion) ? fFieldRegion->IsInside(x,y,z) : kFALSE; +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::IsInsideRegion(Double_t r, Double_t z) +{ + z = Abs(z); + if (!IsInsideMapRegion(r,z)) return kFALSE; + if (!fFieldRegion) return kTRUE; + return (fSwitchFieldRegion) ? fFieldRegion->IsInside(r,z) : kFALSE; +} + +//_____________________________________________________________________________ +void SpdAxialFieldMap::ResetParameters() +{ + SpdField::ResetParameters(); + + fParams[0] = 1.; + fParams[1] = 1.; +} + +//_____________________________________________________________________________ +void SpdAxialFieldMap::SetNFieldParameters(Int_t n) +{ + SpdField::SetNFieldParameters(2); + + fParams[0] = 1.; + fParams[1] = 1.; +} + +//_____________________________________________________________________________ +void SpdAxialFieldMap::SetApproxMethod(Int_t method) +{ + if (method < 0 || method > 2) { + cout << "<SpdAxialFieldMap::SetApproxMethod> " + << " Unknown method approximation type: " << method + << ", set default (0) " << endl; + fApproxMethod = 0; + } + + fApproxMethod = method; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::GetBx(Double_t& f, Double_t x, Double_t y, Double_t z) +{ + Int_t sgn = (z < 0) ? -1 : 1; + z = Abs(z); + + if (!IsInsideRegion(x,y,z)) return kFALSE; + + Double_t v = TMath::Sqrt(x*x+y*y); + + FindCell(v,z); + + if (v < RTOLERANCE) { // very close to z-axis FIXME + // x = 0, y = 0 => phi = pi, cos(phi) = -1 + // (see ROOT TVector2 phi angle definition) + //v = -1.; + f = 0; + return kTRUE; + } + else { + if (Abs(x) > v*1.e-12) v = x/v; // cos(phi) + else { // cos(phi) < 1e-12 => Bx = 0 + f = 0; + return kTRUE; + } + } + + switch (fApproxMethod) + { + case 0 : { f = sgn*v*Approx_0(fFr); return kTRUE; } + case 1 : { f = sgn*v*Approx_1(fFr); return kTRUE; } + case 2 : { f = sgn*v*Approx_2(fFr); return kTRUE; } + + default : return kFALSE; + } + + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::GetBy(Double_t& f, Double_t x, Double_t y, Double_t z) +{ + Int_t sgn = (z < 0) ? -1 : 1; + z = Abs(z); + + if (!IsInsideRegion(x,y,z)) return kFALSE; + + Double_t v = TMath::Sqrt(x*x+y*y); + + FindCell(v,z); + + if (v < RTOLERANCE) { // very close to z-axis FIXME + // x = 0, y = 0 => phi = pi, sin(phi) = 0 => By = 0 + // (see ROOT TVector2 phi angle definition) + f = 0; + return kTRUE; + } + else { + if (Abs(y) > v*1.e-12) v = y/v; // sin(phi) + else { // sin(phi) < 1e-12 => By = 0 + f = 0; + return kTRUE; + } + } + + switch (fApproxMethod) + { + case 0 : { f = sgn*v*Approx_0(fFr); return kTRUE; } + case 1 : { f = sgn*v*Approx_1(fFr); return kTRUE; } + case 2 : { f = sgn*v*Approx_2(fFr); return kTRUE; } + + default : return kFALSE; + } + + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::GetBz(Double_t& f, Double_t x, Double_t y, Double_t z) +{ + z = Abs(z); + + if (!IsInsideRegion(x,y,z)) return kFALSE; + + Double_t v = TMath::Sqrt(x*x+y*y); + + FindCell(v,z); + + switch (fApproxMethod) + { + case 0 : { f = Approx_0(fFz); return kTRUE; } + case 1 : { f = Approx_1(fFz); return kTRUE; } + case 2 : { f = Approx_2(fFz); return kTRUE; } + + default : return kFALSE; + } + + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::GetField(const Double_t point[3], Double_t* bField) +{ + Double_t z = point[2]; + Int_t sgn = (z < 0) ? -1 : 1; + z = Abs(z); + + if (!IsInsideRegion(point[0],point[1],z)) return kFALSE; + + Double_t v = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]); + + FindCell(v,z); + + Double_t cosp(0), sinp(0);// cos(phi), sin(phi) + + if (v < RTOLERANCE) { + // phi = pi, cos(phi) = -1, sin(phi) = 0 + // (see ROOT TVector2 phi angle definition for x = y = 0) + //cosp = -1; + //sinp = 0.; + switch (fApproxMethod) + { + case 0 : bField[2] = Approx_0(fFz); + case 1 : bField[2] = Approx_1(fFz); + case 2 : bField[2] = Approx_2(fFz); + } + + bField[0] = 0; + bField[1] = 0; + + return kTRUE; + } + else { + if (Abs(point[0]) > v*1.e-12) cosp = sgn*point[0]/v; + if (Abs(point[1]) > v*1.e-12) sinp = sgn*point[1]/v; + } + + switch (fApproxMethod) + { + case 0 : { + v = Approx_0(fFr); + + bField[0] = cosp*v; + bField[1] = sinp*v; + bField[2] = Approx_0(fFz); + + //cout << " Point: " << point[0] << " " << point[1] << " " << point[2] << endl; + //cout << " Field: " << bField[0] << " " << bField[1] << " " << bField[2] << endl; + + return kTRUE; + } + case 1 : { + v = Approx_1(fFr); + + bField[0] = cosp*v; + bField[1] = sinp*v; + bField[2] = Approx_1(fFz); + + //cout << " Point: " << point[0] << " " << point[1] << " " << point[2] << endl; + //cout << " Field: " << bField[0] << " " << bField[1] << " " << bField[2] << endl; + + return kTRUE; + } + case 2 : { + v = Approx_2(fFr); + + bField[0] = cosp*v; + bField[1] = sinp*v; + bField[2] = Approx_2(fFz); + + //cout << " Point: " << point[0] << " " << point[1] << " " << point[2] << endl; + //cout << " Field: " << bField[0] << " " << bField[1] << " " << bField[2] << endl; + + return kTRUE; + } + default : return kFALSE; + } + + return kFALSE; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::GetParameters(SpdFieldPar* pars) // protected +{ + pars->GetParameter(Add_Name("filename"),fFileName); + if (fFileName == "unknown") fFileName = ""; + + pars->GetParameter(Add_Name("approx.type"),fApproxMethod); + + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMap::PutParameters(SpdFieldPar* pars) // protected +{ + if (fFileName.IsWhitespace()) pars->SetParameter(Add_Name("filename"),"unknown"); + else pars->SetParameter(Add_Name("filename"),fFileName); + + pars->SetParameter(Add_Name("approx.type"),fApproxMethod); + + return kTRUE; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________ +void SpdAxialFieldMap::PrintFieldParameters() const +{ + cout << "<SpdAxialFieldMap::PrintFieldParameters>" << endl; + + cout << "Init level: " << fInitLevel << endl; + cout << "Approximation method: " << fApproxMethod << endl; + + cout << endl; + + printf(" M(Br) = %12.6e\n",fParams[0]); + printf(" M(Bz) = %12.6e\n",fParams[1]); + + cout << endl; + + SpdAxialFieldMapData::PrintData(); +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________ +void SpdAxialFieldMap::FindCell(const Double_t& r, const Double_t& z) +{ + static Int_t iz, ir; + + iz = Int_t((z - fZmin)/fZstep); + ir = Int_t((r - fRmin)/fRstep); + + fI_00 = ir*fNz + iz; // (z0,r0) + fI_10 = fI_00 + 1; // (z1,r0) + fI_01 = fI_00 + fNz; // (z0,r1) + fI_11 = fI_01 + 1; // (z1,r1) + + fDz1 = z - fZstep * iz - fZmin; // dz1 = z-z1 + fDr1 = r - fRstep * ir - fRmin; // dr1 = r-r1 + + fDz2 = fZstep - fDz1; // dz2 = z2-z + fDr2 = fRstep - fDr1; // dr2 = r2-r +} + +//_____________________________________________________________________________ +Double_t SpdAxialFieldMap::Approx_0(const Double_t* V) const +{ + static Double_t value = 0; + + value = fDz1 * (fDr2 * V[fI_10] + fDr1 * V[fI_11]) // F(10) * dz1*dr2 + F(11) * dz1*dr1 + + fDz2 * (fDr2 * V[fI_00] + fDr1 * V[fI_01]); // F(00) * dz2*dr2 + F(01) * dz2*dr1 + +// cout << "[z0,r0] F(00): " << fI_00 << " " << V[fI_00] << endl; +// cout << "[z1,r0] F(10): " << fI_10 << " " << V[fI_10] << endl; +// cout << "[z0,r1] F(01): " << fI_01 << " " << V[fI_01] << endl; +// cout << "[z1,r1] F(11): " << fI_11 << " " << V[fI_11] << endl; +// +// cout << "value: " << fRevCellSize * value << "; Dz1, Dr1 = " << fDz1 << ", " << fDr1 << "\n\n"; + + return fRevCellSize * value; +} + +//_____________________________________________________________________________ +Double_t SpdAxialFieldMap::Approx_1(const Double_t* V) const +{ + if (fDr1 < 0.5*fRstep) + return (fDz1 < 0.5*fZstep) ? V[fI_00] : V[fI_10]; + else + return (fDz1 < 0.5*fZstep) ? V[fI_01] : V[fI_11]; +} + +//_____________________________________________________________________________ +Double_t SpdAxialFieldMap::Approx_2(const Double_t* V) const +{ + static Double_t value = 0.; + + value = V[fI_00] + V[fI_10] + V[fI_01] + V[fI_11]; + + return 0.25 * value; +} + + + diff --git a/field/SpdAxialFieldMap.h b/field/SpdAxialFieldMap.h new file mode 100644 index 0000000000000000000000000000000000000000..f84d128a313351a5cf7dae4c976e51d2ff0fc936 --- /dev/null +++ b/field/SpdAxialFieldMap.h @@ -0,0 +1,123 @@ +// $Id$ +// Author: artur 2020/07/04 + +#ifndef __SPDAXIALFIELDMAP_H__ +#define __SPDAXIALFIELDMAP_H__ + +#include "SpdField.h" +#include "SpdAxialFieldMapData.h" + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdAxialFieldMap // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdFieldPar; + +class SpdAxialFieldMap : public SpdField, public SpdAxialFieldMapData { + +public: + + SpdAxialFieldMap(); + SpdAxialFieldMap(const Char_t* name, const Char_t* type = ""); + SpdAxialFieldMap(SpdFieldPar* fieldPar, const Char_t* name = "SpdAxialFieldMap"); + + virtual ~SpdAxialFieldMap() {} + + virtual void Clear(); + virtual void ResetParameters(); + + virtual Bool_t InitData(TString fileName, TString path = ""); + + virtual void Init() {}; + + /* ----- transform field data ----- */ + + virtual void MultiplyField(Double_t v); + virtual void MultiplyField(Double_t vr, Double_t vz); + + virtual void RotateField(Double_t /*angle*/, Double_t /*theta*/, Double_t /*phi*/) {} + + /* ----- setters ----- */ + + virtual void SetNFieldParameters(Int_t n /*number of parameters*/); + + void SetApproxMethod(Int_t method); + + /* ----- getters ----- */ + + virtual Bool_t IsInsideRegion(Double_t x, Double_t y, Double_t z); + virtual Bool_t IsInsideRegion(Double_t r, Double_t z); + + inline Int_t GetApproxMethod() { return fApproxMethod; } + + virtual Bool_t GetField(const Double_t point[3], Double_t* bField); + + virtual Bool_t GetBx(Double_t& f, Double_t x, Double_t y, Double_t z); + virtual Bool_t GetBy(Double_t& f, Double_t x, Double_t y, Double_t z); + virtual Bool_t GetBz(Double_t& f, Double_t x, Double_t y, Double_t z); + + inline Double_t GetRStep() const { return fRstep; } + inline Double_t GetZStep() const { return fZstep; } + + virtual Double_t GetZmin() const { return -SpdAxialFieldMapData::GetZmax(); } + virtual Double_t GetZmax() const { return SpdAxialFieldMapData::GetZmax(); } + + virtual Int_t GetNz() const { return 2*fNz-1; } + + inline Double_t GetXstep() const { return fRstep; } + inline Double_t GetYstep() const { return fRstep; } + inline Int_t GetNx() const { return 2*fNr-1; } + inline Int_t GetNy() const { return 2*fNr-1; } + inline Double_t GetXmin() const { return -GetRmax(); } + inline Double_t GetYmin() const { return -GetRmax(); } + inline Double_t GetXmax() const { return GetRmax(); } + inline Double_t GetYmax() const { return GetRmax(); } + + /* ------ print ------ */ + + virtual void PrintFieldParameters() const; + +protected: + + virtual Bool_t GetParameters(SpdFieldPar* pars); + virtual Bool_t PutParameters(SpdFieldPar* pars); + + virtual Bool_t InitData(); + + virtual void FindCell(const Double_t& r, const Double_t& z); + + /* approximation methods */ + + virtual Double_t Approx_0(const Double_t* array) const; + virtual Double_t Approx_1(const Double_t* array) const; + virtual Double_t Approx_2(const Double_t* array) const; + + Int_t fApproxMethod; + + /* const memebers (DATA MAP) */ + + Double_t fRmin; + Double_t fZmin; + + Double_t fRstep; + Double_t fZstep; + + Double_t fRevCellSize; + + const Double_t* fFr; + const Double_t* fFz; + + /* auxiliary memebers */ + + Double_t fDz1, fDr1, fDz2, fDr2; + Int_t fI_00, fI_10, fI_01, fI_11; + + ClassDef(SpdAxialFieldMap,1) + +}; + +#endif /*__SPDAXIALFIELDMAP_H__ */ diff --git a/field/SpdAxialFieldMapData.cxx b/field/SpdAxialFieldMapData.cxx new file mode 100644 index 0000000000000000000000000000000000000000..21d874bd1165aa9f8395245b08b04c7105bbfb67 --- /dev/null +++ b/field/SpdAxialFieldMapData.cxx @@ -0,0 +1,809 @@ +// $Id$ +// Author: artur 2020/07/04 + + +//_____________________________________________________________________________ +// +// SpdAxialFieldMapData +//_____________________________________________________________________________ + +#include "SpdAxialFieldMapData.h" + +#include <TMath.h> +#include <TVector3.h> + +#include "SpdAxialFieldMapData.h" + +#include <fstream> +#include <iostream> +#include <iomanip> + +using std::cout; +using std::endl; + +using TMath::DegToRad; + +ClassImp(SpdAxialFieldMapData) + +//_____________________________________________________________________________ +SpdAxialFieldMapData::SpdAxialFieldMapData(): +fMapName("SpdAxialFieldMapData"), +fPathToData(""),fFileName(""), +fScaleUnit(1.),fFieldUnit(1.), +fInitLevel(0), +fMapRegion(0), +fNr(0),fNz(0), +fBr(0),fBz(0) +{ + +} + +//_____________________________________________________________________________________ +SpdAxialFieldMapData::SpdAxialFieldMapData(const Char_t* name, const Char_t* type): +fMapName(name), +fPathToData(""),fFileName(""), +fScaleUnit(1.),fFieldUnit(1.), +fInitLevel(0), +fMapRegion(0), +fNr(0),fNz(0), +fBr(0),fBz(0) +{ + SetMapType(type); +} + + +//_____________________________________________________________________________ +SpdAxialFieldMapData::~SpdAxialFieldMapData() +{ + if (fBr) delete fBr; + if (fBz) delete fBz; + + if (fMapRegion) delete fMapRegion; +} + +//_____________________________________________________________________________________ +void SpdAxialFieldMapData::Clear() +{ + fPathToData = ""; + fFileName = ""; + + ClearData(); +} + +//_____________________________________________________________________________________ +void SpdAxialFieldMapData::ClearData() +{ + fMapType = "undefined"; + + fFieldUnit = 1.; + fScaleUnit = 1.; + + if (fMapRegion) { delete fMapRegion; fMapRegion = 0; } + + fNr = 0; + fNz = 0; + + if (fBr) { delete fBr; fBr = 0; } + if (fBz) { delete fBz; fBz = 0; } + + fInitLevel = 0; +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::IsGridInit() const +{ + if (fNr < 2 || fNz < 2) return kFALSE; + if (!fMapRegion || !fMapRegion->IsRegionInit()) return kFALSE; + return kTRUE; +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::IsDataInit() const +{ + return (fBr && fBz); +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::IsInsideMapRegion(Double_t x, Double_t y, Double_t z) const +{ + return (fMapRegion) ? fMapRegion->IsInside(x,y,z) : kFALSE; +} +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::IsInsideMapRegion(Double_t r, Double_t z) const +{ + return (fMapRegion) ? fMapRegion->IsInside(r,z) : kFALSE; +} + +//_____________________________________________________________________________________ +Double_t SpdAxialFieldMapData::GetRstep() const +{ + if (!IsGridInit()) return 0; + return fMapRegion->GetDR()/(fNr - 1); +} + +//_____________________________________________________________________________________ +Double_t SpdAxialFieldMapData::GetZstep() const +{ + if (!IsGridInit()) return 0; + return fMapRegion->GetLz()/(fNz - 1); +} + +//_____________________________________________________________________________________ +void SpdAxialFieldMapData::SetPathToData(TString path) +{ + if (path.IsWhitespace()) { + fPathToData = ""; + return; + } + + fPathToData = path; + + if (!path.EndsWith("/")) fPathToData += "/"; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +void SpdAxialFieldMapData::MultiplyField(Double_t v) +{ + MultiplyField(v,v); +} + +//_____________________________________________________________________________________ +void SpdAxialFieldMapData::MultiplyField(Double_t vr, Double_t vz) +{ + if (GetInitLevel() < 1) return; + + for (Int_t i(0); i < GetNTotal(); i++) { + fBr->AddAt(fBr->At(i)*vr,i); + fBz->AddAt(fBz->At(i)*vz,i); + } +} + +//_____________________________________________________________________________ +Bool_t SpdAxialFieldMapData::GetMinMaxStat(Double_t* B) const +{ + // fill (B,Bz,Br)[min,max] + + if (!B) return kFALSE; + + memset(B,0,6*sizeof(Double_t)); + + if (!IsDataInit()) return kFALSE; + + Int_t nTot = GetNTotal(); + + for (Int_t i(0); i<3; i++) { B[2*i] = 1e20; B[2*i+1] = -1e20; } + + Double_t br, bz, b; + + for (Int_t i(0); i<nTot; i++) + { + br = fBr->At(i); + bz = fBz->At(i); + b = TMath::Sqrt(br*br+bz*bz); + + if (B[0] > b) B[0] = b; // min + if (B[1] < b) B[1] = b; // max + + if (B[2] > bz) B[2] = bz; + if (B[3] < bz) B[3] = bz; + + if (B[4] > br) B[4] = br; + if (B[5] < br) B[5] = br; + } + + return kTRUE; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +void SpdAxialFieldMapData::SetMapType(TString type) // protected +{ + if (!type.IsWhitespace()) fMapType = type; + else fMapType = "undefined"; +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::SetScaleUnit(TString unit) // protected +{ + if (unit == "mm") fScaleUnit = 0.1; + else if (unit == "m") fScaleUnit = 100.0; + else if (unit == "cm") fScaleUnit = 1.0; + else { + cout << "-E- <SpdAxialFieldMapData::SetScaleUnit> Unknown unit: " << unit << endl; + fScaleUnit = 1; + return kFALSE; + } + return kTRUE; +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::SetFieldUnit(TString unit) // protected +{ + if (unit == "G") fFieldUnit = 0.001; + else if (unit == "T") fFieldUnit = 10.0; + else if (unit == "kG") fFieldUnit = 1.0; + else { + cout << "-E- <SpdAxialFieldMapData::SetFieldUnit> Unknown unit: " << unit << endl; + fFieldUnit = 1; + return kFALSE; + } + return kTRUE; +} + +//_____________________________________________________________________________________ +TString SpdAxialFieldMapData::GetScaleUnitAsString() const +{ + if (fScaleUnit == 0.1) return "mm"; + if (fScaleUnit == 100.0) return "m"; + if (fScaleUnit == 1.0) return "cm"; + + cout << "-E- <SpdAxialFieldMapData::GetScaleUnitString> Unknown unit: " << fScaleUnit << endl; + return "unknown"; +} + +//_____________________________________________________________________________________ +TString SpdAxialFieldMapData::GetFieldUnitAsString() const +{ + if (fFieldUnit == 0.001) return "G"; + if (fFieldUnit == 10.0) return "T"; + if (fFieldUnit == 1.0) return "kG"; + + cout << "-E- <SpdAxialFieldMapData::GetFieldUnitString> Unknown unit: " << fFieldUnit << endl; + return "unknown"; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::InitData(TString fileName, TString path) +{ + Clear(); + + if (fileName.IsWhitespace()) { + cout << "-E- <SpdAxialFieldMapData::Init> No data file " << endl; + return kFALSE; + } + + SetPathToData(path); + fFileName = fileName; + + if (fileName.EndsWith(".dat")) { + if (!ReadAsciiFile()) { + cout << "-F- <SpdAxialFieldMapData::Init> Bad data (*.dat) file " << endl; + exit(1); + } + } + else if (fileName.EndsWith(".bin")) { + if (!ReadBinaryFile()) { + cout << "-F- <SpdAxialFieldMapData::Init> Bad data (*.bin) file " << endl; + exit(1); + } + } + else { + cout << "-E- <SpdFieldMapData::Init> No proper file name defined: " + << fileName << endl; + Clear(); + return kFALSE; + } + + fInitLevel = 1; + return InitData(); +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::InitData(const SpdAxialFieldMapData* data) +{ + Clear(); + + if (!data) { + cout << "-E- <SpdAxialFieldMapData::Init> No data " << endl; + return kFALSE; + } + + fPathToData = data->GetPathToData(); + fFileName = data->GetFileName(); + + fMapName = data->GetMapName(); + fMapType = data->GetMapType(); + + fScaleUnit = data->GetScaleUnit(); + fFieldUnit = data->GetFieldUnit(); + + // init grid + + if (fMapRegion) delete fMapRegion; + fMapRegion = new SpdTubeRegion(); + + fMapRegion->SetTubeRegion(data->GetRmin(),data->GetRmax(), + data->GetZmin(),data->GetZmax()); + + fNr = data->GetNr(); + fNz = data->GetNz(); + + if (!IsGridInit()) { + cout << "-E- <SpdFieldMapData::Init> Bad grid parameters " << endl; + Clear(); + return kFALSE; + } + + // init data arrays + + if (data->IsDataInit()) { + fBr = new TArrayD(*(data->GetBr())); + fBz = new TArrayD(*(data->GetBz())); + } + else { + Int_t nt = GetNTotal(); + fBr = new TArrayD(nt); + fBz = new TArrayD(nt); + } + + fInitLevel = 1; + return InitData(); +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::InitData(Double_t rmin, Double_t rmax, Int_t nr, + Double_t zmin, Double_t zmax, Int_t nz) +{ + ClearData(); + + if (fMapRegion) delete fMapRegion; + fMapRegion = new SpdTubeRegion(); + + fMapRegion->SetTubeRegion(rmin,rmax,zmin,zmax); + + fNr = nr; + fNz = nz; + + if (!IsGridInit()) { + cout << "-E- <SpdAxialFieldMapData::Init> Bad grid parameters " << endl; + ClearData(); + return kFALSE; + } + + Int_t nt = GetNTotal(); + + fBr = new TArrayD(nt); + fBz = new TArrayD(nt); + + fInitLevel = 1; + return InitData(); +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::InitData() +{ + return kTRUE; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::ReadAsciiFile() // protected +{ + TString fileName = fFileName; + + if (!fPathToData.IsWhitespace()) fileName = fPathToData + fileName; + + cout << "-I- <SpdAxialFieldMapData::ReadAsciiFile> Reading file: " + << fileName << endl; + + std::ifstream mapFile(fileName); + + if (!mapFile.is_open()) { + cout << "-E- <SpdAxialFieldMapData:ReadAsciiFile> Could not open file: " << fileName << endl; + return kFALSE; + } + + // Read map type + mapFile >> fMapType; + + // Read Units + TString unit; + + mapFile >> unit; + if (!SetScaleUnit(unit)) return kFALSE; + + mapFile >> unit; + if (!SetFieldUnit(unit)) return kFALSE; + + // Read grid parameters + + Double_t rmin, rmax, zmin, zmax; + + mapFile >> rmin >> rmax >> fNr; + mapFile >> zmin >> zmax >> fNz; + + if (fMapRegion) delete fMapRegion; + fMapRegion = new SpdTubeRegion(); + + fMapRegion->SetTubeRegion(rmin*fScaleUnit, rmax*fScaleUnit, + zmin*fScaleUnit, zmax*fScaleUnit); + + if (!IsGridInit()) { + cout << "-E- <SpdAxialFieldMapData:ReadAsciiFile> Bad grid parameters: "; + cout << "N(r,z) = " << fNr << ", " << fNz << endl; + cout << "[min,max] = R[" << rmin << ", " << rmax << "], " + << " Z[" << zmin << ", " << zmax << "]" << endl; + return kFALSE; + } + + // Create field arrays + + Int_t nTot = GetNTotal(); + + fBr = new TArrayD(nTot); + fBz = new TArrayD(nTot); + + // Read the field values + + Double_t rr, zz; + Double_t br, bz; + + Int_t n = 0; + for (; n < nTot; n++) { + + if (!mapFile.good()) { + cout << "-E- <SpdAxialFieldMapData::ReadAsciiFile> I/O Error at position " << n << endl; + break; + } + + mapFile >> rr >> zz; + mapFile >> br >> bz; + + //cout << n << "/" << nTot << " " + // << " point: " << rr << " " << zz + // << " field: " << br << " " << bz + // << endl; + + fBr->AddAt(br*fFieldUnit, n); + fBz->AddAt(bz*fFieldUnit, n); + + if (mapFile.eof()) { + cout << "-E- <SpdAxialFieldMapData::ReadAsciiFile> End of file reached at position " << n << endl; + break; + } + } + + mapFile.close(); + + //cout << fBr->At(0) << " " << fBz->At(0) << endl; + //cout << fBr->At(n-1) << " " << fBz->At(n-1) << endl; + + cout << "-I- <SpdAxialFieldMapData::ReadAsciiFile> Read field values: " + << n << "/" << nTot << endl; + + return kTRUE; +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::ReadBinaryFile() +{ + TString fileName = fFileName; + + if (!fPathToData.IsWhitespace()) fileName = fPathToData + fileName; + + cout << "-I- <SpdAxialFieldMapData::ReadBinaryFile> Reading file: " + << fileName << endl; + + FILE* fl = fopen(fileName.Data(),"rb"); + + if (!fl) { + cout << "-E- <SpdAxialFieldMapData::ReadBinaryFile> File cannot be opened: " + << fileName << endl; + return kFALSE; + } + + Int_t len; + char sdata[256]; + Int_t si = sizeof(Int_t); + Int_t sd = sizeof(Double_t); + + // Read map type + fread(&len,si,1,fl); + fgets(sdata,len,fl); + + fMapType = sdata; + + // Read Units + + fread(&len,si,1,fl); + fgets(sdata,len,fl); + + if (!SetScaleUnit(TString(sdata,len-1))) return kFALSE; + + fread(&len,si,1,fl); + fgets(sdata,len,fl); + + if (!SetFieldUnit(TString(sdata,len-1))) return kFALSE; + + // Read grid parameters + + Double_t rmin, rmax, zmin, zmax; + + fread(&rmin,sd,1,fl); + fread(&rmax,sd,1,fl); + fread(&fNr,si,1,fl); + + fread(&zmin,sd,1,fl); + fread(&zmax,sd,1,fl); + fread(&fNz,si,1,fl); + + if (fMapRegion) delete fMapRegion; + fMapRegion = new SpdTubeRegion(); + + fMapRegion->SetTubeRegion(rmin*fScaleUnit, rmax*fScaleUnit, + zmin*fScaleUnit, zmax*fScaleUnit); + + if (!IsGridInit()) { + cout << "-E- <SpdAxialFieldMapData:ReadBinaryFile> Bad grid parameters: "; + cout << "N(r,z) = " << fNr << ", " << fNz << endl; + cout << "[min,max] = R[" << rmin << ", " << rmax << "], " + << " Z[" << zmin << ", " << zmax << "]" << endl; + + fclose(fl); + + return kFALSE; + } + + // Create field arrays + + Int_t nTot = GetNTotal(); + + fBr = new TArrayD(nTot); + fBz = new TArrayD(nTot); + + // Read the field values + + Double_t vd; + + Int_t n = 0; + for (; n < nTot; n++) { + fread(&vd,sd,1,fl); fBr->AddAt(vd*fFieldUnit, n); + fread(&vd,sd,1,fl); fBz->AddAt(vd*fFieldUnit, n); + } + + fclose(fl); + + //cout << fBr->At(0) << " " << fBz->At(0) << endl; + //cout << fBr->At(n-1) << " " << fBz->At(n-1) << endl; + + cout << "-I- <SpdAxialFieldMapData::ReadBinaryFile> Read field values: " + << n << "/" << nTot << endl; + + return kTRUE; +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::WriteAsciiFile(TString fileName, TString dirName) const +{ + // Write the field map to an ASCII file + + if (fileName.IsWhitespace()) { + cout << "-E- <SpdAxialFieldMapData::WriteAsciiFile> File is not defined " << endl; + return kFALSE; + } + + if (!fileName.EndsWith(".dat")) fileName += ".dat"; + + if (!dirName.IsWhitespace()) { + if (!dirName.EndsWith("/")) dirName += "/"; + fileName = dirName + fileName; + } + + cout << "-I- <SpdAxialFieldMapData::WriteAsciiFile> Write field map data to an ASCII file: " + << fileName << endl; + + std::ofstream mapFile(fileName); + if (!mapFile.is_open()) { + cout << "-E- <SpdAxialFieldMapData::WriteAsciiFile> Could not open file: " + << fileName << endl; + return kFALSE; + } + + /* FIXME * FIXME * FIXME * FIXME * FIXME */ +// Double_t sunit_tmp = fScaleUnit; +// Double_t funit_tmp = fFieldUnit; +// +// Double_t& su_tmp = const_cast<Double_t&>(fScaleUnit); +// Double_t& fu_tmp = const_cast<Double_t&>(fFieldUnit); +// +// su_tmp = 1.; +// fu_tmp = 1.; + /* FIXME * FIXME * FIXME * FIXME * FIXME */ + + mapFile << fMapType << endl; + + mapFile << GetScaleUnitAsString() << " " << GetFieldUnitAsString() << endl; + + if (!IsDataInit()) { + + mapFile << GetRmin()/fScaleUnit << " " << GetRmax()/fScaleUnit << " " << 0 << endl; + mapFile << GetZmin()/fScaleUnit << " " << GetZmax()/fScaleUnit << " " << 0 << endl; + + mapFile.close(); + + /* FIXME * FIXME * FIXME * FIXME * FIXME */ +// su_tmp = sunit_tmp; +// fu_tmp = funit_tmp; + /* FIXME * FIXME * FIXME * FIXME * FIXME */ + + cout << "-W- <SpdAxialFieldMapData::WriteAsciiFile> Empty data arrays " << endl; + + return kFALSE; + } + + mapFile << GetRmin()/fScaleUnit << " " << GetRmax()/fScaleUnit << " " << fNr << endl; + mapFile << GetZmin()/fScaleUnit << " " << GetZmax()/fScaleUnit << " " << fNz << endl; + + Double_t dr = GetRstep(); + Double_t dz = GetZstep(); + + Int_t index; + + for (Int_t ir(0); ir < fNr; ir++) { + for (Int_t iz(0); iz < fNz; iz++) { + + index = ir*fNz + iz; + + mapFile << Form("%20.14f %20.14f %20.14f %20.14f \n", + (GetRmin() + ir*dr)/fScaleUnit, + (GetZmin() + iz*dz)/fScaleUnit, + fBr->At(index)/fFieldUnit, + fBz->At(index)/fFieldUnit); + + }} + + /* FIXME * FIXME * FIXME * FIXME * FIXME */ +// su_tmp = sunit_tmp; +// fu_tmp = funit_tmp; + /* FIXME * FIXME * FIXME * FIXME * FIXME */ + + mapFile.close(); + + return kTRUE; +} + +//_____________________________________________________________________________________ +Bool_t SpdAxialFieldMapData::WriteBinaryFile(TString fileName, TString dirName) const +{ + // Write the field map to an ASCII file + + if (fileName.IsWhitespace()) { + cout << "-E- <SpdAxialFieldMapData::WriteBinaryFile> File is not defined " << endl; + return kFALSE; + } + + if (!fileName.EndsWith(".bin")) fileName += ".bin"; + + if (!dirName.IsWhitespace()) { + if (!dirName.EndsWith("/")) dirName += "/"; + fileName = dirName + fileName; + } + + cout << "-I- <SpdAxialFieldMapData::WriteBinaryFile> Write field map data to an BINARY file: " + << fileName << endl; + + FILE* fl = fopen(fileName.Data(),"wb"); + + if (!fl) { + cout << "-E- <SpdAxialFieldMapData::WriteBinaryFile> File cannot be written: " + << fileName << endl; + return kFALSE; + } + + Int_t len , vi; + TString sdata; + Double_t vd; + Int_t si = sizeof(Int_t); + Int_t sd = sizeof(Double_t); + + len = fMapType.Length()+1; + fwrite(&len,si,1,fl); + fputs(fMapType.Data(),fl); + + sdata = GetScaleUnitAsString(); + + len = sdata.Length()+1; + fwrite(&len,si,1,fl); + fputs(sdata.Data(),fl); + + sdata = GetFieldUnitAsString(); + + len = sdata.Length()+1; + fwrite(&len,si,1,fl); + fputs(sdata.Data(),fl); + + Double_t value; + + // Save grid + + if (!IsDataInit()) { + + vi = 0; + + vd = GetRmin()/fScaleUnit; fwrite(&vd,sd,1,fl); + vd = GetRmax()/fScaleUnit; fwrite(&vd,sd,1,fl); + fwrite(&vi,si,1,fl); + + vd = GetZmin()/fScaleUnit; fwrite(&vd,sd,1,fl); + vd = GetZmax()/fScaleUnit; fwrite(&vd,sd,1,fl); + fwrite(&vi,si,1,fl); + + fclose(fl); + + cout << "-W- <SpdAxialFieldMapData::WriteBinaryFile> Empty data arrays " << endl; + + return kFALSE; + } + + vd = GetRmin()/fScaleUnit; fwrite(&vd,sd,1,fl); + vd = GetRmax()/fScaleUnit; fwrite(&vd,sd,1,fl); + fwrite(&fNr,si,1,fl); + + vd = GetZmin()/fScaleUnit; fwrite(&vd,sd,1,fl); + vd = GetZmax()/fScaleUnit; fwrite(&vd,sd,1,fl); + fwrite(&fNz,si,1,fl); + + // Save field values + + Int_t nTot = GetNTotal(); + + for (Int_t n(0); n < nTot; n++) { + + vd = fBr->At(n)/fFieldUnit; fwrite(&vd,sd,1,fl); + vd = fBz->At(n)/fFieldUnit; fwrite(&vd,sd,1,fl); + } + + fclose(fl); + + return kTRUE; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +void SpdAxialFieldMapData::PrintData() const +{ + cout << "<SpdAxialFieldMapData::Print> " << endl; + + cout << "\t Data map name: " << fMapName << endl; + cout << "\t Path to data: " << fPathToData << endl; + cout << "\t File name: " << fFileName << endl; + cout << "\t Map type: " << fMapType << endl; + cout << endl; + cout << "\t Original Scale unit: " << fScaleUnit + << " [" << GetScaleUnitAsString() << "] " << endl; + cout << "\t Original Field unit: " << fFieldUnit << " [" + << GetFieldUnitAsString() << "] " << endl; + cout << endl; + cout << "\t [Grid] " << endl; + cout << "\t N(r,z): " << fNr << ", " << fNz + << " [TOTAL = " << GetNTotal() << "] "<< endl; + + if (fMapRegion) { + cout << "\t R[min,max]: " << fMapRegion->GetRmin() << ", " + << fMapRegion->GetRmax() << " [cm]" << " (dr = " << GetRstep() << " cm) " << endl; + cout << "\t Z[min,max]: " << fMapRegion->GetZmin() << ", " + << fMapRegion->GetZmax() << " [cm]" << " (dz = " << GetZstep() << " cm) " << endl; + } + else { + cout << "\t MAP REGION is not defined " << endl; + } + + cout << endl; +} diff --git a/field/SpdAxialFieldMapData.h b/field/SpdAxialFieldMapData.h new file mode 100644 index 0000000000000000000000000000000000000000..1612a757421f923415dcd7589ca41258cc284ac9 --- /dev/null +++ b/field/SpdAxialFieldMapData.h @@ -0,0 +1,142 @@ +// $Id$ +// Author: artur 2020/07/04 + +#ifndef __SPDAXIALFIELDMAPDATA_H__ +#define __SPDAXIALFIELDMAPDATA_H__ + +#include <TString.h> +#include <TArrayD.h> +#include "SpdRegion.h" + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdRadialField // +// // +// <brief class description> // +// // +// Base units: // +// // +// - FIELD [kG] // +// - SPACING [cm] // +// - ANGLES [deg] // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdAxialFieldMapData { + +public: + + SpdAxialFieldMapData(); + SpdAxialFieldMapData(const Char_t* name, const Char_t* type = ""); + + virtual ~SpdAxialFieldMapData(); + + virtual void Clear(); + virtual void ClearData(); + + virtual Bool_t InitData(TString fileName, TString path = ""); + virtual Bool_t InitData(const SpdAxialFieldMapData* data); + virtual Bool_t InitData(Double_t rmin, Double_t rmax, Int_t nr, + Double_t zmin, Double_t zmax, Int_t nz); + + void SetPathToData(TString path); + + /* ----- transform field data ----- */ + + virtual void MultiplyField(Double_t v); + virtual void MultiplyField(Double_t vr, Double_t vz); + + /* ----- getters ----- */ + + inline TString GetPathToData() const { return fPathToData; } + inline TString GetFileName() const { return fFileName; } + + inline TString GetMapName() const { return fMapName; } + inline TString GetMapType() const { return fMapType; } + + inline Double_t GetScaleUnit() const { return fScaleUnit; } + inline Int_t GetFieldUnit() const { return fFieldUnit; } + + TString GetFieldUnitAsString() const; + TString GetScaleUnitAsString() const; + + inline Bool_t GetInitLevel() const { return fInitLevel; } + + Bool_t IsGridInit() const; + Bool_t IsDataInit() const; + + Bool_t IsInsideMapRegion(Double_t x, Double_t y, Double_t z) const; + Bool_t IsInsideMapRegion(Double_t r, Double_t z) const; + + inline Int_t GetNr() const { return fNr; } + virtual Int_t GetNz() const { return fNz; } + + inline Int_t GetNTotal() const { return fNr*fNz; } + + inline const SpdRegion* GetMapRegion() const { return fMapRegion; } + + inline Double_t GetRmin() const { return (fMapRegion) ? fMapRegion->GetRmin() : 0; } + inline Double_t GetRmax() const { return (fMapRegion) ? fMapRegion->GetRmax() : 0; } + + virtual Double_t GetZmin() const { return (fMapRegion) ? fMapRegion->GetZmin() : 0; } + virtual Double_t GetZmax() const { return (fMapRegion) ? fMapRegion->GetZmax() : 0; } + + Double_t GetRstep() const; + Double_t GetZstep() const; + + inline TArrayD* GetBr() const { return fBr; } + inline TArrayD* GetBz() const { return fBz; } + + inline Double_t GetBr(Int_t n) const { return (fBr && (n > -1) && (n < GetNTotal()) ) ? fBr->At(n) : 0; } + inline Double_t GetBz(Int_t n) const { return (fBz && (n > -1) && (n < GetNTotal()) ) ? fBz->At(n) : 0; } + + virtual Bool_t GetMinMaxStat(Double_t* B /* array of size 6: (B,Bz,Br)[min,max]*/ ) const; + + /* ----- write data to a file ----- */ + + virtual Bool_t WriteAsciiFile(TString fileName, TString dirName = "") const; + virtual Bool_t WriteBinaryFile(TString fileName, TString dirName = "") const; + + /* ----- print data ----- */ + + virtual void PrintData() const; + +protected: + + virtual Bool_t InitData(); + + virtual void SetMapType(TString type = ""); + virtual Bool_t SetScaleUnit(TString unit); + virtual Bool_t SetFieldUnit(TString unit); + + TString fMapName; // Map name + + TString fPathToData; // File name + TString fFileName; // File name + + TString fMapType; // Map type + + Double_t fScaleUnit; // Original grid scale factor (spatial); default = 1 (cm) + Double_t fFieldUnit; // Original field units of the map; default = 1 (kG) + + Int_t fInitLevel; // Initialization level + + SpdTubeRegion* fMapRegion; // Field region + + Int_t fNr; // Grid points in radial direction + Int_t fNz; // Grid points along Z-axis + + /* Arrays with the field values */ + TArrayD* fBr; + TArrayD* fBz; + + virtual Bool_t ReadAsciiFile(); // Read a field map from ASCII file + virtual Bool_t ReadBinaryFile(); // Read a field map from BINARY file + + friend class SpdField; + + ClassDef(SpdAxialFieldMapData,1) +}; + +#endif /* __SPDAXIALFIELDMAPDATA_H__ */ + diff --git a/field/SpdFieldCreator.cxx b/field/SpdFieldCreator.cxx index 52e6f9e60ec313079765ae7466322efa9cd80ea9..b460cc3efcb088e377e989274899453d290363fd 100644 --- a/field/SpdFieldCreator.cxx +++ b/field/SpdFieldCreator.cxx @@ -10,6 +10,7 @@ #include "SpdConstField.h" #include "SpdRadialField.h" #include "SpdFieldMap.h" +#include "SpdAxialFieldMap.h" #include "SpdMultiField.h" #include <iostream> @@ -93,6 +94,7 @@ FairField* SpdFieldCreator::CreateSingleField(TString name, Int_t type) else if (type == 0) MagneticField = new SpdConstField(fFieldPar,name); else if (type == 1) MagneticField = new SpdRadialField(fFieldPar,name); else if (type == 2) MagneticField = new SpdFieldMap(fFieldPar,name); + else if (type == 3) MagneticField = new SpdAxialFieldMap(fFieldPar,name); else { MagneticField = new SpdField(); diff --git a/field/SpdFieldMap.cxx b/field/SpdFieldMap.cxx index ad1db5622f5a52b44f85e3bb277880f95af2a63f..79906ac8b2f2403e24015ad21ddb68feea7cc183 100644 --- a/field/SpdFieldMap.cxx +++ b/field/SpdFieldMap.cxx @@ -5,6 +5,7 @@ #include "SpdFieldMap.h" #include "SpdFieldPar.h" +#include <TSystem.h> #include <TMath.h> #include <iostream> @@ -44,7 +45,7 @@ fApproxMethod(0) { fType = 2; SetTitle("Map"); - + if (!fieldPar) { cout << "-E- <SpdField::SpdFieldMap> Empty parameter container " << endl; SetNFieldParameters(6); @@ -54,13 +55,7 @@ fApproxMethod(0) GetFieldParameters(fieldPar); GetRegionParameters(fieldPar); - TString workdir = getenv("VMCWORKDIR"); - if (workdir.IsNull()) - workdir = "../"; - workdir += "/input/"; - workdir.ReplaceAll("//","/"); - - SpdFieldMapData::InitData(fFileName, workdir); + InitData(fFileName); if (Abs(fParams[0]-1.) > 1e-9 || Abs(fParams[1]-1.) > 1e-9 || @@ -86,14 +81,51 @@ void SpdFieldMap::Clear() //_____________________________________________________________________________ Bool_t SpdFieldMap::InitData(TString fileName, TString path) { - TString pathToData = path; - if(pathToData.IsNull()) { - pathToData = getenv("VMCWORKDIR"); - if (pathToData.IsNull()) - pathToData = "../"; - pathToData += "/input/"; - pathToData.ReplaceAll("//","/"); - } + TString pathToData; + Bool_t found = false; + + while (true) + { + // if absolute path to magnetic field map + if (path.BeginsWith("/") ) { + if (!gSystem->AccessPathName(path.Data())) { + pathToData = path; + found = true; + cout << "-I- <SpdFieldMap::InitData> Path to the field map: " << pathToData << endl; + break; + } + } + + // if MAGFPATH (path to magnetic field map) is set + path = getenv("MAGFPATH"); + path.ReplaceAll("//","/"); + if (!path.IsNull() ) { + if (!gSystem->AccessPathName(path.Data())) { + pathToData = path; + found = true; + cout << "-I- <SpdFieldMap::InitData> Path to the field map ($MAGFPATH): " << pathToData << endl; + break; + } + } + + // if file was not found look it in the standard path + path = TString(getenv("VMCWORKDIR")); + path.ReplaceAll("//","/"); + if (!path.IsNull() ) { + (path.EndsWith("/")) ? path += "input/" : path += "/input/"; + if (!gSystem->AccessPathName(path.Data())) { + pathToData = path; + cout << "-I- <SpdFieldMap::InitData> Path to the field map ($VMCWORKDIR/input): " << pathToData << endl; + found = true; + break; + } + } + + break; + } + + if (!found) cout << "-I- <SpdFieldMap::InitData> Search for the field map in a current directory: " << endl; + return SpdFieldMapData::InitData(fileName,pathToData); } diff --git a/field/SpdFieldMapData.cxx b/field/SpdFieldMapData.cxx index 53922e11773df42de00d738b3d0be0c7a9dcdd62..9f409019123c964c4cd9eb5c5fc75ab46c88bebf 100644 --- a/field/SpdFieldMapData.cxx +++ b/field/SpdFieldMapData.cxx @@ -164,7 +164,7 @@ Bool_t SpdFieldMapData::SetScaleUnit(TString unit) // protected else if (unit == "m") fScaleUnit = 100.0; else if (unit == "cm") fScaleUnit = 1.0; else { - cout << "-E- <SpdFieldMap::SetScaleUnit> Unknown unit: " << unit << endl; + cout << "-E- <SpdFieldMapData::SetScaleUnit> Unknown unit: " << unit << endl; fScaleUnit = 1; return kFALSE; } @@ -178,7 +178,7 @@ Bool_t SpdFieldMapData::SetFieldUnit(TString unit) // protected else if (unit == "T") fFieldUnit = 10.0; else if (unit == "kG") fFieldUnit = 1.0; else { - cout << "-E- <SpdFieldMap::SetFieldUnit> Unknown unit: " << unit << endl; + cout << "-E- <SpdFieldMapData::SetFieldUnit> Unknown unit: " << unit << endl; fFieldUnit = 1; return kFALSE; } @@ -192,7 +192,7 @@ TString SpdFieldMapData::GetScaleUnitAsString() const if (fScaleUnit == 100.0) return "m"; if (fScaleUnit == 1.0) return "cm"; - cout << "-E- <SpdFieldMap::GetScaleUnitString> Unknown unit: " << fScaleUnit << endl; + cout << "-E- <SpdFieldMapData::GetScaleUnitString> Unknown unit: " << fScaleUnit << endl; return "unknown"; } @@ -203,7 +203,7 @@ TString SpdFieldMapData::GetFieldUnitAsString() const if (fFieldUnit == 10.0) return "T"; if (fFieldUnit == 1.0) return "kG"; - cout << "-E- <SpdFieldMap::GetFieldUnitString> Unknown unit: " << fFieldUnit << endl; + cout << "-E- <SpdFieldMapData::GetFieldUnitString> Unknown unit: " << fFieldUnit << endl; return "unknown"; } @@ -226,19 +226,18 @@ Bool_t SpdFieldMapData::InitData(TString fileName, TString path) if (fileName.EndsWith(".dat")) { if (!ReadAsciiFile()) { - cout << "-F- <SpdFieldMap::Init> Bad data (*.dat) file " << endl; + cout << "-F- <SpdFieldMapData::Init> Bad data (*.dat) file " << endl; exit(1); } } else if (fileName.EndsWith(".bin")) { if (!ReadBinaryFile()) { - cout << "-F- <SpdFieldMap::Init> Bad data (*.bin) file " << endl; + cout << "-F- <SpdFieldMapData::Init> Bad data (*.bin) file " << endl; exit(1); } } - else { - cout << "-E- <SpdFieldMap::Init> No proper file name defined: " + cout << "-E- <SpdFieldMapData::Init> No proper file name defined: " << fileName << endl; Clear(); return kFALSE; @@ -461,7 +460,7 @@ Bool_t SpdFieldMapData::ReadAsciiFile() // protected std::ifstream mapFile(fileName); if (!mapFile.is_open()) { - cout << "-E- <SpdFieldMap:ReadAsciiFile> Could not open file: " << fileName << endl; + cout << "-E- <SpdFieldMapData:ReadAsciiFile> Could not open file: " << fileName << endl; return kFALSE; } @@ -493,7 +492,7 @@ Bool_t SpdFieldMapData::ReadAsciiFile() // protected zmin*fScaleUnit, zmax*fScaleUnit); if (!IsGridInit()) { - cout << "-E- <SpdFieldMap:ReadAsciiFile> Bad grid parameters: "; + cout << "-E- <SpdFieldMapData:ReadAsciiFile> Bad grid parameters: "; cout << "N(x,y,z) = " << fNx << ", " << fNy << ", " << fNz << endl; cout << "[min,max] = X[" << xmin << ", " << xmax << "], " << " Y[" << ymin << ", " << ymax << "]," @@ -617,7 +616,7 @@ Bool_t SpdFieldMapData::ReadBinaryFile() zmin*fScaleUnit, zmax*fScaleUnit); if (!IsGridInit()) { - cout << "-E- <SpdFieldMap:ReadAsciiFile> Bad grid parameters: "; + cout << "-E- <SpdFieldMapData:ReadBinaryFile> Bad grid parameters: "; cout << "N(x,y,z) = " << fNx << ", " << fNy << ", " << fNz << endl; cout << "[min,max] = X[" << xmin << ", " << xmax << "], " << " Y[" << ymin << ", " << ymax << "]," diff --git a/field/SpdFieldMapData.h b/field/SpdFieldMapData.h index e6ec447f8f6d5e456bbaf943b9b266fdd1a84fbf..85008648c3cdd1587a3993852dc23f9a4fa93c5f 100644 --- a/field/SpdFieldMapData.h +++ b/field/SpdFieldMapData.h @@ -38,7 +38,7 @@ public: virtual void Clear(); virtual void ClearData(); - virtual Bool_t InitData(TString fileName, TString path = "../input"); + virtual Bool_t InitData(TString fileName, TString path = ""); virtual Bool_t InitData(const SpdFieldMapData* data); virtual Bool_t InitData(Double_t xmin, Double_t xmax, Int_t nx, Double_t ymin, Double_t ymax, Int_t ny, @@ -82,7 +82,7 @@ public: inline Int_t GetNTotal() const { return fNx*fNy*fNz; } - inline const SpdRegion* GetMapRegion() const { return fMapRegion; } + inline const SpdBoxRegion* GetMapRegion() const { return fMapRegion; } inline Double_t GetXmin() const { return (fMapRegion) ? fMapRegion->GetXmin() : 0; } inline Double_t GetXmax() const { return (fMapRegion) ? fMapRegion->GetXmax() : 0; } @@ -134,7 +134,7 @@ protected: Int_t fInitLevel; // Initialization level - SpdRegion* fMapRegion; // Field region + SpdBoxRegion* fMapRegion; // Field region Int_t fNx; // Grid points along X-axis Int_t fNy; // Grid points along Y-axis diff --git a/gconfig/DecayConfig.C b/gconfig/DecayConfig.C index 47e8c9de397a54b3239b069001244f03b83a04e4..21f02782575acaf2262bb40ae924e4613232e2b2 100644 --- a/gconfig/DecayConfig.C +++ b/gconfig/DecayConfig.C @@ -6,12 +6,16 @@ * copied verbatim in the file "LICENSE" * ********************************************************************************/ -void Config(TPythia6Decayer* decayer); +void Config1(SpdPythia6Decayer* decayer); +void Config2(TPythia6Decayer* decayer); +void Config3(TPythia6Decayer* decayer); + +//________________________________________________________________________________________ void DecayConfig() { cout << "-I- <DecayConfig> " << endl; - + // This script uses the external decayer in place of the // concrete Monte Carlo native decay mechanisms only for the // specific types of decays defined below. @@ -19,67 +23,123 @@ void DecayConfig() // Access the external decayer singleton and initialize it //TPythia6Decayer* decayer = TPythia6Decayer::Instance(); - //Config(decayer); - + //Config3(decayer); + //SpdPythia6Decayer* decayer = new SpdPythia6Decayer(); - //Config(decayer); - + //Config3(decayer); + SpdDecayer* spd_decayer = SpdDecayer::Instance(); if (!spd_decayer->GetDecayer()) spd_decayer->SetDecayer("SpdPythia6Decayer",1); SpdPythia6Decayer* decayer = dynamic_cast<SpdPythia6Decayer*>(spd_decayer->GetDecayer()); - if (decayer) { - - //decayer->SetSeed(123456789); - - TPythia6& pythia6 = *(decayer->GetPythia()); - // .... make Pythia6 settings here if necessary ... - + +// if (decayer) { +// +// //decayer->SetSeed(123456789); +// +// TPythia6& pythia6 = *(decayer->GetPythia()); +// +// // .... make Pythia6 settings here if necessary ... +// // activate decays // // pythia6.SetMDCY(pythia6.Pycomp(211),1,1); // pi+ // pythia6.SetMDCY(pythia6.Pycomp(-211),1,1); // pi- // -// force decays for particles of a such type +// force user decayer for particles of a such type // // gMC->SetUserDecay(211); // pi+ // gMC->SetUserDecay(-211); // pi- - - } +// +// } + +// Config1(decayer); // FIXME + //exit(1); + if (!spd_decayer->IsInit()) spd_decayer->Init(); } //________________________________________________________________________________________ -void Config(TPythia6Decayer* decayer) +void Config1(SpdPythia6Decayer* decayer) { - // The following just tells pythia6 to not decay particles only to certain channels. + decayer->Init(); + + gMC->SetExternalDecayer(decayer); - decayer->SetForceDecay(TPythia6Decayer::kAll); + // ===== Print all decay channels ====== -// /* EXAMPLE: Force the J/PSI decay channel e+e- */ -// -// Int_t products[2], mult[2]; -// Int_t npart = 2; + decayer->PrintParticleDecayChannels(421); // D0 + decayer->PrintParticleDecayChannels(411); // D+ + decayer->PrintParticleDecayChannels(-313); // K*0_bar + + //decayer->PrintParticleDecayChannels(-421); // D0_bar (the same as D0) + //decayer->PrintParticleDecayChannels(-411); // D- (the same as D+) + //decayer->PrintParticleDecayChannels(313); // K*0 (the same as K*_0_bar) + + // ===== Select decay channels ====== + + // -> Fix primary vertices: + + // D0 (D0_bar) -> K-, pi+ + decayer->SelectForcedDecay(421,17); // pdg number, channel + //decayer->SelectForcedDecay(-421,17); + + // D+ (D-) -> K*0_bar, pi+ + decayer->SelectForcedDecay(411,24); // pdg number, channel + //decayer->SelectForcedDecay(-411,24); + + // D+ (D-) -> K-, pi+, pi+ + decayer->SelectForcedDecay(411,47); // pdg number, channel + //decayer->SelectForcedDecay(-421,47); + + // -> Fix secondary vertices (if necessary!): + + // K*0_bar (K*0) -> K+, pi- + decayer->SelectForcedDecay(-313,1); // pdg number, channel + + // just tells concrete monte carlo generator (for example, Geant4) + // to use external decayer for these type of particles + gMC->SetUserDecay(-313); // K*0_bar + gMC->SetUserDecay(313); // K*0 + + // ====== Force selected decay channels ====== + + decayer->ForceSelectedDecays(); +} + +//________________________________________________________________________________________ +void Config2(TPythia6Decayer* decayer) +{ + /* EXAMPLE: Force the J/PSI decay channel e+e- */ + +// Int_t products[2], mult[2]; +// Int_t npart = 2; // -// /* decay products */ -// products[0] = 11; -// products[1] = -11; -// -// /* multiplicity */ -// mult[0] = 1; -// mult[1] = 1; -// -// /* force the decay channel */ -// decayer->ForceParticleDecay(443,products,mult,npart); +// /* decay products */ +// products[0] = 11; +// products[1] = -11; +// +// /* minimal multiplicity in final state */ +// mult[0] = 1; +// mult[1] = 1; +// +// /* force J/PSI decay channel */ +// decayer->ForceParticleDecay(443,products,mult,npart); decayer->Init(); gMC->SetExternalDecayer(decayer); - - //return; +} + +//________________________________________________________________________________________ +void Config3(TPythia6Decayer* decayer) +{ + // The following just tells pythia6 to not decay particles only to certain channels. + decayer->SetForceDecay(TPythia6Decayer::kAll); + //-------------------------------------------------------------------- // Tell the concrete monte carlo to use the external decayer. // The external decayer will be used for: diff --git a/gconfig/DecayConfigSpecV0.C b/gconfig/DecayConfigSpecV0.C new file mode 100644 index 0000000000000000000000000000000000000000..7f2e04e41500d8c6084307b27d8d1981c601ad9f --- /dev/null +++ b/gconfig/DecayConfigSpecV0.C @@ -0,0 +1,80 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence version 3 (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +void Config(SpdPythia6Decayer* decayer); + +//________________________________________________________________________________________ +void DecayConfig() +{ + cout << "-I- <DecayConfigSpecV0:DecayConfig> " << endl; + + // This script uses the external decayer in place of the + // concrete Monte Carlo native decay mechanisms only for the + // specific types of decays defined below. + + SpdDecayer* spd_decayer = SpdDecayer::Instance(); + + if (!spd_decayer->GetDecayer()) spd_decayer->SetDecayer("SpdPythia6Decayer",1); + + SpdPythia6Decayer* decayer = dynamic_cast<SpdPythia6Decayer*>(spd_decayer->GetDecayer()); + + Config(decayer); // FIXME + + if (!spd_decayer->IsInit()) spd_decayer->Init(); +} + +//________________________________________________________________________________________ +void Config(SpdPythia6Decayer* decayer) +{ + decayer->Init(); + + gMC->SetExternalDecayer(decayer); + + // ===== Print all decay channels ====== + + //decayer->PrintParticleDecayChannels(421); // D0 + //decayer->PrintParticleDecayChannels(411); // D+ + //decayer->PrintParticleDecayChannels(-313); // K*0_bar + + //decayer->PrintParticleDecayChannels(-421); // D0_bar (the same as D0) + //decayer->PrintParticleDecayChannels(-411); // D- (the same as D+) + //decayer->PrintParticleDecayChannels(313); // K*0 (the same as K*_0_bar) + + // ===== Select decay channels ====== + + // -> Fix primary vertices: + + // D0 (D0_bar) -> K-, pi+ + decayer->SelectForcedDecay(421,17); // pdg number, channel + //decayer->SelectForcedDecay(-421,17); + +/* + // D+ (D-) -> K*0_bar, pi+ + decayer->SelectForcedDecay(411,24); // pdg number, channel + //decayer->SelectForcedDecay(-411,24); + + // D+ (D-) -> K-, pi+, pi+ + decayer->SelectForcedDecay(411,47); // pdg number, channel + //decayer->SelectForcedDecay(-421,47); + + // -> Fix secondary vertices (if necessary!): + + // K*0_bar (K*0) -> K+, pi- + decayer->SelectForcedDecay(-313,1); // pdg number, channel + + // just tells concrete monte carlo generator (for example, Geant4) + // to use external decayer for these type of particles + gMC->SetUserDecay(-313); // K*0_bar + gMC->SetUserDecay(313); // K*0 +*/ + + // ====== Force selected decay channels ====== + + decayer->ForceSelectedDecays(); +} + diff --git a/gconfig/g4Config.C b/gconfig/g4Config.C index 9a3f837c91f6de7ec7e2da835960daecdc51870c..f0264778896f5a8c24afe71ee1d634cd9e7781e1 100644 --- a/gconfig/g4Config.C +++ b/gconfig/g4Config.C @@ -53,7 +53,9 @@ void Config() TG4RunConfiguration* runConfiguration = new TG4RunConfiguration("geomRoot", "QGSP_FTFP_BERT", - "stepLimiter+specialCuts+specialControls+stackPopper"); + "stepLimiter+specialCuts+specialControls+stackPopper", + false + ); // TG4RunConfiguration* runConfiguration = // new TG4RunConfiguration("geomRoot", @@ -65,11 +67,13 @@ void Config() cout << "Geant4 has been created." << endl; + //geant4->ProcessGeantCommand("/mcTracking/skipNeutrino true"); + /* Create the Specific stack */ SpdStack* stack = new SpdStack(1000); - stack->StoreSecondaries(kTRUE); + stack->StoreSecondaries(true); stack->SetMinPoints(0); geant4->SetStack(stack); diff --git a/gconfig/g4config.in b/gconfig/g4config.in index 97aac92fbae1aab2503e40a57c1ebb9b4e01b217..e1abff6ac25b751f09add7278e7a4fda8081d46f 100644 --- a/gconfig/g4config.in +++ b/gconfig/g4config.in @@ -19,10 +19,10 @@ /run/particle/applyCuts -#/mcPhysics/rangeCutForGamma 0.1 mm -#/mcPhysics/rangeCutForElectron 0.1 mm -#/mcPhysics/rangeCutForPositron 0.1 mm -#/mcPhysics/rangeCuts 0.1 mm +/mcPhysics/rangeCutForGamma 0.1 mm +/mcPhysics/rangeCutForElectron 0.1 mm +/mcPhysics/rangeCutForPositron 0.1 mm +/mcPhysics/rangeCuts 0.1 mm #/mcRegions/print 1 diff --git a/geometry/cave_precise.geo b/geometry/cave_precise.geo index 9f4b66660790f6bbeed6e293e285285920fe6943..2e0822aef1d6ffd7c8651c3f4aadfe3a8f542f79 100644 --- a/geometry/cave_precise.geo +++ b/geometry/cave_precise.geo @@ -9,4 +9,4 @@ vacuum2 10000 -10000 10000 10000 10000 10000 -10000 10000 10000 --10000 -10000 10000 \ No newline at end of file +-10000 -10000 10000 diff --git a/geometry/media.geo b/geometry/media.geo index 40073a7f88bbf2ddb77c02d14be1bf24ed76bc5c..969a9f3be1ee1d2fddc6493006eff8d66687c3be 100644 --- a/geometry/media.geo +++ b/geometry/media.geo @@ -1,19 +1,16 @@ -//---------------------------------------------------------- +//---------------------------------------------------------- air 3 14.01 16. 39.95 7. 8. 18. 1.205e-3 .755 .231 .014 0 1 30. .001 - 0 + 0 // 1.205e-3 g/cmВі eq 1e3 mbar (see air) // 1e-8 mbar eq 1.205e-6 * 1e-8 g/cmВі - -vacuumX 1 1.008 1.0 1.e-30 - 0 1 30. .001 - 0 + vacuum0 3 14.01 16. 39.95 7. 8. 18. 1.e-16 .755 .231 .014 0 1 30. .001 0 vacuum 3 14.01 16. 39.95 7. 8. 18. 1.205e-14 .755 .231 .014 - 0 1 30. .001 + 0 1 30. .01 0 vacuum7 3 14.01 16. 39.95 7. 8. 18. 1.205e-13 .755 .231 .014 0 1 30. .001 @@ -2187,11 +2184,29 @@ ArCO2 3 39.948 12.01 15.9994 18. 6. 8. 0.00346 0.9 0.0333 0.0667 // Argon CO2 (70/30) arco27030 -3 39.948 12.01 15.9994 18. 6. 8. 0.0019 700 100 200 1 1 20. 0.001 - 0 + 0 + +// Argon CO2 (70/30), density x 1.5 +arco27030x1p5 -3 39.948 12.01 15.9994 18. 6. 8. 0.00285 700 100 200 + 1 1 20. 0.001 + 0 +// Argon CO2 (70/30), density x 2.0 +arco27030x2p0 -3 39.948 12.01 15.9994 18. 6. 8. 0.0038 700 100 200 + 1 1 20. 0.001 + 0 + // Argon CO2 (80/20) arco28020 -3 39.948 12.01 15.9994 18. 6. 8. 0.0019 800 66.66 133.33 1 1 20. 0.001 0 +// Argon CO2 (80/20), density x 1.5 +arco28020x1p5 -3 39.948 12.01 15.9994 18. 6. 8. 0.00285 800 66.66 133.33 + 1 1 20. 0.001 + 0 +// Argon CO2 (80/20), density x 2.0 +arco28020x2p0 -3 39.948 12.01 15.9994 18. 6. 8. 0.0038 800 66.66 133.33 + 1 1 20. 0.001 + 0 //rohacell 1 rohacell -3 1.0079 12.011 15.999 1. 6. 8. 0.052 8. 5. 2. @@ -2271,8 +2286,29 @@ MCoilSubAl -9 92.9 47.867 63.54 26.98 54.938 28.09 51.996 58.6 41 22 29 13 25 14 24 28 26 4.3 0.038 0.038 0.064 0.688 0.003 0.002 0.033 0.017 0.117 0 1 30. .001 - 0 - + 0 + +// "air" and "vacuum" for a different drawing prperties (for example, transparency) +//------------------------------------------------------------------------------------- +airX 3 14.01 16. 39.95 7. 8. 18. 1.205e-3 .755 .231 .014 + 0 1 30. .001 + 0 +airX1 3 14.01 16. 39.95 7. 8. 18. 1.205e-3 .755 .231 .014 + 0 1 30. .001 + 0 +airX2 3 14.01 16. 39.95 7. 8. 18. 1.205e-3 .755 .231 .014 + 0 1 30. .001 + 0 +vacuumX 3 14.01 16. 39.95 7. 8. 18. 1.205e-14 .755 .231 .014 + 0 1 30. .001 + 0 +vacuumX1 3 14.01 16. 39.95 7. 8. 18. 1.205e-14 .755 .231 .014 + 0 1 30. .001 + 0 +vacuumX2 3 14.01 16. 39.95 7. 8. 18. 1.205e-14 .755 .231 .014 + 0 1 30. .001 + 0 + // ----- Caution with putting materials below that line ----- // The next materials must specify additional parameters! diff --git a/input/map_qsolRZ_6cls2cm.bin b/input/map_qsolRZ_6cls2cm.bin new file mode 100644 index 0000000000000000000000000000000000000000..fa1cea94502fbbb45f2fbf5bac6ff3a4e795dcb4 Binary files /dev/null and b/input/map_qsolRZ_6cls2cm.bin differ diff --git a/input/urqmd_pdg.dat b/input/urqmd_pdg.dat new file mode 100644 index 0000000000000000000000000000000000000000..8241a430601c01230fb8f7e8cc9327df5c4a1bbe --- /dev/null +++ b/input/urqmd_pdg.dat @@ -0,0 +1,316 @@ + 1017 1114 + 1018 31114 + 1019 1112 + 1020 11114 + 1021 11112 + 1022 1116 + 1023 21112 + 1024 21114 + 1025 11116 + 1026 1118 + 1040 3112 + 1041 3114 + 1042 13112 + 1043 13114 + 1044 23112 + 1045 3116 + 1046 13116 + 1047 23114 + 1048 3118 + 1049 3312 + 1050 3314 + 1051 23314 + 1052 13314 + 1053 33314 + 1054 13316 + 1055 3334 + 1101 -211 + 1104 -213 + 1111 -9000211 + 1114 -20213 + 1118 -215 + 1122 -10213 + 1126 -100213 + 1130 -30213 + 2001 2112 + 2002 12112 + 2003 1214 + 2004 22112 + 2005 32112 + 2006 2116 + 2007 12116 + 2008 21214 + 2009 42112 + 2010 31214 + 2011 41214 + 2012 12118 + 2013 52114 + 2016 100012110 + 2017 2114 + 2018 32114 + 2019 1212 + 2020 12114 + 2021 11212 + 2022 1216 + 2023 21212 + 2024 22114 + 2025 11216 + 2026 2118 + 2027 3122 + 2028 13122 + 2029 3124 + 2030 23122 + 2031 33122 + 2032 13124 + 2033 43122 + 2034 53122 + 2035 3126 + 2036 13126 + 2037 23124 + 2038 3128 + 2039 23126 + 2040 3212 + 2041 3214 + 2042 13212 + 2043 13214 + 2044 23212 + 2045 3216 + 2046 13216 + 2047 23214 + 2048 3218 + 2049 3322 + 2050 3324 + 2051 23324 + 2052 13324 + 2053 33324 + 2054 13326 + 2100 22 + 2101 111 + 2102 221 + 2103 223 + 2104 113 + 2105 9000221 + 2106 311 + 2107 331 + 2108 313 + 2109 333 + 2110 333 + 2111 9000111 + 2112 10221 + 2113 20313 + 2114 20113 + 2115 20223 + 2116 20333 + 2117 315 + 2118 115 + 2119 225 + 2120 335 + 2121 10313 + 2122 10113 + 2123 10223 + 2124 10333 + 2125 100313 + 2126 100113 + 2127 100223 + 2128 100333 + 2129 30313 + 2130 30113 + 2131 30223 + 2132 337 + 3001 2212 + 3002 12212 + 3003 2124 + 3004 22212 + 3005 32212 + 3006 2216 + 3007 12216 + 3008 22124 + 3009 42212 + 3010 32124 + 3011 42124 + 3012 12218 + 3013 52214 + 3016 100012210 + 3017 2214 + 3018 32214 + 3019 2122 + 3020 12214 + 3021 12122 + 3022 2126 + 3023 22122 + 3024 22214 + 3025 12126 + 3026 2218 + 3040 3222 + 3041 3224 + 3042 13222 + 3043 13224 + 3044 23222 + 3045 3226 + 3046 13226 + 3047 23224 + 3048 3228 + 3101 211 + 3104 213 + 3106 321 + 3108 323 + 3110 10321 + 3111 9000211 + 3113 20323 + 3114 20213 + 3117 325 + 3118 215 + 3121 10323 + 3122 10213 + 3125 100323 + 3126 100213 + 3129 30323 + 3130 30213 + 4017 2224 + 4018 32224 + 4019 2222 + 4020 12224 + 4021 12222 + 4022 2226 + 4023 22222 + 4024 22224 + 4025 12226 + 4026 2228 + -3055 -3334 + -3054 -13316 + -3053 -33314 + -3052 -13314 + -3051 -23314 + -3050 -3314 + -3049 -3312 + -3048 -3118 + -3047 -23114 + -3046 -13116 + -3045 -3116 + -3044 -23112 + -3043 -13114 + -3042 -13112 + -3041 -3114 + -3040 -3112 + -3026 -1118 + -3025 -11116 + -3024 -21114 + -3023 -21112 + -3022 -1116 + -3021 -11112 + -3020 -11114 + -3019 -1112 + -3018 -31114 + -3017 -1114 + -2129 -30313 + -2125 -100313 + -2121 -10313 + -2117 -315 + -2113 -20313 + -2110 -10311 + -2108 -313 + -2106 -311 + -2055 -3334 + -2054 -13326 + -2053 -33324 + -2052 -13324 + -2051 -23324 + -2050 -3324 + -2049 -3322 + -2048 -3218 + -2047 -23214 + -2046 -13216 + -2045 -3216 + -2044 -23212 + -2043 -13214 + -2042 -13212 + -2041 -3214 + -2040 -3212 + -2039 -23126 + -2038 -3128 + -2037 -23124 + -2036 -13126 + -2035 -3126 + -2034 -53122 + -2033 -43122 + -2032 -13124 + -2031 -33122 + -2030 -23122 + -2029 -3124 + -2028 -13122 + -2027 -3122 + -2026 -2118 + -2025 -11216 + -2024 -22114 + -2023 -21212 + -2022 -1216 + -2021 -11212 + -2020 -12114 + -2019 -1212 + -2018 -32114 + -2017 -2114 + -2016 -100012110 + -2013 -52114 + -2012 -12118 + -2011 -41214 + -2010 -31214 + -2009 -42112 + -2008 -21214 + -2007 -12116 + -2006 -2116 + -2005 -32112 + -2004 -22112 + -2003 -1214 + -2002 -12112 + -2001 -2112 + -1129 -30323 + -1125 -100323 + -1121 -10323 + -1117 -325 + -1113 -20323 + -1110 -10321 + -1108 -323 + -1106 -321 + -1048 -3228 + -1047 -23224 + -1046 -13226 + -1045 -3226 + -1044 -23222 + -1043 -13224 + -1042 -13222 + -1041 -3224 + -1040 -3222 + -1026 -2218 + -1025 -12126 + -1024 -22214 + -1023 -22122 + -1022 -2126 + -1021 -12122 + -1020 -12214 + -1019 -2122 + -1018 -32214 + -1017 -2214 + -1016 -100012210 + -1013 -52214 + -1012 -12218 + -1011 -42124 + -1010 -32124 + -1009 -42212 + -1008 -22124 + -1007 -12216 + -1006 -2216 + -1005 -32212 + -1004 -22212 + -1003 -2124 + -1002 -12212 + -1001 -2212 + -26 -2228 + -25 -12226 + -24 -22224 + -23 -22222 + -22 -2226 + -21 -12222 + -20 -12224 + -19 -2222 + -18 -32224 + -17 -2224 diff --git a/its/CMakeLists.txt b/its/CMakeLists.txt index 74f9f6a328779fc16785f278611ca9f6b2125d86..aca12b25a8c28f0e8123b8b200df9dab18a15089 100644 --- a/its/CMakeLists.txt +++ b/its/CMakeLists.txt @@ -40,6 +40,14 @@ SpdItsPoint.cxx ) +set(HEADERS +SpdItsContFact.h +SpdIts.h +SpdItsParSet.h +SpdItsPoint.h +) + + Set(LINKDEF SpdItsLinkDef.h) Set(LIBRARY_NAME SpdIts) Set(DEPENDENCIES Base SpdData SpdCommon SpdGeometry SpdField) diff --git a/its/SpdIts.cxx b/its/SpdIts.cxx index 703c4b8dfad56793fb820046f02696fffc3948bb..0d0ba4bf6d3c593ee9ec8426610a021dd7a15d32 100644 --- a/its/SpdIts.cxx +++ b/its/SpdIts.cxx @@ -109,7 +109,7 @@ void SpdIts::Initialize() //_____________________________________________________________________________________ void SpdIts::Reset() { - fPointCollection->Clear(); + if (fPointCollection) fPointCollection->Clear(); } //_____________________________________________________________________________________ @@ -124,9 +124,8 @@ void SpdIts::Register() //_____________________________________________________________________________________ Bool_t SpdIts::ProcessHits(FairVolume* vol) { - //cout << "<SpdIts::ProcessHits> " << endl; - + // Set parameters at entrance of volume if (gMC->IsTrackEntering()) { diff --git a/its/SpdItsPoint.cxx b/its/SpdItsPoint.cxx index c6a490aaab3043d1d52b42ce6dd9bcfb8c42141f..b13a8f862367b62bae8c5282b6088d57dbb80e17 100644 --- a/its/SpdItsPoint.cxx +++ b/its/SpdItsPoint.cxx @@ -49,6 +49,32 @@ void SpdItsPoint::GetPosTime(TVector3& pos, Double_t& t) const t = fTime; } +//_____________________________________________________________________________ +Double_t SpdItsPoint::GetSegLength() const +{ + Double_t s2 = (fXOut-fX)*(fXOut-fX) + (fYOut-fY)*(fYOut-fY) + (fZOut-fZ)*(fZOut-fZ); + return TMath::Sqrt(s2); +} + +//_____________________________________________________________________________ +Bool_t SpdItsPoint::IsSpecialPoint(Int_t& vid, Double_t& dep) const +{ + vid = -1; + dep = 0.; + + if (fVid.size() != 2) return kFALSE; + + vid = fVid[0]; + if (vid < 0) { + if (fVid[1] < 0) return kFALSE; + vid = fVid[1]; + } + + dep = fVed[0] + fVed[1]; + + return kTRUE; +} + //_____________________________________________________________________________________ void SpdItsPoint::Print(const Option_t* opt) const { @@ -59,7 +85,8 @@ void SpdItsPoint::Print(const Option_t* opt) const cout << " Node(ID): " << fNodeId << endl; cout << " Position, (in): " << fX << ", " << fY << ", " << fZ << " [cm] " << endl; cout << " Position, (out): " << fXOut << ", " << fYOut << ", " << fZOut << " [cm] " << endl; - cout << " Time, Length: " << fTime << " [ns] " << fLength << " [s] " << endl; + cout << " Time, Length: " << fTime << " [ns] " << fLength << " [s] " << endl; + cout << " Segment length: " << GetSegLength()*10 << " [mm] " << endl; cout << " Momentum (in): " << fPx << ", " << fPy << ", " << fPz << " [GeV]" << endl; cout << " Momentum (out): " << fPxOut << ", " << fPyOut << ", " << fPzOut << " [GeV]" << endl; cout << " Energy loss: " << fELoss*1.0e06 << " [keV] " << endl; diff --git a/its/SpdItsPoint.h b/its/SpdItsPoint.h index 9f0dc10049421f72d2817621b676640088266af0..38f742611d2ccf2feb9822664c103fab85c99ef9 100644 --- a/its/SpdItsPoint.h +++ b/its/SpdItsPoint.h @@ -65,7 +65,10 @@ public: Int_t GetVid(Int_t i) const { return (i > -1 && i < Int_t(fVid.size())) ? fVid[i] : -1; } Double_t GetVed(Int_t i) const { return (i > -1 && i < Int_t(fVed.size())) ? fVed[i] : 0; } - virtual void GetPosTime(TVector3& pos, Double_t& t) const; + virtual void GetPosTime(TVector3& pos, Double_t& t) const; + virtual Double_t GetSegLength() const; + + virtual Bool_t IsSpecialPoint(Int_t& vid, Double_t& dep) const; virtual void Print(const Option_t* opt) const; diff --git a/macro/SimuHyb.C b/macro/SimuHyb.C index 4ed27f931ba8f6382358f918de0b3df26ca71617..4270716c662df7e30502aedbe72b50102b262967 100644 --- a/macro/SimuHyb.C +++ b/macro/SimuHyb.C @@ -44,6 +44,9 @@ void SimuHyb(Int_t nEvents = 1) SpdRunSim* run = new SpdRunSim(); run->SetName("TGeant4"); + //run->SetMaterials("media.geo"); + + //gSystem->Setenv("GEOMPATH","/home/artur/Projects/1/"); run->SetMaterials("media.geo"); run->SetOutputFile(outFile); @@ -61,10 +64,10 @@ void SimuHyb(Int_t nEvents = 1) /* ++++++++++++++++++ CAVE ++++++++++++++++++ */ FairModule* cave = new SpdCave("CAVE"); - //cave->SetGeometryFileName("cave.geo"); - cave->SetGeometryFileName("cave_precise.geo"); + cave->SetGeometryFileName("cave.geo"); + //cave->SetGeometryFileName("cave_precise.geo"); run->AddModule(cave); - +// return; /* ++++++++++++++++++ PIPE ++++++++++++++++++ */ SpdPipe* Pipe = new SpdPipe(); @@ -72,25 +75,24 @@ void SimuHyb(Int_t nEvents = 1) /* +++++++++++++++++ MAGNET +++++++++++++++++ */ - SpdHybMagnet* Magnet = new SpdHybMagnet(); - Magnet->SetGeometryType(1); // 1 (hybrid, deafult), 2 (qsolenoid) + SpdHybMagnet* Magnet = new SpdHybMagnet(); // default geometry type = 2 run->AddModule(Magnet); /* +++++++++++++++++ DETECTORS ++++++++++++++ */ - SpdTsTB* ts_barrel = new SpdTsTB(); /* +++++++++ TST (BARREL) ++++++++++++ */ - SpdTsTEC* ts_ecps = new SpdTsTEC(); /* +++++++++ TST (ENDCAPS) +++++++++++ */ - SpdEcalTB* ecal_barrel = new SpdEcalTB(); /* +++++++++ ECALT (BARREL) ++++++++++ */ - SpdEcalTEC* ecal_ecps = new SpdEcalTEC(); /* +++++++++ ECALT (ENDCAPS) +++++++++ */ - SpdRsTB* rs_barrel = new SpdRsTB(); /* +++++++++ RST (BARREL) ++++++++++++ */ - SpdRsTEC* rs_ecps = new SpdRsTEC(); /* +++++++++ RST (ENDCAPS) +++++++++++ */ - - run->AddModule(ts_barrel); - run->AddModule(ecal_barrel); - run->AddModule(rs_barrel); - run->AddModule(ts_ecps); - run->AddModule(ecal_ecps); - run->AddModule(rs_ecps); + SpdTsTB* ts_barrel = new SpdTsTB(); /* +++++++++ TST (BARREL) ++++++++++++ */ + SpdTsTEC* ts_ecps = new SpdTsTEC(); /* +++++++++ TST (ENDCAPS) +++++++++++ */ + SpdEcalTB* ecal_barrel = new SpdEcalTB(); /* +++++++++ ECALT (BARREL) ++++++++++ */ + SpdEcalTEC* ecal_ecps = new SpdEcalTEC(); /* +++++++++ ECALT (ENDCAPS) +++++++++ */ + SpdRsTB* rs_barrel = new SpdRsTB(); /* +++++++++ RST (BARREL) ++++++++++++ */ + SpdRsTEC* rs_ecps = new SpdRsTEC(); /* +++++++++ RST (ENDCAPS) +++++++++++ */ + + run->AddModule(ts_barrel); + run->AddModule(ecal_barrel); + run->AddModule(rs_barrel); + run->AddModule(ts_ecps); + run->AddModule(ecal_ecps); + run->AddModule(rs_ecps); //ts_barrel->SetParametersType("SpdTsTBParSet"); // TsTBParSet (default), SpdTsTBParSet //ts_barrel->SaveDetIdOption(1); // 1, 2 (default) @@ -119,8 +121,8 @@ void SimuHyb(Int_t nEvents = 1) /* --- field map --- */ SpdFieldMap* MagField = new SpdFieldMap("Hybrid field"); - MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field - //MagField->InitData("map_sol_6cls5cm2.bin"); // "quasi-solenoid" + //MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field + MagField->InitData("map_sol_6cls5cm2.bin"); // "quasi-solenoid" //MagField->SetApproxMethod(0); // 0 (linear,default) or 1 (nearest vertex) //MagField->MultiplyField(1); @@ -160,17 +162,18 @@ void SimuHyb(Int_t nEvents = 1) //----------------------------------------------------------- // Set seed: + //gRandom->SetSeed(0); + gRandom->SetSeed(54545); - gRandom->SetSeed(0); Int_t seed = gRandom->Integer(Int_t(1e9)); - P6gen->SetSeed(seed); + //P6gen->SetSeed(seed); //P6gen->SetSeed(0); //P6gen->SetSeed(144135822, 2); //P6gen->SetSeed(12995,0); //P6gen->SetSeed(19949278, 1); - //P6gen->SetSeed(13495); + P6gen->SetSeed(13495); //P6gen->SetSeed(127472); @@ -181,7 +184,7 @@ void SimuHyb(Int_t nEvents = 1) /* --- Pythia6 initialization --- */ - P6gen->Initialize("cms","p","p",26/*GeV*/); + P6gen->Initialize("cms","p","p",27/*GeV*/); primGen->AddGenerator(P6gen); @@ -206,7 +209,7 @@ void SimuHyb(Int_t nEvents = 1) //run->SetStoreTraj(kTRUE); - SpdCommonGeoMapper::Instance()->SaveEmptyHits(); + //SpdCommonGeoMapper::Instance()->SaveEmptyHits(); //run->ForceParticleLifetime(-211, 26.033/5.); // pdg, life time [ns] //run->ForceParticleLifetime( 211, 26.033/5.); // pdg, life time [ns] @@ -265,12 +268,13 @@ void SimuHyb(Int_t nEvents = 1) cout << endl << endl; cout << "Macro finished succesfully." << endl; - cout << "Output file is " << outFile << endl; - cout << "Parameter file is " << parFile << endl; + cout << "Output file is " << outFile << endl; + cout << "Parameter file is " << parFile << endl; + cout << "Seed (prim.gen.) is " << seed << endl; cout << "Real time " << rtime << " s, CPU time " << ctime << "s" << endl; cout << endl; - cout << " seed = " << seed << endl; + /*--------------------------------------------------*/ //SpdCommonGeoMapper::Instance()->PrintGeometryList(); diff --git a/macro/SimuQsl.C b/macro/SimuQsl.C new file mode 100644 index 0000000000000000000000000000000000000000..633653077d4025cd68b29161ea8bb96abf826bc8 --- /dev/null +++ b/macro/SimuQsl.C @@ -0,0 +1,323 @@ + +//#define _COMPILE_MACRO_ + +#if defined(_COMPILE_MACRO_) + +#include <TRint.h> +#include <TStopwatch.h> + +#include "FairParRootFileIo.h" + +#include "SpdRunSim.h" +#include "SpdMCEventHeader.h" + +#include "SpdCommonGeoMapper.h" + +#include "SpdFields.hh" +#include "SpdGenerators.hh" + +#include "SpdCave.h" +#include "SpdPipe.h" + +#include "SpdIts.h" +#include "SpdTsTB.h" +#include "SpdTsTEC.h" +#include "SpdEcalTB.h" +#include "SpdEcalTEC.h" +#include "SpdRsTB.h" +#include "SpdRsTEC.h" + +#include "SpdItsGeoMapperX.h" +#include "SpdTsTBGeoBuilder.h" + +#endif + +//_________________________________________________________________________ +void SimuQsl(Int_t nEvents = 1) +{ + TString outFile = "run_tor.root"; // Output data file name + TString parFile = "params_tor.root"; // Output parameters file name + + SpdRunSim* run = new SpdRunSim(); + + run->SetName("TGeant4"); + //run->SetMaterials("media.geo"); + + //gSystem->Setenv("GEOMPATH","/home/artur/Projects/1/"); + run->SetMaterials("media.geo"); + + run->SetOutputFile(outFile); + + run->SetPythiaDecayer("DecayConfig.C"); + + run->SetMCEventHeader(new SpdMCEventHeader); + /*--------------------------------------------------*/ + /* +++++++++ GEOMETRY (QSOLENOID) ++++++++ */ + /*--------------------------------------------------*/ + + SpdCommonGeoMapper::Instance()->DefineQslGeometrySet(); + + /* ++++++++++++++++++ CAVE ++++++++++++++++++ */ + + FairModule* cave = new SpdCave("CAVE"); + //cave->SetGeometryFileName("cave.geo"); + //cave->SetGeometryFileName("cave_precise.geo"); + run->AddModule(cave); + + /* ++++++++++++++++++ PIPE ++++++++++++++++++ */ + + SpdPipe* Pipe = new SpdPipe(); + //Pipe->UnsetMaterials("air"); + run->AddModule(Pipe); + + /* +++++++++ MAGNET +++++++++ */ + + SpdHybMagnet* Magnet = new SpdHybMagnet(); + run->AddModule(Magnet); + + /* +++++++++++++++++ DETECTORS ++++++++++++++ */ + SpdEcalTB2* ecal_barrel = new SpdEcalTB2(); /* +++++++++ ECAL (BARREL) ++++++++++ */ + SpdEcalTEC2* ecal_ecps = new SpdEcalTEC2(); /* +++++++++ ECAL (ENDCAPS) +++++++++ */ + SpdRsTB2* rs_barrel = new SpdRsTB2(); /* +++++++++ RS (BARREL) ++++++++++++ */ + SpdRsTEC2* rs_ecps = new SpdRsTEC2(); /* +++++++++ RS (ENDCAPS) +++++++++++ */ + SpdTsTB* ts_barrel = new SpdTsTB(); /* +++++++++ TS (BARREL) ++++++++++++ */ + SpdTsTEC* ts_ecps = new SpdTsTEC(); /* +++++++++ TS (ENDCAPS) +++++++++++ */ + + run->AddModule(ts_barrel); + run->AddModule(ecal_barrel); + run->AddModule(rs_barrel); + run->AddModule(ts_ecps); + run->AddModule(ecal_ecps); + run->AddModule(rs_ecps); + + /* ===== Vertex detector ===== */ + + SpdIts* its = new SpdIts(); + run->AddModule(its); + + //SpdItsGeoMapperX::Instance()->SetGeometryPars(1); + //SpdItsGeoMapperX::Instance()->EnableEndcaps(); // enable(1)/disable(0) Inner Tracker (Its) endcaps ; default = enable + + //its->SaveEmptyHits(); + + /*--------------------------------------------------*/ + /* ++++++++++++ CUSTOMIZE GEOMETRY +++++++++++++ */ + /*--------------------------------------------------*/ + + // Chose TsTEC configuration + // + // option = 1: 2 endcaps x 3 modules, 1 module = 8x2 = 16 layers, total = 48 layers (default) + // option = 2: 2 endcaps x 2 modules, 1 module = 8x2 = 16 layers, total = 32 layers + // option = 3: 2 endcaps x 1 modules, 1 module = 26x2 = 52 layers, total = 52 layers (actual!) + + SpdTsTECGeoMapper::Instance()->SetGeometryPars(3); + + /*--------------------------------------------------*/ + /* ++++++++++++ CUSTOMIZE MATERIALS +++++++++++++ */ + /*--------------------------------------------------*/ + + //SpdParameter* par; + + /* --- alter TsTB straw active media (gas) --- */ + //par = ts_barrel->GetMapper()->AddParameter("TsTBBaseStrawMaterial"); + //if (par) *par = "arco28020x1p5"; // ArCO2, 80/20 %, density x 1.5 + //if (par) *par = "arco28020x2p0"; // ArCO2, 80/20 %, density x 2.0 + //if (par) *par = "arco27030x1p5"; // ArCO2, 70/30 %, density x 1.5 + //if (par) *par = "arco27030x2p0"; // ArCO2, 70/30 %, density x 2.0 + + /* --- alter TsTEC straw active media (gas) --- */ + //par = ts_ecps->GetMapper()->AddParameter("TsTECBaseStrawMaterial"); + //if (par) *par = "arco28020x1p5"; // ArCO2, 80/20 %, density x 1.5 + //if (par) *par = "arco28020x2p0"; // ArCO2, 80/20 %, density x 2.0 + //if (par) *par = "arco27030x1p5"; // ArCO2, 70/30 %, density x 1.5 + //if (par) *par = "arco27030x2p0"; // ArCO2, 70/30 %, density x 2.0 + + /* --- reset all module's materials ---*/ + //ts_barrel->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + //ts_ecps->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + //its->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + + /*--------------------------------------------------*/ + /* ++++++++++++++ MAGNETIC FIELD ++++++++++++++ */ + /*--------------------------------------------------*/ + + /* --- axial field map --- */ + SpdAxialFieldMap* MagField = new SpdAxialFieldMap("QSolenoidal field"); + MagField->InitData("map_qsolRZ_6cls2cm.bin"); + MagField->MultiplyField(0.8); + + /* --- const field --- */ + //SpdConstField* MagField = new SpdConstField(); + //MagField->SetField(0., 0., 8.0); // kG + + /* --- field map --- */ + //SpdFieldMap* MagField = new SpdFieldMap("Hybrid field"); + + //MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field + //MagField->InitData("map_sol_6cls5cm2.bin"); // "quasi-solenoid" + + //MagField->SetApproxMethod(0); // 0 (linear,default) or 1 (nearest vertex) + //MagField->MultiplyField(1); + + /* === define field region === */ + SpdRegion* reg = 0; + + //reg = MagField->CreateFieldRegion("box"); + //reg->SetBoxRegion(-1000, 1000, -1000, 1000, -1000, 1000); // (X,Y,Z)_(min,max), cm + + reg = MagField->CreateFieldRegion("tube"); + reg->SetTubeRegion(0, 174, -246, 246); // (R,Z)_(min,max), cm + + run->SetField(MagField); + + MagField->Print(); + + /*--------------------------------------------------*/ + /* ++++++++++ DEFINE PRIMARY GENERATORS +++++++++++ */ + /*--------------------------------------------------*/ + + SpdPrimaryGenerator* primGen = new SpdPrimaryGenerator(); + + //============================ + // PYTHIA 6 GENERATOR + //============================ + + SpdPythia6Generator* P6gen = new SpdPythia6Generator(); + + //----------------------------------------------------------- + // Option: (decayer for vertex meson- and baryon- resonances) + // 0 = Transport generator + External decayer (particles don't decay in the vertex) + // 1 = Primary generator (DEFAULT value, more safely) + + P6gen->SetVGenOpt(1); + + //----------------------------------------------------------- + // Set seed: + + gRandom->SetSeed(0); + Int_t seed = gRandom->Integer(Int_t(1e9)); + P6gen->SetSeed(seed,0); + + //P6gen->SetSeed(0); + //P6gen->SetSeed(144135822, 2); + + //P6gen->SetSeed(12995,0); + //P6gen->SetSeed(19949278, 1); + //P6gen->SetSeed(13495); + //P6gen->SetSeed(127472); + + + /* --- Set Pythia6 options --- */ + SpdPythia6* gg = (SpdPythia6*)P6gen->GetGenerator(); + + gg->SetMSEL(1); // set miminum bias + + + /* --- Pythia6 initialization --- */ + P6gen->Initialize("cms","p","p",27/*GeV*/); + + primGen->AddGenerator(P6gen); + + primGen->SetVerboseLevel(-10); + primGen->SetVerbose(0); + + //============================ + + run->SetGenerator(primGen); + + primGen->SetBeam(0., 0., 0.1, 0.1); // (X,Y)- position, (X,Y)- (2*delta or sigma) [cm] + primGen->SmearVertexXY(kTRUE); +// //primGen->SmearGausVertexXY(kTRUE); +// + primGen->SetTarget(0.,5.); // Z- position, 2*delta or sigma [cm] + primGen->SmearVertexZ(kTRUE); +// //primGen->SmearGausVertexZ(kTRUE); + + /* ------------------------------------------------ */ + /* +++++++++++++++ GLOBAL OPTIONS +++++++++++++++++ */ + /* ------------------------------------------------ */ + + //run->SetStoreTraj(kTRUE); + + //SpdCommonGeoMapper::Instance()->SaveEmptyHits(); + + //run->ForceParticleLifetime(-211, 26.033/5.); // pdg, life time [ns] + //run->ForceParticleLifetime( 211, 26.033/5.); // pdg, life time [ns] + + //SpdCommonGeoMapper::Instance()->UnsetMaterials(false); + + /* ----------------------------------------------------------------------- */ + /* >>>>>>>>>>>>>>>>>>>>>>>>>>> INITALIZE RUN <<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ + /* ----------------------------------------------------------------------- */ + + cout << "\n\t" << "++++++++++++++++++++++++++++++++++++++++++++" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "+ Init Run (start) +" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "++++++++++++++++++++++++++++++++++++++++++++\n" << endl; + + run->Init(); + + cout << "\n\t" << "++++++++++++++++++++++++++++++++++++++++++++" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "+ Init Run (finish) +" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "++++++++++++++++++++++++++++++++++++++++++++\n" << endl; + + /*--------------------------------------------------*/ + /* +++++++++++++ CREATE RUN PARAMETERS +++++++++++ */ + /*--------------------------------------------------*/ + + Bool_t MergePars = kFALSE; + FairParRootFileIo* parOut = new FairParRootFileIo(MergePars); + if (MergePars) parOut->open(parFile.Data()); + else parOut->open(parFile.Data(),"RECREATE"); + + FairRuntimeDb* rtdb = run->GetRuntimeDb(); + rtdb->setOutput(parOut); + + /* ----------------------------------------------------------------------- */ + /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RUN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ + /* ----------------------------------------------------------------------- */ + + TStopwatch timer; + timer.Start(); + + run->Run(nEvents); + + timer.Stop(); + + /*--------------------------------------------------*/ + /* ++++++++++++ SAVE RUN PARAMETERS +++++++++++++ */ + /*--------------------------------------------------*/ + + rtdb->saveOutput(); + + /*--------------------------------------------------*/ + + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + + cout << endl << endl; + cout << "Macro finished succesfully." << endl; + cout << "Output file is " << outFile << endl; + cout << "Parameter file is " << parFile << endl; + cout << "Seed (prim.gen.) is " << seed << endl; + cout << "Real time " << rtime << " s, CPU time " << ctime << "s" << endl; + cout << endl; + + /*--------------------------------------------------*/ + + //SpdCommonGeoMapper::Instance()->PrintGeometryList(); + SpdCommonGeoMapper::Instance()->PrintGeometry(); + + //SpdItsGeoMapperX::Instance()->PrintVolPars(); + //SpdItsGeoMapperX::Instance()->PrintGeoTable(); + //SpdItsGeoMapperX::Instance()->Print(""); + + /*--------------------------------------------------*/ + + gApplication->Terminate(); +} + + diff --git a/macro/analysis/CheckNodePath.C b/macro/analysis/CheckNodePath.C new file mode 100644 index 0000000000000000000000000000000000000000..8e577e6b6414d0b160b435b470df01ac307554cb --- /dev/null +++ b/macro/analysis/CheckNodePath.C @@ -0,0 +1,46 @@ + + +void Print(SpdGeopathParser& ppath); + +void CheckNodePath() +{ + + SpdGeopathParser ppath; + TString nodepath; + + nodepath = "/cave_1/SideSVol_8/LayerSideSVol_2/L4930EnvelopeVol_5/L4930MDTSVol_1/L4930CellVol_3/L4930GasCellVol_1"; + + ppath.ParsePath(nodepath); + cout << "MODULE NUMBER: " << ppath.Num(2) << endl; + + Print(ppath); + + nodepath = "/cave_1/SideSVol_3/LayerSideSVol_2/L4930EnvelopeVol_5/L4930MDTSVol_1/L4930CellVol_3/L4930GasCellVol_1"; + + ppath.ParsePath(nodepath); + cout << "MODULE NUMBER: " << ppath.Num(2) << endl; + + Print(ppath); + + nodepath = "/cave_1/TsTBModule3_6/TsTBLayer127_25/TsTBStraw89_2/TsTBStraw89Shell_1"; + + ppath.ParsePath(nodepath); + cout << "MODULE NUMBER: " << ppath.Num(2) << endl; + + Print(ppath); + +} + +void Print(SpdGeopathParser& ppath) +{ + Int_t max_geo_level = ppath.GetCurrentPathLevel(); + cout << ppath.GetCurrentPathString() << endl; + + for (Int_t i(1); i<=max_geo_level; i++) { + cout << i << " " << ppath.Num(i) << " "<< ppath.VNum(i) << " "<< ppath.Name(i) << " :: " << ppath.Path(i) << endl; + + } + + + +} diff --git a/macro/analysis/CheckOutputData.C b/macro/analysis/CheckOutputData.C index d71d6b5b282b0b959a1961dc1f840704083c36de..f10c16e22ea4b21249044ab919bffbf17021673c 100644 --- a/macro/analysis/CheckOutputData.C +++ b/macro/analysis/CheckOutputData.C @@ -3,12 +3,15 @@ void check_headers(); void check_mctracks(); void check_points_tstb(); -void check_points_tssb(); - void check_points_tstec(); - void check_points_its(); +void check_points_ecaltb2(); +void check_points_ecaltec2(); + +void check_points_rstb2(); +void check_points_rstec2(); + void check_geotracks(); void readparams(TString stype); @@ -18,19 +21,20 @@ TTree* t = 0; TString inFile, inParFile; //________________________________________________________________________________ -void CheckOutputData(TString stype = "tor") { +void CheckOutputData(TString path = "", TString stype = "tor") { // - + if (!path.IsWhitespace() && !path.EndsWith("/")) path += "/"; + // Input data & parameters files if (stype == "tor" || stype == "hyb") { - inFile = "run_tor.root"; - inParFile = "params_tor.root"; + inFile = path+"run_tor.root"; + inParFile = path+"params_tor.root"; } else if (stype == "sol") { - inFile = "run_sol.root"; - inParFile = "params_sol.root"; + inFile = path+"run_sol.root"; + inParFile = path+"params_sol.root"; } else { cout << "<CheckOutputData> Unknown data type: " << stype << endl; @@ -50,10 +54,16 @@ void CheckOutputData(TString stype = "tor") { check_headers(); check_mctracks(); - //check_points_tstb(); - //check_points_tstec(); + check_points_tstb(); + check_points_tstec(); check_points_its(); + check_points_rstb2(); + check_points_rstec2(); + + check_points_ecaltb2(); + check_points_ecaltec2(); + //check_geotracks(); } @@ -321,27 +331,192 @@ void check_points_its() } //______________________________________________________________________________ -void check_points_tssb() +void check_points_rstb2() +{ + // + if (!t) return; + + TBranch* branch = t->GetBranch("SpdRsTB2Point"); + if (!branch) return; + + cout << "\n+++++++++++++++++ <check_points_rstb> ++++++++++++++++++"; + cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + + TClonesArray *fT = 0; + t->SetBranchAddress("SpdRsTB2Point",&fT) ; + + int entries = branch->GetEntries(); + + cout << "Total number of RSTB2-point COLLECTIONS in the TREE = " << entries << endl; + + if (entries == 0) return; + + SpdRsTB2Point* point; + Int_t ne; + + for (int j(0); j <entries; j++) { + + branch->GetEntry(j); + + ne = fT->GetEntriesFast(); + + cout << "entry: " << j << " points = " << ne << endl; + + if (j == 0) { + cout << ">>>>>>>>>>>>>>>>> Print FIRST entry: " << j << endl; + + for (int i(0); i < ne; i++) { + point = (SpdRsTB2Point*)fT->At(i); + if (i < 2) point->Print(""); + } + + } + + if (j == entries-1) { + cout << ">>>>>>>>>>>>>>>>> Print LAST entry: " << j << endl; + + for (int i(0); i < ne; i++) { + point = (SpdRsTB2Point*)fT->At(i); + if (i < 2) point->Print(""); + } + } + } + + cout << "Total number of RSTB2-point COLLECTIONS in the TREE = " << entries << endl; +} + +//______________________________________________________________________________ +void check_points_rstec2() +{ + // + if (!t) return; + + TBranch* branch = t->GetBranch("SpdRsTEC2Point"); + if (!branch) return; + + cout << "\n+++++++++++++++++ <check_points_rstec> +++++++++++++++++"; + cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + + TClonesArray *fT = 0; + t->SetBranchAddress("SpdRsTEC2Point",&fT) ; + + int entries = branch->GetEntries(); + + cout << "Total number of RSTEC2-point COLLECTIONS in the TREE = " << entries << endl; + + if (entries == 0) return; + + SpdRsTEC2Point* point; + Int_t ne; + + for (int j(0); j <entries; j++) { + + branch->GetEntry(j); + + ne = fT->GetEntriesFast(); + + cout << "entry: " << j << " points = " << ne << endl; + + if (j == 0) { + cout << ">>>>>>>>>>>>>>>>> Print FIRST entry: " << j << endl; + + for (int i(0); i < ne; i++) { + point = (SpdRsTEC2Point*)fT->At(i); + if (i < 2) point->Print(""); + } + + } + + if (j == entries-1) { + cout << ">>>>>>>>>>>>>>>>> Print LAST entry: " << j << endl; + + for (int i(0); i < ne; i++) { + point = (SpdRsTEC2Point*)fT->At(i); + if (i < 2) point->Print(""); + } + } + } + + cout << "Total number of RSTEC2-point COLLECTIONS in the TREE = " << entries << endl; +} + +//______________________________________________________________________________ +void check_points_ecaltb2() +{ + // + if (!t) return; + + TBranch* branch = t->GetBranch("SpdEcalTB2Point"); + if (!branch) return; + + cout << "\n+++++++++++++++ <check_points_ecaltb> +++++++++++++++++"; + cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + + TClonesArray *fT = 0; + t->SetBranchAddress("SpdEcalTB2Point",&fT) ; + + int entries = branch->GetEntries(); + + cout << "Total number of ECALTB2-point COLLECTIONS in the TREE = " << entries << endl; + + if (entries == 0) return; + + SpdEcalTB2Point* point; + Int_t ne; + + for (int j(0); j <entries; j++) { + + branch->GetEntry(j); + + ne = fT->GetEntriesFast(); + + cout << "entry: " << j << " points = " << ne << endl; + + if (j == 0) { + cout << ">>>>>>>>>>>>>>>>> Print FIRST entry: " << j << endl; + + for (int i(0); i < ne; i++) { + point = (SpdEcalTB2Point*)fT->At(i); + if (i < 2) point->Print(""); + } + + } + + if (j == entries-1) { + cout << ">>>>>>>>>>>>>>>>> Print LAST entry: " << j << endl; + + for (int i(0); i < ne; i++) { + point = (SpdEcalTB2Point*)fT->At(i); + if (i < 2) point->Print(""); + } + } + } + + cout << "Total number of ECALTB2-point COLLECTIONS in the TREE = " << entries << endl; +} + +//______________________________________________________________________________ +void check_points_ecaltec2() { // if (!t) return; - TBranch* branch = t->GetBranch("SpdTsSBPoint"); + TBranch* branch = t->GetBranch("SpdEcalTEC2Point"); if (!branch) return; - cout << "\n+++++++++++++++++ <check_points_tssb> ++++++++++++++++++"; + cout << "\n+++++++++++++++ <check_points_ecaltec> +++++++++++++++++"; cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; TClonesArray *fT = 0; - t->SetBranchAddress("SpdTsSBPoint",&fT) ; + t->SetBranchAddress("SpdEcalTEC2Point",&fT) ; int entries = branch->GetEntries(); - cout << "Total number of TSSB-point COLLECTIONS in the TREE = " << entries << endl; + cout << "Total number of ECALTEC2-point COLLECTIONS in the TREE = " << entries << endl; if (entries == 0) return; - SpdTsSBPoint* point; + SpdEcalTEC2Point* point; Int_t ne; for (int j(0); j <entries; j++) { @@ -356,7 +531,7 @@ void check_points_tssb() cout << ">>>>>>>>>>>>>>>>> Print FIRST entry: " << j << endl; for (int i(0); i < ne; i++) { - point = (SpdTsSBPoint*)fT->At(i); + point = (SpdEcalTEC2Point*)fT->At(i); if (i < 2) point->Print(""); } @@ -366,13 +541,13 @@ void check_points_tssb() cout << ">>>>>>>>>>>>>>>>> Print LAST entry: " << j << endl; for (int i(0); i < ne; i++) { - point = (SpdTsSBPoint*)fT->At(i); + point = (SpdEcalTEC2Point*)fT->At(i); if (i < 2) point->Print(""); } } } - cout << "Total number of TSSB-point COLLECTIONS in the TREE = " << entries << endl; + cout << "Total number of ECALTEC2-point COLLECTIONS in the TREE = " << entries << endl; } //______________________________________________________________________________ diff --git a/macro/analysis/CheckOutputParams.C b/macro/analysis/CheckOutputParams.C index 538761ba2a262d5a38db42cf96643ff3450a941c..875ce1dca5688d0b74fe03e0c2014e7b19abc3b9 100644 --- a/macro/analysis/CheckOutputParams.C +++ b/macro/analysis/CheckOutputParams.C @@ -2,19 +2,21 @@ void ReadGeometry(); void ReadModules(); void ReadFieldPars(); -void ReadParameters(TString stype); +void ReadPassivePars(); +void ReadActivePars(TString stype); TString inParFile; TFile* fp; //________________________________________________________________________________ -void CheckOutputParams(TString stype = "tor") { +void CheckOutputParams(TString path = "", TString stype = "tor") { // + if (!path.IsWhitespace() && !path.EndsWith("/")) path += "/"; // Input data & parameters files if (stype == "tor" || stype == "hyb") { - inParFile = "params_tor.root"; + inParFile = path+"params_tor.root"; } else if (stype == "sol") { @@ -33,7 +35,8 @@ void CheckOutputParams(TString stype = "tor") { ReadGeometry(); ReadModules(); ReadFieldPars(); - ReadParameters(stype); + ReadPassivePars(); + ReadActivePars(stype); //fp->Close(); } @@ -65,11 +68,26 @@ void ReadModules() void ReadFieldPars() { SpdFieldPar* field_pars = (SpdFieldPar*)fp->Get("SpdFieldPar"); - if (field_pars) field_pars->print(1); + if (!field_pars) return; + + field_pars->print(1); + + SpdFieldCreator* fieldCreator = new SpdFieldCreator(); + SpdField* field = (SpdField*)fieldCreator->createFairField(field_pars); + if (!field) return; + + field->Print(""); +} + +//________________________________________________________________________ +void ReadPassivePars() +{ + SpdPassiveGeoParSet* passive_pars = (SpdPassiveGeoParSet*)fp->Get("PassiveGeoParSet"); + if (passive_pars) passive_pars->print(1); } //________________________________________________________________________ -void ReadParameters(TString stype) +void ReadActivePars(TString stype) { if (stype == "tor" || stype == "hyb") { diff --git a/macro/analysis/RestoreInput.C b/macro/analysis/RestoreInput.C index f21cd8c196e4d3516cd2261ccd20f75a85152700..041b7b8316659a96ccf81cdf7fd4fa61b1dc888e 100644 --- a/macro/analysis/RestoreInput.C +++ b/macro/analysis/RestoreInput.C @@ -130,9 +130,11 @@ void restore_modules() // load materials and create geometry top level (cave) SpdCommonGeoMapper::Instance()->OpenGeometry(); + + SpdPassiveGeoParSet* paspars = (SpdPassiveGeoParSet*)fp->Get("PassiveGeoParSet"); - FairModule* Cave = new SpdCave(); - Cave->SetGeometryFileName("cave.geo"); + SpdCave* Cave = new SpdCave(); + Cave->LoadParsFrom(paspars); Cave->ConstructGeometry(); // load full set of modules (passive and active) @@ -187,4 +189,4 @@ void restore_modules() } - \ No newline at end of file + diff --git a/macro/analysis/ecalt/CheckEcalTB2Points.C b/macro/analysis/ecalt/CheckEcalTB2Points.C new file mode 100644 index 0000000000000000000000000000000000000000..837ef44ccb0bf7b759aebd3d77f4a9e127b74ac6 --- /dev/null +++ b/macro/analysis/ecalt/CheckEcalTB2Points.C @@ -0,0 +1,186 @@ +TTree* Tree_ = 0; + +SpdParSet* EcalTBPars_; +SpdPrimGenParSet* GenPars_; + +TGeoNavigator* Ntor_ = 0; + +SpdMCEventHeader* Header_ = 0; +TClonesArray* MCTracks_ = 0; +TClonesArray* EcalPoints_ = 0; + +Int_t GeoLevel_ = 0; + +Bool_t LoadGeometryAndPars(TString inParFile); +Bool_t RegisterRunData(TString inFile); + +void AnalyseEvent(Int_t nevent); +Bool_t AnalysePoint(SpdEcalTB2Point* point); + +TTree* t = 0; + +TString inFile, inParFile; + +//________________________________________________________________________________ +void CheckEcalTB2Points() { + + TString inParFile = "test_params.root"; + TString inDataFile = "test_data.root"; + + if (!LoadGeometryAndPars(inParFile)) { + cout << "Bad geometry or parameters " << endl; + return; + } + + if (!RegisterRunData(inDataFile)) { + cout << "Bad data in the file " << endl; + return; + } + + Int_t entries = Tree_->GetEntries(); + + cout << "Entries(tree): " << entries << endl; + + if (entries == 0) return; + + //return; + + cout << "\n>>>>>>>>>>>>>>>> DATA : Ok! <<<<<<<<<<<<<<<<< " << endl; + + //entries = 1; // FIXME + + for (Int_t i(0); i < entries; i++) { + Tree_->GetEntry(i); + AnalyseEvent(i); + } +} + +//________________________________________________________________________________ +void AnalyseEvent(Int_t nevent) +{ + +// Header_->Print(1); + + //-------------------------- MC-TRACKS --------------------------------- +// Int_t ntracks = MCTracks_->GetEntriesFast(); + +// cout << "\n<Analyse> mctracks = " << ntracks << endl; +// +// SpdMCTrack* track; +// for (int i(0); i < ntracks; i++) { +// track = (SpdMCTrack*)MCTracks_->At(i); +// //if (i < 30) track->Print(i); +// if (track->GetMotherId() < 0) track->Print(i); +// } + + //--------------------------- EcalTB POINTS --------------------------- + + Int_t npoints = EcalPoints_->GetEntriesFast(); + + cout << "\n<Analyse> ecalQEC-points = " << npoints << " event: " << nevent << endl; + + SpdEcalTB2Point* point; + + for (Int_t i(0); i < npoints; i++) { + + point = (SpdEcalTB2Point*)EcalPoints_->At(i); + + AnalysePoint(point); + } +} + +//________________________________________________________________________________ +Bool_t AnalysePoint(SpdEcalTB2Point* point) +{ + if (!point) return false; + + cout << ">>>>>>>>>>>>>>>>> ANALYSE POINT >>>>>>>>>>>>>>>>>>>>>" << "\n\n"; + + point->Print(""); + + TString node_path = point->GetNodePath(); + + if (!Ntor_->cd(node_path)) { + cout << "No such node: " << node_path << endl; + return false; + } + else cout << "Current node path: " << Ntor_->GetPath() << "\n\n"; + + cout << "Energy deposited: " << point->GetEloss() << "\n"; + + SpdGeopathParser ppath; + ppath.ParsePath(node_path); + + cout << "\n"; + + return true; +} + +//________________________________________________________________________________ +Bool_t LoadGeometryAndPars(TString inParFile) +{ + TFile* fp = new TFile(inParFile); + if (!fp) return kFALSE; + + /* PRIMARY GENERATOR PARAMETERS */ + + GenPars_ = (SpdPrimGenParSet*)fp->Get("PrimGenParSet"); + if (!GenPars_) { + cout << "No PrimGen parameters " << endl; + return kFALSE; + } + + //GenPars_->print(1); + + /* RANGE SYSTEM BARREL (EcalTB) PARAMETERS */ + + EcalTBPars_ = (SpdParSet*)fp->Get("EcalTBParSet"); + if (!EcalTBPars_) { + cout << "No ECAL parameters " << endl; + return kFALSE; + } + + //EcalTBPars_->print(1); + + /* +++++++++++++++ LOAD GEOMETRY +++++++++++++++ */ + + FairGeoParSet* geoset = (FairGeoParSet*)fp->Get("FairGeoParSet"); + + Ntor_ = gGeoManager->GetCurrentNavigator(); + + /* DRAW GEOMETRY */ + //gGeoManager->SetVisLevel(2); + //gGeoManager->GetMasterVolume()->Draw("ogl"); + + return kTRUE; +} + +//________________________________________________________________________________ +Bool_t RegisterRunData(TString inFile) +{ + TFile* f = new TFile(inFile); + if (!f) return kFALSE; + + TTree* t = (TTree*)f->Get("cbmsim"); + if (!t) return kFALSE; + + TBranch* branch; + + branch = t->GetBranch("MCEventHeader."); + if (!branch) return kFALSE; + t->SetBranchAddress("MCEventHeader.",&Header_) ; + + //branch = t->GetBranch("SpdMCTrack"); + //if (!branch) return kFALSE; + //t->SetBranchAddress("SpdMCTrack",&MCTracks_); + + branch = t->GetBranch("SpdEcalTB2Point"); + if (!branch) return kFALSE; + t->SetBranchAddress("SpdEcalTB2Point",&EcalPoints_) ; + + cout << "\n>>>>>>>>>>>>>>>> FILE & TREE: Ok! <<<<<<<<<<<<<<<<< " << endl; + + Tree_ = t; + + return kTRUE; +} diff --git a/macro/analysis/ecalt/CheckEcalTEC2Points.C b/macro/analysis/ecalt/CheckEcalTEC2Points.C new file mode 100644 index 0000000000000000000000000000000000000000..f15fc1c93bd829b598ed3d8efded3c9991df80b1 --- /dev/null +++ b/macro/analysis/ecalt/CheckEcalTEC2Points.C @@ -0,0 +1,187 @@ +TTree* Tree_ = 0; + +SpdParSet* EcalTBPars_; +SpdPrimGenParSet* GenPars_; + +TGeoNavigator* Ntor_ = 0; + +SpdMCEventHeader* Header_ = 0; +TClonesArray* MCTracks_ = 0; +TClonesArray* EcalPoints_ = 0; + +Int_t GeoLevel_ = 0; + +Bool_t LoadGeometryAndPars(TString inParFile); +Bool_t RegisterRunData(TString inFile); + +void AnalyseEvent(Int_t nevent); +Bool_t AnalysePoint(SpdEcalTEC2Point* point); + +TTree* t = 0; + +TString inFile, inParFile; + +//________________________________________________________________________________ +void CheckEcalTEC2Points() { + + TString inParFile = "params_tor.root"; + TString inDataFile = "run_tor.root"; + + if (!LoadGeometryAndPars(inParFile)) { + cout << "Bad geometry or parameters " << endl; + return; + } + + if (!RegisterRunData(inDataFile)) { + cout << "Bad data in the file " << endl; + return; + } + + Int_t entries = Tree_->GetEntries(); + + cout << "Entries(tree): " << entries << endl; + + if (entries == 0) return; + + //return; + + cout << "\n>>>>>>>>>>>>>>>> DATA : Ok! <<<<<<<<<<<<<<<<< " << endl; + + //entries = 1; // FIXME + + for (Int_t i(0); i < entries; i++) { + Tree_->GetEntry(i); + AnalyseEvent(i); + } +} + +//________________________________________________________________________________ +void AnalyseEvent(Int_t nevent) +{ + +// Header_->Print(1); + + //-------------------------- MC-TRACKS --------------------------------- +// Int_t ntracks = MCTracks_->GetEntriesFast(); + +// cout << "\n<Analyse> mctracks = " << ntracks << endl; +// +// SpdMCTrack* track; +// for (int i(0); i < ntracks; i++) { +// track = (SpdMCTrack*)MCTracks_->At(i); +// //if (i < 30) track->Print(i); +// if (track->GetMotherId() < 0) track->Print(i); +// } + + //--------------------------- EcalTEC POINTS --------------------------- + + Int_t npoints = EcalPoints_->GetEntriesFast(); + + cout << "\n<Analyse> ecalQEC-points = " << npoints << " event: " << nevent << endl; + + SpdEcalTEC2Point* point; + + for (Int_t i(0); i < npoints; i++) { + + point = (SpdEcalTEC2Point*)EcalPoints_->At(i); + + AnalysePoint(point); + } +} + +//________________________________________________________________________________ +Bool_t AnalysePoint(SpdEcalTEC2Point* point) +{ + if (!point) return false; + + cout << ">>>>>>>>>>>>>>>>> ANALYSE POINT >>>>>>>>>>>>>>>>>>>>>" << "\n\n"; + + point->Print(""); + + TString node_path = point->GetNodePath(); + + if (!Ntor_->cd(node_path)) { + cout << "No such node: " << node_path << endl; + return false; + } + else cout << "Current node path: " << Ntor_->GetPath() << "\n\n"; + + cout << "Energy deposited: " << point->GetEloss() << "\n"; + + SpdGeopathParser ppath; + ppath.ParsePath(node_path); + + cout << "\n"; + + return true; +} + +//________________________________________________________________________________ +Bool_t LoadGeometryAndPars(TString inParFile) +{ + TFile* fp = new TFile(inParFile); + if (!fp) return kFALSE; + + /* PRIMARY GENERATOR PARAMETERS */ + + GenPars_ = (SpdPrimGenParSet*)fp->Get("PrimGenParSet"); + if (!GenPars_) { + cout << "No PrimGen parameters " << endl; + return kFALSE; + } + + //GenPars_->print(1); + + /* RANGE SYSTEM BARREL (EcalTB) PARAMETERS */ + + EcalTBPars_ = (SpdParSet*)fp->Get("EcalTECParSet"); + if (!EcalTBPars_) { + cout << "No ECAL parameters " << endl; + return kFALSE; + } + + //EcalTBPars_->print(1); + + /* +++++++++++++++ LOAD GEOMETRY +++++++++++++++ */ + + FairGeoParSet* geoset = (FairGeoParSet*)fp->Get("FairGeoParSet"); + + Ntor_ = gGeoManager->GetCurrentNavigator(); + + /* DRAW GEOMETRY */ + //gGeoManager->SetVisLevel(2); + //gGeoManager->GetMasterVolume()->Draw("ogl"); + + return kTRUE; +} + +//________________________________________________________________________________ +Bool_t RegisterRunData(TString inFile) +{ + TFile* f = new TFile(inFile); + if (!f) return kFALSE; + + TTree* t = (TTree*)f->Get("cbmsim"); + if (!t) return kFALSE; + + TBranch* branch; + + branch = t->GetBranch("MCEventHeader."); + if (!branch) return kFALSE; + t->SetBranchAddress("MCEventHeader.",&Header_) ; + + //branch = t->GetBranch("SpdMCTrack"); + //if (!branch) return kFALSE; + //t->SetBranchAddress("SpdMCTrack",&MCTracks_); + + branch = t->GetBranch("SpdEcalTEC2Point"); + if (!branch) return kFALSE; + t->SetBranchAddress("SpdEcalTEC2Point",&EcalPoints_) ; + + cout << "\n>>>>>>>>>>>>>>>> FILE & TREE: Ok! <<<<<<<<<<<<<<<<< " << endl; + + Tree_ = t; + + return kTRUE; +} + diff --git a/macro/analysis/its/CheckItsData.C b/macro/analysis/its/CheckItsData.C index 734ee30357fdcbaf49ea57708cd753904bd334da..b125c719bf6e316580f969006697e9ed333692f6 100644 --- a/macro/analysis/its/CheckItsData.C +++ b/macro/analysis/its/CheckItsData.C @@ -69,7 +69,7 @@ void CheckItsData() if (entries == 0) return; - return; + //return; cout << "\n>>>>>>>>>>>>>>>> DATA : Ok! <<<<<<<<<<<<<<<<< " << endl; @@ -130,12 +130,12 @@ void AnalyseEvent() point->Print(""); - //--------------- EXTRUCT CHANNEL DATA --------------------------- + //--------------- EXTRACT CHANNEL DATA --------------------------- cout << ">>>>>> Extract chip data: >>>>>>" << endl; ItsGeoBuilder_->SetNodePath(point->GetNodeId()); // set node (chip) - + ItsGeoBuilder_->GetDetectorPosition(pos_chip); // get chip position cout << "chip full path: " << ItsGeoBuilder_->GetNodePath() << endl; diff --git a/macro/analysis/rst/CheckRsTB2Data.C b/macro/analysis/rst/CheckRsTB2Data.C new file mode 100644 index 0000000000000000000000000000000000000000..a8723dfe8304ba0641de72fedd23398ddece30d4 --- /dev/null +++ b/macro/analysis/rst/CheckRsTB2Data.C @@ -0,0 +1,286 @@ +// #define _COMPILE_MACRO_ +// +// #if defined(_COMPILE_MACRO_) + +#include <TStopwatch.h> +#include <TTree.h> +#include <TClonesArray.h> +#include <TGeoManager.h> +#include <TGeoNavigator.h> + +#include "FairGeoParSet.h" +#include "FairBaseParSet.h" +#include "SpdPrimGenParSet.h" + +#include "SpdCommonGeoMapper.h" +#include "SpdCave.h" +#include "SpdDetector.h" + +#include "SpdMCEventHeader.h" +#include "SpdMCTrack.h" + +#include "SpdRsTB2.h" +#include "SpdRsTB2Point.h" + +//#endif + +TTree* Tree_ = 0; + +SpdParSet* RsTBPars_; +SpdPrimGenParSet* GenPars_; + +TGeoNavigator* Ntor_ = 0; + +SpdMCEventHeader* Header_ = 0; +TClonesArray* MCTracks_ = 0; +TClonesArray* RsTBPoints_ = 0; + +Int_t GeoLevel_ = 0; + +Bool_t LoadGeometryAndPars(TString inParFile); +Bool_t RegisterRunData(TString inFile); + +void AnalyseEvent(Int_t nevent); +Bool_t AnalysePoint(SpdRsTB2Point* point); + +Bool_t DetectorPosition(Double_t* p); +Bool_t DetectorOrientation(Double_t* v, Char_t dir); + +TTree* t = 0; + +TString inFile, inParFile; + +//________________________________________________________________________________ +void CheckRsTB2Data() { + // + TString inParFile = "params_tor.root"; + TString inDataFile = "run_tor.root"; + + if (!LoadGeometryAndPars(inParFile)) { + cout << "Bad geometry or parameters " << endl; + return; + } + + if (!RegisterRunData(inDataFile)) { + cout << "Bad data in the file " << endl; + return; + } + + Int_t entries = Tree_->GetEntries(); + + cout << "Entries(tree): " << entries << endl; + + if (entries == 0) return; + + //return; + + cout << "\n>>>>>>>>>>>>>>>> DATA : Ok! <<<<<<<<<<<<<<<<< " << endl; + + //entries = 1; // FIXME + + for (Int_t i(0); i < entries; i++) { + Tree_->GetEntry(i); + AnalyseEvent(i); + } + +} + +//________________________________________________________________________________ +void AnalyseEvent(Int_t nevent) +{ + +// Header_->Print(1); + + //-------------------------- MC-TRACKS --------------------------------- + Int_t ntracks = MCTracks_->GetEntriesFast(); + +// cout << "\n<Analyse> mctracks = " << ntracks << endl; +// +// SpdMCTrack* track; +// for (int i(0); i < ntracks; i++) { +// track = (SpdMCTrack*)MCTracks_->At(i); +// //if (i < 30) track->Print(i); +// if (track->GetMotherId() < 0) track->Print(i); +// } + + //--------------------------- RsTB POINTS ------------------------------- + + Int_t npoints = RsTBPoints_->GetEntriesFast(); + + cout << "\n<Analyse> rstb-points = " << npoints << " event: " << nevent << endl; + + SpdRsTB2Point* point; + + for (Int_t i(0); i < npoints; i++) { + + point = (SpdRsTB2Point*)RsTBPoints_->At(i); + + AnalysePoint(point); + + } +} + +//________________________________________________________________________________ +Bool_t AnalysePoint(SpdRsTB2Point* point) +{ + if (!point) return false; + + cout << ">>>>>>>>>>>>>>>>> ANALYSE POINT >>>>>>>>>>>>>>>>>>>>>" << "\n\n"; + + point->Print(""); + + TString node_path = point->GetHitGeoPath(); + + if (!Ntor_->cd(node_path)) { + cout << "No such node: " << node_path << endl; + return false; + } + else cout << "Current node path: " << Ntor_->GetPath() << "\n\n"; + + Double_t detpos[3]; // hit node position in global CS + Double_t ax[3], ay[3], az[3]; // hit node axis (global CS) + + SpdGeopathParser ppath; + ppath.ParsePath(node_path); + + cout << "RS module number: " << ppath.Num(2) << "\n\n"; + + // print node geometry levels: + for (Int_t i(1); i<= ppath.GetCurrentPathLevel(); i++) { + cout << i << " " << ppath.Num(i) << " "<< ppath.Name(i) << " :: " << ppath.Path(i) << endl; + } + cout << "\n"; + + // Hit detector + DetectorPosition(detpos); + DetectorOrientation(ax,'x'); + DetectorOrientation(ay,'y'); + DetectorOrientation(az,'z'); + + cout << "HIT NODE: " << Ntor_->GetPath() << "\n\n"; + cout << "\t position: " << detpos[0] << " " << detpos[1] << " " << detpos[2] << " " << endl; + cout << "\t x-axis: " << ax[0] << " " << ax[1] << " " << ax[2] << " " << endl; + cout << "\t y-axis: " << ay[0] << " " << ay[1] << " " << ay[2] << " " << endl; + cout << "\t z-axis: " << az[0] << " " << az[1] << " " << az[2] << " " << endl; + cout << "\n"; + + // Module + Ntor_->cd(ppath.Path(2)); + + DetectorPosition(detpos); + DetectorOrientation(ax,'x'); + DetectorOrientation(ay,'y'); + DetectorOrientation(az,'z'); + + cout << "HIT MODULE: " << Ntor_->GetPath() << "\n\n"; + cout << "\t position: " << detpos[0] << " " << detpos[1] << " " << detpos[2] << " " << endl; // always (0,0,0) caused by using TGeoArb8! + cout << "\t x-axis: " << ax[0] << " " << ax[1] << " " << ax[2] << " " << endl; + cout << "\t y-axis: " << ay[0] << " " << ay[1] << " " << ay[2] << " " << endl; + cout << "\t z-axis: " << az[0] << " " << az[1] << " " << az[2] << " " << endl; + cout << "\n"; + + return true; +} + +//_____________________________________________________________________________ +Bool_t DetectorPosition(Double_t* p) +{ + if (!Ntor_) return false; + Double_t ploc[3] = {0, 0, 0}; + Ntor_->LocalToMaster(ploc,p); + return true; +} + +//_____________________________________________________________________________ +Bool_t DetectorOrientation(Double_t* v, Char_t dir) +{ + if (!Ntor_) return false; + + Double_t vloc[3]; + + if (dir == 'x' || dir == 'X') { vloc[0] = 1.; vloc[1] = 0.; vloc[2] = 0.; } + else if (dir == 'y' || dir == 'Y') { vloc[0] = 0.; vloc[1] = 1.; vloc[2] = 0.; } + else if (dir == 'z' || dir == 'Z') { vloc[0] = 0.; vloc[1] = 0.; vloc[2] = 1.; } + else return kFALSE; + + Ntor_->LocalToMasterVect(vloc,v); + + if (TMath::Abs(v[0]) < 1e-15) v[0] = 0.; + if (TMath::Abs(v[1]) < 1e-15) v[1] = 0.; + if (TMath::Abs(v[2]) < 1e-15) v[2] = 0.; + + return true; +} + +//________________________________________________________________________________ +Bool_t RegisterRunData(TString inFile) +{ + TFile* f = new TFile(inFile); + if (!f) return kFALSE; + + TTree* t = (TTree*)f->Get("cbmsim"); + if (!t) return kFALSE; + + TBranch* branch; + + branch = t->GetBranch("MCEventHeader."); + if (!branch) return kFALSE; + t->SetBranchAddress("MCEventHeader.",&Header_) ; + + branch = t->GetBranch("SpdMCTrack"); + if (!branch) return kFALSE; + t->SetBranchAddress("SpdMCTrack",&MCTracks_); + + branch = t->GetBranch("SpdRsTB2Point"); + if (!branch) return kFALSE; + t->SetBranchAddress("SpdRsTB2Point",&RsTBPoints_) ; + + cout << "\n>>>>>>>>>>>>>>>> FILE & TREE: Ok! <<<<<<<<<<<<<<<<< " << endl; + + Tree_ = t; + + return kTRUE; +} + +//________________________________________________________________________________ +Bool_t LoadGeometryAndPars(TString inParFile) +{ + TFile* fp = new TFile(inParFile); + if (!fp) return kFALSE; + + /* PRIMARY GENERATOR PARAMETERS */ + + GenPars_ = (SpdPrimGenParSet*)fp->Get("PrimGenParSet"); + if (!GenPars_) { + cout << "No PrimGen parameters " << endl; + return kFALSE; + } + + //GenPars_->print(1); + + /* RANGE SYSTEM BARREL (RsTB) PARAMETERS */ + + RsTBPars_ = (SpdParSet*)fp->Get("RsTBParSet"); + if (!RsTBPars_) { + cout << "No RsTB parameters " << endl; + return kFALSE; + } + + //RsTBPars_->print(1); + + /* +++++++++++++++ LOAD GEOMETRY +++++++++++++++ */ + + FairGeoParSet* geoset = (FairGeoParSet*)fp->Get("FairGeoParSet"); + + Ntor_ = gGeoManager->GetCurrentNavigator(); + + /* DRAW GEOMETRY */ + //gGeoManager->SetVisLevel(2); + //gGeoManager->GetMasterVolume()->Draw("ogl"); + + return kTRUE; +} + + + + diff --git a/macro/analysis/rst/CheckRsTEC2Data.C b/macro/analysis/rst/CheckRsTEC2Data.C new file mode 100644 index 0000000000000000000000000000000000000000..dda5c71c2cf29fa2cbf51fc14ee72f610bdbafc0 --- /dev/null +++ b/macro/analysis/rst/CheckRsTEC2Data.C @@ -0,0 +1,286 @@ +// #define _COMPILE_MACRO_ +// +// #if defined(_COMPILE_MACRO_) + +#include <TStopwatch.h> +#include <TTree.h> +#include <TClonesArray.h> +#include <TGeoManager.h> +#include <TGeoNavigator.h> + +#include "FairGeoParSet.h" +#include "FairBaseParSet.h" +#include "SpdPrimGenParSet.h" + +#include "SpdCommonGeoMapper.h" +#include "SpdCave.h" +#include "SpdDetector.h" + +#include "SpdMCEventHeader.h" +#include "SpdMCTrack.h" + +#include "SpdRsTEC2.h" +#include "SpdRsTEC2Point.h" + +//#endif + +TTree* Tree_ = 0; + +SpdParSet* RsTECPars_; +SpdPrimGenParSet* GenPars_; + +TGeoNavigator* Ntor_ = 0; + +SpdMCEventHeader* Header_ = 0; +TClonesArray* MCTracks_ = 0; +TClonesArray* RsTECPoints_ = 0; + +Int_t GeoLevel_ = 0; + +Bool_t LoadGeometryAndPars(TString inParFile); +Bool_t RegisterRunData(TString inFile); + +void AnalyseEvent(Int_t nevent); +Bool_t AnalysePoint(SpdRsTEC2Point* point); + +Bool_t DetectorPosition(Double_t* p); +Bool_t DetectorOrientation(Double_t* v, Char_t dir); + +TTree* t = 0; + +TString inFile, inParFile; + +//________________________________________________________________________________ +void CheckRsTEC2Data() { + // + TString inParFile = "params_tor.root"; + TString inDataFile = "run_tor.root"; + + if (!LoadGeometryAndPars(inParFile)) { + cout << "Bad geometry or parameters " << endl; + return; + } + + if (!RegisterRunData(inDataFile)) { + cout << "Bad data in the file " << endl; + return; + } + + Int_t entries = Tree_->GetEntries(); + + cout << "Entries(tree): " << entries << endl; + + if (entries == 0) return; + + //return; + + cout << "\n>>>>>>>>>>>>>>>> DATA : Ok! <<<<<<<<<<<<<<<<< " << endl; + + //entries = 1; // FIXME + + for (Int_t i(0); i < entries; i++) { + Tree_->GetEntry(i); + AnalyseEvent(i); + } + +} + +//________________________________________________________________________________ +void AnalyseEvent(Int_t nevent) +{ + +// Header_->Print(1); + + //-------------------------- MC-TRACKS --------------------------------- + Int_t ntracks = MCTracks_->GetEntriesFast(); + +// cout << "\n<Analyse> mctracks = " << ntracks << endl; +// +// SpdMCTrack* track; +// for (int i(0); i < ntracks; i++) { +// track = (SpdMCTrack*)MCTracks_->At(i); +// //if (i < 30) track->Print(i); +// if (track->GetMotherId() < 0) track->Print(i); +// } + + //--------------------------- RsTEC POINTS ------------------------------- + + Int_t npoints = RsTECPoints_->GetEntriesFast(); + + cout << "\n<Analyse> rstec-points = " << npoints << " event: " << nevent << endl; + + SpdRsTEC2Point* point; + + for (Int_t i(0); i < npoints; i++) { + + point = (SpdRsTEC2Point*)RsTECPoints_->At(i); + + AnalysePoint(point); + + } +} + +//________________________________________________________________________________ +Bool_t AnalysePoint(SpdRsTEC2Point* point) +{ + if (!point) return false; + + cout << ">>>>>>>>>>>>>>>>> ANALYSE POINT >>>>>>>>>>>>>>>>>>>>>" << "\n\n"; + + point->Print(""); + + TString node_path = point->GetHitGeoPath(); + + if (!Ntor_->cd(node_path)) { + cout << "No such node: " << node_path << endl; + return false; + } + else cout << "Current node path: " << Ntor_->GetPath() << "\n\n"; + + Double_t detpos[3]; // hit node position in global CS + Double_t ax[3], ay[3], az[3]; // hit node axis (global CS) + + SpdGeopathParser ppath; + ppath.ParsePath(node_path); + + cout << "RS module number: " << ppath.Num(2) << "\n\n"; + + // print node geometry levels: + for (Int_t i(1); i<= ppath.GetCurrentPathLevel(); i++) { + cout << i << " " << ppath.Num(i) << " "<< ppath.Name(i) << " :: " << ppath.Path(i) << endl; + } + cout << "\n"; + + // Hit detector + DetectorPosition(detpos); + DetectorOrientation(ax,'x'); + DetectorOrientation(ay,'y'); + DetectorOrientation(az,'z'); + + cout << "HIT NODE: " << Ntor_->GetPath() << "\n\n"; + cout << "\t position: " << detpos[0] << " " << detpos[1] << " " << detpos[2] << " " << endl; + cout << "\t x-axis: " << ax[0] << " " << ax[1] << " " << ax[2] << " " << endl; + cout << "\t y-axis: " << ay[0] << " " << ay[1] << " " << ay[2] << " " << endl; + cout << "\t z-axis: " << az[0] << " " << az[1] << " " << az[2] << " " << endl; + cout << "\n"; + + // Module + Ntor_->cd(ppath.Path(2)); + + DetectorPosition(detpos); + DetectorOrientation(ax,'x'); + DetectorOrientation(ay,'y'); + DetectorOrientation(az,'z'); + + cout << "HIT MODULE: " << Ntor_->GetPath() << "\n\n"; + cout << "\t position: " << detpos[0] << " " << detpos[1] << " " << detpos[2] << " " << endl; // always (0,0,0) caused by using TGeoArb8! + cout << "\t x-axis: " << ax[0] << " " << ax[1] << " " << ax[2] << " " << endl; + cout << "\t y-axis: " << ay[0] << " " << ay[1] << " " << ay[2] << " " << endl; + cout << "\t z-axis: " << az[0] << " " << az[1] << " " << az[2] << " " << endl; + cout << "\n"; + + return true; +} + +//_____________________________________________________________________________ +Bool_t DetectorPosition(Double_t* p) +{ + if (!Ntor_) return false; + Double_t ploc[3] = {0, 0, 0}; + Ntor_->LocalToMaster(ploc,p); + return true; +} + +//_____________________________________________________________________________ +Bool_t DetectorOrientation(Double_t* v, Char_t dir) +{ + if (!Ntor_) return false; + + Double_t vloc[3]; + + if (dir == 'x' || dir == 'X') { vloc[0] = 1.; vloc[1] = 0.; vloc[2] = 0.; } + else if (dir == 'y' || dir == 'Y') { vloc[0] = 0.; vloc[1] = 1.; vloc[2] = 0.; } + else if (dir == 'z' || dir == 'Z') { vloc[0] = 0.; vloc[1] = 0.; vloc[2] = 1.; } + else return kFALSE; + + Ntor_->LocalToMasterVect(vloc,v); + + if (TMath::Abs(v[0]) < 1e-15) v[0] = 0.; + if (TMath::Abs(v[1]) < 1e-15) v[1] = 0.; + if (TMath::Abs(v[2]) < 1e-15) v[2] = 0.; + + return true; +} + +//________________________________________________________________________________ +Bool_t RegisterRunData(TString inFile) +{ + TFile* f = new TFile(inFile); + if (!f) return kFALSE; + + TTree* t = (TTree*)f->Get("cbmsim"); + if (!t) return kFALSE; + + TBranch* branch; + + branch = t->GetBranch("MCEventHeader."); + if (!branch) return kFALSE; + t->SetBranchAddress("MCEventHeader.",&Header_) ; + + branch = t->GetBranch("SpdMCTrack"); + if (!branch) return kFALSE; + t->SetBranchAddress("SpdMCTrack",&MCTracks_); + + branch = t->GetBranch("SpdRsTEC2Point"); + if (!branch) return kFALSE; + t->SetBranchAddress("SpdRsTEC2Point",&RsTECPoints_) ; + + cout << "\n>>>>>>>>>>>>>>>> FILE & TREE: Ok! <<<<<<<<<<<<<<<<< " << endl; + + Tree_ = t; + + return kTRUE; +} + +//________________________________________________________________________________ +Bool_t LoadGeometryAndPars(TString inParFile) +{ + TFile* fp = new TFile(inParFile); + if (!fp) return kFALSE; + + /* PRIMARY GENERATOR PARAMETERS */ + + GenPars_ = (SpdPrimGenParSet*)fp->Get("PrimGenParSet"); + if (!GenPars_) { + cout << "No PrimGen parameters " << endl; + return kFALSE; + } + + //GenPars_->print(1); + + /* RANGE SYSTEM BARREL (RsTEC) PARAMETERS */ + + RsTECPars_ = (SpdParSet*)fp->Get("RsTECParSet"); + if (!RsTECPars_) { + cout << "No RsTEC parameters " << endl; + return kFALSE; + } + + //RsTECPars_->print(1); + + /* +++++++++++++++ LOAD GEOMETRY +++++++++++++++ */ + + FairGeoParSet* geoset = (FairGeoParSet*)fp->Get("FairGeoParSet"); + + Ntor_ = gGeoManager->GetCurrentNavigator(); + + /* DRAW GEOMETRY */ + //gGeoManager->SetVisLevel(2); + //gGeoManager->GetMasterVolume()->Draw("ogl"); + + return kTRUE; +} + + + + diff --git a/macro/field/CheckAxialFieldMapData.C b/macro/field/CheckAxialFieldMapData.C new file mode 100644 index 0000000000000000000000000000000000000000..5dd1225fadcd23c84d6a596d14c79900912f8399 --- /dev/null +++ b/macro/field/CheckAxialFieldMapData.C @@ -0,0 +1,93 @@ + + +void CheckAxialFieldMapData() +{ + + Int_t n; + Double_t bx, by, bz, br, bb; + + Int_t N = 10; + const Int_t rnum = 4534343; + + // default path to a field maps + TString path = getenv("VMCWORKDIR"); + path += "/input/"; + + cout << path << endl; + + SpdAxialFieldMapData* mdata = new SpdAxialFieldMapData(); + +//---------------------------------------------- INIT 1 + mdata->InitData("map_qsolRZ_6cls2cm.bin",path); + + mdata->PrintData(); + + //return; + gRandom->SetSeed(rnum); + + N = mdata->GetNTotal(); + + for (Int_t i(1); i<=N; i++) { + + //n = gRandom->Integer(mdata->GetNTotal()); + n = i-1; + + //cout << i << "/" << N << ": " << mdata->GetBr(n) << " " << mdata->GetBz(n) << endl; + + br = mdata->GetBr(n); + bz = mdata->GetBz(n); + bb = TMath::Sqrt(br*br + bz*bz); + + printf("%4d: Br = %9.2e; Bz = %9.2e; |B| = %9.2e; \n",i,br,bz,bb); + + if (i%124 == 0) cout << endl; + if (i == 124) break; + } + +//---------------------------------------------- + +// mdata->WriteAsciiFile("map_qsolRZ_6cls2cm_1.dat"); +// mdata->WriteBinaryFile("map_qsolRZ_6cls2cm_1.bin"); + + //return; + + //---------------------------------------------- INIT 2 + +// mdata->InitData("map_qsolRZ_6cls2cm_1.dat","../macro"); +// +// mdata->PrintData(); +// +// gRandom->SetSeed(rnum); +// +// for (Int_t i(0); i<N; i++) { +// +// //n = gRandom->Integer(mdata->GetNTotal()); +// n = i; +// +// cout << i+1 << " " << mdata->GetBr(n) +// << " " << mdata->GetBz(n) +// << endl; +// if (i == 20) break; +// } + + //---------------------------------------------- INIT 3 + +// mdata->InitData("map_qsolRZ_6cls2cm_1.bin","../macro"); +// +// mdata->PrintData(); +// +// gRandom->SetSeed(rnum); +// +// for (Int_t i(0); i<N; i++) { +// +// //n = gRandom->Integer(mdata->GetNTotal()); +// n = i; +// +// cout << i+1 << " " << mdata->GetBr(n) +// << " " << mdata->GetBz(n) +// << endl; +// if (i == 20) break; +// } + +} + diff --git a/macro/field/CheckField.C b/macro/field/CheckField.C index de745e81af1fce9707e224468a99ba79a642c279..ef37c53bca104aa03e6d66b9b669fd4d05014e0e 100644 --- a/macro/field/CheckField.C +++ b/macro/field/CheckField.C @@ -1,5 +1,19 @@ + +// #include "SpdFieldMap.h" +// #include "SpdAxialFieldMap.h" +// #include "SpdMultiField.h" +// #include "SpdConstField.h" +// #include "SpdRadialField.h" +// #include "SpdFieldCreator.h" +// #include "SpdFieldPar.h" +// #include <TFile.h> +// #include <TRandom.h> +// +// void check0(); +void check0axial(); + void check1(); // set_of_fields -> set_of_fields void check2(); // set_of_fields -> multi_field void check3(); // multi_field -> multi_field @@ -10,7 +24,8 @@ void readparams(TString filename = "params_tor.root"); void CheckField() { - check0(); + //check0(); + check0axial(); //check1(); //check2(); @@ -25,13 +40,16 @@ void CheckField() void check0() { SpdFieldMap* MagField = new SpdFieldMap("Hybrid field"); - MagField->InitData("map_hyb_1T5cm.bin"); + //MagField->InitData("map_hyb_2T5cm.bin"); + MagField->InitData("map_sol_6cls5cm2.bin"); + MagField->PrintData(); - + //MagField->Print(); + Double_t x, y, z; Double_t bx, by, bz; - const Int_t N = 10; + const Int_t N = 20; gRandom->SetSeed(1234); @@ -41,15 +59,104 @@ void check0() y = gRandom->Uniform(MagField->GetYmin(),MagField->GetYmax()); z = gRandom->Uniform(MagField->GetZmin(),MagField->GetZmax()); + x = 0; y = 0; + + MagField->GetBx(bx,x,y,z); + MagField->GetBy(by,x,y,z); + MagField->GetBz(bz,x,y,z); + + printf("(%8.3f, %8.3f, %8.3f); B = (%9.2e, %9.2e, %9.2e); Br = %9.2e; ", + x,y,z,bx,by,bz,TMath::Sqrt(bx*bx+by*by)); + + z = -z; + + MagField->GetBx(bx,x,y,z); + MagField->GetBy(by,x,y,z); + MagField->GetBz(bz,x,y,z); + + cout << " z->-z: "; + + printf("(%8.3f, %8.3f, %8.3f); B = (%9.2e, %9.2e, %9.2e); Br = %9.2e; ", + x,y,z,bx,by,bz,TMath::Sqrt(bx*bx+by*by)); + + cout << endl; + + } +} + +//_______________________________________________________________________ +void check0axial() +{ + SpdAxialFieldMap* MagField = new SpdAxialFieldMap("QSolenoidal field"); + MagField->InitData("map_qsolRZ_6cls2cm.bin"); + + MagField->PrintData(); + //MagField->Print(); + + Double_t x, y, z, r, phi; + Double_t bx, by, bz; + + const Int_t N = 20; + + gRandom->SetSeed(0); + + Double_t point[3], Field[3]; + + for (Int_t i(0); i<N; i++) { + + r = gRandom->Uniform(MagField->GetRmin(),MagField->GetRmax()); + z = gRandom->Uniform(MagField->GetZmin(),MagField->GetZmax()); + + phi = gRandom->Uniform(0,TMath::TwoPi()); + x = r*TMath::Sin(phi); + y = r*TMath::Cos(phi); + + //x = 0; y = 0; + +// point[0] = x; +// point[1] = y; +// point[2] = z; +// +// MagField->GetField(point,Field); +// +// printf("(%8.3f, %8.3f, %8.3f); B = (%9.2e, %9.2e, %9.2e); Br = %9.2e; ", +// point[0],point[1],point[2],Field[0],Field[1],Field[2],TMath::Sqrt(Field[0]*Field[0]+Field[1]*Field[1])); +// +// point[2] = -point[2]; +// +// MagField->GetField(point,Field); +// +// cout << " z->-z: "; +// +// printf("(%8.3f, %8.3f, %8.3f); B = (%9.2e, %9.2e, %9.2e); Br = %9.2e; \n", +// point[0],point[1],point[2],Field[0],Field[1],Field[2],TMath::Sqrt(Field[0]*Field[0]+Field[1]*Field[1])); + + + MagField->GetBx(bx,x,y,z); + MagField->GetBy(by,x,y,z); + MagField->GetBz(bz,x,y,z); + + printf("(%8.3f, %8.3f, %8.3f); B = (%9.2e, %9.2e, %9.2e); Br = %9.2e; ", + x,y,z,bx,by,bz,TMath::Sqrt(bx*bx+by*by)); + + z = -z; + MagField->GetBx(bx,x,y,z); MagField->GetBy(by,x,y,z); MagField->GetBz(bz,x,y,z); - cout << " ( " << x << ", " << y << ", " << z << ") B = " - << " ( " << bx << ", " << by << ", " << bz << ") " - << endl; + cout << " z->-z: "; + + printf("(%8.3f, %8.3f, %8.3f); B = (%9.2e, %9.2e, %9.2e); Br = %9.2e; ", + x,y,z,bx,by,bz,TMath::Sqrt(bx*bx+by*by)); + + cout << endl; - } + } + +// cout << " X[min,max]: " << MagField->GetXmin() << " " << MagField->GetXmax() << " Nx = " << MagField->GetNx() << endl; +// cout << " Y[min,max]: " << MagField->GetYmin() << " " << MagField->GetYmax() << " Ny = " << MagField->GetNy() << endl; +// cout << " Z[min,max]: " << MagField->GetZmin() << " " << MagField->GetZmax() << " Nz = " << MagField->GetNz() << endl; } //________________________________________________________________________ diff --git a/macro/field/CheckFieldMapData.C b/macro/field/CheckFieldMapData.C index 7c04f35a2b59b6e1e7b83dd2d53c220ebdfee54d..18c1344d634c4ef1279d12667fabaa75d166887f 100644 --- a/macro/field/CheckFieldMapData.C +++ b/macro/field/CheckFieldMapData.C @@ -19,26 +19,45 @@ void check_0() Int_t N = 10; const Int_t rnum = 4534343; + // default path to a field maps + TString path = getenv("VMCWORKDIR"); + path += "/input/"; + + cout << path << endl; + SpdFieldMapData* mdata = new SpdFieldMapData(); //---------------------------------------------- INIT 1 - //mdata->InitData("map_sol_6cls5cm2.bin"); - mdata->InitData("map_hyb_1T5cm.bin"); + //mdata->InitData("map_sol_6cls5cm2.bin",path); + + mdata->InitData("map_hyb_1T5cm.bin",path); mdata->PrintData(); + //return; + gRandom->SetSeed(rnum); N = mdata->GetNTotal(); + for (Int_t i(0); i<N; i++) { //n = gRandom->Integer(mdata->GetNTotal()); n = i; - - cout << i << " " << mdata->GetBx(n) - << " " << mdata->GetBy(n) - << " " << mdata->GetBz(n) - << endl; + +// cout << i+1 << "/" << N << ": " << mdata->GetBx(n) +// << " " << mdata->GetBy(n) +// << " " << mdata->GetBz(n) +// << endl; + + bx = mdata->GetBx(n); + by = mdata->GetBy(n); + bz = mdata->GetBz(n); + + printf("%4d: B = (%9.2e, %9.2e, %9.2e); Br = %9.2e; \n", + i+1,bx,by,bz,TMath::Sqrt(bx*bx+by*by)); + + if (i == 20) break; } //---------------------------------------------- diff --git a/macro/field/DrawFieldMap.C b/macro/field/DrawFieldMap.C index 5893a8db73dced91514836689a81ad9e7cc21413..736bb2d5e41308100a11509c95363de9182acbd9 100644 --- a/macro/field/DrawFieldMap.C +++ b/macro/field/DrawFieldMap.C @@ -35,8 +35,17 @@ TH2D* MakeRPlane(Double_t R, TString fvtype, Int_t in = 1, Double_t zcut = 1000. TH2D* MakePhiAveraged(Double_t Rmax, TString fvtype, Int_t in = 1, Double_t zcut = 1000., TH1D* hh = 0); TH2D* MakeZAveraged(Double_t Zmax, TString fvtype, Int_t in = 1, Double_t rcut = 1000., TH1D* hh = 0); + +#define AXIAL_FIELD // !!!FIXME!!! FIXME!!! FIXME!!! + + TString FieldMap_; -SpdFieldMap* MagField_; + +#ifndef AXIAL_FIELD +SpdFieldMap* MagField_ = 0; +#else +SpdAxialFieldMap* MagField_ = 0; +#endif TString GetFtype(TString fvtype); @@ -63,12 +72,15 @@ void SetStyle() //__________________________________________________________________________ void DrawFieldMap() { - FieldMap_ = "map_hyb_1T2cm.bin"; // hybrid HQ, B = 1 T, grid = 2 cm + +#ifndef AXIAL_FIELD + + //FieldMap_ = "map_tor_rot.bin"; // toroid (rotated), grid = 5 cm + //FieldMap_ = "map_hyb_1T2cm.bin"; // hybrid HQ, B = 1 T, grid = 2 cm //FieldMap_ = "map_hyb_1T5cm.bin"; // hybrid LQ, B = 1 T, grid = 5 cm //FieldMap_ = "map_hyb_2T5cm.bin"; // hybrid LQ, B = 2 T, grid = 5 cm - //FieldMap_ = "map_sol_6cls5cm.bin"; // solenoid [3+3-], grid = 5 cm - //FieldMap_ = "map_sol_6cls5cm2.bin"; // solenoid [6+], grid = 5 cm - //FieldMap_ = "map_tor_rot.bin"; // toroid (rotated), grid = 5 cm + //FieldMap_ = "map_sol_6cls5cm.bin"; // qsolenoid [3+3-], grid = 5 cm + FieldMap_ = "map_sol_6cls5cm2.bin"; // qsolenoid [6+], grid = 5 cm MagField_ = new SpdFieldMap("Hybrid field"); MagField_->InitData(FieldMap_); @@ -85,9 +97,29 @@ void DrawFieldMap() cout << "\t Bx (min,max) = " << Bstat[8] << " " << Bstat[9] << " [kG] " << endl; cout << endl; + +#else - SetStyle(); + FieldMap_ = "map_qsolRZ_6cls2cm.bin"; // qsolenoid [6+], grid = 2 cm + + MagField_ = new SpdAxialFieldMap("QSolenoidal field"); + MagField_->InitData(FieldMap_); + MagField_->PrintData(); + + Double_t Bstat[8]; + MagField_->GetMinMaxStat(Bstat); + + cout << "\t Field map statistics (nodes): " << "\n\n"; + cout << "\t B (min,max) = " << Bstat[0] << " " << Bstat[1] << " [kG] " << endl; + cout << "\t Bz (min,max) = " << Bstat[2] << " " << Bstat[3] << " [kG] " << endl; + cout << "\t Br (min,max) = " << Bstat[4] << " " << Bstat[5] << " [kG] " << endl; + cout << endl; + +#endif + + SetStyle(); + DrawHistos(); //CheckPhiSym(); diff --git a/macro/fullchain/FitIdealTracks.C b/macro/fullchain/FitIdealTracks.C index c1905947a4836d32268d66434d0cb5fae31dc043..402cf57946365e4b192468ff2074b3177bef6300 100644 --- a/macro/fullchain/FitIdealTracks.C +++ b/macro/fullchain/FitIdealTracks.C @@ -39,9 +39,10 @@ void FitIdealTracks() // standard options: KalmanFitter->SetSeedMomentum(1.); // Start vertex momentum for fit, GeV/c (default = 1 GeV/c) - KalmanFitter->SetResolution(0.005); // Vertex detector (Its) resolution, cm (default = 0.005 cm) - KalmanFitter->SetWireResolution(0.015); // Wire tracker (TsTB, TsTEC) resolution , cm (default = 0.015 cm) - + KalmanFitter->SetHitRepresentation(kSpdIts,pkPixel); // options: pkPixel, pkSpacepoint + KalmanFitter->SetHitRepresentation(kSpdTsTB,pkWire); // options: pkWire, pkWirePoint, pkSpacepoint + KalmanFitter->SetHitRepresentation(kSpdTsTEC,pkWire); // options: pkWire, pkWirePoint, pkSpacepoint + // advanced options: KalmanFitter->SetVertexFindingMethod(1); // <1 (vertex will not be found), (default = 1) KalmanFitter->SetVertexFindingAngleCut(3.0); // skip tracks with theta 90+-cut degree (default = 3[deg]) diff --git a/macro/fullchain/MakeIdealTracks.C b/macro/fullchain/MakeIdealTracks.C index cd3147b3050124a0c252870c0a15b33af9e877b8..a3aadfb19eddfb0d745b9b7fffbb7be63b1b15a5 100644 --- a/macro/fullchain/MakeIdealTracks.C +++ b/macro/fullchain/MakeIdealTracks.C @@ -41,6 +41,25 @@ void MakeIdealTracks() TrackFinder->SetMinVertexNHits(1); // its hits number cut; default = 1; absiolute min. value = 0; TrackFinder->SetMinTrackerNHits(2); // tstb+tstec hits number cut; default = 2; absiolute min. value = 2; + // set hits resolution + Double_t mkm = 1e-4; + + // ------ INNER TRACKER ----- + + TrackFinder->SetHitResolution(kSpdIts, 'p', 50*mkm, 50*mkm); // ENDCAP: POINT (u=x,v=y) + TrackFinder->SetHitResolution(kSpdIts, 'm', 50*mkm, 50*mkm); // BARREL: MAPS (u,v) + TrackFinder->SetHitResolution(kSpdIts, 's', 50*mkm, 50*mkm); // BARREL: DSSD (u,v) + + // ----- STRAW TRACKER ----- + + // --- barrel --- + TrackFinder->SetHitResolution(kSpdTsTB, 'w', 150*mkm); // Wire(1D) (r,z) + //TrackFinder->SetHitResolution(kSpdTsTB, 'w', 150*mkm, 2. /*cm*/); // Wire(1D,2D) (r,z) + + //--- endcaps --- + TrackFinder->SetHitResolution(kSpdTsTEC,'w', 150*mkm); // Wire(1D) (r,z) + //TrackFinder->SetHitResolution(kSpdTsTEC,'w', 150*mkm, 2. /*cm*/); // Wire(1D,2D) (r,z) + //------------------------------------// Run->AddTask(TrackFinder); diff --git a/macro/geom/CheckGeoLoader.C b/macro/geom/CheckGeoLoader.C index 2646a1915236099e25190231de768d4fac53a336..4a47771c1af1b0406a11ccd69b5f40cd9d6ce68a 100644 --- a/macro/geom/CheckGeoLoader.C +++ b/macro/geom/CheckGeoLoader.C @@ -4,33 +4,48 @@ void CheckGeoLoader() { SpdGeoLoader* loader = new SpdGeoLoader(); - loader->LoadGeometry("params_tor.root"); - //loader->LoadGeometry("params_sol.root"); - //loader->LoadGeometry(""); + /* ---- special loader settings ---- */ - //loader->LoadGeometry(); + //SpdGeoLoader::ForceTopGeoFile("cave_precise.geo"); // force CAVE geometry (material = vacuum) + //SpdGeoLoader::ForceTopGeoFile("cave.geo"); // force CAVE geometry (material = air) - //loader->LoadModule("All"); - //loader->LoadModule("Actives"); + //SpdGeoLoader::ForceMediaFile(TString(getenv("VMCWORKDIR"))+"/geometry/media1.geo"); - //loader->LoadModule("Pipe"); + //SpdGeoLoader::ResetMediaFromParams(false); // actives: false = use basic module's materials, true (default) = use actual parameters + //SpdGeoLoader::ResetPassivesMedia(true); // passives: false (default) = use actual simu materials, true = use deafult materials - loader->LoadModule("Passives"); + //SpdGeoLoader::UnsetMaterials(true); // true = set ALL module's materials as vacuum, false (default) = geometry materials + + /* ---- LoadGeometry: load list of modules and construct TOP (cave) volume ---- */ + + loader->LoadGeometry("params_tor.root"); // load all modules using its parameters, construct TOP volume + //loader->LoadGeometry(); // load all modules, construct TOP volume + + /* ---- LoadModule: construct modules; parameters = [module id, unset materials (default = false)] ---- */ + + // loader->LoadModule("All",false); + // loader->LoadModule("Actives",false); + + loader->LoadModule("Passives",false); - loader->LoadModule("Inner tracker system"); // id = 12 - loader->LoadModule("TS barrel (tor)"); // id = 2 - loader->LoadModule("TS endcaps (tor)"); // id = 3 + // loader->LoadModule("Pipe",false); + +// loader->LoadModule("Inner tracker system",false); // id = 12 +// loader->LoadModule("TS barrel (tor)",false); // id = 2 +// loader->LoadModule("TS endcaps (tor)",false); // id = 3 - //loader->LoadModule(2); - //loader->LoadModule(3); - //loader->LoadModule(12); + loader->LoadModule(2,false); + loader->LoadModule(3,false); + loader->LoadModule(12,false); + /* ---- darwing and dumping ---- */ + loader->DrawGeometry(); //loader->PrintGeometry(); loader->PrintActualGeometry(); - //return; + return; Int_t DetId = 12; @@ -38,12 +53,14 @@ void CheckGeoLoader() SpdGeoMapper* mapper = 0; SpdGeoBuilder* builder = 0; - pars = loader->GetParameters(DetId); + pars = loader->GetActiveParameters(DetId); mapper = loader->GetMapper(DetId); builder = loader->GetBuilder(DetId); - + if (pars) pars->print(1); - if (mapper) cout << "MAPPER: " << mapper->GetName() << endl; + if (mapper) cout << "MAPPER: " << mapper->GetName() << endl; if (builder) cout << "BUILDER: " << builder->GetName() << endl; + delete loader; + } diff --git a/macro/geom/ConstructEcalTB2.C b/macro/geom/ConstructEcalTB2.C new file mode 100644 index 0000000000000000000000000000000000000000..17c85e64a038c26e3c5e37778c3600d7dcd77876 --- /dev/null +++ b/macro/geom/ConstructEcalTB2.C @@ -0,0 +1,139 @@ + +void DefaultGeometryTight(); +void DefaultGeometryTightBasket(); +void DefaultGeometryForceCellSize(); + +void CustomizeGeometry(); + +//______________________________________________________________ +void ConstructEcalTB2() +{ + // + SpdCommonGeoMapper::Instance()->OpenGeometry(); + + FairModule* Cave = new SpdCave(); + Cave->SetGeometryFileName("cave.geo"); + Cave->ConstructGeometry(); + + SpdCommonGeoMapper::Instance()->DefineQslGeometrySet(); + + //SpdPipe* Pipe = new SpdPipe(); + //Pipe->ConstructGeometry(); + //Pipe->Print(""); + + //SpdEcalTEC2* ecaltec = new SpdEcalTEC2(); + //ecaltec->ConstructGeometry(); + //ecaltec->Print(""); + + SpdEcalTB2* ecaltb = new SpdEcalTB2(); + + CustomizeGeometry(); + + ecaltb->ConstructGeometry(); + + /* ~~~~~~~~~~~~~ DRAW GEOMETRY ~~~~~~~~~~~~~~~~~ */ + + TGeoManager *geoMan = gGeoManager; + geoMan->SetVisLevel(3); + + //geoMan->GetMasterVolume()->SetVisContainers(); + geoMan->GetMasterVolume()->Draw("ogl"); + + //ecaltb->GetBasket()->Draw("ogl"); + + TGeoVolume* module; + module = ecaltb->GetModule(0); + + //if (module) module->SetVisContainers(); + //if (module) module->Draw("ogl"); + + ecaltb->Print(""); +} + +//______________________________________________________________ +void CustomizeGeometry() +{ + // 1. recommended default: fixed cell length, automatically calculated cell width + + //DefaultGeometryTight(); + + // 2. trimming cell length (cell length automatically calculated to fit into basket), + // automatically calculated cell width + + //DefaultGeometryTightBasket(); + + // 3. force cell size + + //DefaultGeometryForceCellSize(); +} + +//______________________________________________________________ +void DefaultGeometryTight() +{ + // + // Fill baskets(barrel) with modules tightly (automatically selecting cell transverse size) + // Module length and number of layers are constant + // + SpdEcalTB2GeoMapper* mapper = SpdEcalTB2GeoMapper::Instance(); + + //rough guideline: size will be chosen as close as possible to these values + mapper->SetCellZSize(5.5); // [cm] z-size of cell + mapper->SetCellInnerPhiSize(5.5); // [cm] П†-size of the cell face closer to beam axis + mapper->SetNLayers(200); + mapper->SetAbsorberLayerThickness(0.05); + mapper->SetScintLayerThickness(0.15); + + //additional + mapper->SetModuleClearance(0.1); // [cm] clerance between modules (default: 0.1) + mapper->SetCellClearance(0.05); // [cm] clerance between cells in a module (default: 0.05) +} + +//______________________________________________________________ +void DefaultGeometryTightBasket() +{ + // + // Fill baskets(barrel) with modules tightly (automatically selecting cell transverse size) + // Trim cell length to be inside basket and select number of layers accordingly + // + + SpdEcalTB2GeoMapper* mapper = SpdEcalTB2GeoMapper::Instance(); + mapper->SetForceInsideBasket(true); + mapper->SetCellZSize(5.5); // [cm] z-size of cell + mapper->SetCellInnerPhiSize(5.5); // [cm] П†-size of the cell face closer to beam axis + mapper->SetAbsorberLayerThickness(0.05); + mapper->SetScintLayerThickness(0.15); + + //additional + mapper->SetModuleClearance(0.1); // [cm] clerance between modules (default: 0.1) + mapper->SetCellClearance(0.05); // [cm] clerance between cells in a module (default: 0.05) +} + +//______________________________________________________________ +void DefaultGeometryForceCellSize() +{ + // + // Fill baskets(barrel) with modules, using the given cell size + // + SpdEcalTB2GeoMapper* mapper = SpdEcalTB2GeoMapper::Instance(); + mapper->SetForceCellSize(true); + + //strict values: size will be forced to be this value, but the ECAL may have lots of empty space - choose with caution + mapper->SetCellZSize(5.5); // [cm] z-size of cell + mapper->SetCellInnerPhiSize(5.1); // [cm] П†-size of the cell face closer to beam axis + mapper->SetCellOuterPhiSize(6.6); // [cm] П†-size of the cell face closer to beam axis + + mapper->SetNLayers(200); + mapper->SetAbsorberLayerThickness(0.05); // [cm] + mapper->SetScintLayerThickness(0.15); // [cm] + + //additional + mapper->SetModuleClearance(0.1); // [cm] clerance between modules (default: 0.1) + mapper->SetCellClearance(0.05); // [cm] clerance between cells in a module (default: 0.05) +} + + + + + + + diff --git a/macro/geom/ConstructEcalTEC2.C b/macro/geom/ConstructEcalTEC2.C new file mode 100644 index 0000000000000000000000000000000000000000..f2b469054d62b267f4779ec45de2a365d041062f --- /dev/null +++ b/macro/geom/ConstructEcalTEC2.C @@ -0,0 +1,50 @@ +//______________________________________________________________ +void ConstructEcalTEC2() +{ + // + SpdCommonGeoMapper::Instance()->OpenGeometry(); + + FairModule* Cave = new SpdCave(); + Cave->SetGeometryFileName("cave.geo"); + Cave->ConstructGeometry(); + + SpdCommonGeoMapper::Instance()->DefineQslGeometrySet(); + + SpdPipe* Pipe = new SpdPipe(); + Pipe->ConstructGeometry(); + + SpdEcalTEC2* ecaltec = new SpdEcalTEC2(); + + // customize geometry + SpdEcalTEC2GeoMapper* mapper = SpdEcalTEC2GeoMapper::Instance(); + + mapper->SetCellSize(5.5); // [cm], X/Y size of endcap cell (default: 5.5) + mapper->SetAbsorberLayerThickness(0.05); // [cm], thickness of absorber layer (material hardcoded as lead) (default: 0.05) + mapper->SetScintLayerThickness(0.15); // [cm], thickness of scintillator layer (polystyrene(?)) (default: 0.15) + + // additional: + mapper->SetCellClearance(1.5); // [cm], clerance between cells in a module (default: 0.05) + mapper->SetModuleClearance(1.5); // [cm], clearance between modules (2x2 cells) (default: 0.1) + + // construct geometry + ecaltec->ConstructGeometry(); + + /* ~~~~~~~~~~~~~ PRINT GEOMETRY INFO ~~~~~~~~~~~~~*/ + + SpdEcalTEC2GeoMapper::Instance()->Print(""); // print all parameteecal + + /* ~~~~~~~~~~~~~ DRAW GEOMETRY ~~~~~~~~~~~~~~~~~ */ + + TGeoManager *geoMan = gGeoManager; + geoMan->SetVisLevel(2); + + //geoMan->GetMasterVolume()->SetVisContainers(); + geoMan->GetMasterVolume()->Draw("ogl"); + + //ecaltec->GetEndcap()->Draw("ogl"); + //ecaltec->GetModule()->Draw("ogl"); + //ecaltec->GetCell()->Draw("ogl"); + + return; + +} diff --git a/macro/geom/ConstructHybGeo.C b/macro/geom/ConstructHybGeo.C index 9abc90e0f423e040f98a5e1dba06ae7812e41453..775558458a00c4f308dac717e66414f8d16f30e4 100644 --- a/macro/geom/ConstructHybGeo.C +++ b/macro/geom/ConstructHybGeo.C @@ -11,15 +11,15 @@ void ConstructHybGeo() { Cave->SetGeometryFileName("cave.geo"); Cave->ConstructGeometry(); - Int_t HybGeoSetType = 2; + Int_t HybGeoSetType = 2; // 1, 2 SpdCommonGeoMapper::Instance()->DefineHybGeometrySet(HybGeoSetType); - //SpdCommonGeoMapper::Instance()->SetNGeoSectors(10); + //SpdCommonGeoMapper::Instance()->SetNGeoSectors(4); /* +++++++++ PIPE +++++++++ */ - //SpdPipe* Pipe = new SpdPipe(); + SpdPipe* Pipe = new SpdPipe(); //Pipe->SetPipeType("tor"); //Pipe->SetPipeType("sol"); @@ -32,15 +32,12 @@ void ConstructHybGeo() { SpdHybMagnet* Magnet = new SpdHybMagnet(); - //Magnet->SetGeometryType(2); // type = 1 (default) or type = 2 + //Magnet->SetGeometryType(1); // type = 1 (hybrid) or type = 2 (qsolenoid) //Magnet->SetCoilsMaterial("silicon"); // see avaliable materials: geometry/media.geo //Magnet->UnsetMaterials(0); + -// /* +++++++++ BASKET +++++++++ */ -// - //SpdTorBasket* Basket = new SpdTorBasket(); -// // /* +++++++++ DETECTORS +++++++++ */ // SpdEcalTB* ecal_barrel = new SpdEcalTB(); /* +++++++++ ECALT (BARREL) ++++++++++ */ @@ -59,17 +56,13 @@ void ConstructHybGeo() { //tracker->ConstructGeometry(); } -// /* ===== Vertex detector ===== */ - - SpdIts* vxd = new SpdIts(); - vxd->ConstructGeometry(); + SpdIts* vxd = new SpdIts(); /* +++++++++ VERTEX TRACKER ++++++++++ */ - // SpdTsTECGeoMapper::Instance()->SetGeometryPars(1); // 1,2 + // SpdTsTECGeoMapper::Instance()->SetGeometryPars(1); // 1,2 // SpdTsTBGeoBuilder::Instance()->SetMaxBuildGeoLevel(2); -// // SpdCommonGeoMapper::Instance()->UnsetMaterials(1); -// // +// SpdCommonGeoMapper::Instance()->UnsetMaterials(1); SpdCommonGeoMapper::Instance()->ConstructGeometry(); //SpdCommonGeoMapper::Instance()->PrintGeometryList(); diff --git a/macro/geom/ConstructIts.C b/macro/geom/ConstructIts.C index a26e310fae909cc1bf8e435517328620ef7f88b8..1664bc9c37a8f5dbfaeea56c5af6b06e8ee9bcf4 100644 --- a/macro/geom/ConstructIts.C +++ b/macro/geom/ConstructIts.C @@ -5,7 +5,8 @@ void TestMapper(); void TestBuilder(); //______________________________________________________________ -void ConstructIts() { +void ConstructIts() +{ // //TestMapper(); //return; @@ -18,9 +19,9 @@ void ConstructIts() { SpdCommonGeoMapper::Instance()->DefineHybGeometrySet(); - SpdPipe* Pipe = new SpdPipe(); - Pipe->ConstructGeometry(); - Pipe->Print(""); + //SpdPipe* Pipe = new SpdPipe(); + //Pipe->ConstructGeometry(); + //Pipe->Print(""); SpdItsGeoMapperX::Instance()->SetGeometryPars(3); //1, 2, (3 = default) diff --git a/macro/geom/ConstructQslGeo.C b/macro/geom/ConstructQslGeo.C new file mode 100644 index 0000000000000000000000000000000000000000..7c598ba18b3ef1e59e24714fd534dcb71c9f75ae --- /dev/null +++ b/macro/geom/ConstructQslGeo.C @@ -0,0 +1,86 @@ + +//______________________________________________________________ +void ConstructQslGeo() +{ + // + SpdCommonGeoMapper::Instance()->OpenGeometry(); + + //FairGeoMedia* media = FairGeoLoader::Instance()->getGeoInterface()->getMedia(); + //media->print(); + + FairModule* Cave = new SpdCave(); + Cave->SetGeometryFileName("cave.geo"); + Cave->ConstructGeometry(); + + SpdCommonGeoMapper::Instance()->DefineQslGeometrySet(); + + /* +++++++++ PIPE +++++++++ */ + + SpdPipe* Pipe = new SpdPipe(); + + //Pipe->SetPipeMaterial("silicon"); + //Pipe->UnsetMaterials(1); + + /* +++++++++ MAGNET +++++++++ */ + + SpdHybMagnet* Magnet = new SpdHybMagnet(); + Magnet->ConstructGeometry(); + + /* +++++++++ DETECTORS +++++++++ */ + + SpdEcalTB2* ecal_barrel = new SpdEcalTB2(); /* +++++++++ ECALT (BARREL) ++++++++++ */ + SpdEcalTEC2* ecal_ecps = new SpdEcalTEC2(); /* +++++++++ ECALT (ENDCAPS) +++++++++ */ + SpdRsTB2* rs_barrel = new SpdRsTB2(); /* +++++++++ RST (BARREL) ++++++++++++ */ + SpdRsTEC2* rs_ecps = new SpdRsTEC2(); /* +++++++++ RST (ENDCAPS) +++++++++++ */ + SpdTsTB* ts_barrel = new SpdTsTB(); /* +++++++++ TST (BARREL) ++++++++++++ */ + SpdTsTEC* ts_ecps = new SpdTsTEC(); /* +++++++++ TST (ENDCAPS) +++++++++++ */ + SpdIts* vxd = new SpdIts(); /* +++++++++ VERTEX TRACKER ++++++++++ */ + + /*--------------------------------------------------*/ + /* ++++++++++++ CASTOMIZE GEOMETRY +++++++++++++ */ + /*--------------------------------------------------*/ + + SpdParameter* par; + + //-------------------------------------------------------------------------- + // Chose TsTEC configuration + // + // option = 1: (2x)3 modules, 1 module = 8x2 = 16 layers, total = 48 layers (default) + // option = 2: (2x)2 modules, 1 module = 8x2 = 16 layers, total = 32 layers + // option = 3: (2x)1 modules, 1 module = 26x2 = 52 layers, total = 52 layers (actual!) + + SpdTsTECGeoMapper::Instance()->SetGeometryPars(3); + + /*++++++++++++++++++++++++++++++*/ + +// SpdCommonGeoMapper::Instance()->UnsetMaterials(1); + SpdCommonGeoMapper::Instance()->ConstructGeometry(); + + //SpdCommonGeoMapper::Instance()->PrintGeometryList(); + //SpdCommonGeoMapper::Instance()->PrintGeometry(); +// +// SpdTsTBGeoMapper::Instance()->PrintVolPars(); +// SpdTsTBGeoMapper::Instance()->PrintGeoTable(); + + /* DRAW GEOMETRY */ + + TGeoManager *geoMan = gGeoManager; + geoMan->SetVisLevel(2); + geoMan->GetMasterVolume()->Draw("ogl"); + //geoMan->GetMasterVolume()->Draw(); + + // return; + + /* Save Geometry into the file */ + +// TFile* file = new TFile("geofile_full.root","RECREATE"); +// file->cd(); +// gGeoManager->Write(); +// file->Close(); + + //geoMan->Export("geofile_full.root"); // save as *.root + //geoMan->Export("geofile_full.gdml"); // save as *.gdml + +} + + diff --git a/macro/geom/ConstructRsTB.C b/macro/geom/ConstructRsTB.C index e7bc71b965443db6b3e449dc109e4919cbcd6526..f990709c8db8cd11eccc4beb457922a810a3997b 100644 --- a/macro/geom/ConstructRsTB.C +++ b/macro/geom/ConstructRsTB.C @@ -8,13 +8,17 @@ void ConstructRsTB() Cave->SetGeometryFileName("cave.geo"); Cave->ConstructGeometry(); - SpdCommonGeoMapper::Instance()->DefineHybGeometrySet(); + //SpdCommonGeoMapper::Instance()->DefineHybGeometrySet(); + SpdCommonGeoMapper::Instance()->DefineQSolGeometrySet(); //SpdPipe* Pipe = new SpdPipe(); //Pipe->ConstructGeometry(); //Pipe->Print(""); - SpdRsTBGeoMapper::Instance()->SetGeoType(1); + //SpdRsTBGeoMapper::Instance()->SetGeoType(1); + + //SpdParameter* par = SpdRsTBGeoMapper::Instance()->AddParameter("RsTBClearance"); + //*par = 0.; SpdRsTB* rs = new SpdRsTB(); diff --git a/macro/geom/ConstructRsTB2.C b/macro/geom/ConstructRsTB2.C new file mode 100644 index 0000000000000000000000000000000000000000..304815f2ccb8b1607f1bee4a5a9bf1b19650923f --- /dev/null +++ b/macro/geom/ConstructRsTB2.C @@ -0,0 +1,32 @@ +//______________________________________________________________ +void ConstructRsTB2() { + // + SpdCommonGeoMapper::Instance()->OpenGeometry(); + + FairModule* Cave = new SpdCave(); + Cave->SetGeometryFileName("cave.geo"); + Cave->ConstructGeometry(); + + SpdCommonGeoMapper::Instance()->DefineQslGeometrySet(); + + //SpdPipe* Pipe = new SpdPipe(); + //Pipe->ConstructGeometry(); + //Pipe->Print(""); + + SpdRsTB2* rstb = new SpdRsTB2(); + rstb->ConstructGeometry(); + + /* ~~~~~~~~~~~~~ PRINT GEOMETRY INFO ~~~~~~~~~~~~~~~~~ */ + + SpdRsTB2GeoMapper::Instance()->Print(""); // print all parameters + + /* ~~~~~~~~~~~~~ DRAW GEOMETRY ~~~~~~~~~~~~~~~~~ */ + + TGeoManager *geoMan = gGeoManager; + geoMan->SetVisLevel(3); + + //geoMan->GetMasterVolume()->SetVisContainers(); + geoMan->GetMasterVolume()->Draw("ogl"); + return; + +} diff --git a/macro/geom/ConstructRsTEC2.C b/macro/geom/ConstructRsTEC2.C new file mode 100644 index 0000000000000000000000000000000000000000..b920fa6b1172fa2f0f125bc8c9df44569cd35cb7 --- /dev/null +++ b/macro/geom/ConstructRsTEC2.C @@ -0,0 +1,31 @@ +//______________________________________________________________ +void ConstructRsTEC2() { + // + SpdCommonGeoMapper::Instance()->OpenGeometry(); + + FairModule* Cave = new SpdCave(); + Cave->SetGeometryFileName("cave.geo"); + Cave->ConstructGeometry(); + + SpdCommonGeoMapper::Instance()->DefineQslGeometrySet(); + + SpdPipe* Pipe = new SpdPipe(); + Pipe->ConstructGeometry(); + + SpdRsTEC2* rstec = new SpdRsTEC2(); + rstec->ConstructGeometry(); + + /* ~~~~~~~~~~~~~ PRINT GEOMETRY INFO ~~~~~~~~~~~~~~~~~ */ + + SpdRsTEC2GeoMapper::Instance()->Print(""); // print all parameters + + /* ~~~~~~~~~~~~~ DRAW GEOMETRY ~~~~~~~~~~~~~~~~~ */ + + TGeoManager *geoMan = gGeoManager; + geoMan->SetVisLevel(2); + + //geoMan->GetMasterVolume()->SetVisContainers(); + geoMan->GetMasterVolume()->Draw("ogl"); + return; + +} diff --git a/macro/geom/ConstructTsTB.C b/macro/geom/ConstructTsTB.C index bda3393540caedf2fdb4c28dc1f6ed8f1f040528..a0f94d28d7efcf46e46a327d7833be45083afb33 100644 --- a/macro/geom/ConstructTsTB.C +++ b/macro/geom/ConstructTsTB.C @@ -17,8 +17,8 @@ void ConstructTsTB() { // /* change number of sectors */ //SpdCommonGeoMapper::Instance()->SetNGeoSectors(9); // > 2 && < 13 - //Standard(); - Custom(); + Standard(); + //Custom(); /* ~~~~~~~~~~~~~ PRINT GEOMETRY INFO ~~~~~~~~~~~~~~~~~ */ @@ -160,18 +160,18 @@ void Standard() cout << "\t tid = " << geotable->GetNodeTableNum(path) << " path = " << path << endl; //--------------------------------------------------------------------------------------------- - // 6275 3 2563 1 [ 1 1] TsTBStraw692Wire TsTBStraw692 [ 2564 2564] - // 2296 2 2157 1 [ 6 6] TsTBStraw692 TsTBLayer128 [ 11401 11401] - // 138 1 135 21 [ 22 42] TsTBLayer128 TsTBModule3 [ 440 460] + // 6275 3 1274 1 [ 1 1] TsTBStraw89Shell TsTBStraw89 [ 1275 1275] + // 1217 2 1078 1 [ 2 2] TsTBStraw89 TsTBLayer127 [ 4632 4632] + // 137 1 134 21 [ 22 42] TsTBLayer127 TsTBModule3 [ 419 439] // 2 0 2 8 [ 1 8] TsTBModule3 cave [ 17 24] - - - path = "/cave_1/TsTBModule3_6/TsTBLayer128_25/TsTBStraw692_6/TsTBStraw692Wire_1"; + + path = "/cave_1/TsTBModule3_6/TsTBLayer127_25/TsTBStraw89_2/TsTBStraw89Shell_1"; cout << "\n" << path << endl; tid = geotable->GetNodeTableNum(path); path = geotable->GetNodeGeoPath(tid); cout << "\t tid = " << tid << " path = " << path << endl; + cout << endl; } //________________________________________________________________________________________________ diff --git a/macro/geom/ConstructTsTEC.C b/macro/geom/ConstructTsTEC.C index d0c710c49a1a8d39ac5cbcd0ccbfa4844212bf80..8c671eb61557b1e7796922a4e3e90112bb971ed4 100644 --- a/macro/geom/ConstructTsTEC.C +++ b/macro/geom/ConstructTsTEC.C @@ -71,7 +71,7 @@ void ConstructTsTEC() { /* ~~~~~~~~~~~~~ DRAW GEOMETRY ~~~~~~~~~~~~~~~~~ */ TGeoManager *geoMan = gGeoManager; - geoMan->SetVisLevel(3); + geoMan->SetVisLevel(2); geoMan->GetMasterVolume()->SetVisContainers(); geoMan->GetMasterVolume()->Draw("ogl"); @@ -108,7 +108,7 @@ void Standard(Int_t goption) { mapper->SetGeoType(3); - mapper->SetGeometryPars(1); // 3x8+3x8 modules*layers (default) + //mapper->SetGeometryPars(1); // 3x8+3x8 modules*layers (default) //mapper->SetGeometryPars(2); // 1+1 modules //mapper->SetGeometryPars(3); // 3x24+3x24 modules*layers //mapper->SetGeometryPars(4); // 6x4+6x4 modules*layers @@ -291,9 +291,11 @@ void Custom_1(Int_t goption) mapper->AddIdentModules( 1, 1, 1, 0. /*deg*/); mapper->AddIdentModules(-1, 2, 1, 90. /*deg*/); - //mapper->AddForwardModule(1,0,0); - //mapper->AddBackwardModule(2,0,45.); - //mapper->RecalculateDistance(); +// mapper->AddForwardModule(1,0,0); +// mapper->AddForwardModule(1,0,0); +// mapper->AddBackwardModule(2,0,45.); +// mapper->AddBackwardModule(2,0,45.); +// mapper->RecalculateDistance(); } diff --git a/macro/geom/build_magnet.C b/macro/geom/build_magnet.C index 7705d0e208b7aeb80093a2ec952b308a72a485da..c4dd89447ed194f76a101475e0156a298c45485f 100644 --- a/macro/geom/build_magnet.C +++ b/macro/geom/build_magnet.C @@ -5,6 +5,7 @@ void pipe(); void magnet_tor(); void magnet_sol(); void magnet_hyb(); +void magnet_qsl(); //________________________________________________________________________ void build_magnet() @@ -24,7 +25,8 @@ void build_magnet() //magnet_tor(); //magnet_sol(); - magnet_hyb(); + //magnet_hyb(); + magnet_qsl(); //-------------------------------------------------- @@ -52,7 +54,7 @@ void magnet_tor() //Magnet->PurseCoilsAlongZ(30 /*dz, cm*/); // [cm], new Z_size >= width + rounding //Magnet->SetCoilsMaterial("silicon"); // see avaliable materials in geometry/media.geo - //Magnet->UnsetMaterials(1); + //Magnet->UnsetMaterials(); Magnet->ConstructGeometry(); @@ -66,7 +68,7 @@ void magnet_sol() { SpdSolMagnet* Magnet = new SpdSolMagnet(); - //Magnet->SetGeometryType(1); // type = 1 (default) or type = 2 + Magnet->SetGeometryType(1); // type = 1 (default) or type = 2 //Magnet->SetWidth(50); // [cm], width >= 1 cm //Magnet->SetMaterial("iron"); @@ -85,8 +87,21 @@ void magnet_hyb() { SpdHybMagnet* Magnet = new SpdHybMagnet(); - Magnet->SetGeometryType(1); // type = 1 (default) or type = 2 + Magnet->SetGeometryType(1); // geometry type = 1: hybrid, + //Magnet->SetGeometryType(2); // geometry type = 2: qsolenoid-large + + Magnet->ConstructGeometry(); + + //Magnet->Print(""); +} + +//________________________________________________________________________ +void magnet_qsl() +{ + SpdCommonGeoMapper::Instance()->DefineQslGeometrySet(); // default geometry type = 3: qsolenoid-actual + SpdHybMagnet* Magnet = new SpdHybMagnet(); + Magnet->ConstructGeometry(); //Magnet->Print(""); @@ -105,7 +120,8 @@ void pipe() //Pipe->SetPipeType("hybrid"); //Pipe->SetPipeMaterial("silicon"); - //Pipe->UnsetMaterials(1); + + //Pipe->UnsetMaterials("vacuum"); Pipe->ConstructGeometry(); diff --git a/macro/geom/build_pipe.C b/macro/geom/build_pipe.C index e16e260b1a55355fd912227473e92b40f5a5b84a..65866e2fb80d4ce63c0009f6767f6c4f88e321c6 100644 --- a/macro/geom/build_pipe.C +++ b/macro/geom/build_pipe.C @@ -1,11 +1,12 @@ - void pipe(); void magnet_tor(); void magnet_sol(); void magnet_hyb(); +void pipe_volume(); + //________________________________________________________________________ void build_pipe() { @@ -47,15 +48,18 @@ void pipe() //Pipe->SetPipeType("hyb"); //Pipe->SetPipeMaterial("silicon"); - //Pipe->UnsetMaterials(1); + + Pipe->UnsetMaterials("vacuum"); Pipe->ConstructGeometry(); //Pipe->Print(); } + //________________________________________________________________________ void pipe_volume() { + gSystem->Load("libGeom.so"); SpdPipe* Pipe = new SpdPipe(); @@ -63,11 +67,11 @@ void pipe_volume() TGeoVolume* vol; - vol = Pipe->GetHybPipeISpace(); - //vol = Pipe->GetHybPipeC(); - //vol = Pipe->GetHybPipeLZminus(); - //vol = Pipe->GetHybPipeLZPlus(); + vol = const_cast<TGeoVolume*>(Pipe->GetHybPipeISpace()); + //vol = const_cast<TGeoVolume*>(Pipe->GetHybPipeC()); + //vol = const_cast<TGeoVolume*>(Pipe->GetHybPipeLZminus()); + //vol = const_cast<TGeoVolume*>(Pipe->GetHybPipeLZPlus()); if (vol) vol->Draw("ogl"); -} \ No newline at end of file +} diff --git a/macro/primgen/TestEvtBaseGenerator.C b/macro/primgen/TestEvtBaseGenerator.C index 599dd337caaef85892ac0c8554b768afb484b03c..1d967c8e185c168846c48ccd5eedecabd5d8ef93 100644 --- a/macro/primgen/TestEvtBaseGenerator.C +++ b/macro/primgen/TestEvtBaseGenerator.C @@ -2,6 +2,7 @@ SpdGenerator* InitPythia6(); SpdGenerator* InitFTF(Int_t nevents, Double_t Elab = 25 /*GeV*/); +SpdGenerator* InitUrqmd(TString data); //______________________________________________________________ void TestEvtBaseGenerator(Int_t ngevents = 5, Int_t nevents = 10) @@ -11,13 +12,18 @@ void TestEvtBaseGenerator(Int_t ngevents = 5, Int_t nevents = 10) ingen = InitPythia6(); //ingen = InitFTF(nevents); + //ingen = InitUrqmd("../input/AuAu_ecm9gev_hydroON_EoS1PT_mbias_1000ev_10.f13.gz"); + if (!ingen) return; - ingen->SetVerboseLevel(-10); + //ingen->SetVerboseLevel(-10); ingen->CreateAsciiFile(nevents,"EvtBaseEvents"); //ingen->CreateRootFile(nevents,""EvtBaseEvents"); - + + //ingen->CreateRootFile(1,"UrqmdEvents"); + //ingen->CreateAsciiFile(1,"UrqmdEvents"); + return; //---------------------------------------------------- @@ -88,4 +94,14 @@ SpdGenerator* InitFTF(Int_t nevents, Double_t Elab) return ftfgen; } +//______________________________________________________________ +SpdGenerator* InitUrqmd(TString data) +{ + SpdUrqmdGenerator* gen = new SpdUrqmdGenerator("../input/AuAu_ecm9gev_hydroON_EoS1PT_mbias_1000ev_10.f13.gz"); + + gen->SetVerboseLevel(2); // 0 ("minimal" printing) or 1 + gen->SetKeepEvent(kFALSE); + + return gen; +} diff --git a/macro/primgen/TestIsotropic.C b/macro/primgen/TestIsotropic.C index 5463265b89169c78d780f91c5e38129c3aa8fdf2..aad1c430b8f9cd78bc11c94f6209b8e0931aa9ea 100644 --- a/macro/primgen/TestIsotropic.C +++ b/macro/primgen/TestIsotropic.C @@ -6,7 +6,7 @@ TH3D* DP_(0); TH1D *Theta_(0), *Phi_(0); void FillH(TParticle* part); -void DrawH(Int_t mark_size = 0.3); +void DrawH(Double_t mark_size = 0.3); const Double_t R_ = 1.; @@ -108,7 +108,7 @@ void check_pythia6() } } - DrawH(0.5 /*size of marker */); + DrawH(0.5 /* marker size */); delete gen; } @@ -148,7 +148,7 @@ void FillH(TParticle* part) } //______________________________________________________________ -void DrawH(Int_t mark_size) +void DrawH(Double_t mark_size) { if (DP_) { TCanvas* cDP = new TCanvas("Direction","Direction",800,800); diff --git a/macro/primgen/TestUrqmd.C b/macro/primgen/TestUrqmd.C new file mode 100644 index 0000000000000000000000000000000000000000..5b5c847ff37998bddf3cea4699798b0799c44291 --- /dev/null +++ b/macro/primgen/TestUrqmd.C @@ -0,0 +1,121 @@ +#include "TParticle.h" + +void check_urqmd(); + +TH3D* DP_(0); +TH1D *Theta_(0), *Phi_(0); + +void FillH(TParticle* part); +void DrawH(Double_t mark_size = 0.3); + +const Double_t R_ = 1.; + +//______________________________________________________________ +void TestUrqmd() +{ + gStyle->SetOptStat("e"); + + check_urqmd(); +} + +//______________________________________________________________ +void check_urqmd() +{ + SpdUrqmdGenerator* gen = new SpdUrqmdGenerator("../input/AuAu_ecm9gev_hydroON_EoS1PT_mbias_1000ev_10.f13.gz"); + + //-------------------------------------------------------------------------------- + gen->SetVerboseLevel(2); // 0 ("minimal" printing) or 1 + gen->SetKeepEvent(kTRUE); + //gen->Initialize(211,1,10000); +// gen->Initialize(211,1,5); + + /* ----------- GENERATE EVENT ----------- */ + + Int_t skip_events = 0; + while (true) { + gen->ReadEvent(0); + if (++skip_events == 1) break; + } + + const TClonesArray* event = gen->GetEvent(); + + if (event) { + Int_t size = event->GetEntriesFast(); + for (Int_t i(0); i<size; i++) { + FillH((TParticle*)event->At(i)); + } + } + + DrawH(1.0 /*size of marker */); + + delete gen; +} + +//______________________________________________________________ +void FillH(TParticle* part) +{ + if (!part) return; + + //cout << part->GetPdgCode() << " " << part->GetFirstMother()<< endl; + + if (!DP_) { + DP_ = new TH3D("Direction","", + 100 , -1.5*R_, 1.5*R_, 150, -1.5*R_, 1.5*R_ , 150, -1.5*R_, 1.5*R_ ); + } + + double dd = 0.; + + if (!Theta_) { + Theta_ = new TH1D("Theta","Theta",18,0+dd,180+dd); + Theta_->SetFillColor(kRed); + Theta_->SetMinimum(0); + } + + if (!Phi_) { + Phi_ = new TH1D("Phi","Phi",36,-180+dd,180+dd); + Phi_->SetFillColor(kRed); + Phi_->SetMinimum(0); + } + + TVector3 v(part->Px(),part->Py(),part->Pz()); + v.SetMag(R_); + + DP_->Fill(v.X(),v.Y(),v.Z()); + Theta_->Fill(v.Theta()*TMath::RadToDeg()); + Phi_->Fill(v.Phi()*TMath::RadToDeg()); +} + +//______________________________________________________________ +void DrawH(Double_t mark_size) +{ + if (DP_) { + TCanvas* cDP = new TCanvas("Direction","Direction",800,800); + DP_->SetMarkerStyle(8); + DP_->SetMarkerSize(mark_size); + DP_->Draw(); + + TPolyMarker3D* center = new TPolyMarker3D(1); + center->SetPoint(0,0,0,0); + center->SetMarkerStyle(8); + center->SetMarkerColor(kRed); + center->SetMarkerSize(2); + center->Draw("same"); + } + + if (Theta_) { + TCanvas* cTh = new TCanvas("Theta","Theta",1000,700); + Theta_->Draw(); + } + + if (Phi_) { + TCanvas* cPh = new TCanvas("Phi","Phi",1000,700); + Phi_->Draw(); + } +} + + + + + + + diff --git a/macro/rootlogon.C b/macro/rootlogon.C index 6128517f066e6d7af6dc4e92f32002e7ea2d8c35..7c7cb069b312210dbaf07b94366860d9e5831c2f 100644 --- a/macro/rootlogon.C +++ b/macro/rootlogon.C @@ -51,6 +51,7 @@ void SetMacroPath() macropath += mpath + "/geom" + ":"; macropath += mpath + "/analysis" + ":"; macropath += mpath + "/tracking" + ":"; + macropath += mpath + "/vertexrec" + ":"; //macropath += mpath + "/analysis/its" + ":"; //macropath += mpath + "/analysis/tst" + ":"; @@ -101,9 +102,12 @@ void LoadLibraries() gSystem->Load("libGenFit2"); gSystem->Load("libTrackingGF"); gSystem->Load("libSpdReco"); - + + gSystem->Load("libKFParticle"); + gSystem->Load("libVertexKF"); + //gSystem->ListLibraries(); - + cout << "Ok " << endl; } @@ -166,6 +170,11 @@ void LoadIncludes() gROOT->ProcessLine(".include ../proc/clustering"); gROOT->ProcessLine(".include ../proc/tracking"); + gROOT->ProcessLine(".include ../proc/vertex"); + + + gROOT->ProcessLine(".include ../external/KFParticle/KFParticle"); + gROOT->ProcessLine(".include ../external/KFParticle/KFParticleTest"); cout << " Ok " << endl; } diff --git a/macro/run/SimuEvtBase.C b/macro/run/SimuEvtBase.C index b3c822af47d7bd302deba6674d3331e396b5090a..2b27f5826f2c51a7e969abc101574d05a5cc4cbc 100644 --- a/macro/run/SimuEvtBase.C +++ b/macro/run/SimuEvtBase.C @@ -62,7 +62,7 @@ void SimuEvtBase(Int_t nEvents = 1, Int_t nSkipEvents = 0) /* --- field map --- */ SpdFieldMap* MagField = new SpdFieldMap("Hybrid field"); - MagField->InitData("map_hyb_1T5cm.dat"); + MagField->InitData("map_hyb_1T2cm.bin"); run->SetField(MagField); diff --git a/macro/run/XSimuHyb.C b/macro/run/XSimuHyb.C index c8a034ea60a2a9c61f4f7be1e1ad71304ee85573..62ae71714fbc08686b83061bd4cb91d7700e9108 100644 --- a/macro/run/XSimuHyb.C +++ b/macro/run/XSimuHyb.C @@ -32,7 +32,7 @@ void XSimuHyb(Int_t nEvents = 1) SpdPipe* Pipe = new SpdPipe(); //Pipe->SetPipeMaterial("silicon"); - //Pipe->UnsetMaterials(1); + //Pipe->UnsetMaterials("vacuum2"); run->AddModule(Pipe); diff --git a/macro/run/XSimuSol.C b/macro/run/XSimuSol.C index aa067f6c640e8174042fdd6b8f6056c5025dd009..6a166f0d807dfa9b7f1721efe574baedf29a462a 100644 --- a/macro/run/XSimuSol.C +++ b/macro/run/XSimuSol.C @@ -32,7 +32,7 @@ void XSimuSol(Int_t nEvents = 1) SpdPipe* Pipe = new SpdPipe(); //Pipe->SetPipeMaterial("silicon"); - //Pipe->UnsetMaterials(1); + //Pipe->UnsetMaterials("vacuum2"); run->AddModule(Pipe); diff --git a/macro/run/XSimuTor.C b/macro/run/XSimuTor.C index 91815537d3d783edab850bae31b86825fd779d98..25499e699204b6fa4a953acd98e552d61faa9ad8 100644 --- a/macro/run/XSimuTor.C +++ b/macro/run/XSimuTor.C @@ -32,7 +32,7 @@ void XSimuTor(Int_t nEvents = 1) SpdPipe* Pipe = new SpdPipe(); //Pipe->SetPipeMaterial("silicon"); - //Pipe->UnsetMaterials(1); + //Pipe->UnsetMaterials("vacuum2"); run->AddModule(Pipe); diff --git a/macro/testmisc/SPD_RS_Barrel_Flexible.C b/macro/testmisc/SPD_RS_Barrel_Flexible.C new file mode 100644 index 0000000000000000000000000000000000000000..f3af7565f60962f56c416f4ae2649d4b4132e472 --- /dev/null +++ b/macro/testmisc/SPD_RS_Barrel_Flexible.C @@ -0,0 +1,519 @@ +// $Id$ +// Author: georgy 2020/06/24 + +//_____________________________________________________________________________ +// +// Creates geometry of SPD RS Barrel segment and fills it with MDT detectors +//_____________________________________________________________________________ + + +TGeoVolume* createMDT(Double_t length = 493.0) { +//_____________________________________________________________________________ +// +// Creates MDT of given length; +// Envelope Dimensions(L x W x H): length x 8.5cm x 1.64cm. +// Note: Adopted from Panda Muon System +//_____________________________________________________________________________ + + // Medium description + TGeoMaterial* mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium* pair = new TGeoMedium("air",1,mat_air); + + TGeoMaterial* mat_mix = new TGeoMaterial("MDTMixture",0,0,0); + TGeoMedium* pMDTMixture = new TGeoMedium("MDTMixture",1,mat_mix); + + TGeoMaterial* mat_Al = new TGeoMaterial("Aluminium",0,0,0); + TGeoMedium* paluminium = new TGeoMedium("Aluminium",1,mat_Al); + + TGeoMaterial* mat = new TGeoMaterial("Vacuum",0,0,0); + TGeoMedium* pvacuum = new TGeoMedium("Vacuum",1,mat); + + TGeoMaterial* mat_pvc = new TGeoMaterial("PVC",0,0,0); + TGeoMedium* pPVC = new TGeoMedium("PVC",1,mat_pvc); + + TGeoMaterial* mat_iron = new TGeoMaterial("iron",0,0,0); + TGeoMedium* piron = new TGeoMedium("iron",1,mat_iron); + + TGeoMaterial* mat_g10 = new TGeoMaterial("G10",0,0,0); + TGeoMedium* pg10 = new TGeoMedium("G10",1,mat_g10); + + TGeoMaterial* mat_copper = new TGeoMaterial("copper",0,0,0); + TGeoMedium* pcopper = new TGeoMedium("copper",1,mat_copper); + + // Shapes and volumes --------------------------------------------------------------- + // General dimensions + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + Double_t xSize = 1.0; + Double_t shiftZ = 3.5/2; //distance between layers is 35mm + + TString transName; + Int_t Nenvelopes; + Int_t IncEnv = 0; + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + TGeoRotation* rotZ180 = new TGeoRotation("rotZ180", 0., 0., 180.); + rotZ180->RegisterYourself(); + + //check! + TGeoCombiTrans* M0 = new TGeoCombiTrans("M0", 0., 0, 0., rotNoRot); + TGeoCombiTrans* M1 = new TGeoCombiTrans("M1", 0., -170.5, 0., rotNoRot); + TGeoCombiTrans* M2 = new TGeoCombiTrans("M2", 0., -45.0, 0., rotNoRot); + TGeoCombiTrans* M3 = new TGeoCombiTrans("M3", 0., -184.5, 0., rotNoRot); + M0->RegisterYourself(); + M1->RegisterYourself(); + M2->RegisterYourself(); + M3->RegisterYourself(); + + Double_t empty_value = (2.0+2.0+8.5)+6.5*2; + Double_t L_MDT_Envelope = length; //493.0; + Double_t L_MDT_Envelope_sensitive = L_MDT_Envelope-empty_value; + + +Int_t ind = int(length*10); + //Shapes + //<box name="Indent20_PartBody" x="(42.500000)*2" y="(10.000000)*2" z="(8.200000)*2" lunit="mm"/> + TGeoBBox* Indent20_Shape = new TGeoBBox("Indent20_Shape", widthEnv/2, + 1.0, + thicknessEnv/2); + //<box name="FEB_box_PartBody" x="(42.500000)*2" y="(42.500000)*2" z="(8.200000)*2" lunit="mm"/> + TGeoBBox* FEB_box_Shape = new TGeoBBox("FEB_box_Shape", widthEnv/2, + widthEnv/2, + thicknessEnv/2); + //<box name="DeadMat_PartBody" x="(40.700000)*2" y="(32.500000)*2" z="(5.150000)*2" lunit="mm"/> + TGeoBBox* DeadMat_Shape = new TGeoBBox("DeadMat_Shape", 4.07, + 3.25, + 0.515); + TGeoVolume* Indent20_Vol = new TGeoVolume("Indent20_Vol", Indent20_Shape, pair); + TGeoVolume* FEB_box_Vol = new TGeoVolume("FEB_box_Vol", FEB_box_Shape, pair); + TGeoVolume* DeadMat_Vol = new TGeoVolume("DeadMat_Vol", DeadMat_Shape, pMDTMixture); + + //----------------------4930------------------------------------// + TGeoBBox* L_Al_A_Shape = new TGeoBBox(Form("L%d_Al_A_Shape",ind), 4.03, + L_MDT_Envelope_sensitive/2, + 0.03); + TGeoBBox* L_Al_B_Shape = new TGeoBBox(Form("L%d_Al_B_Shape",ind), 0.03, + L_MDT_Envelope_sensitive/2, + 0.42); + TGeoBBox* L_GasCell_Shape = new TGeoBBox(Form("L%d_GasCell_Shape",ind), 0.47, + L_MDT_Envelope_sensitive/2, + 0.46); + TGeoBBox* L_Cell_Shape = new TGeoBBox(Form("L%d_Cell_Shape",ind), 0.5, + L_MDT_Envelope_sensitive/2, + 0.46); + TGeoBBox* L_MDT_S_Shape = new TGeoBBox(Form("L%d_MDT_S_Shape",ind), 4.0, + L_MDT_Envelope_sensitive/2, + 0.46); + TGeoBBox* L_Envelope_Shape = new TGeoBBox(Form("L%d_Envelope_Shape",ind), widthEnv/2, + L_MDT_Envelope/2, + thicknessEnv/2); + + //Volumes + TGeoVolume* L_Al_A_Vol = new TGeoVolume(Form("L%d_Al_A_Vol",ind), L_Al_A_Shape, paluminium); + TGeoVolume* L_Al_B_Vol = new TGeoVolume(Form("L%d_Al_B_Vol",ind), L_Al_B_Shape, paluminium); + TGeoVolume* L_GasCell_Vol = new TGeoVolume(Form("L%d_GasCell_Vol",ind), L_GasCell_Shape, pMDTMixture); + TGeoVolume* L_Cell_Vol = new TGeoVolume(Form("L%d_Cell_Vol",ind), L_Cell_Shape, pMDTMixture); + TGeoVolume* L_MDT_S_Vol = new TGeoVolume(Form("L%d_MDT_S_Vol",ind), L_MDT_S_Shape, pMDTMixture); + TGeoVolume* L_Envelope_Vol = new TGeoVolume(Form("L%d_Envelope_Vol",ind), L_Envelope_Shape, pair); + + // Volume hierarchy ----------------------------------------------------------------- + //Structure + //GasCell and Al_B in Cell + L_Cell_Vol->AddNode(L_GasCell_Vol, 1, + new TGeoCombiTrans("", -0.03, 0, 0, rotNoRot)); + L_Cell_Vol->AddNode(L_Al_B_Vol, 1, + new TGeoCombiTrans("", 0.47, 0, -0.04, rotNoRot)); + + //8 Cells in MDT_S + for (UInt_t i=0; i<8; i++) { + transName.Form("trans_cell_%d", i); + TGeoCombiTrans* trans1 = new TGeoCombiTrans(transName.Data(), -4.0 + xSize/2. + (Double_t)i*xSize, 0, 0., rotNoRot); + trans1->RegisterYourself(); + L_MDT_S_Vol->AddNode(L_Cell_Vol, i+1, trans1); + } + + L_Envelope_Vol->AddNode(Indent20_Vol, 1, + new TGeoCombiTrans("", 0, L_MDT_Envelope/2 - 1.0, 0, rotNoRot)); + L_Envelope_Vol->AddNode(Indent20_Vol, 2, + new TGeoCombiTrans("", 0, 1.0 - L_MDT_Envelope/2, 0, rotNoRot)); + L_Envelope_Vol->AddNode(FEB_box_Vol, 1, + new TGeoCombiTrans("", 0, L_MDT_Envelope/2-2.0-8.5*0.5, 0, rotNoRot)); + L_Envelope_Vol->AddNode(DeadMat_Vol, 1, + new TGeoCombiTrans("", 0, ((L_MDT_Envelope-(2.0+2.0+8.5))-6.5)/2-widthEnv/2, 0, rotNoRot)); + L_Envelope_Vol->AddNode(DeadMat_Vol, 2, + new TGeoCombiTrans("", 0, -((L_MDT_Envelope-(2.0+2.0+8.5))-6.5)/2-widthEnv/2, 0, rotNoRot)); + L_Envelope_Vol->AddNode(L_Al_A_Vol, 1, + new TGeoCombiTrans("", 0, -widthEnv/2, -0.36, rotNoRot)); + L_Envelope_Vol->AddNode(L_Al_B_Vol, 1, + new TGeoCombiTrans("", -4.0, -widthEnv/2, 0.09, rotNoRot)); + L_Envelope_Vol->AddNode(L_MDT_S_Vol, 1, + new TGeoCombiTrans("", 0.03, -widthEnv/2, 0.13, rotNoRot)); + //----------------------4930------------------------------------// + + return L_Envelope_Vol; +} + +//_____________________________________________________________________________ +// +TGeoVolume* createBottomLayer(Double_t rsRadius, Double_t rsThickness, Double_t rsLength) { +//_____________________________________________________________________________ +// +// Creates trapezoid representing bottom layer of the RS Barrel part +// (6.0cm thick iron absorber and a layer of MDT detectors) +// Parameters: 1. Outer radius of RS from collision point (rsRadius); +// 2. Thickness of RS rsThickness. +// Returns: TGeoVolume object of the layer with absorber and MDTs. +//_____________________________________________________________________________ + + Double_t layerThickness = 6.0+3.5; //cm + + Double_t Sector_dy = rsLength/2.0; + + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + Double_t shiftZ = 3.5/2; //distance between layers is 35mm + + TGeoMaterial *mat_iron = new TGeoMaterial("iron",0,0,0); + TGeoMedium *piron = new TGeoMedium("iron",1,mat_iron); + + TGeoMaterial *mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium *pair = new TGeoMedium("air",1,mat_air); + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + TGeoRotation* rotZ180 = new TGeoRotation("rotZ180", 0., 0., 180.); + rotZ180->RegisterYourself(); + + Double_t Layer1_Sector_dz = layerThickness/2; // z-coord of the layer center + Double_t Layer1_Sector_dx1 = 1.0*(rsRadius-rsThickness)*(sqrt(2.0)-1.0); // X-coord of the bottom base + Double_t Layer1_Sector_dx2 = 1.0*(rsRadius-rsThickness+layerThickness)*(sqrt(2.0)-1.0); // X-coord of the top base + Double_t Layer1_Sector_dy = Sector_dy; // y-coord of the layer center + cout<<"Layer #1 dimensions (bottom base): [" + << Layer1_Sector_dx1*2<<" x " + << Layer1_Sector_dz*2 << " x " + << Layer1_Sector_dy*2 << "] cm" << endl; + cout<<"Layer #1 dimensions (top base): [" + <<Layer1_Sector_dx2*2<<" x " + << Layer1_Sector_dz*2 << " x " + << Layer1_Sector_dy*2 << "] cm" << endl; + + + + TGeoTrd2* Layer1_SideS_Shape = new TGeoTrd2("Layer_SideS_Shape", + 1.0*Layer1_Sector_dx1, + 1.0*Layer1_Sector_dx2, + Layer1_Sector_dy, + Layer1_Sector_dy, + Layer1_Sector_dz); + + TGeoBBox* Layer1_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + 1.0*Layer1_Sector_dx1, + Layer1_Sector_dy, + Layer1_Sector_dz-3.5/2); + + TGeoVolume* Layer1_SideS_Vol = new TGeoVolume("Layer_SideS_Vol", Layer1_SideS_Shape, pair); + TGeoVolume* Layer1_SideS_Abs_Base_Vol = new TGeoVolume("Layer_SideS_Abs_Base_Vol", Layer1_SideS_Abs_Base_Shape, piron); + + Layer1_SideS_Vol->AddNode(Layer1_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, 0, -1.75, rotNoRot)); + + + Double_t Layer1_Envelope_startX = -1.0*Layer1_Sector_dx1; + Double_t Layer1_Envelope_shiftX = Layer1_Envelope_startX + widthEnv/2; + + Double_t Layer1_length = 2*abs(Layer1_Envelope_startX); + cout<<"Layer #1 length: " << Layer1_length << endl; + + int Nenvelopes = int(Layer1_length/widthEnv); + cout << "Number of MDT detector in Layer #1: " << Nenvelopes << endl; + for (UInt_t i=0; i<Nenvelopes; i++) { + //for (UInt_t i=0; i<1; i++) { + + Layer1_SideS_Vol->AddNode(createMDT(493.0), i+1, new TGeoCombiTrans("", Layer1_Envelope_shiftX, 0, 1.75+thicknessEnv/2, rotNoRot)); + Layer1_Envelope_shiftX = Layer1_Envelope_shiftX + widthEnv; + } + + // Zero Bi-Layer Geometry (currently disabled) + // Layer1_Envelope_shiftX = -60.0-0.5; + // Layer1_Envelope_shiftX = Layer1_Envelope_startX + widthEnv/2; + + // Nenvelopes = 14; + // for (UInt_t i=0; i<Nenvelopes; i++) + // { + // Layer1_SideS_Vol->AddNode(createMDT(493.0), i+15, new TGeoCombiTrans("", Layer1_Envelope_shiftX, 0, 1.2+thicknessEnv/2+thicknessEnv, rotNoRot)); + // Layer1_Envelope_shiftX = Layer1_Envelope_shiftX + widthEnv; + // } + + + return Layer1_SideS_Vol; +} + +//_____________________________________________________________________________ +// +TGeoVolume* createRegularLayer(Int_t layerN, Double_t rsRadius, Double_t rsThickness, Double_t rsLength) { +//_____________________________________________________________________________ +// +// Creates trapezoid representing regular layer of the RS Barrel part +// (3.0cm thick iron absorber and a layer of MDT detectors) +// Parameters: 1. Number of layer in a sector +// 2. Outer radius of RS from collision point (rsRadius); +// 3. Thickness of RS rsThickness. +// Returns: TGeoVolume object of the layer with absorber and MDTs. +//_____________________________________________________________________________ + + Double_t layerThickness = 3.0+3.5; //cm + + Double_t Sector_dy = rsLength/2.0; + + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + Double_t shiftZ = 3.5/2; //distance between layers is 35mm + + TGeoMaterial *mat_iron = new TGeoMaterial("iron",0,0,0); + TGeoMedium *piron = new TGeoMedium("iron",1,mat_iron); + + TGeoMaterial *mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium *pair = new TGeoMedium("air",1,mat_air); + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + TGeoRotation* rotZ180 = new TGeoRotation("rotZ180", 0., 0., 180.); + rotZ180->RegisterYourself(); + + Double_t Layer1_Sector_dz = layerThickness/2; // z-coord of the layer center + Double_t Layer1_Sector_dx1 = 1.0*(rsRadius - rsThickness + 9.5 + (layerN-2)*layerThickness)*(sqrt(2.0)-1.0); // X-coord of the bottom base + Double_t Layer1_Sector_dx2 = 1.0*(rsRadius - rsThickness + 9.5 + (layerN-1)*layerThickness)*(sqrt(2.0)-1.0); // X-coord of the top base + Double_t Layer1_Sector_dy = Sector_dy; // y-coord of the layer center + cout<<"Layer #"<< layerN << " dimensions (bottom base): [" + <<Layer1_Sector_dx1*2<<" x " + << Layer1_Sector_dz*2 << " x " + << Layer1_Sector_dy*2 << "] cm" << endl; + cout<<"Layer #"<< layerN << " dimensions (top base): [" + <<Layer1_Sector_dx2*2<<" x " + << Layer1_Sector_dz*2 << " x " + << Layer1_Sector_dy*2 << "] cm" << endl; + + + + TGeoTrd2* Layer1_SideS_Shape = new TGeoTrd2("Layer_SideS_Shape", + 1.0*Layer1_Sector_dx1, + 1.0*Layer1_Sector_dx2, + Layer1_Sector_dy, + Layer1_Sector_dy, + Layer1_Sector_dz); + + TGeoBBox* Layer1_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + 1.0*Layer1_Sector_dx1, + Layer1_Sector_dy, + 3.0/2); + + TGeoVolume* Layer1_SideS_Vol = new TGeoVolume("Layer_SideS_Vol", Layer1_SideS_Shape, pair); + TGeoVolume* Layer1_SideS_Abs_Base_Vol = new TGeoVolume("Layer_SideS_Abs_Base_Vol", Layer1_SideS_Abs_Base_Shape, piron); + + Layer1_SideS_Vol->AddNode(Layer1_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, 0, -1*Layer1_Sector_dz+3.0/2, rotNoRot)); + + if (layerN % 2 != 0) { + Double_t Layer1_Envelope_startX = Layer1_Sector_dx1; + Double_t Layer1_Envelope_shiftX = Layer1_Envelope_startX - widthEnv/2; + + Double_t Layer1_length = 2*abs(Layer1_Envelope_startX); + cout<<"Layer #" << layerN << " length: " << Layer1_length << endl; + + int Nenvelopes = int((Layer1_length - widthEnv/2)/widthEnv); + cout << "Number of MDT detector in Layer" << layerN << ": " << Nenvelopes << endl; + for (UInt_t i=0; i<Nenvelopes; i++) { + + Layer1_SideS_Vol->AddNode(createMDT(493.0), i+1, new TGeoCombiTrans("", Layer1_Envelope_shiftX, 0, 0.75+thicknessEnv/2, rotNoRot)); + Layer1_Envelope_shiftX = Layer1_Envelope_shiftX - widthEnv; + } + } + else { + + Double_t Layer1_Envelope_startX = -1.0*abs(Layer1_Sector_dx1); + Double_t Layer1_Envelope_shiftX = Layer1_Envelope_startX + widthEnv/2; + + Double_t Layer1_length = 2*abs(Layer1_Envelope_startX); + cout<<"Layer #" << layerN << " length: " << Layer1_length << endl; + + int Nenvelopes = int((Layer1_length)/widthEnv); + cout << "Number of MDT detector in Layer" << layerN << ": " << Nenvelopes << endl; + for (UInt_t i=0; i<Nenvelopes; i++) { + + Layer1_SideS_Vol->AddNode(createMDT(493.0), i+1, new TGeoCombiTrans("", Layer1_Envelope_shiftX, 0, 0.75+thicknessEnv/2, rotNoRot)); + Layer1_Envelope_shiftX = Layer1_Envelope_shiftX + widthEnv; + } + } + + return Layer1_SideS_Vol; +} + + +//_____________________________________________________________________________ +// +TGeoVolume* createTopLayer(Int_t layerN, Double_t rsRadius, Double_t rsThickness, Double_t rsLength) { +//_____________________________________________________________________________ +// +// Creates trapezoid representing regular layer of the RS Barrel part +// (3.0cm thick iron absorber and a layer of MDT detectors) +// Parameters: 1. Number of layer in a sector +// 2. Outer radius of RS from collision point (rsRadius); +// 3. Thickness of RS rsThickness. +// Returns: TGeoVolume object of the layer with absorber and MDTs. +//_____________________________________________________________________________ + + Double_t layerThickness = 3.0+3.0; //cm + + Double_t Sector_dy = rsLength/2.0; + + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + Double_t shiftZ = 3.5/2; //distance between layers is 35mm + + TGeoMaterial *mat_iron = new TGeoMaterial("iron",0,0,0); + TGeoMedium *piron = new TGeoMedium("iron",1,mat_iron); + + TGeoMaterial *mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium *pair = new TGeoMedium("air",1,mat_air); + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + TGeoRotation* rotZ180 = new TGeoRotation("rotZ180", 0., 0., 180.); + rotZ180->RegisterYourself(); + + Double_t Layer1_Sector_dz = layerThickness/2; // z-coord of the layer center + Double_t Layer1_Sector_dx1 = 1.0*(rsRadius - rsThickness + 9.5 + (layerN-1)*layerThickness)*(sqrt(2.0)-1.0); // X-coord of the bottom base + Double_t Layer1_Sector_dx2 = 1.0*(rsRadius - rsThickness + 9.5 + (layerN)*layerThickness)*(sqrt(2.0)-1.0); // X-coord of the top base + Double_t Layer1_Sector_dy = Sector_dy; // y-coord of the layer center + cout<<"Layer #"<< layerN << " dimensions (bottom base): [" + <<Layer1_Sector_dx1*2<<" x " + << Layer1_Sector_dz*2 << " x " + << Layer1_Sector_dy*2 << "] cm" << endl; + cout<<"Layer #"<< layerN << " dimensions (top base): [" + <<Layer1_Sector_dx2*2<<" x " + << Layer1_Sector_dz*2 << " x " + << Layer1_Sector_dy*2 << "] cm" << endl; + + + + TGeoTrd2* Layer1_SideS_Shape = new TGeoTrd2("Layer_SideS_Shape", + 1.0*Layer1_Sector_dx1, + 1.0*Layer1_Sector_dx2, + Layer1_Sector_dy, + Layer1_Sector_dy, + Layer1_Sector_dz); + + TGeoBBox* Layer1_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + 1.0*Layer1_Sector_dx1, + Layer1_Sector_dy, + Layer1_Sector_dz); + + TGeoVolume* Layer1_SideS_Vol = new TGeoVolume("Layer_SideS_Vol", Layer1_SideS_Shape, pair); + TGeoVolume* Layer1_SideS_Abs_Base_Vol = new TGeoVolume("Layer_SideS_Abs_Base_Vol", Layer1_SideS_Abs_Base_Shape, piron); + + Layer1_SideS_Vol->AddNode(Layer1_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + + + return Layer1_SideS_Vol; +} + +//_____________________________________________________________________________ +// +void SPD_RS_Barrel_Flexible() { +//_____________________________________________________________________________ +// +// Main: +// Creates a segment of Range System Barrel with a given number of layers +// and fills each layer with MDT detectors. +// Parameters: distance from collision point, barrel size. +//_____________________________________________________________________________ + + gSystem->Load("libGeom"); + + TGeoManager* geoM = new TGeoManager("World", "Barrel"); + + //--- make the top container volume + TGeoVolume *top = new TGeoVolumeAssembly("RS_Barrel"); + gGeoManager->SetTopVolume(top); + + + TGeoRotation* rotTest = new TGeoRotation("", 180., 90., 0.); + rotTest->RegisterYourself(); + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + TGeoRotation* rotZ180 = new TGeoRotation("rotZ180", 0., 0., 180.); + rotZ180->RegisterYourself(); + + TGeoMaterial* mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium* pair = new TGeoMedium("air",1,mat_air); + + //top->AddNode(SideS_Vol, 1, new TGeoCombiTrans("", 0, 0, 45.0, rotTest)); + //top->AddNode(SideS_Vol, 1); + + //top->AddNode(L4930_Envelope_Vol, 1); + //top->AddNode(createMDT(493.0), 1); + + // Fill top volume with Range System layers + // Parameters of the Range System size and position + Double_t rsRadius = 314.4; // cm (Outer radium of the Range System) + Double_t rsThickness = 139.0; //25.7; //139.0; // cm (Thickness of the Range System) + Double_t rsLength = 493.0; // cm (Length of the sector along beam axis) + + TGeoTrd2* SideS_Shape = new TGeoTrd2("SideS_Shape", + (rsRadius - rsThickness)*(sqrt(2.0)-1.0), + (rsRadius )*(sqrt(2.0)-1.0), //1234 Fe without bilayer MDTs + rsLength/2, + rsLength/2, + rsThickness/2); //805 only Fe (without bilayer MDTs) + TGeoVolume* SideS_Vol = new TGeoVolume("SideS_Vol", SideS_Shape, pair); + cout<<"Layer #"<< (rsRadius - rsThickness)*(sqrt(2.0)-1.0) << " dimensions (bottom base): [" + << endl; + cout<<"Layer #"<< (rsRadius )*(sqrt(2.0)-1.0) << " dimensions (top base): [" + << endl; + + + // Number of layers calcluation within RS thickness: + // (Thickness - top absorber - bottom absorber/mdt)/LayerThickness + 1(bottom layer) + Int_t nLayers = int((rsThickness - 6. - 9.5)/6.5) + 1; + cout << "# of Layers within " << rsThickness << " cm: " << nLayers << endl; + + // Add bottom layer (absrober(6.0cm) + mdt detectors(3.5cm)) + SideS_Vol->AddNode(createBottomLayer(rsRadius, rsThickness, rsLength), 1, + new TGeoCombiTrans("", 0, 0, -1.*(rsThickness)/2 + 4.75, rotNoRot)); + + // Add regular layers (3.0cm absorber + 3.5cm mdt detectors) +// for (Int_t i=2; i < nLayers+1; ++i) { +// +// SideS_Vol->AddNode(createRegularLayer(i, rsRadius, rsThickness, rsLength), i, +// //new TGeoCombiTrans("", 0, 0, rsRadius - rsThickness + (i-1)*6.5, rotNoRot)); +// new TGeoCombiTrans("", 0, 0, -1.*(rsThickness)/2 + (i-1)*6.5 + 9.5 - 3.25, rotNoRot)); +// } + // Add top absorber (6.0cm) + SideS_Vol->AddNode(createTopLayer(nLayers+1, rsRadius, rsThickness, rsLength), nLayers+1, + new TGeoCombiTrans("", 0, 0, 1.0*(rsThickness)/2 - 6.0/2, rotNoRot)); + + + top->AddNode(SideS_Vol,1); + + gGeoManager->CloseGeometry(); + top->SetLineColor(kMagenta); + //gGeoManager->SetTopVisible(); // the TOP is invisible + top->Draw(); + + //gGeoManager->CheckGeometry(); + //gGeoManager->CheckGeometryFull(); + //gGeoManager->Test(); + + TString outGeoFilenameRoot = "./Barrel_cm.root"; + TFile* outGeoFileRoot = new TFile(outGeoFilenameRoot, "RECREATE"); + geoM->GetTopVolume()->Write(); + outGeoFileRoot->Close(); + +} + + + + diff --git a/macro/testmisc/SPD_RS_Barrel_Flexible2.C b/macro/testmisc/SPD_RS_Barrel_Flexible2.C new file mode 100644 index 0000000000000000000000000000000000000000..1df4580524846ce4d28cf1ffb6abcb7a2a434d73 --- /dev/null +++ b/macro/testmisc/SPD_RS_Barrel_Flexible2.C @@ -0,0 +1,521 @@ +// $Id$ +// Author: georgy 2020/06/24 + +//_____________________________________________________________________________ +// +// Creates geometry of SPD RS Barrel segment and fills it with MDT detectors +//_____________________________________________________________________________ + + +TGeoVolume* createMDT(Double_t length = 493.0) { +//_____________________________________________________________________________ +// +// Creates MDT of given length; +// Envelope Dimensions(L x W x H): length x 8.5cm x 1.64cm. +// Note: Adopted from Panda Muon System +//_____________________________________________________________________________ + + // Medium description + TGeoMaterial* mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium* pair = new TGeoMedium("air",1,mat_air); + + TGeoMaterial* mat_mix = new TGeoMaterial("MDTMixture",0,0,0); + TGeoMedium* pMDTMixture = new TGeoMedium("MDTMixture",1,mat_mix); + + TGeoMaterial* mat_Al = new TGeoMaterial("Aluminium",0,0,0); + TGeoMedium* paluminium = new TGeoMedium("Aluminium",1,mat_Al); + +// TGeoMaterial* mat = new TGeoMaterial("Vacuum",0,0,0); +// TGeoMedium* pvacuum = new TGeoMedium("Vacuum",1,mat); +// +// TGeoMaterial* mat_pvc = new TGeoMaterial("PVC",0,0,0); +// TGeoMedium* pPVC = new TGeoMedium("PVC",1,mat_pvc); +// +// TGeoMaterial* mat_iron = new TGeoMaterial("iron",0,0,0); +// TGeoMedium* piron = new TGeoMedium("iron",1,mat_iron); +// +// TGeoMaterial* mat_g10 = new TGeoMaterial("G10",0,0,0); +// TGeoMedium* pg10 = new TGeoMedium("G10",1,mat_g10); +// +// TGeoMaterial* mat_copper = new TGeoMaterial("copper",0,0,0); +// TGeoMedium* pcopper = new TGeoMedium("copper",1,mat_copper); + + // Shapes and volumes --------------------------------------------------------------- + // General dimensions + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + Double_t xSize = 1.0; + + TString transName; + Int_t Nenvelopes; + Int_t IncEnv = 0; + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t empty_value = (2.0+2.0+8.5)+6.5*2; + Double_t L_MDT_Envelope = length; //493.0; + Double_t L_MDT_Envelope_sensitive = L_MDT_Envelope-empty_value; + + + Int_t ind = int(length*10); + //Shapes + //<box name="Indent20_PartBody" x="(42.500000)*2" y="(10.000000)*2" z="(8.200000)*2" lunit="mm"/> + TGeoBBox* Indent20_Shape = new TGeoBBox("Indent20_Shape", widthEnv/2, + thicknessEnv/2, + 1.0); + //<box name="FEB_box_PartBody" x="(42.500000)*2" y="(42.500000)*2" z="(8.200000)*2" lunit="mm"/> + TGeoBBox* FEB_box_Shape = new TGeoBBox("FEB_box_Shape", widthEnv/2, + thicknessEnv/2, + widthEnv/2); + //<box name="DeadMat_PartBody" x="(40.700000)*2" y="(32.500000)*2" z="(5.150000)*2" lunit="mm"/> + TGeoBBox* DeadMat_Shape = new TGeoBBox("DeadMat_Shape", 4.07, + 0.515, + 3.25); + TGeoVolume* Indent20_Vol = new TGeoVolume("Indent20_Vol", Indent20_Shape, pair); + TGeoVolume* FEB_box_Vol = new TGeoVolume("FEB_box_Vol", FEB_box_Shape, pair); + TGeoVolume* DeadMat_Vol = new TGeoVolume("DeadMat_Vol", DeadMat_Shape, pMDTMixture); + + //----------------------4930------------------------------------// + TGeoBBox* L_Al_A_Shape = new TGeoBBox(Form("L%d_Al_A_Shape",ind), 4.03, + 0.03, + L_MDT_Envelope_sensitive/2); + TGeoBBox* L_Al_B_Shape = new TGeoBBox(Form("L%d_Al_B_Shape",ind), 0.03, + 0.42, + L_MDT_Envelope_sensitive/2); + TGeoBBox* L_GasCell_Shape = new TGeoBBox(Form("L%d_GasCell_Shape",ind), 0.47, + 0.46, + L_MDT_Envelope_sensitive/2); + TGeoBBox* L_Cell_Shape = new TGeoBBox(Form("L%d_Cell_Shape",ind), 0.5, + 0.46, + L_MDT_Envelope_sensitive/2); + TGeoBBox* L_MDT_S_Shape = new TGeoBBox(Form("L%d_MDT_S_Shape",ind), 4.0, + 0.46, + L_MDT_Envelope_sensitive/2); + TGeoBBox* L_Envelope_Shape = new TGeoBBox(Form("L%d_Envelope_Shape",ind), widthEnv/2, + thicknessEnv/2, + L_MDT_Envelope/2); + + //Volumes + TGeoVolume* L_Al_A_Vol = new TGeoVolume(Form("L%d_Al_A_Vol",ind), L_Al_A_Shape, paluminium); + TGeoVolume* L_Al_B_Vol = new TGeoVolume(Form("L%d_Al_B_Vol",ind), L_Al_B_Shape, paluminium); + TGeoVolume* L_GasCell_Vol = new TGeoVolume(Form("L%d_GasCell_Vol",ind), L_GasCell_Shape, pMDTMixture); + TGeoVolume* L_Cell_Vol = new TGeoVolume(Form("L%d_Cell_Vol",ind), L_Cell_Shape, pMDTMixture); + TGeoVolume* L_MDT_S_Vol = new TGeoVolume(Form("L%d_MDT_S_Vol",ind), L_MDT_S_Shape, pMDTMixture); + TGeoVolume* L_Envelope_Vol = new TGeoVolume(Form("L%d_Envelope_Vol",ind), L_Envelope_Shape, pair); + + // Volume hierarchy ----------------------------------------------------------------- + //Structure + //GasCell and Al_B in Cell + L_Cell_Vol->AddNode(L_GasCell_Vol, 1, + new TGeoCombiTrans("", -0.03, 0, 0, rotNoRot)); + L_Cell_Vol->AddNode(L_Al_B_Vol, 1, + new TGeoCombiTrans("", 0.47, -0.04, 0, rotNoRot)); + + //8 Cells in MDT_S + for (UInt_t i=0; i<8; i++) { + transName.Form("trans_cell_%d", i); + TGeoCombiTrans* trans1 = new TGeoCombiTrans(transName.Data(), -4.0 + xSize/2. + (Double_t)i*xSize, 0, 0., rotNoRot); + trans1->RegisterYourself(); + L_MDT_S_Vol->AddNode(L_Cell_Vol, i+1, trans1); + } + + L_Envelope_Vol->AddNode(Indent20_Vol, 1, + new TGeoCombiTrans("", 0, 0, L_MDT_Envelope/2 - 1.0, rotNoRot)); + L_Envelope_Vol->AddNode(Indent20_Vol, 2, + new TGeoCombiTrans("", 0, 0, 1.0 - L_MDT_Envelope/2, rotNoRot)); + L_Envelope_Vol->AddNode(FEB_box_Vol, 1, + new TGeoCombiTrans("", 0, 0, L_MDT_Envelope/2-2.0-8.5*0.5, rotNoRot)); + L_Envelope_Vol->AddNode(DeadMat_Vol, 1, + new TGeoCombiTrans("", 0, 0, ((L_MDT_Envelope-(2.0+2.0+8.5))-6.5)/2-widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(DeadMat_Vol, 2, + new TGeoCombiTrans("", 0, 0, -((L_MDT_Envelope-(2.0+2.0+8.5))-6.5)/2-widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_Al_A_Vol, 1, + new TGeoCombiTrans("", 0, -0.36, -widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_Al_B_Vol, 1, + new TGeoCombiTrans("", -4.0, 0.09, -widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_MDT_S_Vol, 1, + new TGeoCombiTrans("", 0.03, 0.13, -widthEnv/2, rotNoRot)); + //----------------------4930------------------------------------// + + return L_Envelope_Vol; +} + +//_____________________________________________________________________________ +// +TGeoVolume* createBottomLayer(Double_t rsRadius, Double_t rsThickness, Double_t rsLength) { +//_____________________________________________________________________________ +// +// Creates trapezoid representing bottom layer of the RS Barrel part +// (6.0cm thick iron absorber and a layer of MDT detectors) +// Parameters: 1. Outer radius of RS from collision point (rsRadius); +// 2. Thickness of RS rsThickness. +// Returns: TGeoVolume object of the layer with absorber and MDTs. +//_____________________________________________________________________________ + + Double_t layerThickness = 6.0+3.5; //cm + + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + + TGeoMaterial *mat_iron = new TGeoMaterial("iron",0,0,0); + TGeoMedium *piron = new TGeoMedium("iron",1,mat_iron); + + TGeoMaterial *mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium *pair = new TGeoMedium("air",1,mat_air); + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t v_bottom[16]; + Double_t lmin = (rsRadius - rsThickness)*(sqrt(2.0)-1.0); // dimensions (bottom base) + Double_t lmax = (rsRadius - rsThickness + layerThickness)*(sqrt(2.0)-1.0); // dimensions (top base) + Double_t hmin = (rsRadius - rsThickness); + Double_t hmax = (rsRadius - rsThickness + layerThickness); + + cout<<"lmin: "<<lmin<<endl; + cout<<"lmax: "<<lmax<<endl; + cout<<"hmin: "<<hmin<<endl; + cout<<"hmax: "<<hmax<<endl; + + v_bottom[0] = lmin; v_bottom[1] = hmin; + v_bottom[2] = -lmin; v_bottom[3] = hmin; + v_bottom[4] = -lmax; v_bottom[5] = hmax; + v_bottom[6] = lmax; v_bottom[7] = hmax; + + v_bottom[8] = lmin; v_bottom[9] = hmin; + v_bottom[10] = -lmin; v_bottom[11] = hmin; + v_bottom[12] = -lmax; v_bottom[13] = hmax; + v_bottom[14] = lmax; v_bottom[15] = hmax; + + TGeoArb8* Layer_SideS_Shape = new TGeoArb8("Layer_SideS_Shape", rsLength/2, v_bottom); + + Double_t Layer_Sector_Abs_dx = lmin; + Double_t Layer_Sector_Abs_dy = 6./2; + Double_t Layer_Sector_Abs_dz = rsLength/2; + + + cout<<"Layer_SideS_Abs_Base_Shape: "<<2*Layer_Sector_Abs_dx<<" "<<2*Layer_Sector_Abs_dy<<" "<<2*Layer_Sector_Abs_dz<<endl; + + + TGeoBBox* Layer_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + Layer_Sector_Abs_dx, + Layer_Sector_Abs_dy, + Layer_Sector_Abs_dz); + + TGeoVolume* Layer_SideS_Vol = new TGeoVolume("Layer_SideS_Vol", Layer_SideS_Shape, pair); + TGeoVolume* Layer_SideS_Abs_Base_Vol = new TGeoVolume("Layer_SideS_Abs_Base_Vol", Layer_SideS_Abs_Base_Shape, piron); + + Layer_SideS_Vol->AddNode(Layer_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, hmin+Layer_Sector_Abs_dy, 0, rotNoRot)); + + + Double_t Layer_Envelope_startX = -1.0*lmin; + Double_t Layer_Envelope_shiftX = Layer_Envelope_startX + widthEnv/2; + + Double_t Layer_length = 2*abs(Layer_Envelope_startX); + cout<<"Layer #1 length: " << Layer_length << endl; + + int Nenvelopes = int(Layer_length/widthEnv); + cout << "Number of MDT detector in Layer #1: " << Nenvelopes << endl; + + + for (UInt_t i=0; i<Nenvelopes; i++) { + //for (UInt_t i=0; i<1; i++) { + + Layer_SideS_Vol->AddNode(createMDT(493.0), i+1, new TGeoCombiTrans("", Layer_Envelope_shiftX, hmin+6+3.5/2, 0, rotNoRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + } + + return Layer_SideS_Vol; +} + +//_____________________________________________________________________________ +// +TGeoVolume* createRegularLayer(Int_t layerN, Double_t rsRadius, Double_t rsThickness, Double_t rsLength) { +//_____________________________________________________________________________ +// +// Creates trapezoid representing regular layer of the RS Barrel part +// (3.0cm thick iron absorber and a layer of MDT detectors) +// Parameters: 1. Number of layer in a sector +// 2. Outer radius of RS from collision point (rsRadius); +// 3. Thickness of RS rsThickness. +// Returns: TGeoVolume object of the layer with absorber and MDTs. +//_____________________________________________________________________________ + + Double_t layerThickness = 3.0+3.5; //cm + + Double_t Sector_dy = rsLength/2.0; + + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + + TGeoMaterial *mat_iron = new TGeoMaterial("iron",0,0,0); + TGeoMedium *piron = new TGeoMedium("iron",1,mat_iron); + + TGeoMaterial *mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium *pair = new TGeoMedium("air",1,mat_air); + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t Layer_Sector_dz = layerThickness/2; // z-coord of the layer center + Double_t Layer_Sector_dx1 = 1.0*(rsRadius - rsThickness + 9.5 + (layerN-2)*layerThickness)*(sqrt(2.0)-1.0); // X-coord of the bottom base + Double_t Layer_Sector_dx2 = 1.0*(rsRadius - rsThickness + 9.5 + (layerN-1)*layerThickness)*(sqrt(2.0)-1.0); // X-coord of the top base + Double_t Layer_Sector_dy = Sector_dy; // y-coord of the layer center + cout<<"Layer #"<< layerN << " dimensions (bottom base): [" + <<Layer_Sector_dx1*2<<" x " + << Layer_Sector_dz*2 << " x " + << Layer_Sector_dy*2 << "] cm" << endl; + cout<<"Layer #"<< layerN << " dimensions (top base): [" + <<Layer_Sector_dx2*2<<" x " + << Layer_Sector_dz*2 << " x " + << Layer_Sector_dy*2 << "] cm" << endl; + + Double_t v_regular[16]; + Double_t lmin = (rsRadius - rsThickness + 9.5 + (layerN-2)*layerThickness)*(sqrt(2.0)-1.0); // dimensions (bottom base) + Double_t lmax = (rsRadius - rsThickness + 9.5 + (layerN-1)*layerThickness)*(sqrt(2.0)-1.0); // dimensions (top base) + Double_t hmin = (rsRadius - rsThickness + 9.5 + (layerN-2)*layerThickness); + Double_t hmax = (rsRadius - rsThickness + 9.5 + (layerN-1)*layerThickness); + + cout<<"Layer #"<< layerN << " dimensions (bottom base, lmin): [" << -lmin << "," << lmin << "]" << endl; + cout<<"Layer #"<< layerN << " dimensions (bottom base, lmax): [" << -lmax << "," << lmax << "]" << endl; + cout<<"hmin: "<<hmin<<endl; + cout<<"hmax: "<<hmax<<endl; + + v_regular[0] = lmin; v_regular[1] = hmin; + v_regular[2] = -lmin; v_regular[3] = hmin; + v_regular[4] = -lmax; v_regular[5] = hmax; + v_regular[6] = lmax; v_regular[7] = hmax; + + v_regular[8] = lmin; v_regular[9] = hmin; + v_regular[10] = -lmin; v_regular[11] = hmin; + v_regular[12] = -lmax; v_regular[13] = hmax; + v_regular[14] = lmax; v_regular[15] = hmax; + + TGeoArb8* Layer_SideS_Shape = new TGeoArb8("Layer_SideS_Shape", rsLength/2, v_regular); + + Double_t Layer_Sector_Abs_dx = lmin; + Double_t Layer_Sector_Abs_dy = 3./2; + Double_t Layer_Sector_Abs_dz = rsLength/2; + + + TGeoBBox* Layer_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + Layer_Sector_Abs_dx, + Layer_Sector_Abs_dy, + Layer_Sector_Abs_dz); + + + TGeoVolume* Layer_SideS_Vol = new TGeoVolume("Layer_SideS_Vol", Layer_SideS_Shape, pair); + TGeoVolume* Layer_SideS_Abs_Base_Vol = new TGeoVolume("Layer_SideS_Abs_Base_Vol", Layer_SideS_Abs_Base_Shape, piron); + + Layer_SideS_Vol->AddNode(Layer_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, hmin+Layer_Sector_Abs_dy, 0, rotNoRot)); + + if (layerN % 2 == 0) { + Double_t Layer_Envelope_startX = lmin; + Double_t Layer_Envelope_shiftX = Layer_Envelope_startX - widthEnv/2; + + Double_t Layer_length = 2*abs(Layer_Envelope_startX); + cout<<"Layer #" << layerN << " length: " << Layer_length << endl; + + int Nenvelopes = int((Layer_length)/widthEnv); + cout << "Number of MDT detector in Layer" << layerN << ": " << Nenvelopes << endl; + for (UInt_t i=0; i<Nenvelopes; i++) { + + Layer_SideS_Vol->AddNode(createMDT(493.0), i+1, new TGeoCombiTrans("", Layer_Envelope_shiftX, hmin + 3 + 3.5/2, 0, rotNoRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX - widthEnv; + } + } + else { + + Double_t Layer_Envelope_startX = -1.0*abs(lmin); + Double_t Layer_Envelope_shiftX = Layer_Envelope_startX + widthEnv/2; + + Double_t Layer_length = 2*abs(Layer_Envelope_startX); + cout<<"Layer #" << layerN << " length: " << Layer_length << endl; + + int Nenvelopes = int((Layer_length)/widthEnv); + cout << "Number of MDT detector in Layer" << layerN << ": " << Nenvelopes << endl; + for (UInt_t i=0; i<Nenvelopes; i++) { + + Layer_SideS_Vol->AddNode(createMDT(493.0), i+1, new TGeoCombiTrans("", Layer_Envelope_shiftX, hmin + 3 + 3.5/2, 0, rotNoRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + } + } + + return Layer_SideS_Vol; +} + + +//_____________________________________________________________________________ +// +TGeoVolume* createTopLayer(Int_t layerN, Double_t rsRadius, Double_t rsThickness, Double_t rsLength) { +//_____________________________________________________________________________ +// +// Creates trapezoid representing regular layer of the RS Barrel part +// (3.0cm thick iron absorber and a layer of MDT detectors) +// Parameters: 1. Number of layer in a sector +// 2. Outer radius of RS from collision point (rsRadius); +// 3. Thickness of RS rsThickness. +// Returns: TGeoVolume object of the layer with absorber and MDTs. +//_____________________________________________________________________________ + + Double_t layerThickness = 3.0+3.0; //cm + + Double_t Sector_dy = rsLength/2.0; + + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + + TGeoMaterial *mat_iron = new TGeoMaterial("iron",0,0,0); + TGeoMedium *piron = new TGeoMedium("iron",1,mat_iron); + + TGeoMaterial *mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium *pair = new TGeoMedium("air",1,mat_air); + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t v_top[16]; + Double_t lmin = (rsRadius - rsThickness + 9.5 + (layerN-1)*layerThickness)*(sqrt(2.0)-1.0); // dimensions (bottom base) + Double_t lmax = (rsRadius - rsThickness + 9.5 + (layerN)*layerThickness)*(sqrt(2.0)-1.0); // dimensions (top base) + Double_t hmin = (rsRadius - rsThickness + 9.5 + (layerN-2)*6.5); + Double_t hmax = (rsRadius - rsThickness + 9.5 + (layerN-2)*6.5 + layerThickness); + + cout<<"Layer #"<< layerN << " dimensions (bottom base, lmin): [" << -lmin << "," << lmin << "]" << endl; + cout<<"Layer #"<< layerN << " dimensions (bottom base, lmax): [" << -lmax << "," << lmax << "]" << endl; + cout<<"hmin: "<<hmin<<endl; + cout<<"hmax: "<<hmax<<endl; + + v_top[0] = lmin; v_top[1] = hmin; + v_top[2] = -lmin; v_top[3] = hmin; + v_top[4] = -lmax; v_top[5] = hmax; + v_top[6] = lmax; v_top[7] = hmax; + + v_top[8] = lmin; v_top[9] = hmin; + v_top[10] = -lmin; v_top[11] = hmin; + v_top[12] = -lmax; v_top[13] = hmax; + v_top[14] = lmax; v_top[15] = hmax; + + TGeoArb8* Layer_SideS_Shape = new TGeoArb8("Layer_SideS_Shape", rsLength/2, v_top); + + Double_t Layer_Sector_Abs_dx = lmin; + Double_t Layer_Sector_Abs_dy = layerThickness/2; + Double_t Layer_Sector_Abs_dz = rsLength/2; + + + TGeoBBox* Layer_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + Layer_Sector_Abs_dx, + Layer_Sector_Abs_dy, + Layer_Sector_Abs_dz); + + + TGeoVolume* Layer_SideS_Vol = new TGeoVolume("Layer_SideS_Vol", Layer_SideS_Shape, pair); + TGeoVolume* Layer_SideS_Abs_Base_Vol = new TGeoVolume("Layer_SideS_Abs_Base_Vol", Layer_SideS_Abs_Base_Shape, piron); + + Layer_SideS_Vol->AddNode(Layer_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, hmin+Layer_Sector_Abs_dy, 0, rotNoRot)); + + return Layer_SideS_Vol; +} + +//_____________________________________________________________________________ +// +void SPD_RS_Barrel_Flexible2() { +//_____________________________________________________________________________ +// +// Main: +// Creates a segment of Range System Barrel with a given number of layers +// and fills each layer with MDT detectors. +// Parameters: distance from collision point, barrel size. +//_____________________________________________________________________________ + + gSystem->Load("libGeom"); + + TGeoManager* geoM = new TGeoManager("World", "Barrel"); + + //--- make the top container volume + TGeoVolume *top = new TGeoVolumeAssembly("RS_Barrel"); + gGeoManager->SetTopVolume(top); + + + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + TGeoMaterial* mat_air = new TGeoMaterial("air",0,0,0); + TGeoMedium* pair = new TGeoMedium("air",1,mat_air); + + //top->AddNode(SideS_Vol, 1); + + //top->AddNode(L4930_Envelope_Vol, 1); + + // Fill top volume with Range System layers + // Parameters of the Range System size and position + Double_t rsRadius = 314.4; // cm (Size of the Range System) + Double_t rsThickness = 139.0; //25.7; //139.0; // cm (Thickness of the Range System) + Double_t rsLength = 493.0; // cm (Length of the sector along beam axis) + + Double_t v[16]; + Double_t lmin = (rsRadius - rsThickness)*(sqrt(2.0)-1.0); // dimensions (bottom base) + Double_t lmax = (rsRadius )*(sqrt(2.0)-1.0); // dimensions (top base) + Double_t hmin = (rsRadius-rsThickness); + Double_t hmax = rsRadius; + + v[0] = lmin; v[1] = hmin; + v[2] = -lmin; v[3] = hmin; + v[4] = -lmax; v[5] = hmax; + v[6] = lmax; v[7] = hmax; + + v[8] = lmin; v[9] = hmin; + v[10] = -lmin; v[11] = hmin; + v[12] = -lmax; v[13] = hmax; + v[14] = lmax; v[15] = hmax; + + TGeoArb8* SideS_Shape = new TGeoArb8("SideS_Shape", rsLength/2, v); + TGeoVolume* SideS_Vol = new TGeoVolume("SideS_Vol", SideS_Shape, pair); + + // Number of layers calcluation within RS thickness: + // (Thickness - top absorber - bottom absorber/mdt)/LayerThickness + 1(bottom layer) + Int_t nLayers = int((rsThickness - 6. - 9.5)/6.5) + 1; + cout << "# of Layers within " << rsThickness << " cm: " << nLayers << endl; + + cout<<"Layer #"<< (rsRadius - rsThickness)*(sqrt(2.0)-1.0) << " dimensions (bottom base): [" + << endl; + cout<<"Layer #"<< (rsRadius )*(sqrt(2.0)-1.0) << " dimensions (top base): [" + << endl; + + // Add bottom layer (absrober(6.0cm) + mdt detectors(3.5cm)) + SideS_Vol->AddNode(createBottomLayer(rsRadius, rsThickness, rsLength), 1, + new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + + // Add regular layers (3.0cm absorber + 3.5cm mdt detectors) + + for (Int_t i=2; i < nLayers+1; ++i) { + SideS_Vol->AddNode(createRegularLayer(i, rsRadius, rsThickness, rsLength), i, + new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + } + + // Add top absorber (6.0cm) + SideS_Vol->AddNode(createTopLayer(nLayers+1, rsRadius, rsThickness, rsLength), nLayers+1, + new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + + + top->AddNode(SideS_Vol,1); + //top->AddNode(createMDT(493.0), 1); + gGeoManager->CloseGeometry(); + top->SetLineColor(kMagenta); + //gGeoManager->SetTopVisible(); // the TOP is invisible + top->Draw(); + + //gGeoManager->CheckGeometry(); + //gGeoManager->CheckGeometryFull(); + //gGeoManager->Test(); + + TString outGeoFilenameRoot = "./Barrel_cm.root"; + TFile* outGeoFileRoot = new TFile(outGeoFilenameRoot, "RECREATE"); + geoM->GetTopVolume()->Write(); + outGeoFileRoot->Close(); + +} diff --git a/macro/testmisc/check_tor.C b/macro/testmisc/check_tor.C index 6eeb15500eaa866a45f56a6bd07ba67d83e5a9ae..2d05b7cb4f6c04deb71d66b45a1d95b326c2dcfe 100644 --- a/macro/testmisc/check_tor.C +++ b/macro/testmisc/check_tor.C @@ -136,6 +136,7 @@ void MakeBarrel(const char* name, TGeoMedium* med, } } + //________________________________________________________________________________ void MakeBarrel_1(const char* name_c, const char* name_s, TGeoMedium* med, int nsec, double dz, double hmin_c, double hmin_s, double hmax, diff --git a/macro/tracking/CheckFittedTracks.C b/macro/tracking/CheckFittedTracks.C index d72aa37e9428d9ecf7051747b11261b5903025de..663fc73e95619e5ab91c4c20e722fe75117e1503 100644 --- a/macro/tracking/CheckFittedTracks.C +++ b/macro/tracking/CheckFittedTracks.C @@ -12,15 +12,16 @@ TTree* Tree_ = 0; void check_KFres(); void check_geometry(); -void check_tracks(Int_t nevent = 0); TString inFile, inParFile; //______________________________________________________________________________ -void CheckFittedTracks() +void CheckFittedTracks(TString path = "") { - inFile = "IdealFittedTracks.root"; - inParFile = "params_tor.root"; + if (!path.IsWhitespace() && !path.EndsWith("/")) path += "/"; + + inFile = path + "IdealFittedTracks.root"; + inParFile = path + "params_tor.root"; TFile* f = new TFile(inFile); if (!f) return; @@ -63,7 +64,7 @@ void check_KFres() { for (int j(0); j < entries; j++) { branch->GetEntry(j); cout << "\n------------------------------------------------------------------------------\n"; - Res->PrintData(0); // 0(default), 1, 2 + Res->PrintData(2); // 0(default), 1, 2 if (Res->IsWellFittedEvent()) NWellFittedEvents++; Res->ClearData(); } @@ -84,50 +85,3 @@ void check_geometry() gGeoManager->GetMasterVolume()->Draw("ogl"); } -//______________________________________________________________________________ -void check_tracks(Int_t nevent) -{ - if (!Tree_) return; - - TBranch* branch = Tree_->GetBranch("genfit::Track"); - if (!branch) return; - - int entries = branch->GetEntries(); - - if (nevent < 0 || nevent >= entries) return; - - TClonesArray *fT = 0; - Tree_->SetBranchAddress("genfit::Track",&fT) ; - - branch->GetEntry(nevent); - - genfit::Track* track = 0; - - Int_t ntr = fT->GetEntriesFast(); - - cout << "event = " << nevent << " tracks = " << ntr << endl; - - for (Int_t i(0); i<ntr; i++) { - track = (genfit::Track*)fT->At(i); - cout << i << " track " << track << endl; - //if (track && i == 4) track->Print(); - } - - //genfit::EventDisplay* display = genfit::EventDisplay::getInstance(); - - //genfit::Track* trackX = new genfit::Track(); - //*trackX = *(genfit::Track*)fT->At(3); - - //track = (genfit::Track*)fT->At(0); - //track->fillPointsWithMeasurement(); - //track->checkConsistency(); - - //track->Print(); - - //display->addEvent(track); - - //display->open(); -} - - - diff --git a/macro/tracking/CheckFittedTracks_1.C b/macro/tracking/CheckFittedTracks_1.C new file mode 100644 index 0000000000000000000000000000000000000000..5cf89e5b4654bc3fc62430c555cbc86c4b3385a2 --- /dev/null +++ b/macro/tracking/CheckFittedTracks_1.C @@ -0,0 +1,423 @@ +#include <TFile.h> +#include <TTree.h> +#include <Riostream.h> +#include <TGeoManager.h> +#include <TClonesArray.h> +#include "FairGeoParSet.h" +#include "SpdKFSimpleRes.h" +#include "SpdBaseParSet.h" +#include <vector> +#include <TStyle.h> +#include <TCanvas.h> +#include <TH1D.h> +#include <TH2D.h> +#include <TProfile.h> +#include <TProfile2D.h> + +TTree* Tree_ = 0; + +void check_KFres(); +void check_geometry(); + +TString inFile, inParFile; + +//______________________________________________________________________________ +void CheckFittedTracks_1(TString path = "") +{ + if (!path.IsWhitespace() && !path.EndsWith("/")) path += "/"; + + inFile = path + "IdealFittedTracks.root"; + inParFile = path + "params_tor.root"; + + TFile* fp = new TFile(inParFile); + if (fp) { + SpdPassiveGeoParSet* passive_pars = (SpdPassiveGeoParSet*)fp->Get("PassiveGeoParSet"); + if (passive_pars) passive_pars->print(1); + fp->Close(); + } + + TFile* f = new TFile(inFile); + if (!f) return; + + Tree_ = (TTree*)f->Get("cbmsim"); + if (!Tree_) return; + + SpdBaseParSet* pars = (SpdBaseParSet*)f->Get("IdealKalmanFitterParams"); + if (pars) pars->print(1); + + cout << "\n>>>>>>>>>>>>>>>> DATA FILE & TREE: Ok! <<<<<<<<<<<<<<<<< " << endl; + + check_KFres(); +} + +//----------------------------------------------------------------------------- +Bool_t AcceptTrack(SpdKFSimpleRes* res, Int_t ntrack) +{ + + //if (res->GetIsFitted(ntrack)) + //if (res->GetIsFullyConvergent(ntrack)) + //if (res->HasNoErrors(ntrack)) + if (res->GetIsGood(ntrack)) + //if (res->GetMCPtheta(ntrack) > 25. && res->GetMCPtheta(ntrack) < 155.) + //if (res->GetMCPtheta(ntrack) > 100. || res->GetMCPtheta(ntrack) < 80.) + { + return true; + } + + return false; +} + +//______________________________________________________________________________ +void check_KFres() +{ + if (!Tree_) return; + + TBranch* branch = Tree_->GetBranch("SpdKFSimpleRes."); + if (!branch) return; + + int entries = branch->GetEntries(); + + cout << "Total number of ENTRIES in the TREE = " << entries << endl; + + if (entries == 0) return; + + SpdKFSimpleRes* Res = 0; + + Tree_->SetBranchAddress("SpdKFSimpleRes.",&Res) ; + + Int_t NWellFittedEvents = 0; + Int_t NTotalTracks = 0; + Int_t NWellFittedTracks = 0; + Int_t ntracks = 0; + + TH1D* hN = new TH1D("Multiplicity (mc)","n_{tracks}/event (mc)",25,0,25); + TH1D* hn = new TH1D("Multiplicity (mc,selected)","n_{tracks}/event (mc)",25,0,25); + + TH1D* hchi2ndf = new TH1D("chi2/ndf","#chi^{2}/ndf ",100,0,2); + + // seed values + TH1D* hp = new TH1D("p (mc)","p (mc)",100,0,10); + TH1D* hpt = new TH1D("pt (mc)","p_{T} (mc)",100,0,5); + TH1D* hpz = new TH1D("pz (mc)","p_{z} (mc)",100,-10,10); + TH1D* hth = new TH1D("theta (mc)","#theta (mc)",180,0,180); + TH1D* hfi = new TH1D("phi (mc)","#phi (mc)",180,-180,180); + + // resolution + TH1D* hpr = new TH1D("dp/p","|dp|/p",50,0,1); + TH1D* hptr = new TH1D("dpt/pt","|dp_{T}|/p_{T}",50,0,1); + TH1D* hpzr = new TH1D("dpz/pz","|dp_{z}/p_{z}|",50,0,1); + TH1D* hthr = new TH1D("dtheta","|d#theta|",180,0,45); + TH1D* hfir = new TH1D("dphi","|d#phi|",180,0,180); + + // dp/p + TProfile* hppr = new TProfile("dp/p vs. p "," |dp|/p vs. p ",20,0,10, 0,1.0); + TProfile* hpthr = new TProfile("dp/p vs. theta"," |dp|/p vs. #theta",60,0,180, 0,1.0); + TProfile* hpfir = new TProfile("dp/p vs. phi"," |dp|/p vs. #phi",90,-180,180, 0,1.0); + TProfile2D* hhppth = new TProfile2D("dp/p(theta,p)","|dp|/p (#theta,p)", 40,0,180, 40,0,10, 0,0.1); + + // dpt/pt + TProfile* hptpr = new TProfile("dpt/pt vs. p "," |dp_{T}|/p_{T} vs. p ",20,0,10, 0,1.0); + TProfile* hptthr = new TProfile("dpt/pt vs. theta"," |dp_{T}|/p_{T} vs. #theta",60,0,180, 0,1.0); + TProfile* hptfir = new TProfile("dpt/pt vs. phi"," |dp_{T}|/p_{T} vs. #phi",90,-180,180, 0,1.0); + TProfile2D* hhptpth = new TProfile2D("dpt/pt(theta,p)","|dp_{T}|/p_{T} (#theta,p)", 40,0,180, 40,0,10, 0,0.1); + + // dpz/pz + TProfile* hpzpr = new TProfile("dpz/pz vs. p "," |dp_{z}/p_{z}| vs. p ",20,0,10, 0,1.0); + TProfile* hpzthr = new TProfile("dpz/pz vs. theta"," |dp_{z}/p_{z}| vs. #theta",60,0,180, 0,1.0); + TProfile* hpzfir = new TProfile("dpz/pz vs. phi"," |dp_{z}|/p_{z} vs. #phi",90,-180,180, 0,1.0); + TProfile2D* hhpzpth = new TProfile2D("dpz/p(theta,p})","|dp_{z}/p_{z}| (#theta,p)", 40,0,180, 40,0,10, 0,0.1); + + // dtheta + TProfile* hthpr = new TProfile("dtheta vs. p ","|d#theta| vs. p ",20,0,1, 0,1.0); + TProfile* hththr = new TProfile("dtheta vs. theta"," |d#theta| vs. #theta",60,0,180, 0,1.0); + TProfile* hthfir = new TProfile("dtheta vs. phi"," |d#theta| vs. #phi",90,-180,180, 0,1.0); + TProfile2D* hhthpth = new TProfile2D("d#theta(theta,p)","|d#theta}| (#theta,p)", 40,0,180, 40,0,10, 0,0.1); + + //chisquare + TProfile2D* hhchi2pth = new TProfile2D("chisquare(theta,p)","#chi^{2} (#theta,p)", 100,0,180, 100,0,10, 0,2.); + TProfile* hchi2pr = new TProfile("chisquare vs. dp/p","#chi^{2} vs. |dp|/p", 50,0,0.1, 0,2); + TProfile* hchi2ptr = new TProfile("chisquare vs. dpt/pt","#chi^{2} vs. |dp_{T}|/p_{T}", 50,0,0.1, 0,2); + TProfile* hchi2pzr = new TProfile("chisquare vs. dpz/pz","#chi^{2} vs. |dp_{z}/p_{z}|", 50,0,0.1, 0,2); + TProfile* hchi2thr = new TProfile("chisquare vs. d#theta","#chi^{2} vs. |d#theta|", 50,0,5., 0,2); + + // additional + TProfile* hpptr = new TProfile("dp/p vs. pt"," |dp|/p vs. p_{T}",20,0, 5, 0,1.0); + TProfile* hppzr = new TProfile("dp/p vs. pz"," |dp|/p vs. |p_{z}|",20,0,10, 0,1.0); + TProfile* hptptr = new TProfile("dpt/pt vs. pt"," |dp_{T}|/p_{T} vs. p_{T}",20,0, 5, 0,1.0); + TProfile* hptpzr = new TProfile("dpt/pt vs. pz"," |dp_{T}|/p_{T} vs. |p_{z}|",20,0,10, 0,1.0); + TProfile* hpzptr = new TProfile("dpz/pz vs. pt"," |dp_{z}/p_{z}| vs. p_{T}",20,0, 5, 0,1.0); + TProfile* hpzpzr = new TProfile("dpz/pz vs. pz"," |dp_{z}/p_{z}| vs. |p_{z}|",20,0,10, 0,1.0); + + // vertex + TH1D* hvr = new TH1D("Vertex: r (mc)","Vertex: r (mc)",100,0,3.0); + TH1D* hvdr = new TH1D("Vertex: dr","Vertex: |dr| ",100,0,1.); + TH1D* hvz = new TH1D("Vertex: Z (mc)","Vertex: Z (mc)",100,-2.5,2.5); + TH1D* hvdz = new TH1D("Vertex: dZ","Vertex: dZ ",200,-1,1); + TH1D* hvrt = new TH1D("Vertex: rt","Vertex: r_{T} ",100,0,0.071); // 0.071 = ~Sqrt(2*0.05*0.05) + TH1D* hvdphi = new TH1D("Vertex: dphi","Vertex: |d#phi_{r}| ",180,0,180); + + // hits + TH1D* hitsh = new TH1D("itsNH","Its hits/track",10,0,10); + TH1D* htstbh = new TH1D("tstbNH","TsTB hits/track",120,0,120); + TH1D* htstech = new TH1D("tstecNH","TsTEC hits/track",75,0,75); + TH1D* htotalh = new TH1D("totalNH","Total hits/track",140,0,140); + + TProfile2D* hpthh = new TProfile2D("nh/track(theta,p)","total: hits/track(#theta,p)", 90,0,180, 90,0,10, 0,150); + TProfile2D* hitspthh = new TProfile2D("its nh/track(theta,p)","its: hits/track(#theta,p)", 90,0,180, 90,0,10, 0,150); + TProfile2D* htstbpthh = new TProfile2D("tstb nh/track(theta,p)","tstb: hits/track(#theta,p)", 90,0,180, 90,0,10, 0,150); + TProfile2D* htstecpthh = new TProfile2D("tstec nh/track(theta,p)","tstec: hits/track(#theta,p)", 90,0,180, 90,0,10, 0,150); + + for (int j(0); j < entries; j++) { + + branch->GetEntry(j); + //cout << "\n------------------------------------------------------------------------------\n"; + + //Res->PrintData(1); // 0(default) or 1 + + if (Res->IsWellFittedEvent()) NWellFittedEvents++; + //else continue; + + ntracks = Res->GetNTracks(); + NTotalTracks += ntracks; + + Int_t nm(0); + + for (Int_t i(0); i<ntracks; i++) { + if (AcceptTrack(Res,i)) + { + NWellFittedTracks++; + + hchi2ndf->Fill(Res->GetChi2toNDF(i)); + + // seed values + hp->Fill(Res->GetMomentumMC(i)); + hth->Fill(Res->GetMCPtheta(i)); + hfi->Fill(Res->GetMCPphi(i)); + hpt->Fill(Res->GetMCPt(i)); + hpz->Fill(Res->GetMCPz(i)); + + // resolution + hpr->Fill(Res->GetMomRes(i)); + hptr->Fill(Res->GetPtRes(i)); + hpzr->Fill(Res->GetPzRes(i)); + hthr->Fill(Res->GetDTheta(i)); + hfir->Fill(Res->GetDPhi(i)); + + // dp/p + hppr->Fill(Res->GetMomentumMC(i),Res->GetMomRes(i),1); + hpthr->Fill(Res->GetMCPtheta(i),Res->GetMomRes(i),1); + hpfir->Fill(Res->GetMCPphi(i),Res->GetMomRes(i),1); + hhppth->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetMomRes(i)); + + // dpt/pt + hptpr->Fill(Res->GetMomentumMC(i),Res->GetPtRes(i),1); + hptthr->Fill(Res->GetMCPtheta(i),Res->GetPtRes(i),1); + hptfir->Fill(Res->GetMCPphi(i),Res->GetPtRes(i),1); + hhptpth->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetPtRes(i)); + + // dpz/pz + hpzpr->Fill(Res->GetMomentumMC(i),Res->GetPzRes(i),1); + hpzthr->Fill(Res->GetMCPtheta(i),Res->GetPzRes(i),1); + hpzfir->Fill(Res->GetMCPphi(i),Res->GetPzRes(i),1); + hhpzpth->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetPzRes(i)); + + // dtheta + hthpr->Fill(Res->GetMomentumMC(i),Res->GetDTheta(i),1); + hththr->Fill(Res->GetMCPtheta(i),Res->GetDTheta(i),1); + hthfir->Fill(Res->GetMCPphi(i),Res->GetDTheta(i),1); + hhthpth->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetDTheta(i)); + + // chisquare + hhchi2pth->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetChi2toNDF(i)); + hchi2pr->Fill(Res->GetMomRes(i),Res->GetChi2toNDF(i),1); + hchi2ptr->Fill(Res->GetPtRes(i),Res->GetChi2toNDF(i),1); + hchi2pzr->Fill(Res->GetPzRes(i),Res->GetChi2toNDF(i),1); + hchi2thr->Fill(Res->GetDTheta(i),Res->GetChi2toNDF(i),1); + + // additional + hpptr->Fill(Res->GetMCPt(i),Res->GetMomRes(i),1); + hppzr->Fill(TMath::Abs(Res->GetMCPz(i)),Res->GetMomRes(i),1); + hptptr->Fill(Res->GetMCPt(i),Res->GetPtRes(i),1); + hptpzr->Fill(TMath::Abs(Res->GetMCPz(i)),Res->GetPtRes(i),1); + hpzptr->Fill(Res->GetMCPt(i),Res->GetPzRes(i),1); + hpzpzr->Fill(TMath::Abs(Res->GetMCPz(i)),Res->GetPzRes(i),1); + + // hits + hitsh->Fill(Res->GetNVhits(i)); + htstbh->Fill(Res->GetNTBhits(i)); + htstech->Fill(Res->GetNTEChits(i)); + htotalh->Fill(Res->GetNTThits(i)); + + hpthh->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetNTThits(i)); + hitspthh->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetNVhits(i)); + htstbpthh->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetNTBhits(i)); + htstecpthh->Fill(Res->GetMCPtheta(i),Res->GetMomentumMC(i),Res->GetNTEChits(i)); + + nm++; + } + } + + hN->Fill(ntracks); + hn->Fill(nm); + + // vertex + hvr->Fill(Res->GetVertexMCr()); + hvz->Fill(Res->GetVertexMCz()); + hvrt->Fill(Res->GetVertexMCrt()); + + hvdr->Fill(Res->GetVertexDMag()); + hvdz->Fill(Res->GetVertexDZ()); + hvdphi->Fill(Res->GetVertexDPhi()); + + Res->ClearData(); + } + + gStyle->SetOptStat("ermou"); + + // seed values +// TCanvas* cp = new TCanvas("cp","cp",750,850); +// cp->Divide(2,3); +// cp->cd(1); hn->SetFillColor(kBlue-7); hn->Draw(); +// hN->SetLineColor(kBlack); hN->SetLineWidth(3); hN->Draw("same"); +// cp->cd(2); hp->SetFillColor(kBlue+1); hp->Draw(); +// cp->cd(3); hpt->SetFillColor(kBlue+2); hpt->Draw(); +// cp->cd(4); hpz->SetFillColor(kBlue+2); hpz->Draw(); +// cp->cd(5); hth->SetFillColor(kBlue+3); hth->Draw(); +// cp->cd(6); hfi->SetFillColor(kBlue+3); hfi->SetMinimum(0); hfi->Draw(); +// cp->cd(0); + + // resolution + TCanvas* cr = new TCanvas("cr","cr",750,850); + cr->Divide(2,3); + cr->cd(1); hchi2ndf->SetFillColor(kMagenta+3); hchi2ndf->Draw(); + cr->cd(2); hpr->SetFillColor(kMagenta); hpr->Draw(); cr->cd(2)->SetLogy(); + cr->cd(3); hptr->SetFillColor(kMagenta+1); hptr->Draw(); cr->cd(3)->SetLogy(); + cr->cd(4); hpzr->SetFillColor(kMagenta+1); hpzr->Draw(); cr->cd(4)->SetLogy(); + cr->cd(5); hthr->SetFillColor(kMagenta+2); hthr->Draw(); cr->cd(5)->SetLogy(); + cr->cd(6); hfir->SetFillColor(kMagenta+2); hfir->Draw(); cr->cd(6)->SetLogy(); + cr->cd(0); + + // dp/p + TCanvas* cpr = new TCanvas("cpr","cpr",900,600); + cpr->Divide(2,2); + cpr->cd(1); hppr->Draw("e1"); + cpr->cd(2); hpthr->Draw(); cpr->cd(2)->SetLogy(); + cpr->cd(3); hpfir->Draw(); hpfir->SetMinimum(0); + cpr->cd(4); hhppth->Draw("colz"); + cpr->cd(0); + + // dpt/pt + TCanvas* cptr = new TCanvas("cptr","cptr",900,600); + cptr->Divide(2,2); + cptr->cd(1); hptpr->Draw("e1"); + cptr->cd(2); hptthr->Draw(); cptr->cd(2)->SetLogy(); + cptr->cd(3); hptfir->Draw(); hptfir->SetMinimum(0); + cptr->cd(4); hhptpth->Draw("colz"); + cptr->cd(0); + + // dpz/pz + TCanvas* cpzr = new TCanvas("cpzr","cpzr",900,600); + cpzr->Divide(2,2); + cpzr->cd(1); hpzpr->Draw("e1"); + cpzr->cd(2); hpzthr->Draw(); cpzr->cd(2)->SetLogy(); + cpzr->cd(3); hpzfir->Draw(); hpzfir->SetMinimum(0); + cpzr->cd(4); hhpzpth->Draw("colz"); + cpzr->cd(0); + + // dtheta +// TCanvas* cthr = new TCanvas("cthr","cthr",900,600); +// cthr->Divide(2,2); +// cthr->cd(1); hthpr->Draw("e1"); +// cthr->cd(2); hththr->Draw(); cthr->cd(2)->SetLogy(); +// cthr->cd(3); hthfir->Draw(); hthfir->SetMinimum(0); +// cthr->cd(4); hhthpth->Draw("colz"); +// cpzr->cd(0); + + // vertex + TCanvas* cv = new TCanvas("cv","cv",750,850); + cv->Divide(2,3); + cv->cd(1); hvr->SetFillColor(kGreen+1); hvr->SetMinimum(0); hvr->Draw(); + cv->cd(2); hvdr->SetFillColor(kGreen+1); hvdr->Draw(); + cv->cd(3); hvz->SetFillColor(kGreen+2); hvz->SetMinimum(0); hvz->Draw(); + cv->cd(4); hvdz->SetFillColor(kGreen+2); hvdz->Draw(); + cv->cd(5); hvrt->SetFillColor(kGreen+3); hvrt->Draw(); + cv->cd(6); hvdphi->SetFillColor(kGreen); hvdphi->Draw(); + cv->cd(0); + + // chisquare +// TCanvas* cchi2pth = new TCanvas("cchi2pth","cchi2pth",600,600); +// Double_t dd = 0.5; hhchi2pth->SetMinimum(0.98-dd); hhchi2pth->SetMaximum(0.98+dd); +// hhchi2pth->Draw("colz"); +// cchi2pth->cd(0); + +// TCanvas* cchi2r = new TCanvas("cchi2r","cchi2r",900,600); +// cchi2r->Divide(2,2); +// cchi2r->cd(1); hchi2pr->Draw("e1"); +// cchi2r->cd(2); hchi2ptr->Draw("e1"); +// cchi2r->cd(3); hchi2pzr->Draw("e1"); +// cchi2r->cd(4); hchi2thr->Draw("e1"); +// cchi2r->cd(0); + +// // additional +// TCanvas* cr2 = new TCanvas("cr2","cr2",750,850); +// cr2->Divide(2,3); +// cr2->cd(1); hpptr->Draw("e1"); +// cr2->cd(2); hppzr->Draw("e1"); +// cr2->cd(3); hptptr->Draw("e1"); +// cr2->cd(4); hptpzr->Draw("e1"); +// cr2->cd(5); hpzptr->Draw("e1"); +// cr2->cd(6); hpzpzr->Draw("e1"); +// cr2->cd(0); + + // hits +// TCanvas* chh = new TCanvas("chh","chh",900,600); +// chh->Divide(2,2); +// Double_t hhscale = 1./hitsh->GetEntries(); +// chh->cd(1)->SetLogy(); hitsh->SetFillColor(kRed+2); hitsh->GetXaxis()->CenterLabels(); hitsh->Scale(hhscale); hitsh->Draw("h"); +// chh->cd(2)->SetLogy(); htstbh->SetFillColor(kRed+2); htstbh->GetXaxis()->CenterLabels(); htstbh->Scale(hhscale); htstbh->Draw("h"); +// chh->cd(3)->SetLogy(); htstech->SetFillColor(kRed+2); htstech->GetXaxis()->CenterLabels(); htstech->Scale(hhscale); htstech->Draw("h"); +// chh->cd(4)->SetLogy(); htotalh->SetFillColor(kRed+4); htotalh->GetXaxis()->CenterLabels(); htotalh->Scale(hhscale); htotalh->Draw("h"); +// chh->cd(0); + + TCanvas* chhpth = new TCanvas("chhpth","chhpth",900,900); + chhpth->Divide(2,2); + chhpth->cd(1); hpthh->Draw("colz"); + chhpth->cd(2); hitspthh->Draw("colz"); + chhpth->cd(3); htstbpthh->Draw("colz"); + chhpth->cd(4); htstecpthh->Draw("colz"); + chhpth->cd(0); + + if (hp) { + + Double_t sump(0), q(0.5); + + if (hp->GetQuantiles(1,&sump,&q)) { + cout << "\n"; + cout << "Median (p_mc) = " << sump << " [GeV/c] \n"; + cout << "Mean (p_mc) = " << hp->GetMean() << " [GeV/c] \n"; + cout << "Dev. (p_mc) = " << hp->GetRMS() << " [GeV/c] \n"; + } + + if (hpr->GetQuantiles(1,&sump,&q)) { + cout << "\n"; + cout << "Median (|dp|/p) = " << 100.*sump << " [%] \n"; + cout << "Mean (|dp|/p) = " << 100.*hpr->GetMean() << " [%] \n"; + cout << "Dev. (|dp|/p) = " << 100.*hpr->GetRMS() << " [%] \n"; + } + + if (hptr->GetQuantiles(1,&sump,&q)) { + cout << "\n"; + cout << "Median (|dpt|/pt) = " << 100.*sump << " [%] \n"; + cout << "Mean (|dpt|/pt) = " << 100.*hptr->GetMean() << " [%] \n"; + cout << "Dev. (|dpt|/pt) = " << 100.*hptr->GetRMS() << " [%] \n"; + } + } + + cout << "\nEVENTS [nice/total]: " << NWellFittedEvents << "/" << entries + << " (" << 100.*NWellFittedEvents/Double_t(entries) << " %)" << "\n"; + cout << "TRACKS [selected/total]: " << NWellFittedTracks << "/" << NTotalTracks + << " (" << 100*NWellFittedTracks/Double_t(NTotalTracks) << "%)" << "\n\n"; + +} + + diff --git a/macro/tracking/CheckGFTracks.C b/macro/tracking/CheckGFTracks.C new file mode 100644 index 0000000000000000000000000000000000000000..c39052aea8f6e1a6f673a0d8dd48b045b67d6d16 --- /dev/null +++ b/macro/tracking/CheckGFTracks.C @@ -0,0 +1,108 @@ +// #include <TFile.h> +// #include <TTree.h> +// #include <TGeoManager.h> +// #include <TClonesArray.h> +// #include "FairGeoParSet.h" +// #include "SpdKFSimpleRes.h" +// #include "GFCore.hh" +// #include "EventDisplay.h" +// #include "SpdGFTrackW.h" +// #include <vector> + +TTree* Tree_ = 0; + +void check_tracks(Int_t nevent = 0); + +TString inFile, inParFile; + +//______________________________________________________________________________ +void CheckGFTracks(TString path = "") +{ + if (!path.IsWhitespace() && !path.EndsWith("/")) path += "/"; + + inFile = path + "IdealFittedTracks.root"; + inParFile = path + "params_tor.root"; + + TFile* f = new TFile(inFile); + if (!f) return; + + Tree_ = (TTree*)f->Get("cbmsim"); + if (!Tree_) return; + + cout << "\n >>>>>>>>>>>>>>>> DATA FILE & TREE: Ok! <<<<<<<<<<<<<<<<< " << endl; + + check_tracks(0); + + //SpdBaseParSet* pars = (SpdBaseParSet*)f->Get("IdealKalmanFitterParams"); + //if (pars) pars->print(1); +} + +//______________________________________________________________________________ +void check_tracks(Int_t nevent) +{ + if (!Tree_) return; + + TBranch* branch = Tree_->GetBranch("SpdGFTrackW."); + if (!branch) { cout << " no \"GF tracks\" branch " << endl; return; } + + Int_t entries = branch->GetEntries(); + + cout << "Total entries in the \"GF tracks\" branch: " << entries << endl; + + if (nevent < 0 || nevent >= entries) return; + + TObjArray *fT = 0; + Tree_->SetBranchAddress("SpdGFTrackW.",&fT) ; + + //------------------------ + + TBranch* data_branch = Tree_->GetBranch("SpdKFSimpleRes."); + if (!data_branch) { cout << " no \"KF data\" branch " << endl; return; } + + SpdKFSimpleRes* Res = 0; + Tree_->SetBranchAddress("SpdKFSimpleRes.",&Res) ; + + //------------------------ + + branch->GetEntry(nevent); + data_branch->GetEntry(nevent); + + if (Res) Res->PrintData(2); + + SpdGFTrackW* wtrack = 0; + genfit::Track* track = 0; + + Int_t ntr = fT->GetEntriesFast(); + + cout << "\nevent = " << nevent << " tracks = " << ntr << endl; + + for (Int_t i(0); i<ntr; i++) { + wtrack = (SpdGFTrackW*)fT->At(i); + if (!wtrack) continue; + cout << "wtrack " << i << " data: " << wtrack->GetDataID() << endl; + track = wtrack->GetTrack(); + if (!track) continue; + + //if (track && i == 4) + // track->Print(); + + cout<< "------ track: " << i+1 << "/" << ntr << endl; + } + + //genfit::EventDisplay* display = genfit::EventDisplay::getInstance(); + + //genfit::Track* trackX = new genfit::Track(); + //*trackX = *(genfit::Track*)fT->At(3); + + //track = (genfit::Track*)fT->At(0); + //track->fillPointsWithMeasurement(); + //track->checkConsistency(); + + //track->Print(); + + //display->addEvent(track); + + //display->open(); +} + + diff --git a/macro/tracking/CheckIdealTracks.C b/macro/tracking/CheckIdealTracks.C index 2c8a8e23f414d40d7b4a010d08382a6fc809a4c2..eff37a88cf0b74cb0b310853dd9fa4d6c72590b1 100644 --- a/macro/tracking/CheckIdealTracks.C +++ b/macro/tracking/CheckIdealTracks.C @@ -9,11 +9,12 @@ void check_params(); TString inFile, inParFile; //______________________________________________________________________________ -void CheckIdealTracks() +void CheckIdealTracks(TString path = "") { + if (!path.IsWhitespace() && !path.EndsWith("/")) path += "/"; - inFile = "IdealTracks.root"; - inParFile = "params_tor.root"; + inFile = path + "IdealTracks.root"; + inParFile = path + "params_tor.root"; TFile* f = new TFile(inFile); if (!f) return; @@ -97,8 +98,8 @@ void check_events() { if (Event->GetNTracks() > 0) { track = (SpdIdealTrack*)Event->GetTrack(0); - //track->PrintTrack(true); - track->PrintTrack(false); + if (track) track->PrintTrack(true); + //if (track) track->PrintTrack(false); } Event->DeleteAll(); // clear event diff --git a/macro/tracking/FitIdealTracks.C b/macro/tracking/FitIdealTracks.C index ba8b0e6f30dfb9c6dd1a93d64c8a710903b32bbd..ec93ec5dbe3543508090041a626668004d21f4e3 100644 --- a/macro/tracking/FitIdealTracks.C +++ b/macro/tracking/FitIdealTracks.C @@ -30,17 +30,18 @@ void FitIdealTracks() KalmanFitter->SetVerboseLevel(2); // level = <1 (no prints), 1(default), 2, 3, 4 - KalmanFitter->SetTrackingGeoModules(); // add Its,TsTB,TsTEC modules to analysis + //KalmanFitter->SetTrackingGeoModules(); // add Its,TsTB,TsTEC modules to analysis - //KalmanFitter->AddModule(12); // Its - //KalmanFitter->AddModule(2); // TsTB - //KalmanFitter->AddModule(3); // TsTEC + KalmanFitter->AddModule(12); // Its + KalmanFitter->AddModule(2); // TsTB + KalmanFitter->AddModule(3); // TsTEC // standard options: KalmanFitter->SetSeedMomentum(1.); // Start vertex momentum for fit, GeV/c (default = 1 GeV/c) - - KalmanFitter->SetResolution(0.005); // Vertex detector (Its) resolution, cm (default = 0.005 cm) - KalmanFitter->SetWireResolution(0.015); // Wire tracker (TsTB, TsTEC) resolution , cm (default = 0.015 cm) + + KalmanFitter->SetHitRepresentation(kSpdIts,pkPixel); // options: pkPixel, pkSpacepoint + KalmanFitter->SetHitRepresentation(kSpdTsTB,pkWire); // options: pkWire, pkWirePoint, pkSpacepoint + KalmanFitter->SetHitRepresentation(kSpdTsTEC,pkWire); // options: pkWire, pkWirePoint, pkSpacepoint // advanced options: KalmanFitter->SetVertexFindingMethod(1); // <1 (vertex will not be found), (default = 1) @@ -53,14 +54,22 @@ void FitIdealTracks() KalmanFitter->SetSmearingAngleDelta(3.0); // [SeedMethod = 1] track start angle smearing (+-)value, deg (default = 3.0 deg) KalmanFitter->SetSmearingVertexDelta(0.5); // [SeedMethod = 1] track start vertex position smearing (+-)value, cm (default = 0.5 cm) KalmanFitter->SetNPointsVertexUse(0); // [SeedMethod = 2] <1 (default): number of points is the maximum possible (usually 5-6 ) + + KalmanFitter->SetFitterMaxIterations(8); // default: 8, minimum: 4 + KalmanFitter->SetFitterMaxTrials(2); // default: 10, minimum: 1 // Material effects option: < 1 : fit without materials; // >= 1 : fit taking into accont material effects (default); KalmanFitter->SetMaterialEffectsOption(1); + + //SpdGeoLoader::ForceTopGeoFile("cave_precise.geo"); // force top volume (Cave) geometry (default: parameters will be used); // method to update covariance matrix (default = 1) - KalmanFitter->SetFitterOption(1); + KalmanFitter->SetFitterOption(1); + + //store fitted tracks (full fitter info, by default = false) + KalmanFitter->SetStoreTracks(true); //------------------------------------// Run->AddTask(KalmanFitter); @@ -71,12 +80,38 @@ void FitIdealTracks() Run->Initialize(); - //return; + // advanced settings + SpdGFMeasurementCreator* mcreator = KalmanFitter->GetMeasurementCreator(); + + // +++++ ADVANCED OPTIONS +++++ + + // change hit representation (if needed) + //KalmanFitter->SetHitRepresentation(kSpdIts,pkSpacepoint); // pkPixel -> pkSpacepoint + //KalmanFitter->SetHitRepresentation(kSpdTsTB,pkSpacepoint); // pkWire -> pkSpacepoint + //KalmanFitter->SetHitRepresentation(kSpdTsTEC,pkSpacepoint); // pkWire -> pkSpacepoint + + // force hit resolution (if needed) + //Double_t mkm = 1e-4; + + //mcreator->SetPointHitResolutionXYZ(50*mkm, 50*mkm, 50*mkm); // res(x(u),y(v),z): pkPixel -> (x=u,y=v); pkSpacepoint -> (x,y,z) + //mcreator->SetWireHitResolutionRZ(150*mkm, 150*mkm); // res(r,z): pkWire -> (r); pkWirePoint -> (r,z) + + //mcreator->ForcePointHitResolution(); // use specified by SetPointHitResolutionXYZ resolution for all point-like hits + //mcreator->ForceWireHitResolution(); // use specified by SetWireHitResolutionRZ resolution for all wire-like hits + + // use mc-point as hit + //mcreator->UseMCPointAsPointHit(true); // if option = true, smear point using defined resolution (default option = false) + //mcreator->UseMCPointAsWireHit(true); // if option = true, smear point using defined resolution (default option = false) + - Run->Run(0, nEvents); - //Run->Run(0,1000); - //Run->Run(0,10); - + // Run fitting + + //Run->Run(0, nEvents); + //Run->Run(100,200); + Run->Run(0,100); + + KalmanFitter->DeleteGeoLoader(); + timer.Stop(); Double_t rtime = timer.RealTime(); @@ -88,6 +123,6 @@ void FitIdealTracks() cout << "Parameter file is " << parFile << endl; cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << endl; cout << endl; - + gApplication->Terminate(); } diff --git a/macro/tracking/MakeIdealTracks.C b/macro/tracking/MakeIdealTracks.C index 93a6e5999842e6b16b444c19a382deae9d9fdff6..0b63e007a34b735bdf3c672e688cdc0c8cb904b8 100644 --- a/macro/tracking/MakeIdealTracks.C +++ b/macro/tracking/MakeIdealTracks.C @@ -7,7 +7,7 @@ void MakeIdealTracks() TString inFile = "run_tor.root"; // Input file (MC events) TString parFile = "params_tor.root"; // Parameter file - TString outFile = "IdealTracks.root"; // Output file + TString outFile = "IdealTracks.root"; // Output file SpdRunAna* Run = new SpdRunAna(); @@ -38,9 +38,30 @@ void MakeIdealTracks() // set cuts TrackFinder->SetMinMomentum(1e-2); // momentum cut; default = 1e-2 (10 Mev); absiolute min. value = 4e-3 (4 MeV) TrackFinder->SetMinGammaBeta(0.5); // p/m cut; default = 0.5; absiolute min. value = 0.05 - TrackFinder->SetMinVertexNHits(1); // its hits number cut; default = 1; absiolute min. value = 0; + TrackFinder->SetMinVertexNHits(1); // its hits number cut; default = 1; absolute min. value = 0; TrackFinder->SetMinTrackerNHits(2); // tstb+tstec hits number cut; default = 2; absiolute min. value = 2; + // set hits resolution + Double_t mkm = 1e-4; + + // ------ INNER TRACKER ----- + + TrackFinder->SetHitResolution(kSpdIts, 'p', 50*mkm, 50*mkm); // ENDCAP: POINT (u=x,v=y) + TrackFinder->SetHitResolution(kSpdIts, 'm', 50*mkm, 50*mkm); // BARREL: MAPS (u,v) + TrackFinder->SetHitResolution(kSpdIts, 's', 50*mkm, 50*mkm); // BARREL: DSSD (u,v) + + // ----- STRAW TRACKER ----- + + // --- barrel --- + TrackFinder->SetHitResolution(kSpdTsTB, 'w', 150*mkm); // Wire(1D) (r) + //TrackFinder->SetHitResolution(kSpdTsTB, 'w', 150*mkm, 2. /*cm*/); // Wire(1D,2D) (r,z) + + //--- endcaps --- + TrackFinder->SetHitResolution(kSpdTsTEC,'w', 150*mkm); // Wire(1D) (r) + //TrackFinder->SetHitResolution(kSpdTsTEC,'w', 150*mkm, 2. /*cm*/); // Wire(1D,2D) (r,z) + + //TrackFinder->AppendSecondaryTracks(); + //------------------------------------// Run->AddTask(TrackFinder); @@ -48,11 +69,15 @@ void MakeIdealTracks() cout << "Start ... " << endl; - Run->LoadGeoParSet(kFALSE); + Run->LoadGeoParSet(false); Run->Initialize(); + + //return; Run->Run(0, nEvents); + TrackFinder->DeleteGeoLoader(); + timer.Stop(); Double_t rtime = timer.RealTime(); @@ -64,7 +89,7 @@ void MakeIdealTracks() cout << "Parameter file is " << parFile << endl; cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << endl; cout << endl; - + /* DRAW GEOMETRY */ // TGeoManager *geoMan = gGeoManager; diff --git a/macro/tracking/Simu_tr11.C b/macro/tracking/SimuDmesons.C similarity index 90% rename from macro/tracking/Simu_tr11.C rename to macro/tracking/SimuDmesons.C index b22c980e9b0e5b956c61df07d626e404f371f376..3b4f2cbe7c2bfc066e653607de4886f2a0e6e140 100644 --- a/macro/tracking/Simu_tr11.C +++ b/macro/tracking/SimuDmesons.C @@ -38,7 +38,7 @@ void CustomizeGeometryTsTB(); void CustomizeGeometryTsTEC(); //_________________________________________________________________________ -void Simu_tr11(Int_t nEvents = 1) +void SimuDmesons(Int_t nEvents = 1) { TString outFile = "run_tor.root"; // Output data file name TString parFile = "params_tor.root"; // Output parameters file name @@ -112,13 +112,11 @@ void Simu_tr11(Int_t nEvents = 1) /* --- field map --- */ SpdFieldMap* MagField = new SpdFieldMap("Hybrid field"); -// MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field + //MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field MagField->InitData("map_sol_6cls5cm2.bin"); // "quasi-solenoid" -// MagField->InitData("map_tor_rot.bin"); - //MagField->SetApproxMethod(0); // 0 (linear,default) or 1 (nearest vertex) - //MagField->MultiplyField(2.0); + //MagField->MultiplyField(1); /* === define field region === */ SpdRegion* reg = 0; @@ -145,32 +143,46 @@ void Simu_tr11(Int_t nEvents = 1) SpdIsotropicGenerator* isogen1 = new SpdIsotropicGenerator("isogen1"); - isogen1->Initialize(-2212,3.0,50); // pdg number, momentum (GeV/c), particles per event or LEVEL 2212 + // D+ + isogen1->Initialize(411,5.,1); // pdg number, momentum (GeV/c), particles per event or LEVEL isogen1->SetVerboseLevel(1); - isogen1->SetVGenOpt(1); // (+-)1, (+-)2 - isogen1->SetSpherical(146.5,153.500,0,360); + isogen1->SetVGenOpt(-1); // (+-)1, (+-)2 primGen->AddGenerator(isogen1); - + //=========================== // ISOTROPIC GENERATOR (2) //=========================== SpdIsotropicGenerator* isogen2 = new SpdIsotropicGenerator("isogen2"); - isogen2->Initialize(2212,3.0,50); // pdg number, momentum (GeV/c), particles per event or LEVEL + // D- + isogen2->Initialize(-411,1.5,1); // pdg number, momentum (GeV/c), particles per event or LEVEL isogen2->SetVerboseLevel(1); - isogen2->SetVGenOpt(1); // (+-)1, (+-)2 - isogen2->SetSpherical(26.5,33.500,0,360); + isogen2->SetVGenOpt(-1); // (+-)1, (+-)2 primGen->AddGenerator(isogen2); - //============================ + //=========================== + // ISOTROPIC GENERATOR (3) + //=========================== - run->SetGenerator(primGen); - - gRandom->SetSeed(0); // reset "global" random generator + SpdIsotropicGenerator* isogen3 = new SpdIsotropicGenerator("isogen3"); + + // D0 + isogen3->Initialize(421,5.,1); // pdg number, momentum (GeV/c), particles per event or LEVEL + isogen3->SetVerboseLevel(1); + isogen3->SetVGenOpt(-1); // (+-)1, (+-)2 + + primGen->AddGenerator(isogen3); + + //============================ + + run->SetGenerator(primGen); + primGen->SetVerboseLevel(-10); + //primGen->SetVerbose(0); + primGen->SetBeam(0., 0., 0.1, 0.1); // (X,Y)- position, (X,Y)- (0.5*delta or sigma) [cm] primGen->SmearVertexXY(kTRUE); //primGen->SmearGausVertexXY(kTRUE); @@ -183,7 +195,7 @@ void Simu_tr11(Int_t nEvents = 1) /* +++++++++++++++ GLOBAL OPTIONS +++++++++++++++++ */ /* ------------------------------------------------ */ - run->SetStoreTraj(kTRUE); + //run->SetStoreTraj(kTRUE); //SpdCommonGeoMapper::Instance()->SaveEmptyHits(); diff --git a/macro/tracking/SimuHyb_1.C b/macro/tracking/SimuHyb_1.C index b3faa64064564c94ea69c0f189f151f17541950d..9ed29fe044731bf468e686cf028d86c3b0d22e22 100644 --- a/macro/tracking/SimuHyb_1.C +++ b/macro/tracking/SimuHyb_1.C @@ -23,10 +23,6 @@ #include "SpdIts.h" #include "SpdTsTB.h" #include "SpdTsTEC.h" -#include "SpdEcalTB.h" -#include "SpdEcalTEC.h" -#include "SpdRsTB.h" -#include "SpdRsTEC.h" #include "SpdItsGeoMapperX.h" #include "SpdTsTBGeoBuilder.h" @@ -48,7 +44,7 @@ void SimuHyb_1(Int_t nEvents = 1) run->SetOutputFile(outFile); - run->SetPythiaDecayer("DecayConfig.C"); + //run->SetPythiaDecayer("DecayConfig.C"); run->SetMCEventHeader(new SpdMCEventHeader); @@ -61,66 +57,86 @@ void SimuHyb_1(Int_t nEvents = 1) /* ++++++++++++++++++ CAVE ++++++++++++++++++ */ FairModule* cave = new SpdCave("CAVE"); - cave->SetGeometryFileName("cave.geo"); + //cave->SetGeometryFileName("cave.geo"); //cave->SetGeometryFileName("cave_precise.geo"); run->AddModule(cave); /* ++++++++++++++++++ PIPE ++++++++++++++++++ */ SpdPipe* Pipe = new SpdPipe(); + //Pipe->UnsetMaterials("air"); run->AddModule(Pipe); /* +++++++++++++++++ MAGNET +++++++++++++++++ */ - //SpdHybMagnet* Magnet = new SpdHybMagnet(); - //Magnet->SetGeometryType(2); // 1 = "hybrid" (deafult), 2 = "qsolenoid" - //run->AddModule(Magnet); +// SpdHybMagnet* Magnet = new SpdHybMagnet(); //default geometry type = 2 +// run->AddModule(Magnet); /* +++++++++++++++++ DETECTORS ++++++++++++++ */ SpdTsTB* ts_barrel = new SpdTsTB(); /* +++++++++ TST (BARREL) ++++++++++++ */ SpdTsTEC* ts_ecps = new SpdTsTEC(); /* +++++++++ TST (ENDCAPS) +++++++++++ */ - //SpdEcalTB* ecal_barrel = new SpdEcalTB(); /* +++++++++ ECALT (BARREL) ++++++++++ */ - //SpdEcalTEC* ecal_ecps = new SpdEcalTEC(); /* +++++++++ ECALT (ENDCAPS) +++++++++ */ - //SpdRsTB* rs_barrel = new SpdRsTB(); /* +++++++++ RST (BARREL) ++++++++++++ */ - //SpdRsTEC* rs_ecps = new SpdRsTEC(); /* +++++++++ RST (ENDCAPS) +++++++++++ */ - + run->AddModule(ts_barrel); - //run->AddModule(ecal_barrel); - //run->AddModule(rs_barrel); run->AddModule(ts_ecps); - //run->AddModule(ecal_ecps); - //run->AddModule(rs_ecps); //ts_barrel->SetParametersType("SpdTsTBParSet"); // TsTBParSet (default), SpdTsTBParSet //ts_barrel->SaveDetIdOption(1); // 1, 2 (default) - + /* ===== Vertex detector ===== */ SpdIts* its = new SpdIts(); run->AddModule(its); - SpdItsGeoMapperX::Instance()->EnableEndcaps(); // enable(1)/disable(0) Inner Tracker (Its) endcaps + //SpdItsGeoMapperX::Instance()->SetGeometryPars(1); + + //SpdItsGeoMapperX::Instance()->EnableEndcaps(); // enable(1)/disable(0) Inner Tracker (Its) endcaps ; default = enable + //its->SaveEmptyHits(); /*--------------------------------------------------*/ - /* ++++++++++++ CASTOMIZE GEOMETRY +++++++++++++ */ + /* ++++++++++++ CUSTOMIZE GEOMETRY +++++++++++++ */ /*--------------------------------------------------*/ CustomizeGeometry(); - + + /*--------------------------------------------------*/ + /* ++++++++++++ CUSTOMIZE MATERIALS +++++++++++++ */ + /*--------------------------------------------------*/ + + //SpdParameter* par; + + /* --- alter TsTB straw active media (gas) --- */ + //par = ts_barrel->GetMapper()->AddParameter("TsTBBaseStrawMaterial"); + //if (par) *par = "arco28020x1p5"; // ArCO2, 80/20 %, density x 1.5 + //if (par) *par = "arco28020x2p0"; // ArCO2, 80/20 %, density x 2.0 + //if (par) *par = "arco27030x1p5"; // ArCO2, 70/30 %, density x 1.5 + //if (par) *par = "arco27030x2p0"; // ArCO2, 70/30 %, density x 2.0 + + /* --- alter TsTEC straw active media (gas) --- */ + //par = ts_ecps->GetMapper()->AddParameter("TsTECBaseStrawMaterial"); + //if (par) *par = "arco28020x1p5"; // ArCO2, 80/20 %, density x 1.5 + //if (par) *par = "arco28020x2p0"; // ArCO2, 80/20 %, density x 2.0 + //if (par) *par = "arco27030x1p5"; // ArCO2, 70/30 %, density x 1.5 + //if (par) *par = "arco27030x2p0"; // ArCO2, 70/30 %, density x 2.0 + + /* --- reset all module's materials ---*/ + //ts_barrel->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + //ts_ecps->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + //its->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + /*--------------------------------------------------*/ /* ++++++++++++++ MAGNETIC FIELD ++++++++++++++ */ /*--------------------------------------------------*/ /* --- const field --- */ //SpdConstField* MagField = new SpdConstField(); - //MagField->SetField(0., 0. , 2.5); // kG + //MagField->SetField(0., 0., 4); // kG /* --- field map --- */ SpdFieldMap* MagField = new SpdFieldMap("Hybrid field"); - //MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field - MagField->InitData("map_sol_6cls5cm2.bin"); // "quasi-solenoid" + MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field + //MagField->InitData("map_sol_6cls5cm2.bin"); // "quasi-solenoid" //MagField->SetApproxMethod(0); // 0 (linear,default) or 1 (nearest vertex) //MagField->MultiplyField(1); @@ -160,9 +176,9 @@ void SimuHyb_1(Int_t nEvents = 1) //----------------------------------------------------------- // Set seed: - gRandom->SetSeed(0); - Int_t seed = gRandom->Integer(Int_t(1e9)); - P6gen->SetSeed(seed); + gRandom->SetSeed(12345); + Int_t seed = 127472;//gRandom->Integer(Int_t(1e9)); + P6gen->SetSeed(seed,0); //P6gen->SetSeed(0); //P6gen->SetSeed(144135822, 2); @@ -180,7 +196,7 @@ void SimuHyb_1(Int_t nEvents = 1) /* --- Pythia6 initialization --- */ - P6gen->Initialize("cms","p","p",26/*GeV*/); + P6gen->Initialize("cms","p","p",27/*GeV*/); primGen->AddGenerator(P6gen); @@ -210,8 +226,8 @@ void SimuHyb_1(Int_t nEvents = 1) //run->ForceParticleLifetime(-211, 26.033/5.); // pdg, life time [ns] //run->ForceParticleLifetime( 211, 26.033/5.); // pdg, life time [ns] - //SpdCommonGeoMapper::Instance()->UnsetMaterials(1); // set all materials = vacuum (precise) - + //SpdCommonGeoMapper::Instance()->UnsetMaterials(true); + /* ----------------------------------------------------------------------- */ /* >>>>>>>>>>>>>>>>>>>>>>>>>>> INITALIZE RUN <<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ /* ----------------------------------------------------------------------- */ @@ -263,15 +279,15 @@ void SimuHyb_1(Int_t nEvents = 1) Double_t rtime = timer.RealTime(); Double_t ctime = timer.CpuTime(); - + cout << endl << endl; cout << "Macro finished succesfully." << endl; - cout << "Output file is " << outFile << endl; - cout << "Parameter file is " << parFile << endl; + cout << "Output file is " << outFile << endl; + cout << "Parameter file is " << parFile << endl; + cout << "Seed (prim.gen.) is " << seed << endl; cout << "Real time " << rtime << " s, CPU time " << ctime << "s" << endl; cout << endl; - cout << " seed = " << seed << endl; /*--------------------------------------------------*/ //SpdCommonGeoMapper::Instance()->PrintGeometryList(); diff --git a/macro/tracking/SimuQsl_1.C b/macro/tracking/SimuQsl_1.C new file mode 100644 index 0000000000000000000000000000000000000000..903b0c42292b16036375f7cb6b0d842f434cf638 --- /dev/null +++ b/macro/tracking/SimuQsl_1.C @@ -0,0 +1,316 @@ + +//#define _COMPILE_MACRO_ + +#if defined(_COMPILE_MACRO_) + +#include <TRint.h> +#include <TStopwatch.h> + +#include "FairParRootFileIo.h" + +#include "SpdRunSim.h" +#include "SpdMCEventHeader.h" + +#include "SpdCommonGeoMapper.h" + +#include "SpdFields.hh" +#include "SpdGenerators.hh" + +#include "SpdCave.h" +#include "SpdPipe.h" + +#include "SpdIts.h" +#include "SpdTsTB.h" +#include "SpdTsTEC.h" + +#include "SpdItsGeoMapperX.h" +#include "SpdTsTBGeoBuilder.h" + +#endif + +//_________________________________________________________________________ +void SimuQsl_1(Int_t nEvents = 1) +{ + TString outFile = "run_tor.root"; // Output data file name + TString parFile = "params_tor.root"; // Output parameters file name + + SpdRunSim* run = new SpdRunSim(); + + run->SetName("TGeant4"); + run->SetMaterials("media.geo"); + + run->SetOutputFile(outFile); + + //run->SetPythiaDecayer("DecayConfig.C"); + + run->SetMCEventHeader(new SpdMCEventHeader); + + /*--------------------------------------------------*/ + /* +++++++++ GEOMETRY (QSOLENOID) ++++++++ */ + /*--------------------------------------------------*/ + + SpdCommonGeoMapper::Instance()->DefineQslGeometrySet(); + + /* ++++++++++++++++++ CAVE ++++++++++++++++++ */ + + FairModule* cave = new SpdCave("CAVE"); + //cave->SetGeometryFileName("cave.geo"); + //cave->SetGeometryFileName("cave_precise.geo"); + run->AddModule(cave); + + /* ++++++++++++++++++ PIPE ++++++++++++++++++ */ + + SpdPipe* Pipe = new SpdPipe(); + //Pipe->UnsetMaterials("air"); + run->AddModule(Pipe); + + /* +++++++++++++++++ DETECTORS ++++++++++++++ */ + + SpdTsTB* ts_barrel = new SpdTsTB(); /* +++++++++ TST (BARREL) ++++++++++++ */ + SpdTsTEC* ts_ecps = new SpdTsTEC(); /* +++++++++ TST (ENDCAPS) +++++++++++ */ + + run->AddModule(ts_barrel); + run->AddModule(ts_ecps); + + /* ===== Vertex detector ===== */ + + SpdIts* its = new SpdIts(); + run->AddModule(its); + + //SpdItsGeoMapperX::Instance()->SetGeometryPars(1); + + //SpdItsGeoMapperX::Instance()->EnableEndcaps(); // enable(1)/disable(0) Inner Tracker (Its) endcaps ; default = enable + //its->SaveEmptyHits(); + + /*--------------------------------------------------*/ + /* ++++++++++++ CUSTOMIZE GEOMETRY +++++++++++++ */ + /*--------------------------------------------------*/ + + // Chose TsTEC configuration + // + // option = 1: (2x)3 modules, 1 module = 8x2 = 16 layers, total = 48 layers (default) + // option = 2: (2x)2 modules, 1 module = 8x2 = 16 layers, total = 32 layers + // option = 3: (2x)1 modules, 1 module = 26x2 = 52 layers, total = 52 layers (actual!) + + SpdTsTECGeoMapper::Instance()->SetGeometryPars(3); + + SpdParameter* parg; + + // RsTB geo. parameters + parg = SpdRsTBGeoMapper::Instance()->AddParameter("RsTBClearance"); + *parg = 0.; + + // EcalTB geo. parameters + parg = SpdEcalTBGeoMapper::Instance()->AddParameter("EcalTBClearance"); + *parg = 0.; + + /*--------------------------------------------------*/ + /* ++++++++++++ CUSTOMIZE MATERIALS +++++++++++++ */ + /*--------------------------------------------------*/ + + //SpdParameter* par; + + /* --- alter TsTB straw active media (gas) --- */ + //par = ts_barrel->GetMapper()->AddParameter("TsTBBaseStrawMaterial"); + //if (par) *par = "arco28020x1p5"; // ArCO2, 80/20 %, density x 1.5 + //if (par) *par = "arco28020x2p0"; // ArCO2, 80/20 %, density x 2.0 + //if (par) *par = "arco27030x1p5"; // ArCO2, 70/30 %, density x 1.5 + //if (par) *par = "arco27030x2p0"; // ArCO2, 70/30 %, density x 2.0 + + /* --- alter TsTEC straw active media (gas) --- */ + //par = ts_ecps->GetMapper()->AddParameter("TsTECBaseStrawMaterial"); + //if (par) *par = "arco28020x1p5"; // ArCO2, 80/20 %, density x 1.5 + //if (par) *par = "arco28020x2p0"; // ArCO2, 80/20 %, density x 2.0 + //if (par) *par = "arco27030x1p5"; // ArCO2, 70/30 %, density x 1.5 + //if (par) *par = "arco27030x2p0"; // ArCO2, 70/30 %, density x 2.0 + + /* --- reset all module's materials ---*/ + //ts_barrel->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + //ts_ecps->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + //its->GetMapper()->UnsetMaterials("air"); // "air" or "vacuum" + + /*--------------------------------------------------*/ + /* ++++++++++++++ MAGNETIC FIELD ++++++++++++++ */ + /*--------------------------------------------------*/ + + /* --- axial field map --- */ + SpdAxialFieldMap* MagField = new SpdAxialFieldMap("QSolenoidal field"); + MagField->InitData("map_qsolRZ_6cls2cm.bin"); + MagField->MultiplyField(0.8); + + /* --- const field --- */ + //SpdConstField* MagField = new SpdConstField(); + //MagField->SetField(0., 0., 8.0); // kG + + /* --- field map --- */ + //SpdFieldMap* MagField = new SpdFieldMap("Hybrid field"); + + //MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field + //MagField->InitData("map_sol_6cls5cm2.bin"); // "quasi-solenoid" + + //MagField->SetApproxMethod(0); // 0 (linear,default) or 1 (nearest vertex) + //MagField->MultiplyField(1); + + /* === define field region === */ + SpdRegion* reg = 0; + + //reg = MagField->CreateFieldRegion("box"); + //reg->SetBoxRegion(-1000, 1000, -1000, 1000, -1000, 1000); // (X,Y,Z)_(min,max), cm + + reg = MagField->CreateFieldRegion("tube"); + reg->SetTubeRegion(0, 174, -246, 246); // (R,Z)_(min,max), cm + + run->SetField(MagField); + + MagField->Print(); + + /*--------------------------------------------------*/ + /* ++++++++++ DEFINE PRIMARY GENERATORS +++++++++++ */ + /*--------------------------------------------------*/ + + SpdPrimaryGenerator* primGen = new SpdPrimaryGenerator(); + + //============================ + // PYTHIA 6 GENERATOR + //============================ + + SpdPythia6Generator* P6gen = new SpdPythia6Generator(); + + //----------------------------------------------------------- + // Option: (decayer for vertex meson- and baryon- resonances) + // 0 = Transport generator + External decayer (particles don't decay in the vertex) + // 1 = Primary generator (DEFAULT value, more safely) + + P6gen->SetVGenOpt(1); + + //----------------------------------------------------------- + // Set seed: + + gRandom->SetSeed(12345); + Int_t seed = gRandom->Integer(Int_t(1e9)); + P6gen->SetSeed(seed,0); + + //P6gen->SetSeed(0); + //P6gen->SetSeed(144135822, 2); + + //P6gen->SetSeed(12995,0); + //P6gen->SetSeed(19949278, 1); + //P6gen->SetSeed(13495); + //P6gen->SetSeed(127472); + + + /* --- Set Pythia6 options --- */ + SpdPythia6* gg = (SpdPythia6*)P6gen->GetGenerator(); + + gg->SetMSEL(1); // set miminum bias + + + /* --- Pythia6 initialization --- */ + P6gen->Initialize("cms","p","p",27/*GeV*/); + + primGen->AddGenerator(P6gen); + + primGen->SetVerboseLevel(-10); + primGen->SetVerbose(0); + + //============================ + + run->SetGenerator(primGen); + + primGen->SetBeam(0., 0., 0.1, 0.1); // (X,Y)- position, (X,Y)- (2*delta or sigma) [cm] + primGen->SmearVertexXY(kTRUE); +// //primGen->SmearGausVertexXY(kTRUE); +// + primGen->SetTarget(0.,5.); // Z- position, 2*delta or sigma [cm] + primGen->SmearVertexZ(kTRUE); +// //primGen->SmearGausVertexZ(kTRUE); + + /* ------------------------------------------------ */ + /* +++++++++++++++ GLOBAL OPTIONS +++++++++++++++++ */ + /* ------------------------------------------------ */ + + //run->SetStoreTraj(kTRUE); + + //SpdCommonGeoMapper::Instance()->SaveEmptyHits(); + + //run->ForceParticleLifetime(-211, 26.033/5.); // pdg, life time [ns] + //run->ForceParticleLifetime( 211, 26.033/5.); // pdg, life time [ns] + + //SpdCommonGeoMapper::Instance()->UnsetMaterials(true); + + /* ----------------------------------------------------------------------- */ + /* >>>>>>>>>>>>>>>>>>>>>>>>>>> INITALIZE RUN <<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ + /* ----------------------------------------------------------------------- */ + + cout << "\n\t" << "++++++++++++++++++++++++++++++++++++++++++++" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "+ Init Run (start) +" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "++++++++++++++++++++++++++++++++++++++++++++\n" << endl; + + run->Init(); + + cout << "\n\t" << "++++++++++++++++++++++++++++++++++++++++++++" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "+ Init Run (finish) +" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "++++++++++++++++++++++++++++++++++++++++++++\n" << endl; + + //return; + + /*--------------------------------------------------*/ + /* +++++++++++++ CREATE RUN PARAMETERS +++++++++++ */ + /*--------------------------------------------------*/ + + Bool_t MergePars = kFALSE; + FairParRootFileIo* parOut = new FairParRootFileIo(MergePars); + if (MergePars) parOut->open(parFile.Data()); + else parOut->open(parFile.Data(),"RECREATE"); + + FairRuntimeDb* rtdb = run->GetRuntimeDb(); + rtdb->setOutput(parOut); + + /* ----------------------------------------------------------------------- */ + /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RUN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ + /* ----------------------------------------------------------------------- */ + + TStopwatch timer; + timer.Start(); + + run->Run(nEvents); + + timer.Stop(); + + /*--------------------------------------------------*/ + /* ++++++++++++ SAVE RUN PARAMETERS +++++++++++++ */ + /*--------------------------------------------------*/ + + rtdb->saveOutput(); + + /*--------------------------------------------------*/ + + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + + cout << endl << endl; + cout << "Macro finished succesfully." << endl; + cout << "Output file is " << outFile << endl; + cout << "Parameter file is " << parFile << endl; + cout << "Seed (prim.gen.) is " << seed << endl; + cout << "Real time " << rtime << " s, CPU time " << ctime << "s" << endl; + cout << endl; + + /*--------------------------------------------------*/ + + //SpdCommonGeoMapper::Instance()->PrintGeometryList(); + SpdCommonGeoMapper::Instance()->PrintGeometry(); + + //SpdItsGeoMapperX::Instance()->PrintVolPars(); + //SpdItsGeoMapperX::Instance()->PrintGeoTable(); + //SpdItsGeoMapperX::Instance()->Print(""); + + /*--------------------------------------------------*/ + + gApplication->Terminate(); +} + diff --git a/macro/tracking/TestKFParticle.C b/macro/tracking/TestKFParticle.C new file mode 100644 index 0000000000000000000000000000000000000000..721b53d655c00127e72a8be59bfccd5497fbdeb2 --- /dev/null +++ b/macro/tracking/TestKFParticle.C @@ -0,0 +1,7 @@ + +void TestKFParticle() { + + SpdKFParticleTest kfptest; + kfptest.RunTest(); + +} diff --git a/macro/vertexrec/FitIdealTracksV0exam.C b/macro/vertexrec/FitIdealTracksV0exam.C new file mode 100644 index 0000000000000000000000000000000000000000..5edb11f13a7b41c4cd009f1b7949eae6e34bff99 --- /dev/null +++ b/macro/vertexrec/FitIdealTracksV0exam.C @@ -0,0 +1,127 @@ + + +void FitIdealTracksV0exam() +{ + // + Int_t nEvents = 0; + + TString inFile = "IdealTracksV0exam.root"; // Input file (MC trakcs) + TString parFile = "params_torV0exam.root"; // Parameter file + TString outFile = "IdealFittedTracksV0exam.root"; // Output file for tracks + + TString userOutFile = "IdealFindedV0exam.root"; // Output file for V0 + + SpdRunAna* Run = new SpdRunAna(); + + Run->SetInputFile(inFile); + Run->SetOutputFile(outFile); + Run->SetUserOutputFileName(userOutFile); + + FairRuntimeDb* rtdb = Run->GetRuntimeDb(); + FairParRootFileIo* parInput = new FairParRootFileIo(); + parInput->open(parFile.Data()); + rtdb->setFirstInput(parInput); + + TStopwatch timer; + timer.Start(); + + //-------------------------------------// + // Make task // + //-------------------------------------// + + SpdIdealV0Finder* KalmanFitter = new SpdIdealV0Finder(); + + KalmanFitter->SetVerboseLevel(2); // level = <1 (no prints), 1(default), 2, 3, 4 + + //KalmanFitter->SetTrackingGeoModules(); // add Its,TsTB,TsTEC modules to analysis + + KalmanFitter->AddModule(12); // Its + KalmanFitter->AddModule(2); // TsTB + KalmanFitter->AddModule(3); // TsTEC + + // standard options: + KalmanFitter->SetSeedMomentum(1.); // Start vertex momentum for fit, GeV/c (default = 1 GeV/c) + +// KalmanFitter->SetHitRepresentation(kSpdIts,pkPixel); // options: pkPixel, pkSpacepoint +// KalmanFitter->SetHitRepresentation(kSpdTsTB,pkWire); // options: pkWire, pkWirePoint, pkSpacepoint +// KalmanFitter->SetHitRepresentation(kSpdTsTEC,pkWire); // options: pkWire, pkWirePoint, pkSpacepoint + + KalmanFitter->SetHitRepresentation(kSpdIts,pkSpacepoint); // options: pkPixel, pkSpacepoint + KalmanFitter->SetHitRepresentation(kSpdTsTB,pkSpacepoint); // options: pkWire, pkWirePoint, pkSpacepoint + KalmanFitter->SetHitRepresentation(kSpdTsTEC,pkSpacepoint); // options: pkWire, pkWirePoint, pkSpacepoint + + // advanced options: + KalmanFitter->SetVertexFindingMethod(1); // <1 (vertex will not be found), (default = 1) + KalmanFitter->SetVertexFindingAngleCut(3.0); // skip tracks with theta 90+-cut degree (default = 3[deg]) + + KalmanFitter->SetStartSeedMethod(2); // set [SeedMethod]: choose start value initialization method (1, 2 = default) + + KalmanFitter->SetSmearSeedValues(true); // [SeedMethod = 1,2] start values smearing flag (default = true) + KalmanFitter->SetSmearingMomDelta(0.1); // [SeedMethod = 1,2] track start momentum smearing (+-)value, GeV/c (default = 0.1 GeV/c) + KalmanFitter->SetSmearingAngleDelta(3.0); // [SeedMethod = 1] track start angle smearing (+-)value, deg (default = 3.0 deg) + KalmanFitter->SetSmearingVertexDelta(0.5); // [SeedMethod = 1] track start vertex position smearing (+-)value, cm (default = 0.5 cm) + KalmanFitter->SetNPointsVertexUse(0); // [SeedMethod = 2] <1 (default): number of points is the maximum possible (usually 5-6 ) + + KalmanFitter->SetFitterMaxIterations(8); // default: 8, minimum: 4 + KalmanFitter->SetFitterMaxTrials(2); // default: 10, minimum: 1 + +// option for V0 finder +//----------------------- + KalmanFitter->SetFirstDaughter(321); // PDG code for the first daughter + KalmanFitter->SetSecondDaughter(211); // PDG code for the second daughter + KalmanFitter->SetUsedTypeOfPV(1); // = 0 => use sim PV or = 1 => use reco PV + KalmanFitter->SetConstrainToPV(1); // = 0 => without constrain, = 1 with PV constrain + KalmanFitter->SetMinTrackPVchi2(2.0); // minimum topo Chi2 of track to PV + KalmanFitter->SetMinDistDaughter(0.075); // minimum distance between daughter particles + KalmanFitter->SetMinimumMass(0.00); // minimum mass of mother (V0) particle + KalmanFitter->SetMaximumMass(2.50); // maximum mass of mother (V0) particle + + // Material effects option: < 1 : fit without materials; + // >= 1 : fit taking into accont material effects (default); + + KalmanFitter->SetMaterialEffectsOption(1); +// KalmanFitter->SetMaterialEffectsOption(0); + + //SpdGeoLoader::ForceTopGeoFile("cave_precise.geo"); // force top volume (Cave) geometry (default: parameters will be used); + + // method to update covariance matrix (default = 1) + KalmanFitter->SetFitterOption(1); + + //store fitted tracks (full fitter info, by default = false) + KalmanFitter->SetStoreTracks(true); + + //------------------------------------// + Run->AddTask(KalmanFitter); + + //return; + + cout << "Start ... " << endl; + + Run->Initialize(); + + //return; + + Run->Run(0, nEvents); + //Run->Run(100,200); +// Run->Run(0,500); +// Run->Run(0,100); +// Run->Run(0,50); +// Run->Run(0,10); +// Run->Run(0,5); + + KalmanFitter->DeleteGeoLoader(); + + timer.Stop(); + + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + + cout << endl << endl; + cout << "Macro finished succesfully." << endl; + cout << "Output file is " << outFile << endl; + cout << "Parameter file is " << parFile << endl; + cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << endl; + cout << endl; + + gApplication->Terminate(); +} diff --git a/macro/vertexrec/MakeIdealTracksAndV0.C b/macro/vertexrec/MakeIdealTracksAndV0.C new file mode 100644 index 0000000000000000000000000000000000000000..86dc7f22ac9f3aa7c430e13f6fdb4624e0557b1e --- /dev/null +++ b/macro/vertexrec/MakeIdealTracksAndV0.C @@ -0,0 +1,115 @@ + + +void MakeIdealTracksAndV0() +{ + // + Int_t nEvents = 0; + +// TString inFile = "run_torV02.root"; // Input file (MC events) +// TString parFile = "params_torV02.root"; // Parameter file +// TString outFile = "IdealTracksV02.root"; // Output file + + TString inFile = "run_torV0exam.root"; // Input file (MC events) + TString parFile = "params_torV0exam.root"; // Parameter file + TString outFile = "IdealTracksV0exam.root"; // Output file + + SpdRunAna* Run = new SpdRunAna(); + + Run->SetInputFile(inFile); + Run->SetOutputFile(outFile); + + FairRuntimeDb* rtdb = Run->GetRuntimeDb(); + FairParRootFileIo* parInput = new FairParRootFileIo(); + parInput->open(parFile.Data()); + rtdb->setFirstInput(parInput); + + TStopwatch timer; + timer.Start(); + + //-------------------------------------// + // Make task // + //-------------------------------------// + + SpdIdealTrackFinder* TrackFinder = new SpdIdealTrackFinder(); + + // set geometry + //TrackFinder->SetTrackingGeoModules(); // Its,TsTB,TsTEC + + TrackFinder->AddModule(12); // Its + TrackFinder->AddModule(2); // TsTB + TrackFinder->AddModule(3); // TsTEC + + // set cuts +// TrackFinder->SetMinMomentum(1e-2); // momentum cut; default = 1e-2 (10 Mev); absiolute min. value = 4e-3 (4 MeV) +// TrackFinder->SetMinGammaBeta(0.5); // p/m cut; default = 0.5; absiolute min. value = 0.05 +// TrackFinder->SetMinVertexNHits(1); // its hits number cut; default = 1; absolute min. value = 0; +// TrackFinder->SetMinTrackerNHits(2); // tstb+tstec hits number cut; default = 2; absiolute min. value = 2; + + TrackFinder->SetMinMomentum(0.350); // momentum cut; default = 1e-2 (10 Mev); absiolute min. value = 4e-3 (4 MeV) + TrackFinder->SetMinGammaBeta(0.50); // p/m cut; default = 0.5; absiolute min. value = 0.05 + TrackFinder->SetMinVertexNHits(3); // its hits number cut; default = 1; absolute min. value = 0; + TrackFinder->SetMinTrackerNHits(10); // tstb+tstec hits number cut; default = 2; absiolute min. value = 2; + + // set hits resolution + Double_t mkm = 1e-4; + + // ------ INNER TRACKER ----- + + TrackFinder->SetHitResolution(kSpdIts, 'p', 50*mkm, 50*mkm); // ENDCAP: POINT (u=x,v=y) + TrackFinder->SetHitResolution(kSpdIts, 'm', 50*mkm, 50*mkm); // BARREL: MAPS (u,v) + TrackFinder->SetHitResolution(kSpdIts, 's', 50*mkm, 50*mkm); // BARREL: DSSD (u,v) + + // ----- STRAW TRACKER ----- + + // --- barrel --- + TrackFinder->SetHitResolution(kSpdTsTB, 'w', 150*mkm); // Wire(1D) (r,z) + //TrackFinder->SetHitResolution(kSpdTsTB, 'w', 150*mkm, 2. /*cm*/); // Wire(1D,2D) (r,z) + + //--- endcaps --- + TrackFinder->SetHitResolution(kSpdTsTEC,'w', 150*mkm); // Wire(1D) (r,z) + //TrackFinder->SetHitResolution(kSpdTsTEC,'w', 150*mkm, 2. /*cm*/); // Wire(1D,2D) (r,z) + + TrackFinder->AppendSecondaryTracks(); + + //------------------------------------// + Run->AddTask(TrackFinder); + + //return; + + cout << "Start ... " << endl; + + Run->LoadGeoParSet(false); + Run->Initialize(); + + //return; + + Run->Run(0, nEvents); +// Run->Run(0, 10); + + TrackFinder->DeleteGeoLoader(); + + timer.Stop(); + + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + + cout << endl << endl; + cout << "Macro finished succesfully." << endl; + cout << "Output file is " << outFile << endl; + cout << "Parameter file is " << parFile << endl; + cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << endl; + cout << endl; + + /* DRAW GEOMETRY */ + +// TGeoManager *geoMan = gGeoManager; +// +// if (geoMan && geoMan->GetMasterVolume()) { +// geoMan->SetVisLevel(2); +// geoMan->GetMasterVolume()->Draw("ogl"); +// //geoMan->GetMasterVolume()->Draw(); +// } + + gApplication->Terminate(); +} + diff --git a/macro/vertexrec/SimuV0IdealExam.C b/macro/vertexrec/SimuV0IdealExam.C new file mode 100644 index 0000000000000000000000000000000000000000..5934a89cd09027b27506535699c32d6a68f47985 --- /dev/null +++ b/macro/vertexrec/SimuV0IdealExam.C @@ -0,0 +1,347 @@ + +//#define _COMPILE_MACRO_ + +#if defined(_COMPILE_MACRO_) + +#include <TRint.h> +#include <TStopwatch.h> + +#include "FairParRootFileIo.h" + +#include "SpdRunSim.h" +#include "SpdMCEventHeader.h" + +#include "SpdCommonGeoMapper.h" + +#include "SpdFields.hh" +#include "SpdGenerators.hh" + +#include "SpdCave.h" +#include "SpdPipe.h" +#include "SpdHybMagnet.h" + +#include "SpdIts.h" +#include "SpdTsTB.h" +#include "SpdTsTEC.h" +#include "SpdEcalTB.h" +#include "SpdEcalTEC.h" +#include "SpdRsTB.h" +#include "SpdRsTEC.h" + +#include "SpdItsGeoMapperX.h" +#include "SpdTsTBGeoBuilder.h" + +#endif + +void CustomizeGeometryIts(); +void CustomizeGeometryTsTB(); +void CustomizeGeometryTsTEC(); + +//_________________________________________________________________________ +void SimuV0IdealExam(Int_t nEvents = 200) +{ + TString outFile = "run_torV0exam.root"; // Output data file name + TString parFile = "params_torV0exam.root"; // Output parameters file name + + SpdRunSim* run = new SpdRunSim(); + + run->SetName("TGeant4"); + run->SetMaterials("media.geo"); + + run->SetOutputFile(outFile); + + TString decayer = "DecayConfigSpecV0.C"; + run->SetPythiaDecayer(decayer); + + run->SetMCEventHeader(new SpdMCEventHeader); + + /*--------------------------------------------------*/ + /* +++++++++ GEOMETRY (HYBRID) +++++++++++ */ + /*--------------------------------------------------*/ + + SpdCommonGeoMapper::Instance()->DefineHybGeometrySet(); + +// SpdCommonGeoMapper::Instance()->UnsetMaterials(1); // all geom is vacuum + + /* ++++++++++++++++++ CAVE ++++++++++++++++++ */ + + FairModule* cave = new SpdCave("CAVE"); + //cave->SetGeometryFileName("cave.geo"); + cave->SetGeometryFileName("cave_precise.geo"); + run->AddModule(cave); + + /* ++++++++++++++++++ PIPE ++++++++++++++++++ */ + + SpdPipe* Pipe = new SpdPipe(); + run->AddModule(Pipe); + + /* +++++++++++++++++ MAGNET +++++++++++++++++ */ + +// SpdHybMagnet* Magnet = new SpdHybMagnet(); +// //Magnet->SetGeometryType(2); // 1 = "hybrid" (deafult), 2 = "qsolenoid" +// run->AddModule(Magnet); + + /* +++++++++++++++++ DETECTORS ++++++++++++++ */ + + SpdTsTB* ts_barrel = new SpdTsTB(); /* +++++++++ TST (BARREL) ++++++++++++ */ + SpdTsTEC* ts_ecps = new SpdTsTEC(); /* +++++++++ TST (ENDCAPS) +++++++++++ */ + + run->AddModule(ts_barrel); + run->AddModule(ts_ecps); + + /* ===== Vertex detector ===== */ + + SpdIts* its = new SpdIts(); + run->AddModule(its); + + SpdItsGeoMapperX::Instance()->EnableEndcaps(); // enable(1)/disable(0) endcaps + + /*--------------------------------------------------*/ + /* ++++++++++++ CASTOMIZE GEOMETRY +++++++++++++ */ + /*--------------------------------------------------*/ + + CustomizeGeometryIts(); + CustomizeGeometryTsTB(); + CustomizeGeometryTsTEC(); + + /*--------------------------------------------------*/ + /* ++++++++++++++ MAGNETIC FIELD ++++++++++++++ */ + /*--------------------------------------------------*/ + + /* --- const field --- */ + SpdConstField* MagField = new SpdConstField(); + MagField->SetField(0., 0. , 10.0); // kG + + /* --- field map --- */ +// SpdFieldMap* MagField = new SpdFieldMap("Hybrid field"); + + // MagField->InitData("map_hyb_1T2cm.bin"); // standard "hybrid" field +// MagField->InitData("map_sol_6cls5cm2.bin"); // "quasi-solenoid" + + // MagField->SetApproxMethod(0); // 0 (linear,default) or 1 (nearest vertex) + // MagField->MultiplyField(1); + +// MagField->MultiplyField(1); + + /* === define field region === */ + SpdRegion* reg = 0; + + //reg = MagField->CreateFieldRegion("box"); + //reg->SetBoxRegion(-1000, 1000, -1000, 1000, -1000, 1000); // (X,Y,Z)_(min,max), cm + + reg = MagField->CreateFieldRegion("tube"); + reg->SetTubeRegion(0, 250, -300, 300); // (R,Z)_(min,max), cm + + run->SetField(MagField); + + MagField->Print(); + + /*--------------------------------------------------*/ + /* ++++++++++ DEFINE PRIMARY GENERATORS +++++++++++ */ + /*--------------------------------------------------*/ + + SpdPrimaryGenerator* primGen = new SpdPrimaryGenerator(); + + //============================ + // PYTHIA 6 GENERATOR + //============================ + + SpdPythia6Generator* P6gen = new SpdPythia6Generator(); + + //----------------------------------------------------------- + // Option: (decayer for vertex meson- and baryon- resonances) + // 0 = Transport generator + External decayer (particles don't decay in the vertex) + // 1 = Primary generator (DEFAULT value, more safely) + + P6gen->SetVGenOpt(1); + + //----------------------------------------------------------- + // Set seed: + gRandom->SetSeed(54545); + + Int_t seed = gRandom->Integer(Int_t(1e9)); + //P6gen->SetSeed(seed); + P6gen->SetSeed(13495); + + /* --- Set Pythia6 options --- */ + SpdPythia6* gg = (SpdPythia6*)P6gen->GetGenerator(); + + gg->SetMSEL(1); // set miminum bias + + /* --- Pythia6 initialization --- */ + P6gen->Initialize("cms","p","p",27/*GeV*/); + + primGen->AddGenerator(P6gen); + + //=========================== + // ISOTROPIC GENERATOR (1) + //=========================== + + SpdIsotropicGenerator* isogen = new SpdIsotropicGenerator("isogen"); + +// isogen->Initialize(310, 1.5, 1); // Ks^0 + isogen->Initialize(421, 1.5, 1); // D^0 +// isogen->Initialize(411, 1.5, 1); // D^+ + isogen->SetVerboseLevel(1); + isogen->SetSeed(39211); +// isogen->SetVGenOpt(-1); // (+-)1, (+-)2 + isogen->SetVGenOpt(1); // (+-)1, (+-)2 + +// isogen->SetSpherical(70.0, 110.0, 0.0, 360.0); // theta[min,max], phi[min,max] + primGen->AddGenerator(isogen); + + /* run generator */ + + run->SetGenerator(primGen); + + primGen->SetVerboseLevel(-10); +// primGen->SetVerbose(0); + +// primGen->SetBeam(0., 0., 0.1, 0.1); // (X,Y)- position, (X,Y)- (0.5*delta or sigma) [cm] + primGen->SetBeam(0., 0., 0.0, 0.0); // (X,Y)- position, (X,Y)- (0.5*delta or sigma) [cm] + primGen->SmearVertexXY(kFALSE); +// primGen->SmearVertexXY(kTRUE); +// primGen->SmearGausVertexXY(kTRUE); + +// primGen->SetTarget(0.,5.); // Z- position, 0.5*delta or sigma [cm] + primGen->SetTarget(0., 0.); // Z- position, 0.5*delta or sigma [cm] + primGen->SmearVertexZ(kFALSE); + // primGen->SmearVertexZ(kTRUE); + // primGen->SmearGausVertexZ(kTRUE); + + /* ------------------------------------------------ */ + /* +++++++++++++++ GLOBAL OPTIONS +++++++++++++++++ */ + /* ------------------------------------------------ */ + + //run->SetStoreTraj(kTRUE); + +// SpdCommonGeoMapper::Instance()->SaveEmptyHits(); + + //SpdCommonGeoMapper::Instance()->UnsetMaterials(1); // set all materials = vacuum (precise) + + /* ----------------------------------------------------------------------- */ + /* >>>>>>>>>>>>>>>>>>>>>>>>>>> INITALIZE RUN <<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ + /* ----------------------------------------------------------------------- */ + + cout << "\n\t" << "++++++++++++++++++++++++++++++++++++++++++++" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "+ Init Run (start) +" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "++++++++++++++++++++++++++++++++++++++++++++\n" << endl; + + run->Init(); + + cout << "\n\t" << "++++++++++++++++++++++++++++++++++++++++++++" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "+ Init Run (finish) +" << endl; + cout << "\t" << "+ +" << endl; + cout << "\t" << "++++++++++++++++++++++++++++++++++++++++++++\n" << endl; + + /*--------------------------------------------------*/ + /* +++++++++++++ CREATE RUN PARAMETERS +++++++++++ */ + /*--------------------------------------------------*/ + + Bool_t MergePars = kFALSE; + FairParRootFileIo* parOut = new FairParRootFileIo(MergePars); + if (MergePars) parOut->open(parFile.Data()); + else parOut->open(parFile.Data(),"RECREATE"); + + FairRuntimeDb* rtdb = run->GetRuntimeDb(); + rtdb->setOutput(parOut); + + /* ----------------------------------------------------------------------- */ + /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RUN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ + /* ----------------------------------------------------------------------- */ + + TStopwatch timer; + timer.Start(); + + run->Run(nEvents); + + timer.Stop(); + + /*--------------------------------------------------*/ + /* ++++++++++++ SAVE RUN PARAMETERS +++++++++++++ */ + /*--------------------------------------------------*/ + + rtdb->saveOutput(); + + /*--------------------------------------------------*/ + + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + + cout << endl << endl; + cout << "Macro finished succesfully." << endl; + cout << "Output file is " << outFile << endl; + cout << "Parameter file is " << parFile << endl; + cout << "Real time " << rtime << " s, CPU time " << ctime << "s" << endl; + cout << endl; + + /*--------------------------------------------------*/ + + //SpdCommonGeoMapper::Instance()->PrintGeometryList(); + SpdCommonGeoMapper::Instance()->PrintGeometry(); + + //SpdItsGeoMapperX::Instance()->PrintVolPars(); + //SpdItsGeoMapperX::Instance()->PrintGeoTable(); + //SpdItsGeoMapperX::Instance()->Print(""); + + /*--------------------------------------------------*/ + + gApplication->Terminate(); + +} + +//________________________________________________________________________________________________ +void CustomizeGeometryTsTB() +{ + //return; + + //SpdTsTECGeoMapper::Instance()->SetGeometryPars(2); + + SpdTsTBGeoBuilder* builder = SpdTsTBGeoBuilder::Instance(); + + // --------------------------------------------------- + // SpdTsTBGeoBuilder::AddRejection(volname ,nmin, nmax, lcycle). + // Remove nj = n + j*lcycle layers, where + // n = [nmin,nmax], j = 0,1,... , lcycle >= n. + // volname = unique part of volume name placed + // before its number (for example SpdTsTBLayer23 -> + // SpdTsTBLayer, TsTBLayer, TBLayer or Layer). + // --------------------------------------------------- + + Int_t lcycle = 8; // number of different layer (layer cycle) + + builder->AddRejection("Layer", 1, 2, lcycle); + builder->AddRejection("Layer", 3, 4, lcycle); + //builder->AddRejection("Layer", 5, 6, lcycle); + builder->AddRejection("Layer", 7, 8, lcycle); + + +// builder->AddRejection("Layer", 16); +// builder->AddRejection("Layer", 30); +// builder->AddRejection("Layer", 35, 45); +// builder->AddRejection("Layer", 56, 67); +// builder->AddRejection("Layer", 80, 88); + +} + +//________________________________________________________________________________________________ +void CustomizeGeometryTsTEC() +{ + + +} + +//________________________________________________________________________________________________ +void CustomizeGeometryIts() +{ + + +} + + + + + diff --git a/passive/CMakeLists.txt b/passive/CMakeLists.txt index b535ca8dd596c5d1f74d4b6c3464ed4a22f2e159..6ac6e2637ab81f5a0fa2ddea8c4e721f004e8360 100644 --- a/passive/CMakeLists.txt +++ b/passive/CMakeLists.txt @@ -32,10 +32,19 @@ SpdTorBasket.cxx SpdSolMagnet.cxx SpdTorMagnet.cxx SpdHybMagnet.cxx -SpdPassiveContFact.cxx ) -Set(HEADERS ) +Set(HEADERS +SpdCave.h +SpdGeoCave.h +SpdGeoFrame.h +SpdHybMagnet.h +SpdPipe.h +SpdSolMagnet.h +SpdTorBasket.h +SpdTorMagnet.h +) + Set(LINKDEF PassiveLinkDef.h) Set(LIBRARY_NAME SpdPassive) Set(DEPENDENCIES Base GeoBase ParBase SpdCommon SpdData) diff --git a/passive/PassiveLinkDef.h b/passive/PassiveLinkDef.h index 5d5ff94fefca9296f7ef2b512d4e9d1ca2cde4bc..bc3e49659149013d0489a91da9e92e062adf1ce6 100644 --- a/passive/PassiveLinkDef.h +++ b/passive/PassiveLinkDef.h @@ -14,7 +14,6 @@ #pragma link C++ class SpdCave+; #pragma link C++ class SpdGeoCave+; -#pragma link C++ class SpdPassiveContFact+; #pragma link C++ class SpdGeoFrame+; #pragma link C++ class SpdTorBasket+; #pragma link C++ class SpdPipe+; diff --git a/passive/SpdCave.cxx b/passive/SpdCave.cxx index bf3e06da1bd51afdfebe4b8e0b7d3f1cf8aa07d3..4b8bb07e18906c28ee726a592c07b2f1e60fe1e7 100644 --- a/passive/SpdCave.cxx +++ b/passive/SpdCave.cxx @@ -2,13 +2,20 @@ #include "SpdCave.h" #include "SpdGeoCave.h" -#include "FairGeoInterface.h" -#include "FairGeoLoader.h" +#include "SpdParSetContFact.h" +#include "SpdPassiveGeoParSet.h" + +#include "FairGeoMedia.h" + +#include <iostream> + +using std::cout; +using std::endl; ClassImp(SpdCave) //_____________________________________________________________________________________ -SpdCave::SpdCave(): FairModule() +SpdCave::SpdCave():FairModule() { } @@ -32,11 +39,135 @@ void SpdCave::ConstructGeometry() Bool_t rc = GeoInterface->readSet(MGeo); if (rc) MGeo->create(loader->getGeoBuilder()); + + FillParsIn(GetParameters()); + + cout << "-I- <SpdCave::ConstructGeometry> actual geometry: " << fgeoName << endl; } +//_____________________________________________________________________________________ +void SpdCave::SetGeometryFileName(TString fname, TString geoVer) +{ + if (fgeoName == "Not defined" || fgeoName.IsWhitespace()) { + FairModule::SetGeometryFileName(fname); + cout << "-I- <SpdCave::SetGeometryFileName> Geometry: " << fgeoName << endl; + return; + } + + if (fname == fgeoName) { + cout << "-I- <SpdCave::SetGeometryFileName> Geometry has already been defined: " + << fgeoName << endl; + return; + } + + FairModule::SetGeometryFileName(fname); + cout << "-I- <SpdCave::SetGeometryFileName> New geomery: " << fgeoName << endl; +} +//_____________________________________________________________________________________ +TString SpdCave::GetGeometryFileName() +{ + SpdPassiveGeoParSet* pars = GetParameters(); + + if (fgeoName != "Not defined" && !fgeoName.IsWhitespace()) { + + if (!pars) return fgeoName; + + TString s = fgeoName; + if (s.Contains("/")) s.Remove(0,s.Last('/')+1); + TString ss; + if (pars->GetParameter("SpdCave/GeometryFileName",ss)) { + if (s != ss) { + cout << "-W- <SpdCave::GetGeometryFileName> geometry is changed: " + << ss << " -> " << s << endl; + } + else return fgeoName; + } + else { + pars->SetParameter("SpdCave/GeometryFileName",s.Data()); // save user geometry + pars->setChanged(); + pars->setInputVersion(FairRun::Instance()->GetRunId(),1); + } + cout << "-I- <SpdCave::GetGeometryFileName> set user geometry: " << fgeoName << endl; + } + else { + TString s; + if (pars) { + if (pars->GetParameter("SpdCave/GeometryFileName",s)) { + cout << "-I- <SpdCave::GetGeometryFileName> set geometry from parameters: " << s << endl; + } + else { + s = "cave.geo"; + cout << "-W- <SpdCave::GetGeometryFileName> set default geometry: " << s << endl; + pars->SetParameter("SpdCave/GeometryFileName",s.Data()); // save default geometry + pars->setChanged(); + pars->setInputVersion(FairRun::Instance()->GetRunId(),1); + } + } + else { + s = "cave.geo"; + cout << "-W- <SpdCave::GetGeometryFileName> set default geometry (*): " << s << endl; + } + SetGeometryFileName(s); + } + + return fgeoName; +} +//_____________________________________________________________________________________ +Bool_t SpdCave::FillParsIn(SpdPassiveGeoParSet* params) +{ + if (!params) return kFALSE; + + FairGeoLoader* loader = FairGeoLoader::Instance(); + FairGeoInterface* GeoInterface = loader->getGeoInterface(); + + TString s = GeoInterface->getMedia()->getInputFile(); + if (s.Contains("/")) s.Remove(0,s.Last('/')+1); + + TString ss; + if (params->GetParameter("Global/MediaFileName",ss)) { + if (s != ss) { + cout << "-W- <SpdCave::FillParsIn> media file is changed: " + << ss << " -> " << s << endl; + } + } + else { + params->SetParameter("Global/MediaFileName",s.Data()); + } + + return kTRUE; +} + +//_____________________________________________________________________________________ +Bool_t SpdCave::LoadParsFrom(SpdPassiveGeoParSet* params) +{ + if (!params) return kFALSE; + + TString s; + if (!params->GetParameter("SpdCave/GeometryFileName",s)) { + cout << "-W- <SpdCave::LoadParsFrom> geometry is not defined: " << endl; + return kFALSE; + } + + SetGeometryFileName(s); + + cout << "-I- <SpdCave::LoadParsFrom> load geometry: " << fgeoName << endl; + + return kTRUE; +} + +//_____________________________________________________________________________________ +SpdPassiveGeoParSet* SpdCave::GetParameters() +{ + FairRun* run = FairRun::Instance(); + if (!run) return 0; + FairRuntimeDb* rtdb = run->GetRuntimeDb(); + if (!rtdb) return 0; + SpdPassiveGeoParSet* pars = (SpdPassiveGeoParSet*)(rtdb->getContainer("PassiveGeoParSet")); + return pars; +} diff --git a/passive/SpdCave.h b/passive/SpdCave.h index 3dcec1cd89bc8bd646a546bad801a179647110f4..7b303de709f75b6212e242a6c58d32aa1e80116c 100644 --- a/passive/SpdCave.h +++ b/passive/SpdCave.h @@ -3,6 +3,7 @@ #define __SPDCAVE_H__ #include "FairModule.h" +#include "SpdPassiveGeoParSet.h" ///////////////////////////////////////////////////////////////////////////////// // @@ -22,9 +23,18 @@ public: virtual ~SpdCave() {} virtual void ConstructGeometry(); + + virtual TString GetGeometryFileName(); + virtual void SetGeometryFileName(TString fname, TString geoVer = "0"); + SpdPassiveGeoParSet* GetParameters(); + TString GetActualGeometryFileName() const { return fgeoName; } + + Bool_t FillParsIn(SpdPassiveGeoParSet* params); + Bool_t LoadParsFrom(SpdPassiveGeoParSet* params); + private: - + ClassDef(SpdCave,1) }; diff --git a/passive/SpdGeoFrame.cxx b/passive/SpdGeoFrame.cxx index acc9fc9481a11d22c5cb05f6bdd76bc1e4c40368..fe244a6d1c94b738f3a744d1f1a560d70ca0dc9d 100644 --- a/passive/SpdGeoFrame.cxx +++ b/passive/SpdGeoFrame.cxx @@ -72,9 +72,9 @@ Double_t SpdGeoFrame::GetMass() const } //_____________________________________________________________________________________ -void SpdGeoFrame::UnsetMaterials(Bool_t precise) +void SpdGeoFrame::UnsetMaterials(TString media) { - + fUnsetMedia = media; } //_____________________________________________________________________________________ @@ -85,3 +85,18 @@ void SpdGeoFrame::Print(Option_t*) const cout <<"\n"; } +//_____________________________________________________________________________ +Bool_t SpdGeoFrame::FillParsIn(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::FillParsIn(params)) return kFALSE; + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdGeoFrame::LoadParsFrom(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::LoadParsFrom(params)) return kFALSE; + return kTRUE; +} + + diff --git a/passive/SpdGeoFrame.h b/passive/SpdGeoFrame.h index e2882a811d1dd82756a50c496ddcac15a9a542fc..ec6a8e9746363138401fb704d5dfea083234ca2c 100644 --- a/passive/SpdGeoFrame.h +++ b/passive/SpdGeoFrame.h @@ -30,9 +30,12 @@ public: virtual Double_t GetCapacity() const; // cm^3 virtual Double_t GetMass() const; // g - virtual void UnsetMaterials(Bool_t precise = kTRUE); + virtual void UnsetMaterials(TString media = "vacuum2"); virtual void Print(Option_t*) const; + + virtual Bool_t FillParsIn(SpdPassiveGeoParSet* params); + virtual Bool_t LoadParsFrom(SpdPassiveGeoParSet* params); private: diff --git a/passive/SpdHybMagnet.cxx b/passive/SpdHybMagnet.cxx index 082b516c5503963fe278d22e569f78656886b04a..55989fc18a4a4acd80aaeda7bb52577774d97598 100644 --- a/passive/SpdHybMagnet.cxx +++ b/passive/SpdHybMagnet.cxx @@ -8,6 +8,7 @@ #include "SpdHybMagnet.h" #include "SpdCommonGeoMapper.h" +#include "SpdPassiveGeoParSet.h" #include <TGeoManager.h> #include <TGeoTube.h> @@ -142,13 +143,16 @@ void SpdHybMagnet::ConstructGeometry() return; } - if (fGeoType == 1) fLockGeom = ConstructGeometry_1(); + if (fGeoType == 1) fLockGeom = ConstructGeometry_1(); else if (fGeoType == 2) fLockGeom = ConstructGeometry_2(); + else if (fGeoType == 3) fLockGeom = ConstructGeometry_2(); else { cout << "-E- <SpdHybMagnet::ConstructGeometry> " << " Unknown geometry type: " << fGeoType << endl; fGeoType = 0; } + + FillParsIn(GetParameters()); } //_____________________________________________________________________________ @@ -198,7 +202,7 @@ Bool_t SpdHybMagnet::ConstructGeometry_1() // private fRingCoil.counts_ = 4; - cout << "-I- <SpdHybMagnet::ConstructGeometry_1> "<< endl; + cout << "-I- <SpdHybMagnet::ConstructGeometry_1> Geometry type: " << fGeoType << endl; return kTRUE; } @@ -221,7 +225,7 @@ Bool_t SpdHybMagnet::ConstructGeometry_2() // private fRingCoil.counts_ = 6; - cout << "-I- <SpdHybMagnet::ConstructGeometry_2> "<< endl; + cout << "-I- <SpdHybMagnet::ConstructGeometry_2> Geometry type: " << fGeoType << endl; return kTRUE; } @@ -357,8 +361,9 @@ void SpdHybMagnet::SetGeometryType(Int_t type) SetGeoPars(0); return; } - else if (type == 1) SetGeoPars(1); - else if (type == 2) SetGeoPars(2); + else if (type == 1) SetGeoPars(type); + else if (type == 2) SetGeoPars(type); + else if (type == 3) SetGeoPars(type); else { cout << "-E- <SpdHybMagnet::SetGeometryType> " << " Unknown geometry type: " << type << endl; @@ -367,7 +372,7 @@ void SpdHybMagnet::SetGeometryType(Int_t type) } //_____________________________________________________________________________ -void SpdHybMagnet::UnsetMaterials(Bool_t precise) +void SpdHybMagnet::UnsetMaterials(TString media) { if (fLockGeom) { cout << "-E- <SpdHybMagnet::UnsetMaterials> " @@ -375,13 +380,20 @@ void SpdHybMagnet::UnsetMaterials(Bool_t precise) return; } - TString material; - - (precise) ? material = "vacuum2" : material = "vacuum"; + //cout << "-I- <SpdHybMagnet::UnsetMaterials> " << media << endl; + + fLoopCoil.base_material_ = media; + fLoopCoil.coil_material_ = media; + fRingCoil.coil_material_ = media; - fLoopCoil.base_material_ = material; - fLoopCoil.coil_material_ = material; - fRingCoil.coil_material_ = material; + fUnsetMedia = media; +} + +//_____________________________________________________________________________ +void SpdHybMagnet::ResetMaterials() +{ + if (fLockGeom) return; + SetDefaultMaterials(fGeoType); } //_____________________________________________________________________________ @@ -734,6 +746,7 @@ void SpdHybMagnet::Print(Option_t*) const cout << "\tGeometry type: " << fGeoType << endl; cout << "\tUnique module Id: " << fModuleId << endl; + cout << "\tUnset media: " << fUnsetMedia << endl; if (fGeoType < 1) { cout << endl; return; } @@ -801,7 +814,7 @@ void SpdHybMagnet::SetGeoPars(Int_t geotype) // private fRingCoilAxialDistanceL2 = 0; fRingCoilAxialDistanceC = 0; - if (geotype != 1 && geotype != 2) { + if (geotype < 1 && geotype > 3) { cout << "-I- <SpdHybMagnet::SetGeoPars> No geometry will be built " << endl; return; } @@ -860,9 +873,74 @@ void SpdHybMagnet::SetGeoPars(Int_t geotype) // private //fRingCoil.line_color_ = kBlue+3; //fRingCoil.transparency_ = 10; } + + else if (fGeoType == 3) { + + fRingCoil.coil_max_radius_ = SpdCommonGeoMapper::GetHybMagnetRingSize(); + fRingCoil.coil_width_ = SpdCommonGeoMapper::GetHybMagnetCoilWidth(); + fRingCoil.coil_thickness_ = SpdCommonGeoMapper::GetHybMagnetCoilThickness(); + + fRingCoilAxialDistanceC = SpdCommonGeoMapper::GetHybMagnetDistToAxis(); + fRingCoilAxialDistanceL1 = SpdCommonGeoMapper::GetHybMagnetDistToAxis1(); + fRingCoilAxialDistanceL2 = SpdCommonGeoMapper::GetHybMagnetDistToAxis2(); + + fRingCoil.coil_material_ = SpdCommonGeoMapper::GetHybMagnetCoilMaterial(); + + //fRingCoil.fill_color_ = kBlue+3; + //fRingCoil.line_color_ = kBlue+3; + //fRingCoil.transparency_ = 10; + } } +//_____________________________________________________________________________ +void SpdHybMagnet::SetDefaultMaterials(Int_t geotype) // private +{ + //cout <<"<SpdHybMagnet::SetDefaultMaterials> geometry type: " << geotype << endl; + + if (geotype != 1 && geotype != 2) { + cout << "-I- <SpdHybMagnet::DefaultMaterials> No geometry will be built " << endl; + return; + } + + if (geotype == 1) { + + fLoopCoil.base_material_ = "air"; + fLoopCoil.coil_material_ = SpdCommonGeoMapper::GetHybMagnetCoilMaterial(); + + //fLoopCoil.fill_color_ = kBlue+3; + //fLoopCoil.line_color_ = kBlue+3; + //fLoopCoil.transparency_ = 10; + + fRingCoil.coil_material_ = SpdCommonGeoMapper::GetHybMagnetCoilMaterial(); + + //fRingCoil.fill_color_ = kBlue+3; + //fRingCoil.line_color_ = kBlue+3; + //fRingCoil.transparency_ = 10; + } + + else if (fGeoType == 2) { + + fRingCoil.coil_material_ = SpdCommonGeoMapper::GetHybMagnetCoilMaterial(); + + //fRingCoil.fill_color_ = kBlue+3; + //fRingCoil.line_color_ = kBlue+3; + //fRingCoil.transparency_ = 10; + } +} +//_____________________________________________________________________________ +Bool_t SpdHybMagnet::FillParsIn(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::FillParsIn(params)) return kFALSE; + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdHybMagnet::LoadParsFrom(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::LoadParsFrom(params)) return kFALSE; + return kTRUE; +} diff --git a/passive/SpdHybMagnet.h b/passive/SpdHybMagnet.h index 8700fa93aec863403d1f678f3a22176679bee7ca..7904eee58e2341440a1c94b707c96d876bd42f9d 100644 --- a/passive/SpdHybMagnet.h +++ b/passive/SpdHybMagnet.h @@ -14,7 +14,6 @@ // // //////////////////////////////////////////////////////////////////////////////// - class SpdHybMagnet: public SpdPassiveModule { public: @@ -30,7 +29,8 @@ public: virtual void SetGeometryType(Int_t type); - virtual void UnsetMaterials(Bool_t precise = kTRUE); // (all coils) + virtual void UnsetMaterials(TString media = "vacuum2"); + virtual void ResetMaterials(/*set dafault materials*/); void SetCoilsMaterial(TString material); // (all coils) @@ -145,6 +145,9 @@ public: ClassDef(SpdHybMagnet::LoopCoil,1) }; + + virtual Bool_t FillParsIn(SpdPassiveGeoParSet* params); + virtual Bool_t LoadParsFrom(SpdPassiveGeoParSet* params); private: @@ -159,6 +162,7 @@ private: RingCoil fRingCoil; void SetGeoPars(Int_t geotype); + void SetDefaultMaterials(Int_t geotype); Bool_t ConstructGeometry_1(); Bool_t ConstructGeometry_2(); diff --git a/passive/SpdPassiveContFact.cxx b/passive/SpdPassiveContFact.cxx deleted file mode 100644 index afa2a4ab549a9f12aca7e07df845260eaaef3303..0000000000000000000000000000000000000000 --- a/passive/SpdPassiveContFact.cxx +++ /dev/null @@ -1,59 +0,0 @@ - -#include "SpdPassiveContFact.h" -#include "SpdPassiveGeoPar.h" -#include "FairRuntimeDb.h" - -ClassImp(SpdPassiveContFact) - -static SpdPassiveContFact gSpdPassiveContFact; - -//_____________________________________________________________________________ -SpdPassiveContFact::SpdPassiveContFact():FairContFact() -{ - fName = "SpdPassiveContFact"; - fTitle = "Factory for parameter containers in libSpdPassive"; - - setAllContainers(); - - FairRuntimeDb::instance()->addContFactory(this); -} - -//_____________________________________________________________________________ -FairParSet* SpdPassiveContFact::createContainer(FairContainer* c) -{ - /* - Calls the constructor of the corresponding parameter container. - For an actual context, which is not an empty string and not - the default context of this container, the name is concatenated - with the context. - */ - - const char* name = c->GetName(); - FairParSet* p = 0; - -// if (strcmp(name,"SpdPassiveGeoPar") == 0) { -// p = new SpdPassiveGeoPar(c->getConcatName().Data(), -// c->GetTitle(), -// c->getContext()); -// } - - return p; -} - -//_____________________________________________________________________________ -void SpdPassiveContFact::setAllContainers() -{ - /* - Creates the Container objects with all accepted - contexts and adds them to - the list of containers for the SpdPassive library. - */ - - FairContainer* p = new FairContainer("FairGeoPassivePar", - "SpdPassive Geometry Parameters", - "TestDefaultContext"); - p->addContext("TestNonDefaultContext"); - - containers->Add(p); -} - diff --git a/passive/SpdPassiveContFact.h b/passive/SpdPassiveContFact.h deleted file mode 100644 index ab0154543ef0901c545d4b1b81fd5c9309c95f56..0000000000000000000000000000000000000000 --- a/passive/SpdPassiveContFact.h +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef __SPDPASSIVECONTFACT_H__ -#define __SPDPASSIVECONTFACT_H__ - -#include "FairContFact.h" - -///////////////////////////////////////////////////////////////////////////////// -// // -// SpdPassiveContFact // -// // -// Factory for the parameter containers in library SpdPassive // -// // -///////////////////////////////////////////////////////////////////////////////// - -class FairParSet; - -class SpdPassiveContFact : public FairContFact { - -public: - - SpdPassiveContFact(); - ~SpdPassiveContFact() {} - - virtual FairParSet* createContainer(FairContainer*); - - ClassDef(SpdPassiveContFact,1) - -private: - - void setAllContainers(); - -}; - -#endif diff --git a/passive/SpdPipe.cxx b/passive/SpdPipe.cxx index b2864ad3a578dfa91e818f63be2f15d4bb04036a..a8e37d76071f3128fc4379308db62dd2c5c141f0 100644 --- a/passive/SpdPipe.cxx +++ b/passive/SpdPipe.cxx @@ -1,13 +1,13 @@ #include "SpdPipe.h" +#include "SpdCommonGeoMapper.h" +#include "SpdPassiveGeoParSet.h" #include <TGeoPcon.h> #include <TGeoCone.h> #include <TGeoManager.h> #include <TMath.h> -#include "SpdCommonGeoMapper.h" - #include <iostream> using std::cout; using std::endl; @@ -44,7 +44,7 @@ void SpdPipe::SetPipeType(TString type) //_____________________________________________________________________________________ void SpdPipe::ConstructGeometry() -{ +{ if (fGeoType < 1 || fGeoType > 4) return; if (fPipe) { @@ -85,6 +85,8 @@ void SpdPipe::ConstructGeometry() fMasterVolume->AddNode(fHybPipeLZplus,1); fMasterVolume->AddNode(fHybPipeISpace,1); } + + FillParsIn(GetParameters()); } //_____________________________________________________________________________________ @@ -250,20 +252,24 @@ void SpdPipe::SetPipeMaterial(TString material, Int_t n) } //_____________________________________________________________________________ -void SpdPipe::UnsetMaterials(Bool_t precise) +void SpdPipe::UnsetMaterials(TString media) { if (fPipe) return; - if (precise) { - fBaseMaterial = "vacuum2"; - fMaterial[0] = "vacuum2"; - fMaterial[1] = "vacuum2"; - } - else { - fBaseMaterial = "vacuum2"; - fMaterial[0] = "vacuum"; - fMaterial[1] = "vacuum"; - } + //cout << "-I- <SpdPipe::UnsetMaterials> " << media << endl; + + fBaseMaterial = media; + fMaterial[0] = media; + fMaterial[1] = media; + + fUnsetMedia = media; +} + +//_____________________________________________________________________________ +void SpdPipe::ResetMaterials() +{ + if (fPipe) return; + SetDefaultMaterials(fGeoType); } //_____________________________________________________________________________________ @@ -374,6 +380,25 @@ void SpdPipe::SetDefault(Int_t geotype) } } +//_____________________________________________________________________________________ +void SpdPipe::SetDefaultMaterials(Int_t geotype) +{ + //cout <<"<SpdPipe::SetDefaultMaterials> " << geotype << endl; + + fBaseMaterial = "vacuum"; + + if (geotype < 1 || geotype > 4) { + + fMaterial[0] = "vacuum2"; + fMaterial[1] = "vacuum2"; + + return; + } + + fMaterial[0] = SpdCommonGeoMapper::GetPipeMaterial1(); + fMaterial[1] = SpdCommonGeoMapper::GetPipeMaterial2(); +} + //_____________________________________________________________________________________ void SpdPipe::Print(Option_t*) const { @@ -382,6 +407,7 @@ void SpdPipe::Print(Option_t*) const cout <<"\n"; cout << "\tGeometry type: " << fPipeType << endl; cout << "\tUnique module Id: " << fModuleId << endl; + cout << "\tUnset media: " << fUnsetMedia << endl; if (fGeoType < 1) { cout << endl; return; } @@ -443,3 +469,17 @@ void SpdPipe::Print(Option_t*) const cout <<"\n"; } + +//_____________________________________________________________________________ +Bool_t SpdPipe::FillParsIn(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::FillParsIn(params)) return kFALSE; + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdPipe::LoadParsFrom(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::LoadParsFrom(params)) return kFALSE; + return kTRUE; +} diff --git a/passive/SpdPipe.h b/passive/SpdPipe.h index d969d90cbe7947fc250fc15bf2265c85558c99f8..c95e4d5845610d9b511dfad6f7f3bd396852cce7 100644 --- a/passive/SpdPipe.h +++ b/passive/SpdPipe.h @@ -35,7 +35,8 @@ public: void SetPipeMaterial(TString material, Int_t n = 0); - virtual void UnsetMaterials(Bool_t precise = kTRUE); + virtual void UnsetMaterials(TString media = "vacuum2"); + virtual void ResetMaterials(/*set dafault materials*/); /* ----- getters ------ */ @@ -63,17 +64,21 @@ public: virtual void Print(Option_t*) const; + virtual Bool_t FillParsIn(SpdPassiveGeoParSet* params); + virtual Bool_t LoadParsFrom(SpdPassiveGeoParSet* params); + protected: void SetDefault(Int_t geotype); + void SetDefaultMaterials(Int_t geotype); void BuildHybridPipe(); - - TString fPipeType; // pipe type - TString fPipeName; // pipe volume name - Double_t fR; // outer radius of the pipe [cm] - Double_t fThickness; // pipe thicknes [cm] - Double_t fHalfLength; // pipe half length [cm] + TString fPipeType; // pipe type + TString fPipeName; // pipe volume name + + Double_t fR; // outer radius of the pipe [cm] + Double_t fThickness; // pipe thicknes [cm] + Double_t fHalfLength; // pipe half length [cm] TString fBaseMaterial; // base pipe material TString fMaterial[2]; // pipe material @@ -82,10 +87,10 @@ protected: /* For "hybrid" geometry */ - TGeoVolume* fHybPipeC; // central part of the "hybrid" pipe - TGeoVolume* fHybPipeLZminus; // lateral(z-) part of the "hybrid" pipe - TGeoVolume* fHybPipeLZplus; // lateral(z+) part of the "hybrid" pipe - TGeoVolume* fHybPipeISpace; // inner space of the "hybrid" pipe + TGeoVolume* fHybPipeC; //! central part of the "hybrid" pipe + TGeoVolume* fHybPipeLZminus; //! lateral(z-) part of the "hybrid" pipe + TGeoVolume* fHybPipeLZplus; //! lateral(z+) part of the "hybrid" pipe + TGeoVolume* fHybPipeISpace; //! inner space of the "hybrid" pipe ClassDef(SpdPipe,1) diff --git a/passive/SpdSolMagnet.cxx b/passive/SpdSolMagnet.cxx index c891573d7290be68af34644cbb24babd20d05c2d..ca8c48fe433a6ee43ddb2358e7a7a7c8150ccc3c 100644 --- a/passive/SpdSolMagnet.cxx +++ b/passive/SpdSolMagnet.cxx @@ -154,11 +154,21 @@ Double_t SpdSolMagnet::GetCryoMass() const } //_____________________________________________________________________________ -void SpdSolMagnet::UnsetMaterials(Bool_t precise) +void SpdSolMagnet::UnsetMaterials(TString media) { if (fMagnetSection) return; - (precise) ? fBaseMaterial = "vacuum2" : fBaseMaterial = "vacuum"; - (precise) ? fCryoMaterial = "vacuum2" : fCryoMaterial = "vacuum"; + + fBaseMaterial = media; + fCryoMaterial = media; + + fUnsetMedia = media; +} + +//_____________________________________________________________________________ +void SpdSolMagnet::ResetMaterials() +{ + if (fMagnetSection) return; + SetDefaultMaterials(fGeoType); } //_____________________________________________________________________________ @@ -189,6 +199,8 @@ void SpdSolMagnet::ConstructGeometry() << " Unknown geometry type: " << fGeoType << endl; fGeoType = 0; } + + FillParsIn(GetParameters()); } //_____________________________________________________________________________ @@ -420,6 +432,46 @@ void SpdSolMagnet::SetGeoPars(Int_t geotype) } } +//_____________________________________________________________________________ +void SpdSolMagnet::SetDefaultMaterials(Int_t geotype) +{ + //cout <<"<SpdSolMagnet::SetDefaultMaterials> " << geotype << endl; + + if (geotype < 1 || geotype > 2) { + //cout << "-I- <SpdSolMagnet::SetDefaultMaterials> No geometry will be built" << endl; + + fBaseMaterial = "vacuum2"; + + fFillColor = 0; + fLineColor = 0; + fTransparency = 0; + + return; + } + + fBaseMaterial = SpdCommonGeoMapper::GetSolMagnetBaseMaterial(); + + if (fGeoType == 1) { + + fCryoMaterial = SpdCommonGeoMapper::GetSolMagnetCryoMaterial(); + + fFillColor = kRed+3; + fLineColor = kRed+3; + fTransparency = 50; + + return; + } + + if (fGeoType == 2) { + + fFillColor = kRed+3; + fLineColor = kRed+3; + fTransparency = 50; + + return; + } +} + //_____________________________________________________________________________ void SpdSolMagnet::Print(Option_t*) const { @@ -431,6 +483,7 @@ void SpdSolMagnet::Print(Option_t*) const cout << "\tGeometry type: " << fGeoType << endl; cout << "\tUnique module Id: " << fModuleId << endl; + cout << "\tUnset media: " << fUnsetMedia << endl; if (fGeoType < 1) { cout << endl; return; } @@ -452,7 +505,19 @@ void SpdSolMagnet::Print(Option_t*) const cout <<"\n"; } - + //_____________________________________________________________________________ +Bool_t SpdSolMagnet::FillParsIn(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::FillParsIn(params)) return kFALSE; + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdSolMagnet::LoadParsFrom(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::LoadParsFrom(params)) return kFALSE; + return kTRUE; +} diff --git a/passive/SpdSolMagnet.h b/passive/SpdSolMagnet.h index 7e0e11fdee4141b7ea9341bc0dfb607f4b283ea9..3f47119e3b9d8d7c459b9e2c278f2735cec6498d 100644 --- a/passive/SpdSolMagnet.h +++ b/passive/SpdSolMagnet.h @@ -32,7 +32,8 @@ public: void SetWidth(Double_t width /*cm*/); // width >= 1 cm void SetBaseMaterial(TString material); - virtual void UnsetMaterials(Bool_t precise = kTRUE); + virtual void UnsetMaterials(TString media = "vacuum2"); + virtual void ResetMaterials(/*set dafault materials*/); /* ----- getters ------ */ @@ -55,6 +56,9 @@ public: inline const TGeoVolume* GetSection() const { return fMagnetSection; } virtual void Print(Option_t*) const; + + virtual Bool_t FillParsIn(SpdPassiveGeoParSet* params); + virtual Bool_t LoadParsFrom(SpdPassiveGeoParSet* params); private: @@ -86,6 +90,7 @@ private: Int_t fTransparency; void SetGeoPars(Int_t geotype); + void SetDefaultMaterials(Int_t geotype); void ConstructGeometry_1(); void ConstructGeometry_2(); diff --git a/passive/SpdTorBasket.cxx b/passive/SpdTorBasket.cxx index 2342d52c87cfa9d351ce242a57e2fcf5d72fa7b7..b425e0a7f1dc21bdf58ebfd1c1e2eaef9375bd1c 100644 --- a/passive/SpdTorBasket.cxx +++ b/passive/SpdTorBasket.cxx @@ -79,6 +79,8 @@ void SpdTorBasket::ConstructGeometry() BuildSection(2, 2*fLeafBoxHalfZ); fLockGeom = kTRUE; + + FillParsIn(GetParameters()); } //_____________________________________________________________________________ @@ -152,7 +154,7 @@ Double_t SpdTorBasket::GetCasingWallDensity() const } //_____________________________________________________________________________________ -void SpdTorBasket::UnsetMaterials(Bool_t precise) +void SpdTorBasket::UnsetMaterials(TString media) { if (fLockGeom) { cout << "-E- <SpdTorBasket::UnsetMaterials> " @@ -160,14 +162,18 @@ void SpdTorBasket::UnsetMaterials(Bool_t precise) return; } - TString material; - - (precise) ? material = "vacuum2" : material = "vacuum"; + fLeafMaterial = media; + fCasingMaterial = media; - fLeafMaterial = material; - fCasingMaterial = material; + fUnsetMedia = media; } +//_____________________________________________________________________________ +void SpdTorBasket::ResetMaterials() +{ + if (fLockGeom) return; + SetDefaultMaterials(fGeoType); +} //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -348,6 +354,24 @@ void SpdTorBasket::SetGeoPars(Int_t geotype) // private fLeafBoxHalfZ = width/2.; } +//_____________________________________________________________________________ +void SpdTorBasket::SetDefaultMaterials(Int_t geotype) // private +{ + //cout <<"<SpdTorBasket::SetDefaultMaterials> " << geotype << endl; + + if (geotype != 1) return; + + if (SpdCommonGeoMapper::Instance()->GetTorMagnetDefGeoType() != 1) return; + + fBaseMaterial = SpdCommonGeoMapper::Instance()->GetTorBasketBaseMaterial(); + + //fLeafMaterial = fBaseMaterial; + //fCasingMaterial = fBaseMaterial; + + fLeafMaterial = SpdCommonGeoMapper::Instance()->GetTorBasketLeafMaterial(); + fCasingMaterial = SpdCommonGeoMapper::Instance()->GetTorBasketCasingMaterial(); +} + //_____________________________________________________________________________________ void SpdTorBasket::Print(Option_t*) const { @@ -359,6 +383,7 @@ void SpdTorBasket::Print(Option_t*) const cout << "\tGeometry type: " << fGeoType << endl; cout << "\tUnique module Id: " << fModuleId << endl; + cout << "\tUnset media: " << fUnsetMedia << endl; if (fGeoType < 1) { cout << endl; return; } @@ -395,3 +420,16 @@ void SpdTorBasket::Print(Option_t*) const cout << "\n"; } +//_____________________________________________________________________________ +Bool_t SpdTorBasket::FillParsIn(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::FillParsIn(params)) return kFALSE; + return kTRUE; +} + +//_____________________________________________________________________________ +Bool_t SpdTorBasket::LoadParsFrom(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::LoadParsFrom(params)) return kFALSE; + return kTRUE; +} diff --git a/passive/SpdTorBasket.h b/passive/SpdTorBasket.h index 3e2d7c3c10cafebb88639ee26bdce678f89f1369..61edb086d0bb2ac342a68e0049b454791a3df4c3 100644 --- a/passive/SpdTorBasket.h +++ b/passive/SpdTorBasket.h @@ -25,21 +25,25 @@ public: virtual void ConstructGeometry(); - virtual Bool_t IsGeometryLocked() const { return kFALSE; } + virtual Bool_t IsGeometryLocked() const { return fLockGeom; } virtual Double_t GetCapacity() const; // cm^3 virtual Double_t GetMass() const; // g - virtual void UnsetMaterials(Bool_t precise = kTRUE); + virtual void UnsetMaterials(TString media = "vacuum2"); + virtual void ResetMaterials(/*set dafault materials*/); virtual void Print(Option_t*) const; + + virtual Bool_t FillParsIn(SpdPassiveGeoParSet* params); + virtual Bool_t LoadParsFrom(SpdPassiveGeoParSet* params); private: Bool_t fLockGeom; //! if true, prevent geometry modifications - TGeoVolume* fLeafBox; - TGeoVolume* fCasingWall; + TGeoVolume* fLeafBox; //! + TGeoVolume* fCasingWall; //! TString fBaseMaterial; TString fLeafMaterial; @@ -70,6 +74,7 @@ private: Bool_t BuildCasingWall(); void SetGeoPars(Int_t geotype); + void SetDefaultMaterials(Int_t geotype); TGeoVolume* BuildArb(TString volname, TString matname, Double_t HalfLen, Double_t Hmin, Double_t Hmax, diff --git a/passive/SpdTorMagnet.cxx b/passive/SpdTorMagnet.cxx index 0b4fa8b310fd1ebc27c3f7b2f29dfd61cdab3e51..4f62ae69a9b3ce9a3febacba307ea032a08a434f 100644 --- a/passive/SpdTorMagnet.cxx +++ b/passive/SpdTorMagnet.cxx @@ -116,6 +116,8 @@ void SpdTorMagnet::ConstructGeometry() << " Unknown geometry type: " << fGeoType << endl; fGeoType = 0; } + + FillParsIn(GetParameters()); } //_____________________________________________________________________________ @@ -560,7 +562,7 @@ void SpdTorMagnet::PurseCoilsAlongZ(Double_t dz /*cm*/) } //_____________________________________________________________________________ -void SpdTorMagnet::UnsetMaterials(Bool_t precise) +void SpdTorMagnet::UnsetMaterials(TString media) { if (fLockGeom) { cout << "-E- <SpdTorMagnet::UnsetMaterials> " @@ -568,14 +570,19 @@ void SpdTorMagnet::UnsetMaterials(Bool_t precise) return; } - TString material; - - (precise) ? material = "vacuum2" : material = "vacuum"; - for (int i(0); i<SPD_TORMAGNET_NDCOILS; i++) { - fCoil[i].base_material_ = material; - fCoil[i].coil_material_ = material; + fCoil[i].base_material_ = media; + fCoil[i].coil_material_ = media; } + + fUnsetMedia = media; +} + +//_____________________________________________________________________________ +void SpdTorMagnet::ResetMaterials() +{ + if (fLockGeom) return; + SetDefaultMaterials(fGeoType); } //_____________________________________________________________________________ @@ -613,6 +620,7 @@ void SpdTorMagnet::Print(Option_t*) const cout << "\tGeometry type: " << fGeoType << endl; cout << "\tUnique module Id: " << fModuleId << endl; + cout << "\tUnset media: " << fUnsetMedia << endl; if (fGeoType < 1) { cout << endl; return; } @@ -725,7 +733,52 @@ void SpdTorMagnet::SetGeoPars(Int_t geotype) // private //fCoil[2].transparency_ = 10; } +//_____________________________________________________________________________ +void SpdTorMagnet::SetDefaultMaterials(Int_t geotype) // private +{ + //cout <<"<SpdTorMagnet::SetDefaultMaterials> " << geotype << endl; + + if (geotype < 1 || geotype > 2) return; + + fCoil[0].base_material_ = "air"; + fCoil[0].coil_material_ = SpdCommonGeoMapper::GetTorMagnetCoilMaterial(); + + //fCoil[0].fill_color_ = kBlue+3; + //fCoil[0].line_color_ = kBlue+3; + //fCoil[0].transparency_ = 10; + + //------------------------------------ + + fCoil[1].base_material_ = "air"; + fCoil[1].coil_material_ = SpdCommonGeoMapper::GetTorMagnetCoilMaterial(); + + //fCoil[1].fill_color_ = kBlue+3; + //fCoil[1].line_color_ = kBlue+3; + //fCoil[1].transparency_ = 10; + + //------------------------------------ + + fCoil[2].base_material_ = "air"; + fCoil[2].coil_material_ = SpdCommonGeoMapper::GetTorMagnetCoilMaterial(); + + //fCoil[2].fill_color_ = kBlue+3; + //fCoil[2].line_color_ = kBlue+3; + //fCoil[2].transparency_ = 10; +} + +//_____________________________________________________________________________ +Bool_t SpdTorMagnet::FillParsIn(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::FillParsIn(params)) return kFALSE; + return kTRUE; +} +//_____________________________________________________________________________ +Bool_t SpdTorMagnet::LoadParsFrom(SpdPassiveGeoParSet* params) +{ + if (!SpdPassiveModule::LoadParsFrom(params)) return kFALSE; + return kTRUE; +} diff --git a/passive/SpdTorMagnet.h b/passive/SpdTorMagnet.h index cc8f2642e5f4ca50c15a86efdfe7f29b4b866a34..6af1ba17ed0090cac264847f3983669d282469ec 100644 --- a/passive/SpdTorMagnet.h +++ b/passive/SpdTorMagnet.h @@ -42,13 +42,14 @@ public: void StretchCoilsAlongR(Double_t dr /*cm*/); // dr: > or < 0; new R_size >= width + ROUNDING void PurseCoilsAlongZ(Double_t dz /*cm*/); // dz -> |dz|; new Z_size >= width + ROUNDING - virtual void UnsetMaterials(Bool_t precise = kTRUE); + virtual void UnsetMaterials(TString media = "vacuum2"); + virtual void ResetMaterials(/*set dafault materials*/); /* ----- getters ------ */ - virtual Bool_t IsGeometryLocked() const { return fLockGeom; } + virtual Bool_t IsGeometryLocked() const { return fLockGeom; } - inline Double_t GetAxialDistance() const { return fAxialDistance; } + inline Double_t GetAxialDistance() const { return fAxialDistance; } virtual Double_t GetCapacity() const; // cm^3 virtual Double_t GetMass() const; // g @@ -70,6 +71,9 @@ public: virtual void Print(Option_t*) const; + virtual Bool_t FillParsIn(SpdPassiveGeoParSet* params); + virtual Bool_t LoadParsFrom(SpdPassiveGeoParSet* params); + //______________________________________________________________// struct tmcoil_ : public TObject { @@ -115,6 +119,7 @@ private: tmcoil_ fCoil[SPD_TORMAGNET_NDCOILS]; void SetGeoPars(Int_t geotype); + void SetDefaultMaterials(Int_t geotype); Bool_t ConstructGeometry_1(); Bool_t ConstructGeometry_2(); diff --git a/proc/CMakeLists.txt b/proc/CMakeLists.txt index 274560ec0c1ebb5d73ca296f2ee29cad626c61cd..d07ffe2054b11482e85285df4eb8a4bfdb422291 100644 --- a/proc/CMakeLists.txt +++ b/proc/CMakeLists.txt @@ -8,6 +8,4 @@ ELSE() MESSAGE(STATUS "PROC: the \"Tracking\" dictionary could not be built; \"GenFit2\" is required") ENDIF() - - - +add_subdirectory (vertex) diff --git a/proc/clustering/CMakeLists.txt b/proc/clustering/CMakeLists.txt index 619592f5ac41ba9864aa095f78475aaf41bfc365..819375af75047a204747cdacab6a38942d93ed03 100644 --- a/proc/clustering/CMakeLists.txt +++ b/proc/clustering/CMakeLists.txt @@ -29,6 +29,13 @@ ClusterCollection.cxx ClManager.cxx ) +set(HEADERS +ClManager.h +ClusterCollection.h +ClusterElement.h +Cluster.h +) + Set(LINKDEF ClusterLinkDef.h) Set(LIBRARY_NAME Clustering) Set(DEPENDENCIES Base) diff --git a/proc/tracking/CMakeLists.txt b/proc/tracking/CMakeLists.txt index d52505f775950b82552b43b921ac840400c4a2a3..87bddc06f1d86245327e304a7d0672e85a637c30 100644 --- a/proc/tracking/CMakeLists.txt +++ b/proc/tracking/CMakeLists.txt @@ -45,6 +45,13 @@ SpdGFMeasurementCreator.cxx SpdKalmanFitterRefTrack.cxx ) +set(HEADERS +SpdGFMagneticField.h +SpdGFMeasurementCreator.h +SpdGFTrackW.h +SpdKalmanFitterRefTrack.h +) + Set(LINKDEF TrackingGFLinkDef.h) Set(LIBRARY_NAME TrackingGF) Set(DEPENDENCIES Base GenFit2 SpdData SpdField SpdCommon SpdGeometry) diff --git a/proc/tracking/SpdGFMeasurementCreator.cxx b/proc/tracking/SpdGFMeasurementCreator.cxx index 5a0c307375d4d337f436744ddbc42c07e6cd4881..b391acd42b479a8b7b88aff8e177a44a098fbbc6 100644 --- a/proc/tracking/SpdGFMeasurementCreator.cxx +++ b/proc/tracking/SpdGFMeasurementCreator.cxx @@ -7,8 +7,8 @@ // SpdGFMeasurementCreator //_____________________________________________________________________________ -#include "SpdGFMeasurementCreator.h" #include "GFmeasurements.h" +#include "SpdGFMeasurementCreator.h" #include <TRandom.h> #include <TMath.h> @@ -24,9 +24,12 @@ ClassImp(SpdGFMeasurementCreator) //_____________________________________________________________________________ SpdGFMeasurementCreator::SpdGFMeasurementCreator():fMeasurementCounter_(0), -fResolution_(0.01),fResolutionWire_(0.1) -{ - +fForcePointHitResolution(false),fForceWireHitResolution(false), +fUseMCPointAsPointHit(false),fUseMCPointAsWireHit(false), +fSmearPointHitResolution(false),fSmearWireHitResolution(false) +{ + SetPointHitResolutionXYZ(0.005,0.005,0.005); // -> 50 mkm + SetWireHitResolutionRZ(0.005,0.005); // -> 50 mkm } //_____________________________________________________________________________ @@ -35,52 +38,415 @@ SpdGFMeasurementCreator::~SpdGFMeasurementCreator() } +//_____________________________________________________________________________ +void SpdGFMeasurementCreator::ResetOptions() +{ + fForcePointHitResolution = false; + fForceWireHitResolution = false; + fUseMCPointAsPointHit = false; + fUseMCPointAsWireHit = false; + fSmearPointHitResolution = false; + fSmearWireHitResolution = false; +} + //_____________________________________________________________________________ std::vector<genfit::AbsMeasurement*> SpdGFMeasurementCreator::CreateHit(SpdIdealHit* hit, GFMeasurementType mtype) { - SpdIdealSpacepointHit* shit = dynamic_cast<SpdIdealSpacepointHit*>(hit); - if (shit) return CreateHit(shit,mtype); + SpdIdealSpacepointHit* sphit = dynamic_cast<SpdIdealSpacepointHit*>(hit); + if (sphit) return CreateHit(sphit,mtype); - SpdIdealWirepointHit* whit = dynamic_cast<SpdIdealWirepointHit*>(hit); - if (whit) return CreateHit(whit,mtype); + SpdIdealWirepointHit* wphit = dynamic_cast<SpdIdealWirepointHit*>(hit); + if (wphit) return CreateHit(wphit,mtype); - return CreateSpacepointHit(hit->GetPoint()); + return CreateSpacepointHit(hit->GetPoint(),hit->GetResolution()); } //_____________________________________________________________________________ std::vector<genfit::AbsMeasurement*> SpdGFMeasurementCreator::CreateHit(SpdIdealSpacepointHit* hit, GFMeasurementType mtype) { - return CreateSpacepointHit(hit->GetPoint()); + if (mtype == pkPixel) return CreatePixelHit(hit); + if (mtype == pkSpacepoint) return CreateSpacepointHitP(hit); + + // default + return CreatePixelHit(hit); } //_____________________________________________________________________________ std::vector<genfit::AbsMeasurement*> SpdGFMeasurementCreator::CreateHit(SpdIdealWirepointHit* hit, GFMeasurementType mtype) { - return CreateSpacepointHit(hit->GetPoint()); + if (mtype == pkWire) return CreateWireHit(hit); + if (mtype == pkWirePoint) return CreateWirePointHit(hit); + if (mtype == pkSpacepoint) return CreateSpacepointHitW(hit); + + // default + return CreateWireHit(hit); } //_____________________________________________________________________________ -std::vector<AbsMeasurement*> SpdGFMeasurementCreator::CreateSpacepointHit(TVector3 point) // private +std::vector<AbsMeasurement*> SpdGFMeasurementCreator::CreateSpacepointHit(TVector3 point, TVector3 res, Char_t spec) { - std::vector<AbsMeasurement*> retVal; + std::vector<AbsMeasurement*> mm; - //cout << "-I- <SpdGFMeasurementCreator::CreateSpacepointHit> create SpacepointHit" << endl; + //cout << "-I- <SpdGFMeasurementCreator::CreateSpacepointHit> " << endl; + //cout << "\t specifity: " << spec << " resolution: " << res.X() << " " << res.Y() << " " << res.Z() << endl; TVectorD hitCoords(3); - hitCoords(0) = gRandom->Gaus(point.X(),fResolution_); - hitCoords(1) = gRandom->Gaus(point.Y(),fResolution_); - hitCoords(2) = gRandom->Gaus(point.Z(),fResolution_); + if (spec == 'n' || spec == 'p' || fSmearPointHitResolution) { + hitCoords(0) = gRandom->Gaus(point.X(),res.X()); + hitCoords(1) = gRandom->Gaus(point.Y(),res.Y()); + hitCoords(2) = gRandom->Gaus(point.Z(),res.Z()); + } + else { + hitCoords(0) = point.X(); + hitCoords(1) = point.Y(); + hitCoords(2) = point.Z(); + } + + TMatrixDSym hitCov(3); + + hitCov(0,0) = res.X()*res.X(); + hitCov(1,1) = res.Y()*res.Y(); + hitCov(2,2) = res.Z()*res.Z(); + + AbsMeasurement* measurement = new SpacepointMeasurement(hitCoords, hitCov, pkSpacepoint, + fMeasurementCounter_, nullptr); + mm.push_back(measurement); + + return mm; +} + +//_____________________________________________________________________________ +std::vector<AbsMeasurement*> SpdGFMeasurementCreator::CreateSpacepointHitP(SpdIdealSpacepointHit* hit) +{ + std::vector<AbsMeasurement*> mm; + + //cout << "-I- <SpdGFMeasurementCreator::CreateSpacepointHitP> " << endl; + + TVector3 pos; + if (fUseMCPointAsPointHit) hit->GetPoint(pos); + else hit->GetHit(pos); + + TVector3 res; + if (fForcePointHitResolution) res = fPointHitResolution; + else res = hit->GetResolution(); + + Char_t spec = hit->GetSpecifity(); + + //cout << "\t specifity: " << spec + // << " position: " << pos.X() << " " << pos.Y() << " " << pos.Z() + // << " resolution: " << res.X() << " " << res.Y() << " " << res.Z() << endl; + TVectorD hitCoords(3); + + if (spec == 'n' || spec == 'p' || fSmearPointHitResolution) { + hitCoords(0) = gRandom->Gaus(pos.X(),res.X()); + hitCoords(1) = gRandom->Gaus(pos.Y(),res.Y()); + hitCoords(2) = gRandom->Gaus(pos.Z(),res.Z()); + } + else { + hitCoords(0) = pos.X(); + hitCoords(1) = pos.Y(); + hitCoords(2) = pos.Z(); + } + TMatrixDSym hitCov(3); - hitCov(0,0) = fResolution_*fResolution_; - hitCov(1,1) = fResolution_*fResolution_; - hitCov(2,2) = fResolution_*fResolution_; + hitCov(0,0) = res.X()*res.X(); + hitCov(1,1) = res.Y()*res.Y(); + hitCov(2,2) = res.Z()*res.Z(); AbsMeasurement* measurement = new SpacepointMeasurement(hitCoords, hitCov, pkSpacepoint, fMeasurementCounter_, nullptr); - retVal.push_back(measurement); + mm.push_back(measurement); + + return mm; +} + +//_____________________________________________________________________________ +std::vector<AbsMeasurement*> SpdGFMeasurementCreator::CreateSpacepointHitW(SpdIdealWirepointHit* hit) +{ + std::vector<AbsMeasurement*> mm; + + //cout << "-I- <SpdGFMeasurementCreator::CreateSpacepointHitW> " << endl; + + TVector3 pos; + if (fUseMCPointAsPointHit) hit->GetPoint(pos); + else hit->GetHit(pos); + + TVector3 res; + if (fForcePointHitResolution) res = fPointHitResolution; + else res = hit->GetResolution(); + + Char_t spec = hit->GetSpecifity(); + + //cout << "\t specifity: " << spec + // << " position: " << pos.X() << " " << pos.Y() << " " << pos.Z() + // << " resolution: " << res.X() << " " << res.Y() << " " << res.Z() << endl; + + TVectorD hitCoords(3); + + if (spec == 'n' || spec == 'p' || fSmearPointHitResolution) { + hitCoords(0) = gRandom->Gaus(pos.X(),res.X()); + hitCoords(1) = gRandom->Gaus(pos.Y(),res.Y()); + hitCoords(2) = gRandom->Gaus(pos.Z(),res.Z()); + } + else { + hitCoords(0) = pos.X(); + hitCoords(1) = pos.Y(); + hitCoords(2) = pos.Z(); + } + + TMatrixDSym hitCov(3); + + hitCov(0,0) = res.X()*res.X(); + hitCov(1,1) = res.Y()*res.Y(); + hitCov(2,2) = res.Z()*res.Z(); + + AbsMeasurement* measurement = new SpacepointMeasurement(hitCoords, hitCov, pkSpacepoint, + fMeasurementCounter_, nullptr); + mm.push_back(measurement); + + return mm; +} + +//_____________________________________________________________________________ +std::vector<genfit::AbsMeasurement*> SpdGFMeasurementCreator::CreatePixelHit(SpdIdealSpacepointHit* hit) +{ + std::vector<AbsMeasurement*> mm; + + //cout << "-I- <SpdGFMeasurementCreator::CreatePixelHit> " << endl; + + Char_t spec = hit->GetSpecifity(); + + if (spec != 'p' && spec != 'm' && spec != 's') { + cout << "<SpdGFMeasurementCreator::CreatePixelHit> Unexpected hit specifity: '" << spec + << "' , create point-like hit " << endl; + return CreateSpacepointHit(hit->GetHit(),hit->GetResolution(),spec); + } + + Double_t pos[2]; + if (fUseMCPointAsPointHit) { pos[0] = hit->GetPointU(); pos[1] = hit->GetPointV(); } + else { pos[0] = hit->GetHitU(); pos[1] = hit->GetHitV(); } + + Double_t res[2]; + if (fForcePointHitResolution) { res[0] = fPointHitResolution.X(); res[1] = fPointHitResolution.Y(); } + else { res[0] = hit->GetResolutionU(); res[1] = hit->GetResolutionV(); } + + //cout << "\t specifity: " << spec << " detector: " << hit->GetDetId() + // << " resolution (U,V): " << res.X() << " " << res.Y() + // << " [U, V, N]: " << pos.X() << " " << pos.Y() << " " << pos.Z() << endl; + + //hit->PrintHit(); + + TVectorD hitCoords(2); + + if (fSmearPointHitResolution) { + hitCoords(0) = gRandom->Gaus(pos[0],res[0]); + hitCoords(1) = gRandom->Gaus(pos[1],res[1]); + } + else { + hitCoords(0) = pos[0]; + hitCoords(1) = pos[1]; + } + + TMatrixDSym hitCov(2); + + hitCov(0,0) = res[0]*res[0]; + hitCov(1,1) = res[1]*res[1]; - return retVal; + PlanarMeasurement* measurement = new PlanarMeasurement(hitCoords, hitCov, hit->GetDetId(), fMeasurementCounter_, nullptr); + + SharedPlanePtr plane(new DetPlane(hit->GetDetPos(),hit->GetU(),hit->GetV())); + + measurement->setPlane(plane, fMeasurementCounter_); + + mm.push_back(measurement); + + return mm; } + +//_____________________________________________________________________________ +std::vector<genfit::AbsMeasurement*> SpdGFMeasurementCreator::CreateWireHit(SpdIdealWirepointHit* hit) +{ + std::vector<AbsMeasurement*> mm; + + //cout << "-I- <SpdGFMeasurementCreator::CreateWireHit> " << endl; + + Char_t spec = hit->GetSpecifity(); + + if (spec != 'w') { + cout << "<SpdGFMeasurementCreator::CreateWireHit> Unexpected hit specifity: '" << spec + << "' , create point-like hit " << endl; + return CreateSpacepointHit(hit->GetHit(),hit->GetResolution(),spec); + } + + Double_t rdrift; + if (fUseMCPointAsWireHit) rdrift = hit->GetPointRdrift(); + else rdrift = hit->GetRdrift(); + + Double_t res; + if (fForceWireHitResolution) res = fWireHitResolution.X(); + else res = hit->GetResolutionR(); + + //cout << "\t specifity: " << spec << " detector: " << hit->GetDetId() + // << " resolution (R): " << res << " [R]: " << rdrift << endl; + + TVector3 wirepoint; + + TVectorD hitCoords(7); + + wirepoint = hit->GetWirePoint1(); + + hitCoords(0) = wirepoint.X(); + hitCoords(1) = wirepoint.Y(); + hitCoords(2) = wirepoint.Z(); + + wirepoint = hit->GetWirePoint2(); + + hitCoords(3) = wirepoint.X(); + hitCoords(4) = wirepoint.Y(); + hitCoords(5) = wirepoint.Z(); + + Double_t rmax = hit->GetWireMaxRadius(); + + if (fSmearWireHitResolution) + { + static Double_t ktol = 0.99999; + + if (res < rmax/TMath::Sqrt(12)) { + hitCoords(6) = rdrift + gRandom->Gaus(0,res); + if (hitCoords(6) < 0) hitCoords(6) = 0; + else if (!(hitCoords(6) < rmax)) hitCoords(6) = ktol*rmax; + } + else hitCoords(6) = gRandom->Uniform(0,ktol*rmax); + } + else hitCoords(6) = rdrift; + + TMatrixDSym hitCov(7); + + hitCov(6,6) = res*res; + + WireMeasurement* measurement = new WireMeasurement(hitCoords, hitCov, hit->GetDetId(), fMeasurementCounter_, nullptr); + + measurement->setMaxDistance(rmax); + //measurement->setLeftRightResolution(hit->GetLRtype()); + + mm.push_back(measurement); + + return mm; +} + +//_____________________________________________________________________________ +std::vector<genfit::AbsMeasurement*> SpdGFMeasurementCreator::CreateWirePointHit(SpdIdealWirepointHit* hit) +{ + std::vector<AbsMeasurement*> mm; + + //cout << "-I- <SpdGFMeasurementCreator::CreateWirePointHit> " << endl; + + Char_t spec = hit->GetSpecifity(); + + if (spec != 'w') { + cout << "<SpdGFMeasurementCreator::CreateWirePointHit> Unexpected hit specifity: '" << spec + << "' , create point-like hit " << endl; + return CreateSpacepointHit(hit->GetHit(),hit->GetResolution(),spec); + } + + Double_t rdrift, zwire; + if (fUseMCPointAsWireHit) { rdrift = hit->GetPointRdrift(); zwire = hit->GetPointZwire(); } + else { rdrift = hit->GetRdrift(); zwire = hit->GetPointZwire(); } + + Double_t resR, resZ; + if (fForceWireHitResolution) { resR = fWireHitResolution.X(); resZ = fWireHitResolution.Y(); } + else { resR = hit->GetResolutionR(); resR = hit->GetResolutionZ(); } + + //cout << "\t specifity: " << spec << " detector: " << hit->GetDetId() + // << " resolution (R,Z): " << resR << " " << resZ + // << "\t [R, Z]: " << rdrift << " " << zwire << " Wire length: " << hit->GetWireLength() << endl; + + TVectorD hitCoords(8); + + TVector3 wirepoint; + + wirepoint = hit->GetWirePoint1(); + + hitCoords(0) = wirepoint.X(); + hitCoords(1) = wirepoint.Y(); + hitCoords(2) = wirepoint.Z(); + + wirepoint = hit->GetWirePoint2(); + + hitCoords(3) = wirepoint.X(); + hitCoords(4) = wirepoint.Y(); + hitCoords(5) = wirepoint.Z(); + + Double_t rmax = hit->GetWireMaxRadius(); + Double_t zmax = hit->GetWireLength(); + + if (fSmearWireHitResolution) + { + static Double_t ktol = 0.99999; + + if (resR < rmax/TMath::Sqrt(12)) { + hitCoords(6) = rdrift + gRandom->Gaus(0,resR); + if (hitCoords(6) < 0) hitCoords(6) = 0; + else if (!(hitCoords(6) < rmax)) hitCoords(6) = ktol*rmax; + } + else hitCoords(6) = gRandom->Uniform(0,ktol*rmax); + + if (resZ < zmax/TMath::Sqrt(12)) { + hitCoords(7) = zwire + gRandom->Gaus(0,resZ); + if (hitCoords(7) < 0) hitCoords(7) = 0; + else if (!(hitCoords(7) < zmax)) hitCoords(7) = ktol*zmax; + } + else hitCoords(7) = gRandom->Uniform(0,ktol*zmax); + } + else { + hitCoords(6) = rdrift; + hitCoords(7) = zwire; + } + + TMatrixDSym hitCov(8); + + hitCov(6,6) = resR*resR; + hitCov(7,7) = resZ*resZ; + + WirePointMeasurement* measurement = new WirePointMeasurement(hitCoords, hitCov, hit->GetDetId(), fMeasurementCounter_, nullptr); + + measurement->setMaxDistance(rmax); + //measurement->setLeftRightResolution(hit->GetLRtype()); + + mm.push_back(measurement); + + return mm; +} + +// //_____________________________________________________________________________ +// std::vector<genfit::AbsMeasurement*> SpdGFMeasurementCreator::CreateWireHit2(SpdIdealWirepointHit* hit) +// { +// std::vector<AbsMeasurement*> mm; +// +// Char_t spec = hit->GetSpecifity(); +// +// if (spec != 'w') { +// cout << "<SpdGFMeasurementCreator::CreateWireHit2> Unexpected hit specifity: '" << spec +// << "' , create point-like hit " << endl; +// return CreateSpacepointHit(hit->GetHit(),hit->GetResolution(),spec); +// } +// +// // cout << "\t specifity: " << spec << " detector: " << hit->GetDetId() +// // << " resolution (R): " << hit->GetResolutionR() +// // << " [R]: " << hit->GetRdrift() << endl; +// +// WireMeasurementNew* measurement = new WireMeasurementNew(hit->GetRdrift(),hit->GetResolutionR(), +// hit->GetWirePoint1(),hit->GetWirePoint2(), +// hit->GetDetId(), fMeasurementCounter_, nullptr); +// +// measurement->setMaxDistance(hit->GetWireMaxRadius()); +// //measurement->setLeftRightResolution(hit->GetLRtype()); +// +// mm.push_back(measurement); +// +// return mm; +// } + diff --git a/proc/tracking/SpdGFMeasurementCreator.h b/proc/tracking/SpdGFMeasurementCreator.h index 0bef6dbd2437eb418afd60220a03375d16bb21df..b6d5613fd1f70386b9bcbba832d87dad5ddf55ac 100644 --- a/proc/tracking/SpdGFMeasurementCreator.h +++ b/proc/tracking/SpdGFMeasurementCreator.h @@ -42,21 +42,64 @@ public: std::vector<genfit::AbsMeasurement*> CreateHit(SpdIdealHit* hit, GFMeasurementType mtype = pkSpacepoint); std::vector<genfit::AbsMeasurement*> CreateHit(SpdIdealSpacepointHit* hit, GFMeasurementType mtype = pkSpacepoint); std::vector<genfit::AbsMeasurement*> CreateHit(SpdIdealWirepointHit* hit, GFMeasurementType mtype = pkSpacepoint); - - void SetResolution(double res) { fResolution_ = res; } - void SetResolutionWire(double res) { fResolutionWire_ = res; } + + inline void SetPointHitResolutionXYZ(Double_t rx /*cm*/, Double_t ry /*cm*/, Double_t rz /*cm*/); + inline void SetWireHitResolutionRZ(Double_t rr /*cm*/, Double_t rz = -1/*cm*/); + + inline void ForcePointHitResolution() { fForcePointHitResolution = true; } + inline void ForceWireHitResolution() { fForceWireHitResolution = true; } + + inline void UseMCPointAsPointHit(Bool_t smear = false) { fUseMCPointAsPointHit = true; fSmearPointHitResolution = smear; } + inline void UseMCPointAsWireHit(Bool_t smear = false) { fUseMCPointAsWireHit = true; fSmearWireHitResolution = smear; } + + void ResetOptions(); private: - std::vector<genfit::AbsMeasurement*> CreateSpacepointHit(TVector3 pos); + std::vector<genfit::AbsMeasurement*> CreateSpacepointHit(TVector3 pos, TVector3 res, Char_t spec = 'n'); + + std::vector<genfit::AbsMeasurement*> CreateSpacepointHitP(SpdIdealSpacepointHit* hit); + std::vector<genfit::AbsMeasurement*> CreateSpacepointHitW(SpdIdealWirepointHit* hit); + + std::vector<genfit::AbsMeasurement*> CreatePixelHit(SpdIdealSpacepointHit* hit); + std::vector<genfit::AbsMeasurement*> CreateWireHit(SpdIdealWirepointHit* hit); + std::vector<genfit::AbsMeasurement*> CreateWirePointHit(SpdIdealWirepointHit* hit); + //std::vector<genfit::AbsMeasurement*> CreateWireHit2(SpdIdealWirepointHit* hit); + Int_t fMeasurementCounter_; - Double_t fResolution_; // cm; resolution of generated measurements - Double_t fResolutionWire_; // cm; resolution in wire direction (wire and prolate spacepoint measurements) - + TVector3 fPointHitResolution; + TVector3 fWireHitResolution; + + Bool_t fForcePointHitResolution; + Bool_t fForceWireHitResolution; + + Bool_t fUseMCPointAsPointHit; + Bool_t fUseMCPointAsWireHit; + + Bool_t fSmearPointHitResolution; + Bool_t fSmearWireHitResolution; + ClassDef(SpdGFMeasurementCreator,1) }; +void SpdGFMeasurementCreator::SetPointHitResolutionXYZ(Double_t rx, Double_t ry, Double_t rz) +{ + // set resolution for x(u), y(v), z: pkPixel -> (x=u,y=v); pkSpacepoint -> (x,y,z) + // for example r(x,y,z) = 0.005 = 50*1e-4 = 50 mkm + + fPointHitResolution.SetXYZ(rx,ry,rz); +} + +void SpdGFMeasurementCreator::SetWireHitResolutionRZ(Double_t rr, Double_t rz) +{ + // set resolution for r,z: pkWire -> (r); pkWirePoint -> (r,z) + // for example r(x,y,z) = 0.005 = 50*1e-4 = 50 mkm + + if (rz < 0) rz = rr; + fWireHitResolution.SetXYZ(rr,rz,0.); +} + #endif /* __SPDGFMEASUREMENTCREATOR_H__ */ diff --git a/proc/tracking/SpdGFTrackW.h b/proc/tracking/SpdGFTrackW.h index 4ee9d49c690c1af40a856d25c06124188576c866..9ac33d59ae06086c23d4d764d7d320ab392adf96 100644 --- a/proc/tracking/SpdGFTrackW.h +++ b/proc/tracking/SpdGFTrackW.h @@ -34,7 +34,7 @@ public: void SetDataID(Int_t id) { fDataID = id; } genfit::Track* GetTrack() { return fTrackGF; } - Int_t GetDataID() const { return fDataID;} + Int_t GetDataID() const { return fDataID; } genfit::Track* ReplaceTrack(genfit::Track* track); diff --git a/proc/tracking/SpdKalmanFitterRefTrack.cxx b/proc/tracking/SpdKalmanFitterRefTrack.cxx index a8193a6a07bf2a2114f7e7ba932208e60748b139..c3f4dde0ad86b5f8be7192d2347d8ce89426c777 100644 --- a/proc/tracking/SpdKalmanFitterRefTrack.cxx +++ b/proc/tracking/SpdKalmanFitterRefTrack.cxx @@ -251,7 +251,7 @@ void SpdKalmanFitterRefTrack::processTrackWithRep(Track* tr, const AbsTrackRep* cout << "\n<SpdKalmanFitterRefTrack::processTrackWithRep> (2.7) end iteration " << nIt << "; fit: converged = " << converged << " " << "finished = " << finished - << " failed hits: " << nFailedHits << endl; + << " failed hits: " << nFailedHits << " points: " << tr->getNumPoints() << endl; if (finished) { @@ -295,7 +295,7 @@ void SpdKalmanFitterRefTrack::processTrackWithRep(Track* tr, const AbsTrackRep* // fill FitStatus TrackPoint* tp = tr->getPointWithMeasurementAndFitterInfo(0, rep); - + double charge(0); if (tp != nullptr) { if (static_cast<KalmanFitterInfo*>(tp->getFitterInfo(rep))->hasBackwardUpdate()) { @@ -319,7 +319,6 @@ void SpdKalmanFitterRefTrack::processTrackWithRep(Track* tr, const AbsTrackRep* status->setBackwardChi2(chi2BW); status->setForwardNdf(ndfFW); status->setBackwardNdf(ndfBW); - } //______________________________________________________________________________________________________________________ diff --git a/proc/vertex/CMakeLists.txt b/proc/vertex/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..82a96091e17ac51631cbaf03162dcbf943d8d3b1 --- /dev/null +++ b/proc/vertex/CMakeLists.txt @@ -0,0 +1,44 @@ + +# +# Create a library called "VertexKF" +# + +set(INCLUDE_DIRECTORIES +${ROOT_INCLUDE_DIR} +${BASE_INCLUDE_DIRECTORIES} +${CMAKE_SOURCE_DIR}/proc/ +${CMAKE_SOURCE_DIR}/proc/vertex +${CMAKE_SOURCE_DIR}/external/KFParticle/ +${CMAKE_SOURCE_DIR}/external/KFParticle/KFParticle +${CMAKE_SOURCE_DIR}/external/KFParticle/KFParticlePerformance +${CMAKE_SOURCE_DIR}/spddata/ +${CMAKE_SOURCE_DIR}/spddata/IdealTrackData +) + +include_directories( ${INCLUDE_DIRECTORIES}) +include_directories(SYSTEM ${SYSTEM_INCLUDE_DIRECTORIES}) + +set(LINK_DIRECTORIES +${ROOT_LIBRARY_DIR} +${FAIRROOT_LIBRARY_DIR} +) + +link_directories( ${LINK_DIRECTORIES}) + +set(SRCS +SpdKFParticleTest.cxx +) + +set(HEADERS +SpdKFParticleTest.h +) + +ADD_DEFINITIONS(-DHomogeneousField) +#ADD_DEFINITIONS(-DNonhomogeneousField) + +Set(LINKDEF VertexKFLinkDef.h) +Set(LIBRARY_NAME VertexKF) +Set(DEPENDENCIES Base) + +GENERATE_LIBRARY() + diff --git a/proc/vertex/SpdKFParticleTest.cxx b/proc/vertex/SpdKFParticleTest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1d84cf8ad439732e0580a8a6f5afb7c6404226f7 --- /dev/null +++ b/proc/vertex/SpdKFParticleTest.cxx @@ -0,0 +1,231 @@ + +//_____________________________________________________________________________ +// +// SpdKFParticleTest +//_____________________________________________________________________________ + +#include "SpdKFParticleTest.h" + +#include "KFParticle.h" +#include "KFPTrack.h" +#include "KFPVertex.h" +#include "KFParticleSIMD.h" + +#include <iostream> +#include <iomanip> +#include <cmath> + +ClassImp(SpdKFParticleTest) + + +std::ostream& operator<<(std::ostream& os, const KFParticleBase& particle) { + static const char *vn[14] = {"x","y","z","px","py","pz","E","S","M","t","p","Q","Chi2","NDF"}; + + for (Int_t i = 0; i < 8; i++) { + if (i == 6) continue; // E + if (i == 7 && particle.GetParameter(i) <= 0.0) continue; // S + if (particle.GetParameter(i) == 0. && particle.GetCovariance(i,i) == 0) continue; + if (particle.GetCovariance(i,i) > 0) + os << " " << vn[i]<<": "<< std::setw(8) << particle.GetParameter(i)<< " +/- " << std::setw(6) << sqrt(particle.GetCovariance(i,i)); + else + os << " " << vn[i] << ": " << std::setw(8) << particle.GetParameter(i); + } + float Mtp[3], MtpErr[3]; + particle.GetMass(Mtp[0], MtpErr[0]); if (MtpErr[0] < 1e-7 || MtpErr[0] > 1e10) MtpErr[0] = -13; + particle.GetLifeTime(Mtp[1], MtpErr[1]); if (MtpErr[1] <= 0 || MtpErr[1] > 1e10) MtpErr[1] = -13; + particle.GetMomentum(Mtp[2], MtpErr[2]); if (MtpErr[2] <= 0 || MtpErr[2] > 1e10) MtpErr[2] = -13; + for (Int_t i = 8; i < 11; i++) { + if (i == 9 && Mtp[i-8] <= 0.0) continue; // t + if (MtpErr[i-8] > 0 && MtpErr[i-8] < 1e10) os << " " << vn[i] << ": " << std::setw(8) << Mtp[i-8] << " +/-" << std::setw(7) << MtpErr[i-8]; + else os << " " << vn[i] << ": " << std::setw(8) << Mtp[i-8]; + } + os << " pdg:" << std::setw(5) << particle.GetPDG() << " Q: "<< std::setw(2) << int(particle.GetQ()) << " chi2/NDF: " << std::setw(8) << particle.GetChi2() << "/" << std::setw(2) << particle.GetNDF(); + return os; +} + +//_____________________________________________________________________________ +SpdKFParticleTest::SpdKFParticleTest():fMotherSingle(0),fMotherSIMD(0) +{ + fMotherSingle = new KFParticle(); + fMotherSIMD = new KFParticleSIMD(); +} + +//_____________________________________________________________________________ +SpdKFParticleTest::~SpdKFParticleTest() +{ + if (fMotherSingle) delete fMotherSingle; + if (fMotherSIMD) delete fMotherSIMD; +} + +//_____________________________________________________________________________ +void SpdKFParticleTest::RunTest() +{ + RunTestSingle(); + RunTestSIMD(); +} + +//_____________________________________________________________________________ +void SpdKFParticleTest::RunTestSingle() +{ + +std::cout << "----------------------------------------------------------------------------" <<std::endl; +#ifdef HomogeneousField + std::cout << "\n ---- HomogeneousField \n" << std::endl; +#endif + +#ifdef NonhomogeneousField + std::cout << "\n ---- NonhomogeneousField \n" << std::endl; +#endif +std::cout << "----------------------------------------------------------------------------" <<std::endl; + + std::cout.setf(std::ios::fixed); + std::cout.setf(std::ios::showpoint); + std::cout.precision(3); + + std::cout << "Try different constructors" << std::endl<< std::endl; + std::cout << "1. Construction from Vertex" << std::endl<< std::endl; + KFPVertex vert; + vert.SetXYZ(0.0, 0.0, 10.0); + vert.SetCovarianceMatrix( 0.01, + 0.00, 0.01, + 0.00, 0.00, 0.01 ); + vert.SetNContributors(2); + vert.SetChi2(1.01); + + KFParticle p1(vert); + std::cout << "Vertex Particle p1" << std::endl << " " << p1 << std::endl; + + /// ***************************************************************************************** + +#ifdef HomogeneousField + KFParticle::SetField(4.9797992706298828); +#endif + + float point[3]={0.f}; + float b[3] = {0.f}; + p1.GetFieldValue(point,b); + std::cout << "Set Field " << std::setw(6) << b[2] << std::endl; + + std::cout << std::endl << "2. Construction from Track" << std::endl<< std::endl; + + KFPTrack track; + track.SetParameters(-0.061996019110347252, -1.3579236865955473, 27.147283554077148, + 0.62539337626870062, -0.028552340672283318, -0.18467358509984011); + float C[21]= {3.3055800809774214e-05, + 0.00098316976438185002, 0.04740889543423539, + -8.5596097466772512e-05, -0.0037516094381694971, 0.032156504690647125, + -2.2812597903705375e-05, -0.0012121012247057524, 3.0646383360925928e-05, 6.1388628418184652e-05, + -4.4071909055788304e-06,-0.00048870318030618627, 3.8062554692505919e-05, 1.2177141510445709e-05, 7.6900178535210476e-06, + 6.6224441962932268e-06, 0.00034363110217286891, -0.00031520420397528146,-1.6277704753223909e-05,-3.4322154557097545e-06, 1.027411488502718e-05}; + track.SetCovarianceMatrix(C); + track.SetNDF(1); + track.SetChi2(1.5); + track.SetCharge(-1); + + KFParticle p2(track, -211); + + std::cout << "Track Particle p2" << std::endl <<" "<< p2 << std::endl; + + /// ***************************************************************************************** + + std::cout << std::endl << "3. Now we will create one more particle from track and call the construction from these 2 particles" << std::endl<< std::endl; + + KFPTrack track2; + track2.SetParameters(-0.20371287092090862, 3.0678058943547839, -19.93988037109375, + 0.37533048135363339, 0.024923235867488316, 0.19031024520542122); + float C2[21]= + { 0.00022312908970259721, + -0.00064291160449645151, 0.089331037457232143, + 0.00047880877483649206, -0.045478494677353445, 0.11199165135622025, + 4.6362085390124077e-07, 0.00070978326424729935, -0.00014164977426380486, 1.7553871209443515e-05, + -2.2044831998838091e-05,-0.00059994741249631909, 0.00030148707952079015,-4.6574515272730461e-06, 7.2618497455845866e-06, + -1.2427988441207971e-06, 0.00030830063771211896, -0.00061853865528922161, 5.4390968700069889e-06,-1.9914477627292868e-06, 8.9837108094398403e-06}; + + track2.SetCovarianceMatrix(C2); + track2.SetNDF(2); + track2.SetChi2(2.5); + track2.SetCharge(+1); + KFParticle p3(track2, 211); // PDG = 11 + std::cout << "Track Particle p3 " << std::endl <<" "<< p3 << std::endl; + + KFParticle p4(p2, p3); + std::cout << "Particle p4(p2,p3)" << std::endl << " " << p4 << std::endl; + + /// ***************************************************************************************** + std::cout << std::endl << "4. Construction with constrained Mass or (and) vertex position values" << std::endl<< std::endl; + +/// This is the example of the KFParticleBase::Construct function usage. +/// parameter 1 - array of the daughter particles +/// parameter 2 - number of the daughter particles +/// parameter 3 - vertex (it should be the object of the KFParticle class) +/// parameter 4 - the value we force the particle mass to be equial to. + + const KFParticle pVertex = p1; + int NDaughters = 2; + const KFParticle *vDaughters[2] = {&p2, &p3}; + + Double_t Mass = 0.497614; + + std::cout << "4.1 Construction with constrained Mass, without vertex hypothesis " << std::endl<< std::endl; +/// we assume Mass to be the mass of the constructed particle + KFParticle K0; + K0.Construct(vDaughters,NDaughters,0,Mass); + std::cout << "Dauthers" << std::endl + << " " << *vDaughters[0] << std::endl + << " " << *vDaughters[1] << std::endl + << "Mass " << Mass << std::endl; + std::cout << "Particle K0" << std::endl << K0 << std::endl; + K0.SetProductionVertex(pVertex); + std::cout << " Add parent Vertex" << std::endl; + std::cout << " K0 with vertex " << K0 << std::endl; + std::cout << std::endl << "4.2 Construction without constrained Mass, with vertex hypothesis " << std::endl<< std::endl; +/// we assume p1 to be the vertex of the constructed particle + KFParticle K0_1; + K0_1.Construct(vDaughters,NDaughters,&pVertex,-1); + + std::cout << "Dauthers" << std::endl + << " " << *vDaughters[0] << std::endl + << " " << *vDaughters[1] << std::endl + << "PV " << std::endl << " " << pVertex << std::endl; + std::cout << "K0_1" << std::endl <<" " << K0_1 << std::endl; + std::cout << std::endl << "4.3 Construction with constrained Mass, with vertex hypothesis " << std::endl<< std::endl; +///we assume p1 to be the vertex of the constructed particle, Mass to be the mass of the constructed particle + KFParticle K0_2; + K0_2.Construct(vDaughters,NDaughters,&pVertex,Mass); + + std::cout << "Dauthers" << std::endl + << " " << *vDaughters[0] << std::endl + << " " << *vDaughters[1] << std::endl + << "PV " << std::endl << " " << pVertex << std::endl + << "Mass " << Mass << std::endl; + std::cout << "K0_2" << std::endl << " " << K0_2 << std::endl; + + std::cout << std::endl << "4.4 Construction K0_3(p2,p3) without constrained Mass, without vertex hypothesis " << std::endl<< std::endl; +///we assume p1 to be the vertex of the constructed particle, Mass to be the mass of the constructed particle + KFParticle K0_3; + K0_3.Construct(vDaughters,NDaughters,0,-1); + + std::cout << "Dauthers" << std::endl + << " " << *vDaughters[0] << std::endl + << " " << *vDaughters[1] << std::endl; + std::cout << "K0_3" << std::endl << " " << K0_3 << std::endl; + + std::cout << "----------------------------------------------------------------------------" <<std::endl; +} + +//_____________________________________________________________________________ +void SpdKFParticleTest::RunTestSIMD() +{ +} + +//_____________________________________________________________________________ +void SpdKFParticleTest::CompareSingleAndSIMDResults() +{ +} + +//_____________________________________________________________________________ +void SpdKFParticleTest::PrintTutorial() +{ +} + + diff --git a/proc/vertex/SpdKFParticleTest.h b/proc/vertex/SpdKFParticleTest.h new file mode 100644 index 0000000000000000000000000000000000000000..f948c684ab6604955385d4158f1a934c96e21995 --- /dev/null +++ b/proc/vertex/SpdKFParticleTest.h @@ -0,0 +1,50 @@ + +#ifndef __SPDKFPARTICLETEST_H__ +#define __SPDKFPARTICLETEST_H__ + +#include <TObject.h> + +class KFParticle; +class KFParticleSIMD; + +//--------------------------------------------------------------------------------- +// The KFParticle class +// . +// @author Maksym Zyzak +// @version 1.0 +// @since 13.05.07 +// +// Class to reconstruct and store the decayed particle parameters. +// The method is described in CBM-SOFT note 2007-003, +// ``Reconstruction of decayed particles based on the Kalman filter'', +// http://www.gsi.de/documents/DOC-2007-May-14-1.pdf +// +// This class is ALICE interface to general mathematics in KFParticleBase +// +// -= Copyright © ALICE HLT and CBM L1 Groups =- +//_________________________________________________________________________________ + +class SpdKFParticleTest: public TObject { + +public: + + SpdKFParticleTest(); + virtual ~SpdKFParticleTest(); + + void PrintTutorial(); + void RunTest(); + +private: + + void RunTestSingle(); + void RunTestSIMD(); + void CompareSingleAndSIMDResults(); + + KFParticle* fMotherSingle; + KFParticleSIMD* fMotherSIMD; + + ClassDef(SpdKFParticleTest,1) +}; + +#endif /* __SPDKFPARTICLETEST_H__ */ + diff --git a/proc/vertex/VertexKFLinkDef.h b/proc/vertex/VertexKFLinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..9840348c034841bd5b6611ec9f3dc8d8200a8462 --- /dev/null +++ b/proc/vertex/VertexKFLinkDef.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 SpdKFParticleTest+; + +#endif diff --git a/procmc/SpdIdealTrackFinder.cxx b/procmc/SpdIdealTrackFinder.cxx index 67ba16dc67ac0337f7beda1340a7529a285f0343..f9a7f11204e370476d4155b820e67c82aa491b5c 100644 --- a/procmc/SpdIdealTrackFinder.cxx +++ b/procmc/SpdIdealTrackFinder.cxx @@ -8,6 +8,7 @@ #include "SpdIdealTrackFinder.h" +#include <TRandom.h> #include <TClonesArray.h> #include <TGeoManager.h> #include <TDatabasePDG.h> @@ -45,25 +46,72 @@ ClassImp(SpdIdealTrackFinder) //_____________________________________________________________________________ SpdIdealTrackFinder::SpdIdealTrackFinder(): FairTask("SPD Ideal track finder"), +fOwnGeoLoader(false), fGeoLoader(0), fEventHeader(0), fMCTracksArray(0), fEvent(0), fParameters(0), -fNErrors(0) +fPrimVertexOnly(true), +fNErrors(0), +fNFailedHits(0) { fMinMomentum[0] = 4e-3; fMinMomentum[1] = 1e-2; // pmin = [4,10] MeV fMinGammaBeta[0] = 0.05; fMinGammaBeta[1] = 0.5; // p/m fMinVertexNHits[0] = 0; fMinVertexNHits[1] = 1; fMinTrackerNHits[0] = 2; fMinTrackerNHits[1] = 2; + Double_t mkm = 1e-4; + + // set hits resolution (undefined type): x, y, z + SetHitResolution(kSpdIts, 'n', 100*mkm, 100*mkm, 100*mkm); + SetHitResolution(kSpdTsTB, 'n', 150*mkm, 150*mkm, 150*mkm); + SetHitResolution(kSpdTsTEC,'n', 150*mkm, 150*mkm, 150*mkm); + + // set hits resolution default point-like hits + SetHitResolution(kSpdTsTB, 'p', 150*mkm, 150*mkm, 150*mkm); + SetHitResolution(kSpdTsTEC, 'p', 150*mkm, 150*mkm, 150*mkm); + fParameters = new SpdBaseParSet(); } //_____________________________________________________________________________ SpdIdealTrackFinder::~SpdIdealTrackFinder() { - if (fGeoLoader) delete fGeoLoader; +} + +//_____________________________________________________________________________ +void SpdIdealTrackFinder::DeleteGeoLoader() +{ + if (fOwnGeoLoader && fGeoLoader) { + cout << "-I- <SpdIdealTrackFinder::DeleteGeoLoader> Remove geometry loader" << endl; + delete fGeoLoader; + fGeoLoader = 0; + fOwnGeoLoader = false; + } +} + +//_____________________________________________________________________________ +void SpdIdealTrackFinder::SetHitResolution(Int_t det, Char_t spec, Double_t res1, Double_t res2, Double_t res3) +{ + TVector3 res(res1,res2,res3); + + if (res2 < 0) res.SetY(res1); + if (res3 < 0) res.SetZ(TMath::Max(res1,res2)); + + fResolution[DetResKey(det,spec)] = res; + + //cout << fResolution.size() << " "<< fResolution[DetResKey(det,spec)].X() << " " + // << fResolution[DetResKey(det,spec)].Y() << " " + // << fResolution[DetResKey(det,spec)].Z() << "\n"; +} + +//_____________________________________________________________________________ +TVector3 SpdIdealTrackFinder::GetHitResolution(Int_t det, Char_t spec) +{ + TString reskey = DetResKey(det,spec); + std::map< TString, TVector3 >::const_iterator it = fResolution.find(reskey); + return (it != fResolution.end()) ? it->second : TVector3(0.01,0.01,0.01); } //_____________________________________________________________________________ @@ -80,9 +128,14 @@ void SpdIdealTrackFinder::SetTrackingGeoModules(Bool_t add_passives) //_____________________________________________________________________________ void SpdIdealTrackFinder::LoadGeometry() { - if (fGeoLoader) delete fGeoLoader; + fGeoLoader = SpdGeoLoader::Instance(); + + if (!fGeoLoader) { + fGeoLoader = new SpdGeoLoader(); + fOwnGeoLoader = true; + } + else fOwnGeoLoader = false; - fGeoLoader = new SpdGeoLoader(); fGeoLoader->LoadGeometry(); // load TOP level only (cave) Int_t n = fGeoModules.size(); @@ -186,7 +239,7 @@ InitStatus SpdIdealTrackFinder::Init() std::map<Int_t,ITF_info*>::iterator it = fInputData.begin(); for (; it != fInputData.end(); it++) { - pars = fGeoLoader->GetParameters(it->first); + pars = fGeoLoader->GetActiveParameters(it->first); pars->GetParameter("Detector/NOutData",NDataOut); if (NDataOut < 1) { @@ -223,6 +276,7 @@ InitStatus SpdIdealTrackFinder::Init() cout << "-I- <SpdIdealTrackFinder:Init> Intialization successfull " << endl; fNErrors = 0; + fNFailedHits = 0; return kSUCCESS; } @@ -235,6 +289,8 @@ void SpdIdealTrackFinder::Exec(Option_t* opt) fEvent->ClearData(); + Int_t nfailedhits = fNFailedHits; + // >>>>> Fill event <<<<< fEvent->SetRunId(fEventHeader->GetRunID()); @@ -278,14 +334,15 @@ void SpdIdealTrackFinder::Exec(Option_t* opt) } if (Nt == 0) { - cout << "<SpdIdealTrackFinder::Exec> No data for the event: " << fEventHeader->GetEventID() << endl; + cout << "<SpdIdealTrackFinder::Exec> No accepted data for the event: " << fEventHeader->GetEventID() << endl; + fEventHeader->Reset(); return; } - cout << "<SpdIdealTrackFinder::Exec> event: " << fEventHeader->GetEventID() - << "; add tracks: " << Nt << "/" << Nmc << endl; + //cout << "<SpdIdealTrackFinder::Exec> event: " << fEventHeader->GetEventID() + // << "; add tracks: " << Nt << "/" << Nmc << endl; - fEvent->SetInfoNTracks(Nt); + fEvent->SetInfoNTracks(Nt); // +++++ +++++ CREATE HITS +++++ +++++ @@ -332,10 +389,15 @@ void SpdIdealTrackFinder::Exec(Option_t* opt) std::map< Int_t,std::map<Double_t, SpdIdealHit*> >::iterator itx = htracks.begin(); Int_t n(0); + Int_t hit_uid(0); for ( ; itx != htracks.end(); itx++) { track = fEvent->GetTrack(n); std::map<Double_t, SpdIdealHit*>::iterator itxx = itx->second.begin(); - for (; itxx != itx->second.end(); itxx++) track->AddHit(itxx->second); + for (; itxx != itx->second.end(); itxx++) { + itxx->second->AddTrackId(n); + itxx->second->SetId(hit_uid++); + track->AddHit(itxx->second); + } n++; } @@ -357,11 +419,11 @@ void SpdIdealTrackFinder::Exec(Option_t* opt) track = fEvent->GetTrack(htrnums[i]); np1 = mctrack->GetNPoints(DetectorId(it->first)); - np2 = dinfo->GetTrackHits(htrnums[i]); + np2 = dinfo->GetTrackHits(htrnums[i]); nn += np1; - if (np1 != np2) { + if (np1 != np2) { cout << "-W- <SpdIdealTrackFinder::Exec> Number of hits: " << np1 << "/"<< np2 << endl; nerrrors++; @@ -379,8 +441,13 @@ void SpdIdealTrackFinder::Exec(Option_t* opt) } if (fEvent->GetErrorFlag() != 0) fNErrors++; + + if (fNFailedHits > nfailedhits) { + if (fEvent->GetErrorFlag() == 0) fEvent->SetErrorFlag(2); + else fEvent->SetErrorFlag(3); + } - fEvent->PrintData(); + //fEvent->PrintData(); fEventHeader->Reset(); } @@ -398,7 +465,7 @@ SpdIdealTrack* SpdIdealTrackFinder::CreateTrack(Int_t id, SpdMCTrack* mctrack, B // check track number if (fTracksSelected.empty()) { - if (mctrack->GetFirstMotherId() != -1) + if (fPrimVertexOnly && mctrack->GetFirstMotherId() != -1) { accept_track = kFALSE; //ATTENTION selmark = kVertexParticle; @@ -477,7 +544,12 @@ SpdIdealHit* SpdIdealTrackFinder::CreateHit(FairMCPoint* point, Int_t DetId, ITF SpdIdealHit* SpdIdealTrackFinder::CreateItsHit(FairMCPoint* point, ITF_info* info) { info->htype = kSpacepoint; + + if (!fGeoLoader) return 0; + SpdDetector* det = fGeoLoader->GetActive(kSpdIts); + if (!det) return 0; + SpdItsPoint* p = dynamic_cast<SpdItsPoint*>(point); if (!p) return 0; @@ -492,21 +564,272 @@ SpdIdealHit* SpdIdealTrackFinder::CreateItsHit(FairMCPoint* point, ITF_info* inf hit->SetDetId(1,id); - TVector3 v; - Double_t x[3], t; + TVector3 v; // MC-hit position + Double_t t; // MC-hit time p->GetPosTime(v,t); - hit->SetPoint(v); + hit->SetPoint(v); // ATTENTION set MC-POINT position hit->SetTimeStamp(t); + + TString path = builder->GetNodePath(); + + // check detector part (barrel or endcap) ATTENTION + Bool_t barrel_part = true; + if (path.Contains("EClayer")) barrel_part = false; + Double_t x[3]; + + // set detector position if (builder->GetDetectorPosition(x)) hit->SetDetPos(x[0],x[1],x[2]); - if (builder->GetDetectorOrientation(x,'z')) hit->SetU(TVector3(x[0],x[1],x[2])); - if (builder->GetDetectorOrientation(x,'x')) hit->SetV(TVector3(x[0],x[1],x[2])); + + // set chip local axis + if (barrel_part) { + // BARREL: (z->u, x->v, y->n) + if (builder->GetDetectorOrientation(x,'z')) hit->SetU(TVector3(x[0],x[1],x[2])); + if (builder->GetDetectorOrientation(x,'x')) hit->SetV(TVector3(x[0],x[1],x[2])); + if (builder->GetNodeSize(x)) hit->SetL(x[2],x[0],x[1]); //u,v,n-sizes + } + else { + // ENDCAPS: (x->u, y->v, z->n) + if (builder->GetDetectorOrientation(x,'x')) hit->SetU(TVector3(x[0],x[1],x[2])); + if (builder->GetDetectorOrientation(x,'y')) hit->SetV(TVector3(x[0],x[1],x[2])); + if (builder->GetNodeSize(x)) hit->SetL(x[0],x[1],x[2]); //u,v,n-sizes + } - if (builder->GetNodeSize(x)) hit->SetL(x[2],x[0],x[1]); + //=============================================== + // searching for HIT position and specification + //=============================================== - return hit; + //cout << "\n<SpdIdealTrackFinder::CreateItsHit> Check specifity, find hit position " << "\n\n"; + + SpdGeoVVolumeBox2D* vvol = dynamic_cast<SpdGeoVVolumeBox2D*>(builder->GetNodeVVolume()); + + //if (vvol) vvol->PrintVolume(); + //p->Print(""); + + Bool_t nehits = !det->GetSaveEmptyHits(); + + Char_t spec = 'n'; // hit specification + Int_t submod_id(0); // submodule id for vertex detector: 0 = barrel part, 1 = endcaps + + // check submodule id + if (!barrel_part) { + submod_id = 1; + hit->SetDetId(2,submod_id); + hit->SetSpecifity('p'); // specification = "point" + + //hit->SetHit(v); // ATTENTION set HIT position = MC-POINT for ITS endcaps + hit->SetHit(v[0],v[1],hit->GetDetPosZ()); // ATTENTION set HIT position = MC-POINT(X,Y)+DET_POS(Z) for ITS endcaps + + hit->SetResolution(GetHitResolution(kSpdIts,hit->GetSpecifity())); // set hit resolution + + // ATTENTION + if (TMath::Abs(hit->GetHitN()) > 1e-14) { + hit->SetSpecifity('n'); + fNFailedHits++; + //cout << "(1) spec "<< hit->GetSpecifity() << " U, V, N: " + // << hit->GetHitU() << " " << hit->GetHitV() << " " << hit->GetHitN() << endl; + } + return hit; + } + + // check if hit is empty + if (nehits && !(point->GetEnergyLoss() > 0)) { + + hit->SetDetId(2,submod_id); + hit->SetSpecifity('n'); // specification = "undefined" + hit->SetHit(v); // ATTENTION set HIT position = MC-POINT + hit->SetResolution(GetHitResolution(kSpdIts,hit->GetSpecifity())); // set hit resolution + fNFailedHits++; + return hit; + } + + // check hit specification + if (vvol) { + TString vvolname = vvol->GetName(); + if (vvolname.Contains("DSSD")) spec = 's'; + else if (vvolname.Contains("MAPS")) spec = 'm'; + } + + Double_t hit_pos[3] = {0, 0, 0}; // chip channel global position (x,y,z) + + //cout << "Hit production; spec = " << hit->GetSpecifity() << " " << vvol << " " << path << endl; + + // standard hit specifications + if (spec == 's' || spec == 'm') + { + Int_t nchan = p->GetVDataSize(); // number of hitted channels in the chip + Int_t vid; // chip channel id + if (nchan < 1) spec = 'n'; + else if (nchan == 1) { + if (nehits && !(p->GetVed(0) > 0)) spec = 'n'; + else { + vid = p->GetVid(0); + if (vid < 0) spec = 'n'; + else { + builder->SetVid(vid); // set channel C.S. + if (!builder->GetDetectorPosition(hit_pos)) spec = 'n'; + } + } + } + else { + Int_t iz_ch, iphi_ch; // chip channel id's: iz_ch = id1, iphi_ch = id2 + Int_t nc(0), az_ch(0), aphi_ch(0); + for (Int_t j(0); j < nchan; j++) { + vid = p->GetVid(j); + if (vid < 0) continue; + if (nehits && !(p->GetVed(j) > 0)) continue; + vvol->CellId(vid, iz_ch, iphi_ch); + az_ch += iz_ch; + aphi_ch += iphi_ch; + nc++; + //cout << j << " (z,phi): " << iz_ch << " " << iphi_ch << endl; + } + //cout << " a(z,phi): " << az_ch/Double_t(nc) << " " << aphi_ch/Double_t(nc) << " nc = " << nc << endl; + if (nc == 0) { + Double_t dep = 0; + if (p->IsSpecialPoint(vid,dep)) { // special case: very short (~several mkm) track segment + if (nehits && !(dep > 0)) spec = 'n'; + else { + builder->SetVid(vid); // set channel C.S. + if (!builder->GetDetectorPosition(hit_pos)) spec = 'n'; + //cout << "spec: " << spec << " vid = " << vid << " dep = " << dep << endl; + } + } + else spec = 'n'; + } + else if (nc == 1) { + vid = vvol->CellId(az_ch,iphi_ch); + builder->SetVid(vid); // set channel C.S. + if (!builder->GetDetectorPosition(hit_pos)) spec = 'n'; + } + else { + Double_t pos[3]; + vvol->GetPos(az_ch/Double_t(nc),aphi_ch/Double_t(nc),pos); + builder->SetVid(-1); // set chip C.S. + if (!builder->LocalToGlobalP(pos,hit_pos)) spec = 'n'; + } + } + +// cout << "\t vol.name = " << vvol->GetName() << "; specifity: " << spec << "; sub_mod: " << submod_id +// << "; nchannels: " << nchan << "; " << builder->GetNodePath() << "\n\n"; +// printf("\t its point (1): %14.8f %14.8f %14.8f\n",v.X(),v.Y(),v.Z()); +// printf("\t its point (2): %14.8f %14.8f %14.8f\n",hit_pos[0],hit_pos[1],hit_pos[2]); +// printf("\n"); + + } + + if (spec == 'n') { + hit->SetDetId(2,submod_id); + hit->SetSpecifity('n'); // specification = "undefined" + hit->SetHit(v); // ATTENTION set HIT position = MC-POINT + hit->SetResolution(GetHitResolution(kSpdIts,hit->GetSpecifity())); + fNFailedHits++; + //p->Print(""); + return hit; + } + + hit->SetDetId(2,submod_id); + hit->SetSpecifity(spec); // specification = 'm' (MAPS) or 's' (DSSD) + hit->SetHit(hit_pos[0],hit_pos[1],hit_pos[2]); // ATTENTION set hit position + hit->SetResolution(GetHitResolution(kSpdIts,hit->GetSpecifity())); + + // ATTENTION + if (TMath::Abs(hit->GetHitN()) > 1e-14) { + hit->SetSpecifity('n'); + fNFailedHits++; + //cout << "(2) spec "<< hit->GetSpecifity() << " U, V, N: " + // << hit->GetHitU() << " " << hit->GetHitV() << " " << hit->GetHitN() << endl; + } + + return hit; + + // calculate resolution "on the fly" +// if (spec == 'm') +// { +// static Int_t nr = 0; +// static Double_t rsum = 0; +// static Double_t rsum2 = 0; +// static Double_t dd = -1.; +// +// Double_t r2 = (v.X()-hit_pos[0])*(v.X()-hit_pos[0])+ +// (v.Y()-hit_pos[1])*(v.Y()-hit_pos[1])+ +// (v.Z()-hit_pos[2])*(v.Z()-hit_pos[2]); +// Double_t r = TMath::Sqrt(r2); +// +// nr++; +// rsum2 += r2; +// rsum += r; +// if (r > dd) dd = r; +// +// cout << "[ITS] specifity: " << spec +// << " diff. distance (current, max, ave) = " << r*1e4 +// << " " << dd*1e4 << " " << 1e4*rsum/nr << " [mkm] " +// << " sigma = " << 1e4*TMath::Sqrt(TMath::Abs(rsum2/nr-rsum*rsum/(nr*nr))) << " [mkm] " << endl; +// +// //printf("\t its point (1): %14.8f %14.8f %14.8f\n",v.X(),v.Y(),v.Z()); +// //printf("\t its point (2): %14.8f %14.8f %14.8f\n",hit_pos[0],hit_pos[1],hit_pos[2]); +// //p->Print(""); +// } +// else if (spec == 's') +// { +// static Int_t nr = 0; +// static Double_t rsum = 0; +// static Double_t rsum2 = 0; +// static Double_t dd = -1.; +// +// static Double_t xsum2[3] = {0,0,0}; +// static Double_t xsum[3] = {0,0,0}; +// static Double_t xd[3] = {-1,-1,-1}; +// +// Double_t r2 = (v.X()-hit_pos[0])*(v.X()-hit_pos[0])+ +// (v.Y()-hit_pos[1])*(v.Y()-hit_pos[1])+ +// (v.Z()-hit_pos[2])*(v.Z()-hit_pos[2]); +// Double_t r = TMath::Sqrt(r2); +// +// Double_t du = TMath::Abs(hit->GetHitU()-hit->GetPointU()); +// Double_t dv = TMath::Abs(hit->GetHitV()-hit->GetPointV()); +// Double_t dn = TMath::Abs(hit->GetHitN()-hit->GetPointN()); +// +// nr++; +// +// rsum2 += r2; +// rsum += r; +// if (r > dd) dd = r; +// +// xsum[0] += du; +// xsum[1] += dv; +// xsum[1] += dv; +// +// xsum2[0] += du*du; +// xsum2[1] += dv*dv; +// xsum2[2] += dn*dn; +// +// if (du > xd[0]) xd[0] = du; +// if (dv > xd[1]) xd[1] = dv; +// if (dn > xd[2]) xd[2] = dn; +// +// cout << "[ITS] specifity: " << spec +// << " diff. distance (current, max, ave) = " << r*1e4 +// << " " << dd*1e4 << " " << 1e4*rsum/nr << " [mkm] " +// << " sigma = " << 1e4*TMath::Sqrt(TMath::Abs(rsum2/nr-rsum*rsum/(nr*nr))) << " [mkm] " +// << "\n\t (du,dv,dn) = " << du*1e4 << ", " << dv*1e4 << ", " << dn*1e4 << " [mkm] " +// << " max(du,dv,dn) = " << xd[0]*1e4 << "," << xd[1]*1e4 << "," << xd[2]*1e4 << " [mkm] " +// << " sigma(du,dv,dn) = " << 1e4*TMath::Sqrt(TMath::Abs(xsum2[0]/nr-xsum[0]*xsum[0]/(nr*nr))) +// << ", " << 1e4*TMath::Sqrt(TMath::Abs(xsum2[1]/nr-xsum[1]*xsum[1]/(nr*nr))) +// << ", " << 1e4*TMath::Sqrt(TMath::Abs(xsum2[2]/nr-xsum[2]*xsum[2]/(nr*nr))) +// << endl; +// +// //printf("\t its point (1): %14.8f %14.8f %14.8f\n",v.X(),v.Y(),v.Z()); +// //printf("\t its point (2): %14.8f %14.8f %14.8f\n",hit_pos[0],hit_pos[1],hit_pos[2]); +// //cout << hit->GetHitN() << " " << hit->GetPointN() << endl; +// } + + //p->Print(""); + //hit->PrintHit(); + +// return hit; } //________________________________________________________________________________________ @@ -526,20 +849,15 @@ SpdIdealHit* SpdIdealTrackFinder::CreateTsTBHit(FairMCPoint* point, ITF_info* in SpdIdealWirepointHit* hit = new SpdIdealWirepointHit(); - hit->SetDetId(1,id); - - TVector3 v; - Double_t x[3],t; - - p->GetPosTime(v,t); + hit->SetSpecifity('w'); - hit->SetPoint(v); - hit->SetTimeStamp(t); + hit->SetDetId(1,id); + hit->SetDetId(2,0); // barrel - t = p->GetPointDir(v); - hit->SetDirInPoint(v,t); + Double_t x[3], s, t, rmax, zmax, resR, resZ, R(0), Z(0); + TVector3 pos, dir, size, res, Lr, Lz; - TVector3 pos, dir, size; + // --- detector if (builder->GetDetectorPosition(x)) pos.SetXYZ(x[0],x[1],x[2]); if (builder->GetDetectorOrientation(x,'z')) dir.SetXYZ(x[0],x[1],x[2]); if (builder->GetNodeSize(x)) size.SetXYZ(x[0],x[1],x[2]); @@ -548,7 +866,80 @@ SpdIdealHit* SpdIdealTrackFinder::CreateTsTBHit(FairMCPoint* point, ITF_info* in hit->SetWireMaxRadius(size.X()); hit->SetWire(pos,dir,size.Z()); - + + rmax = hit->GetWireMaxRadius(); + zmax = hit->GetWireLength(); + + // --- + p->GetPosTime(pos,t); // point position and time + s = p->GetPointDir(dir); // s = segment length, dir = track direction in the point + + // --- point + hit->SetPoint(pos); // position + hit->SetDirInPoint(dir,s); // track direction in the point, segment length + + // --- hit resolution + hit->SetResolution(GetHitResolution(kSpdTsTB,hit->GetSpecifity())); + + // --- hit time & position + hit->SetTimeStamp(t); // time + hit->SetHit(pos); // position FIXME + + //-------------------------------------------- + // ATTENTION >>>> create hit position >>>> ATTENTION + resR = hit->GetResolutionR(); + resZ = hit->GetResolutionZ(); + + Lr = hit->GetDriftDirR(); + Lz = hit->GetWireDirZ(); + + R = Lr.Mag(); + Z = Lz.Mag(); + + Double_t ktol = 0.99999; + if (resR > 0) { + if (resR < rmax/TMath::Sqrt(12)) { + R += gRandom->Gaus(0,resR); + if (R < 0) R = 0; + else if (!(R < rmax)) R = ktol*rmax; + } + else R = gRandom->Uniform(0,ktol*rmax); + if (R > 0) Lr.SetMag(R); + } + + if (resZ > 0) { + if (resZ < zmax/TMath::Sqrt(12)) { + Z += gRandom->Gaus(0,resZ); + if (Z < 0) Z = 0; + else if (!(Z < zmax)) Z = ktol*zmax; + } + else Z = gRandom->Uniform(0,ktol*zmax); + if (Z > 0) Lz.SetMag(Z); + } + + pos = hit->GetWirePoint1(); + if (Z > 0) pos += Lz; + if (R > 0) pos += Lr; + // ATTENTION <<<< create hit position <<<<< ATTENTION + //-------------------------------------------- + + hit->SetHit(pos); // new position FIXME + + // ATTENTION + if (hit->GetRdrift() > rmax || + hit->GetZwire() > zmax ) { + hit->SetSpecifity('n'); + fNFailedHits++; + //cout << "<TsTB> R drift = " << hit->GetRdrift() << " Max. R = " << rmax + // << " z = " << hit->GetZwire() << " Length = " << zmax << endl; + } + + //cout << "<TsTB> R drift = " << hit->GetRdrift() << " / " << hit->GetDriftDirR().Mag() + // << " resolution (r,z): " << resR << "," << resZ << " R,Z = " << R << ", " << Z << "\n\n"; + + //p->Print(""); + //hit->PrintHit(); + return hit; } @@ -569,29 +960,92 @@ SpdIdealHit* SpdIdealTrackFinder::CreateTsTECHit(FairMCPoint* point, ITF_info* i SpdIdealWirepointHit* hit = new SpdIdealWirepointHit(); - hit->SetDetId(1,id); - - TVector3 v; - Double_t x[3],t; + hit->SetSpecifity('w'); - p->GetPosTime(v,t); - - hit->SetPoint(v); - hit->SetTimeStamp(t); - - t = p->GetPointDir(v); - hit->SetDirInPoint(v,t); + hit->SetDetId(1,id); + hit->SetDetId(2,1); // endcap + + Double_t x[3], s, t, rmax, zmax, resR, resZ, R(0), Z(0); + TVector3 pos, dir, size, res, Lr, Lz; - TVector3 pos, dir, size; + // --- detector if (builder->GetDetectorPosition(x)) pos.SetXYZ(x[0],x[1],x[2]); if (builder->GetDetectorOrientation(x,'z')) dir.SetXYZ(x[0],x[1],x[2]); if (builder->GetNodeSize(x)) size.SetXYZ(x[0],x[1],x[2]); - dir.SetMag(1); - hit->SetWireMaxRadius(size.X()); hit->SetWire(pos,dir,size.Z()); + rmax = hit->GetWireMaxRadius(); + zmax = hit->GetWireLength(); + + // --- + p->GetPosTime(pos,t); // point position and time + s = p->GetPointDir(dir); // s = segment length, dir = track direction in the point + + // --- point + hit->SetPoint(pos); // position + hit->SetDirInPoint(dir,s); // track direction in the point, segment length + + // --- hit resolution + hit->SetResolution(GetHitResolution(kSpdTsTEC,hit->GetSpecifity())); + + // --- hit time & position + hit->SetTimeStamp(t); // time + hit->SetHit(pos); // position FIXME + + //-------------------------------------------- + // ATTENTION >>>> create hit position >>>> ATTENTION + resR = hit->GetResolutionR(); + resZ = hit->GetResolutionZ(); + + Lr = hit->GetDriftDirR(); + Lz = hit->GetWireDirZ(); + + R = Lr.Mag(); + Z = Lz.Mag(); + + Double_t ktol = 0.99999; + if (resR > 0) { + if (resR < rmax/TMath::Sqrt(12)) { + R += gRandom->Gaus(0,resR); + if (R < 0) R = 0; + else if (!(R < rmax)) R = ktol*rmax; + } + else R = gRandom->Uniform(0,ktol*rmax); + if (R > 0) Lr.SetMag(R); + } + + if (resZ > 0) { + if (resZ < zmax/TMath::Sqrt(12)) { + Z += gRandom->Gaus(0,resZ); + if (Z < 0) Z = 0; + else if (!(Z < zmax)) Z = ktol*zmax; + } + else Z = gRandom->Uniform(0,ktol*zmax); + if (Z > 0) Lz.SetMag(Z); + } + + pos = hit->GetWirePoint1(); + if (Z > 0) pos += Lz; + if (R > 0) pos += Lr; + // ATTENTION <<<< create hit position <<<<< ATTENTION + //-------------------------------------------- + + hit->SetHit(pos); // new position FIXME + + // ATTENTION + if (hit->GetRdrift() > hit->GetWireMaxRadius() || + hit->GetZwire() > hit->GetWireLength() ) { + hit->SetSpecifity('n'); + fNFailedHits++; + //cout << "<TsTEC> R drift = " << hit->GetRdrift() << " Max. R = " << hit->GetWireMaxRadius() << " z = " + // << hit->GetZwire() << " Length = " << hit->GetWireLength() << endl; + } + + //p->Print(""); + //hit->PrintHit(); + return hit; } @@ -605,7 +1059,8 @@ SpdIdealTrackFinder::ITF_info* SpdIdealTrackFinder::FindInfo(Int_t id) // protec //________________________________________________________________________________________ void SpdIdealTrackFinder::Finish() { - cout << "-I- <SpdIdealTrackFinder::Finish> Errors: " << fNErrors << endl; + cout << "-I- <SpdIdealTrackFinder::Finish> errors: " << fNErrors + << "; failed hits: " << fNFailedHits << endl; } //________________________________________________________________________________________ @@ -624,8 +1079,11 @@ void SpdIdealTrackFinder::FillParametersIn(SpdBaseParSet* params) params->SetParameter("IdealTrackFinder/MinVertexNHits",fMinVertexNHits[1]); params->SetParameter("IdealTrackFinder/MinTrackerNHits",fMinTrackerNHits[1]); - if (fTracksSelected.empty()) params->SetParameter("IdealTrackFinder/TrackSelection","vertex"); - else params->SetParameter("IdealTrackFinder/TrackSelection","id"); + if (!fTracksSelected.empty()) params->SetParameter("IdealTrackFinder/TrackSelection","selected"); + else { + if (fPrimVertexOnly) params->SetParameter("IdealTrackFinder/TrackSelection","prim"); + else params->SetParameter("IdealTrackFinder/TrackSelection","all"); + } } //________________________________________________________________________________________ diff --git a/procmc/SpdIdealTrackFinder.h b/procmc/SpdIdealTrackFinder.h index 9ae3819f7ea48d8504a5b3c1078e5b5605bcd797..141c0939c6b94856d959f06d368e3e2cebbeb7a4 100644 --- a/procmc/SpdIdealTrackFinder.h +++ b/procmc/SpdIdealTrackFinder.h @@ -40,6 +40,8 @@ public: virtual void Exec(Option_t* opt); virtual void Finish(); + void DeleteGeoLoader(); + void SetTrackingGeoModules(Bool_t add_passives = kFALSE); void AddModule(TString module) { fGeoModules.push_back(module); } @@ -51,12 +53,18 @@ public: inline Int_t GetMinVertexNHits() const { return fMinVertexNHits[1]; } inline Int_t GetMinTrackerNHits() const { return fMinTrackerNHits[1]; } Bool_t FindSelectedTrack(Int_t eid, Int_t tid) const; + + inline void AppendPrimaryTracksOnly(Bool_t prim = true) { fPrimVertexOnly = prim; } + inline void AppendSecondaryTracks(Bool_t sec = true) { fPrimVertexOnly = !sec; } inline void SetMinMomentum(Double_t pmin); inline void SetMinGammaBeta(Double_t gbmin); inline void SetMinVertexNHits(Int_t nhits); inline void SetMinTrackerNHits(Int_t nhits); + virtual void SetHitResolution(Int_t det, Char_t spec, Double_t res1, Double_t res2 = -1, Double_t res3 = -1); + virtual TVector3 GetHitResolution(Int_t det, Char_t spec); + virtual void AddTrackAsSelected(Int_t event /* >=1 */, Int_t track /*>= 0*/); virtual void PrintInput() const; @@ -77,7 +85,8 @@ public: void FillParametersIn(SpdBaseParSet* params); void LoadParametersFrom(SpdBaseParSet* params); - inline Int_t GetNErrors() const { return fNErrors; } + inline Int_t GetNErrors() const { return fNErrors; } + inline Int_t GetNFailedHits() const { return fNFailedHits; } protected: @@ -96,6 +105,7 @@ protected: /* Geometry */ + Bool_t fOwnGeoLoader; //! indicates geometry loader owning SpdGeoLoader* fGeoLoader; //! SPD geometry std::vector<TString> fGeoModules; //! geometry modules are to be built @@ -116,9 +126,15 @@ protected: Int_t fMinVertexNHits[2]; // number of hits in ITS Int_t fMinTrackerNHits[2]; // total number of hits in TSTB+TSTEC + Bool_t fPrimVertexOnly; // if true, select tracks which belong to primary vertex only (default = true) + std::map< Int_t, std::set<Int_t> > fTracksSelected; // list of selected tracks (id's) <event, set of tracks> Int_t fNErrors; + Int_t fNFailedHits; + + TString DetResKey(Int_t d, Char_t s) { return Form("Det%d_%c",d,s); } + std::map< TString, TVector3 > fResolution; // hit's resolution table ClassDef(SpdIdealTrackFinder,1) }; diff --git a/reco/CMakeLists.txt b/reco/CMakeLists.txt index f739d9080211b740ff8f143fe0d201ae488b4765..accb7825a11d2b643819de1d1d03fea10fa982d6 100644 --- a/reco/CMakeLists.txt +++ b/reco/CMakeLists.txt @@ -34,7 +34,10 @@ ${CMAKE_SOURCE_DIR}/external/GenFit2/fitters/include ${CMAKE_SOURCE_DIR}/external/GenFit2/measurements/include ${CMAKE_SOURCE_DIR}/external/GenFit2/trackReps/include ${CMAKE_SOURCE_DIR}/external/GenFit2/utilities/include +${CMAKE_SOURCE_DIR}/external/KFParticle/KFParticle +${CMAKE_SOURCE_DIR}/external/KFParticle/KFParticlePerformance ${CMAKE_SOURCE_DIR}/proc/tracking +${CMAKE_SOURCE_DIR}/proc/vertex ) include_directories( ${INCLUDE_DIRECTORIES}) @@ -49,14 +52,18 @@ link_directories( ${LINK_DIRECTORIES}) set(SRCS SpdIdealKalmanFitter.cxx +SpdIdealV0Finder.cxx ) +ADD_DEFINITIONS(-DHomogeneousField) +#ADD_DEFINITIONS(-DNonhomogeneousField) + Set(HEADERS ) set(LINKDEF SpdRecoLinkDef.h) set(LIBRARY_NAME SpdReco) -set(DEPENDENCIES Base GenFit2 SpdCommon SpdData SpdGeometry TrackingGF) +set(DEPENDENCIES Base GenFit2 SpdCommon SpdData SpdGeometry TrackingGF KFParticle) GENERATE_LIBRARY() diff --git a/reco/SpdIdealKalmanFitter.cxx b/reco/SpdIdealKalmanFitter.cxx index d5cc1e538a57c77868a61e67bd0c32aeec526da6..bc78d4430ab2d65a87ca883d3c0e9624b1af047b 100644 --- a/reco/SpdIdealKalmanFitter.cxx +++ b/reco/SpdIdealKalmanFitter.cxx @@ -25,10 +25,11 @@ #include "SpdIdealTrackData.hh" -#include "SpdGFMeasurementCreator.h" #include "SpdGFMagneticField.h" + #include "SpdKalmanFitterRefTrack.h" #include "KalmanFitterRefTrack.h" +#include "KalmanFitter.h" #include "RKTrackRep.h" #include "MeasuredStateOnPlane.h" @@ -57,14 +58,12 @@ ClassImp(SpdIdealKalmanFitter) //_____________________________________________________________________________ SpdIdealKalmanFitter::SpdIdealKalmanFitter():FairTask("SPD Ideal Kalman fitter"), -fField(0),fMeasCreator(0),fFitter(0),fGeoLoader(0), +fField(0),fMeasCreator(0),fFitter(0),fOwnGeoLoader(false),fGeoLoader(0), fEvent(0),fKFres(0),fTracks(0),fParameters(0), fVerboseLevel(1), // Fitter options: fMaterialsOpt(1), fSeedMomentum(1.), -fResolution(0.005), -fWireResolution(0.015), fVertexFitMethod(1), fVertexFitAngleCut(3.0), fStartSeedMethod(2), @@ -95,6 +94,17 @@ SpdIdealKalmanFitter::~SpdIdealKalmanFitter() if (fTracks) delete fTracks; } +//_____________________________________________________________________________ +void SpdIdealKalmanFitter::DeleteGeoLoader() +{ + if (fOwnGeoLoader && fGeoLoader) { + cout << "-I- <SpdIdealKalmanFitter::DeleteGeoLoader> Remove geometry loader" << endl; + delete fGeoLoader; + fGeoLoader = 0; + fOwnGeoLoader = false; + } +} + //_____________________________________________________________________________ void SpdIdealKalmanFitter::SetTrackingGeoModules(Bool_t add_passives) { @@ -109,8 +119,17 @@ void SpdIdealKalmanFitter::SetTrackingGeoModules(Bool_t add_passives) //_____________________________________________________________________________ void SpdIdealKalmanFitter::LoadGeometry() { - fGeoLoader = new SpdGeoLoader(); - fGeoLoader->LoadGeometry(); // load TOP level only (cave) + fGeoLoader = SpdGeoLoader::Instance(); + + if (!fGeoLoader) { + fGeoLoader = new SpdGeoLoader(); + fOwnGeoLoader = true; + } + else fOwnGeoLoader = false; + + if (fMaterialsOpt < 1) fGeoLoader->UnsetMaterials(true); // ATTENTION + + fGeoLoader->LoadGeometry(); // construct TOP level only (cave) //return; @@ -153,6 +172,7 @@ void SpdIdealKalmanFitter::InitFitter() if (fFitter) delete fFitter; if (fFitterOption == 1) fFitter = new KalmanFitterRefTrack(fFitterMaxIterations,1e-3,1e3,true); else fFitter = new KalmanFitterRefTrack(fFitterMaxIterations,1e-3,1e3,false); + //fFitter = new SpdKalmanFitterRefTrack(fFitterMaxIterations,1e-3,1e3,true); } //_____________________________________________________________________________ @@ -206,9 +226,8 @@ InitStatus SpdIdealKalmanFitter::Init() fKFres = new SpdKFSimpleRes(); ioman->Register("SpdKFSimpleRes.", "IdealKFres", fKFres, kTRUE); - //fTracks = new TClonesArray("GFTrack",100); fTracks = new TObjArray(100); - //ioman->Register("GFTrack", "GFTracks", fTracks, kTRUE); + if (fStoreTracks) ioman->Register("SpdGFTrackW.", "GFTracks", fTracks, kTRUE); cout << "-I- <SpdIdealKalmanFitter::Init> Intialization successfull " << endl; @@ -218,7 +237,7 @@ InitStatus SpdIdealKalmanFitter::Init() //________________________________________________________________________________________ void SpdIdealKalmanFitter::Exec(Option_t* opt) { - cout << "-I- <SpdIdealKalmanFitter::Exec> " << endl; + //cout << "-I- <SpdIdealKalmanFitter::Exec> " << endl; if (!fEvent) return; if (!fTracks) return; @@ -349,7 +368,7 @@ void SpdIdealKalmanFitter::Exec(Option_t* opt) cout << "-W- <SpdIdealKalmanFitter::Exec> Fitter errors: " << emsg << endl; } } - + if (!is_fitted) { not_fitted++; mcMom = itrack->GetStartMomentum(); @@ -359,7 +378,7 @@ void SpdIdealKalmanFitter::Exec(Option_t* opt) } status = (KalmanFitStatus*)track->getFitStatus(); - + if (status) { is_fitted = status->isFitted(); @@ -387,7 +406,7 @@ void SpdIdealKalmanFitter::Exec(Option_t* opt) cout << "-W- <SpdIdealKalmanFitter::Exec> Fitter errors: " << fKFres->GetErrorMessage(n) << endl; } } - + if (fVerboseLevel > 3) { cout << " >>>>>>> <SpdIdealKalmanFitter::Exec> track (finish): " << i << " is fitted: " << is_fitted << endl; } @@ -396,14 +415,34 @@ void SpdIdealKalmanFitter::Exec(Option_t* opt) not_fitted++; mcMom = itrack->GetStartMomentum(); fKFres->SetPmc(n,mcMom); + fKFres->AddErrorMessage(n,"not_fitted_track"); delete track; continue; } - + if (fKFres->GetConvergency(n)) nconv_tracks++; - + mcMom = itrack->GetStartMomentum(); - recMom = track->getFittedState().getMom(); + + track->checkConsistency(); + + // let's try to get averaged final state + try { + recMom = track->getFittedState().getMom(); + } + catch (Exception& e) { + is_fitted = false; + } + + // ill-conditioned covariance matrix (KalmanFitterInfo::calcAverageState) + if (!is_fitted) { + fKFres->SetIsFitted(n,is_fitted); + not_fitted++; + fKFres->SetPmc(n,mcMom); + fKFres->AddErrorMessage(n,"ill-conditioned_cov._matrix_in_the_final_state"); + delete track; + continue; + } if (fVerboseLevel > 3) { cout << " >>>>>>>>> <SpdIdealKalmanFitter::Exec> (finish 1): track = " << i << " / event: " << fEvent->GetEventId() @@ -544,46 +583,39 @@ genfit::Track* SpdIdealKalmanFitter::BuildTrack(Int_t n, genfit::Track* track) track = new Track(rep, seedState, seedCov); - // fill track + // add hits to the track Int_t NTrackHits = itrack->GetNHits(); for (Int_t j(0); j<NTrackHits; j++) { ihit = (SpdIdealHit*)itrack->GetHit(j); - - //if (ihit->GetDetId(0) == kSpdIts) continue; //FIXME - - fMeasCreator->SetResolution(HitResolution(ihit)); - - vector<AbsMeasurement*> measurements = fMeasCreator->CreateHit(ihit); + vector<AbsMeasurement*> measurements = fMeasCreator->CreateHit(ihit,GetHitRepresentation(ihit->GetDetId())); point = new TrackPoint(measurements,track); - track->insertPoint(point); } - - //track->checkConsistency(); return track; } //________________________________________________________________________________________ -Double_t SpdIdealKalmanFitter::HitResolution(const SpdIdealHit* hit) const +void SpdIdealKalmanFitter::SetHitRepresentation(Int_t DetId, GFMeasurementType GFhitType) { - SpdHitType detID = SpdHitType(hit->GetDetId(0)); - - // cm - switch (detID) - { - case kSpdIts: return fResolution; - case kSpdTsTB: return fWireResolution; - case kSpdTsTEC: return fWireResolution; - default: break; - } - - return 0.010; // 100 mkm + fHitRepresentation[DetId] = GFhitType; + +// for (auto& it1 : fHitRepresentation) { +// cout << "Size: " << fHitRepresentation.size() +// << " Detector/Hit: " << it1.first << " " << it1.second << endl; +// } } +//________________________________________________________________________________________ +GFMeasurementType SpdIdealKalmanFitter::GetHitRepresentation(Int_t DetId) const +{ + auto it = fHitRepresentation.find(DetId); + return (it != fHitRepresentation.end()) ? GFMeasurementType(it->second) : pkSpacepoint; +} + //________________________________________________________________________________________ void SpdIdealKalmanFitter::DefineTrackStartVertexAndMom(const SpdIdealTrack* track) { @@ -635,7 +667,7 @@ void SpdIdealKalmanFitter::DefineTrackStartVertexAndMom(const Int_t ntrack, cons hit = static_cast<SpdIdealSpacepointHit*>(xhit); if (!hit) continue; if (++npx > np) nerr = 1; - points.push_back(hit->GetPoint()); + points.push_back(hit->GetHit()); } TVector3 p1(0,0,0), n1(0,0,1); @@ -965,12 +997,22 @@ void SpdIdealKalmanFitter::FillParametersIn(SpdBaseParSet* params) params->SetParameter("IdealKalmanFitter/MaterialsOpt",fMaterialsOpt); params->SetParameter("IdealKalmanFitter/SeedMomentum",fSeedMomentum); - params->SetParameter("IdealKalmanFitter/Resolution",fResolution); - params->SetParameter("IdealKalmanFitter/WireResolution",fWireResolution); - params->SetParameter("IdealKalmanFitter/VertexFitMethod",fVertexFitMethod); params->SetParameter("IdealKalmanFitter/VertexFitAngleCut",fVertexFitAngleCut); + Int_t n = fHitRepresentation.size(); + + params->SetParameter("IdealKalmanFitter/NHRepresentations",n); + + if (n > 0) { + Int_t i(0); + for (auto& it : fHitRepresentation) { + params->SetParameter(Form("IdealKalmanFitter/HitRepDetId[%d]",i),it.first); + params->SetParameter(Form("IdealKalmanFitter/HitRepDet[%d]",i),it.second); + i++; + } + } + params->SetParameter("IdealKalmanFitter/fStartSeedMethod",fStartSeedMethod); params->SetParameter("IdealKalmanFitter/fSmearSeedValues",fSmearSeedValues); @@ -999,6 +1041,8 @@ void SpdIdealKalmanFitter::LoadParametersFrom(SpdBaseParSet* params) { if (!params) return; + fHitRepresentation.clear(); + Int_t pi; Double_t pd; Bool_t pb; @@ -1006,12 +1050,20 @@ void SpdIdealKalmanFitter::LoadParametersFrom(SpdBaseParSet* params) if (params->GetParameter("IdealKalmanFitter/MaterialsOpt",pi)) SetMaterialEffectsOption(pi); if (params->GetParameter("IdealKalmanFitter/SeedMomentum",pd)) SetSeedMomentum(pd); - if (params->GetParameter("IdealKalmanFitter/Resolution",pd)) SetResolution(pd); - if (params->GetParameter("IdealKalmanFitter/WireResolution",pd)) SetWireResolution(pd); - if (params->GetParameter("IdealKalmanFitter/VertexFitMethod",pi)) SetVertexFindingMethod(pi); if (params->GetParameter("IdealKalmanFitter/VertexFitAngleCut",pd)) SetVertexFindingAngleCut(pd); + if (params->GetParameter("IdealKalmanFitter/NHRepresentations",pi)) { + if (pi > 0) { + Int_t pi2, pi3; + for (Int_t i(0); i<pi; i++) { + params->GetParameter(Form("IdealKalmanFitter/HitRepDetId[%d]",i),pi2); + params->GetParameter(Form("IdealKalmanFitter/HitRepDet[%d]",i),pi3); + fHitRepresentation[pi2] = pi3; + } + } + } + if (params->GetParameter("IdealKalmanFitter/fStartSeedMethod",pi)) SetStartSeedMethod(pi); if (params->GetParameter("IdealKalmanFitter/fSmearSeedValues",pb)) SetSmearSeedValues(pb); diff --git a/reco/SpdIdealKalmanFitter.h b/reco/SpdIdealKalmanFitter.h index 3a020c33614f880d9d4fe031f556d4b49e536626..47c43285bdc9a96ec4cb83cf682d10f9186fcde8 100644 --- a/reco/SpdIdealKalmanFitter.h +++ b/reco/SpdIdealKalmanFitter.h @@ -11,7 +11,9 @@ #include "SpdGeoLoader.h" #include "SpdIdealTrack.h" #include "SpdBaseParSet.h" +#include "SpdGFMeasurementCreator.h" #include "AbsKalmanFitter.h" +//#include <map> //////////////////////////////////////////////////////////////////////////////// // // @@ -44,6 +46,8 @@ public: virtual void Exec(Option_t* opt); virtual void Finish(); + void DeleteGeoLoader(); + /* SETTERS */ void SetVerboseLevel(Int_t level) { fVerboseLevel = level; } @@ -51,8 +55,7 @@ public: void SetMaterialEffectsOption(Int_t opt /*-1,0(default),1 */) { fMaterialsOpt = opt; } void SetSeedMomentum(Double_t mom /* GeV/c */) { fSeedMomentum = fabs(mom); } - void SetResolution(Double_t res /*cm*/) { fResolution = res; } - void SetWireResolution(Double_t res /*cm*/) { fWireResolution = res; } + void SetHitRepresentation(Int_t DetId, GFMeasurementType GFhitType); void SetVertexFindingMethod(Int_t method) { fVertexFitMethod = method; } void SetVertexFindingAngleCut(Double_t acut /*deg*/) { fVertexFitAngleCut = acut; } @@ -72,6 +75,11 @@ public: void SetStoreTracks(Bool_t store = true) { fStoreTracks = store; } + /* GETTERS */ + + SpdGFMeasurementCreator* GetMeasurementCreator() { return fMeasCreator; } + + // Parameters void FillParametersIn(SpdBaseParSet* params); void LoadParametersFrom(SpdBaseParSet* params); @@ -89,7 +97,7 @@ private: genfit::Track* BuildTrack(Int_t n, genfit::Track* track = 0); - Double_t HitResolution(const SpdIdealHit* hit) const; + GFMeasurementType GetHitRepresentation(Int_t DetId) const; void DefineTrackStartVertexAndMom(const SpdIdealTrack* track); void DefineTrackStartVertexAndMom(const Int_t ntrack, const SpdIdealTrack* track); @@ -98,7 +106,7 @@ private: void FindVertex(TVector3& vertex); /* Geometry */ - + Bool_t fOwnGeoLoader; //! indicates geometry loader owning SpdGeoLoader* fGeoLoader; //! SPD geometry std::vector<TString> fGeoModules; //! geometry modules are to be built @@ -118,8 +126,7 @@ private: // standard Double_t fSeedMomentum; // start track vertex momentum [GeV/c] - Double_t fResolution; // cm - Double_t fWireResolution; // cm + std::map<Int_t,Int_t> fHitRepresentation; // <Detector Id, GFMeasurementType> // advanced Int_t fVertexFitMethod; // <1 (no fit); 1 (default) diff --git a/reco/SpdIdealV0Finder.cxx b/reco/SpdIdealV0Finder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..44a653341486832cfcf63940087f54317f1410d3 --- /dev/null +++ b/reco/SpdIdealV0Finder.cxx @@ -0,0 +1,1424 @@ +// $Id$ +// Author: vladimir andreev 2020/08/29 + +//_____________________________________________________________________________ +// +// SpdIdealV0Finder +//_____________________________________________________________________________ + +#include <TRandom.h> +#include <TVectorD.h> +#include <TMatrixDSym.h> + +#include "FairRuntimeDb.h" +#include "FairRootManager.h" +#include "FairRun.h" +#include "FairRunAna.h" + +#include "SpdFieldCreator.h" +#include "SpdFieldPar.h" + +#include "SpdIdealV0Finder.h" + +#include "SpdGeoLoader.h" +#include "SpdKFSimpleRes.h" + +#include "SpdIdealTrackData.hh" + +#include "SpdGFMagneticField.h" + +#include "SpdKalmanFitterRefTrack.h" +#include "KalmanFitterRefTrack.h" +#include "KalmanFitter.h" + +#include "RKTrackRep.h" +#include "MeasuredStateOnPlane.h" +#include "Track.h" +#include "TrackPoint.h" +#include "Exception.h" +#include "KalmanFitStatus.h" + +#include <vector> +#include <iostream> + +using std::cout; +using std::endl; +using std::vector; + +#include "GFCore.hh" +#include "GFTrackReps.hh" + +#include "SpdGFTrackW.h" + +using namespace genfit; + +//using TMath::SignBit; + +ClassImp(SpdIdealV0Finder) + +//_____________________________________________________________________________ +SpdIdealV0Finder::SpdIdealV0Finder():FairTask("SPD Ideal V0 finder"), +fField(0),fMeasCreator(0),fFitter(0),fOwnGeoLoader(false),fGeoLoader(0), +fEvent(0),fKFres(0),fTracks(0),fParameters(0), +fVerboseLevel(1), +// Fitter options: +fMaterialsOpt(1), +fSeedMomentum(1.), +fVertexFitMethod(1), +fVertexFitAngleCut(3.0), +fStartSeedMethod(2), +fSmearSeedValues(true), +fSmearingMomDelta(0.1), +fSmearingAngleDelta(3.0), +fSmearingVertexDelta(0.5), +fNPointsVertexUse(0), +fFitterMaxIterations(8), +fFitterMaxTrials(10), +fFitterOption(1), +fStoreTracks(false), +// V0 finder +fFirstDaughter(321), +fSecondDaughter(211), +fUsedTypeOfPV(0), +fConstrainToPV(1), +fMinChi2PV(2.0), +fMinDist(0.075), +fMinMass(0.00), +fMaxMass(2.50) +{ + +} + +//_____________________________________________________________________________ +SpdIdealV0Finder::~SpdIdealV0Finder() +{ + if (fField) delete fField; + if (fMeasCreator) delete fMeasCreator; + if (fFitter) delete fFitter; + + if (fGeoLoader) delete fGeoLoader; + + if (fEvent) delete fEvent; + if (fKFres) delete fKFres; + if (fTracks) delete fTracks; + + if (fV0file) delete fV0file; + if (fV0tree) delete fV0tree; +} + +//_____________________________________________________________________________ +void SpdIdealV0Finder::DeleteGeoLoader() +{ + if (fOwnGeoLoader && fGeoLoader) { + cout << "-I- <SpdIdealD0Finder::DeleteGeoLoader> Remove geometry loader" << endl; + delete fGeoLoader; + fGeoLoader = 0; + fOwnGeoLoader = false; + } + +} + +//_____________________________________________________________________________ +void SpdIdealV0Finder::SetTrackingGeoModules(Bool_t add_passives) +{ + fGeoModules.clear(); + if (add_passives) fGeoModules.push_back("Passives"); + + fGeoModules.push_back("Inner tracker system"); + fGeoModules.push_back("TS barrel (tor)"); + fGeoModules.push_back("TS endcaps (tor)"); +} + +//_____________________________________________________________________________ +void SpdIdealV0Finder::LoadGeometry() +{ + fGeoLoader = SpdGeoLoader::Instance(); + + if (!fGeoLoader) { + fGeoLoader = new SpdGeoLoader(); + fOwnGeoLoader = true; + } + else fOwnGeoLoader = false; + + if (fMaterialsOpt < 1) fGeoLoader->UnsetMaterials(true); // ATTENTION + + fGeoLoader->LoadGeometry(); // construct TOP level only (cave) + + //return; + + Int_t n = fGeoModules.size(); + + if (n < 1) return; + + for (Int_t i(0); i<n; i++) { + if (fGeoModules[i].IsDigit()) fGeoLoader->LoadModule(fGeoModules[i].Atoi()); + else fGeoLoader->LoadModule(fGeoModules[i]); + } + + fGeoLoader->PrintActualGeometry(); + + MaterialEffects::getInstance()->init(new TGeoMaterialInterface()); +} + +//_____________________________________________________________________________ +void SpdIdealV0Finder::LoadField() +{ + FairRuntimeDb* rtdb = FairRun::Instance()->GetRuntimeDb(); + SpdFieldCreator* fieldCreator = new SpdFieldCreator(); + SpdFieldPar *fpars = (SpdFieldPar*)rtdb->getContainer("SpdFieldPar"); + + fField = new SpdGFMagneticField(); + + if (fpars) { + ((FairParSet*)fpars)->init(); + SpdField* field = (SpdField*)fieldCreator->createFairField(fpars); + fField->SetField(field,kTRUE); + if (field) field->Print(""); + } + + FieldManager::getInstance()->init(fField); +} + +//_____________________________________________________________________________ +void SpdIdealV0Finder::InitFitter() +{ + if (fFitter) delete fFitter; + if (fFitterOption == 1) fFitter = new KalmanFitterRefTrack(fFitterMaxIterations,1e-3,1e3,true); + else fFitter = new KalmanFitterRefTrack(fFitterMaxIterations,1e-3,1e3,false); + //fFitter = new SpdKalmanFitterRefTrack(fFitterMaxIterations,1e-3,1e3,true); +} + +//_____________________________________________________________________________ +InitStatus SpdIdealV0Finder::Init() +{ + // get RootManager + + FairRootManager* ioman = FairRootManager::Instance(); + if (!ioman) { + cout << "-E- <SpdIdealV0Finder::Init> " + << "RootManager not instantiated!" << endl; + return kFATAL; + } + + // Load Field, Geometry + + LoadField(); + LoadGeometry(); + + // Init + fMeasCreator = new SpdGFMeasurementCreator(); + + // Init Fitter + InitFitter(); + + // get Input data objects + + fEvent = (SpdIdealTrackColl*)ioman->GetObject("IdealTrackColl."); + + if (!fEvent) { + cout << "-E- <SpdIdealV0Finder::Init>" << "No HEADER object inside " << endl; + return kERROR; + } + + TFile* infile = ioman->GetInFile(); + if (infile) fParameters = (SpdBaseParSet*)infile->Get("IdealTrackFinderParams"); + if (!fParameters) fParameters = new SpdBaseParSet(); + + fParameters->print(1); + + FillParametersIn(fParameters); + + TFile* f = gFile; + TFile* ff = ioman->GetOutFile(); + ff->cd(); +// fParameters->Write("IdealKalmanFitterParams",TObject::kOverwrite); + fParameters->Write("IdealV0FinderParams",TObject::kOverwrite); + gFile = f; + + // Create and register output data objects + + fKFres = new SpdKFSimpleRes(); + ioman->Register("SpdKFSimpleRes.", "IdealKFres", fKFres, kTRUE); + + fTracks = new TObjArray(100); + if (fStoreTracks) ioman->Register("SpdGFTrackW.", "GFTracks", fTracks, kTRUE); + + cout << "-I- <SpdIdealV0Finder::Init> Intialization successfull " << endl; + + // name of output root-file for V0 particle + //-------------------------------------------- + FairRunAna* userFile = FairRunAna::Instance(); + if (!userFile) { + cout << "-E- <SpdIdealV0Finder::Init> " + << "FairRunAna not instantiated!" << endl; + return kFATAL; + } + + TString v0_outfile_name = userFile->GetUserOutputFileName(); + InitV0nTuple( v0_outfile_name); + + return kSUCCESS; +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::Exec(Option_t* opt) +{ + //cout << "-I- <SpdIdealV0Finder::Exec> " << endl; + + if (!fEvent) return; + if (!fTracks) return; + if (!fKFres) return; + + //if (fVerboseLevel > 0) + cout << "-I- <SpdIdealV0Finder::Exec> Event: " << fEvent->GetEventId() << endl; + + fKFres->ClearData(); + fTracks->Delete(); + + // Init Fitter + //InitFitter(); + + fKFres->SetRunId(fEvent->GetRunId()); + fKFres->SetEventId(fEvent->GetEventId()); + fKFres->SetNPrimTracks(fEvent->GetNPrimTracks()); + + TVector3 mcMom, recMom; + Track* track(0); + + TObjArray* tracks = fEvent->GetTracks(); + Int_t NTracks = tracks->GetEntriesFast(); + + fKFres->SetNSelectedTracks(NTracks); + + Int_t n; + + SpdIdealDataInfo* dinfo_its = fEvent->FindDataInfo(kSpdIts); + SpdIdealDataInfo* dinfo_tstb = fEvent->FindDataInfo(kSpdTsTB); + SpdIdealDataInfo* dinfo_tstec = fEvent->FindDataInfo(kSpdTsTEC); + + KalmanFitStatus* status; + + Bool_t material_effects; + + static Int_t ntotal_tracks = 0; + static Int_t nconv_tracks = 0; + static Int_t ncorrd = 0; + static Int_t not_fitted = 0; + static Int_t n_errors = 0; + static Int_t n_good = 0; + + Int_t n_refit; + Bool_t refit_tracks = false; + + if (fMaterialsOpt < 1) { + material_effects = false; + MaterialEffects::getInstance()->setNoEffects(true); + } + else { + material_effects = true; + MaterialEffects::getInstance()->setNoEffects(false); + } + + Exception::setEmessgflag(true); + + for (Int_t i(0); i<NTracks; i++) { + + SpdIdealTrack* itrack = (SpdIdealTrack*)tracks->At(i); + + if (fVerboseLevel > 3) { + cout << " >>>>>>> <SpdIdealV0Finder::Exec> track (start): " << i << " / event: " << fEvent->GetEventId() + << " points = " << itrack->GetNPoints() << endl; + } + + //itrack->PrintTrack(); + //continue; + + ntotal_tracks++; + + n = fKFres->AddTrack(itrack->GetTrackId(),itrack->GetPdgCode()); + + if (dinfo_its) fKFres->SetNVhits(n,dinfo_its->GetTrackHits(n)); + if (dinfo_tstb) fKFres->SetNTBhits(n,dinfo_tstb->GetTrackHits(n)); + if (dinfo_tstec) fKFres->SetNTEChits(n,dinfo_tstec->GetTrackHits(n)); + + // build track + track = BuildTrack(i); + if (!track) continue; + + Bool_t is_fitted = false; + + n_refit = 0; + + while (true) { + + try + { + fFitter->processTrack(track); + is_fitted = true; + } + catch(Exception& e) + { + is_fitted = false; + } + + if (n_refit < fFitterMaxTrials) { + status = (KalmanFitStatus*)track->getFitStatus(); + if (status && !status->isFitConverged()) { + n_refit++; + if (fVerboseLevel > 2) cout << "\t Rebuild and refit track: " << n_refit << "/" << fFitterMaxTrials << endl; + track = BuildTrack(i,track); + Exception::clearEmessg(); + continue; + } + } + + //track->checkConsistency(); + + break; + } + + Int_t nem = Exception::getNEmessg(); + if (nem > 0) { + n_errors++; + TString emsg; + for (Int_t j(0); j<nem; j++) { + emsg += Exception::getEmessg(j); + if (j != nem-1) emsg += "/"; + } + Exception::clearEmessg(); + + fKFres->SetErrorFlag(n,1); + fKFres->SetErrorMessage(n,emsg); + + if (fVerboseLevel > 2) { + cout << "-W- <SpdIdealV0Finder::Exec> Fitter errors: " << emsg << endl; + } + } + + if (!is_fitted) { + not_fitted++; + mcMom = itrack->GetStartMomentum(); + fKFres->SetPmc(n,mcMom); + delete track; + continue; + } + + status = (KalmanFitStatus*)track->getFitStatus(); + + if (status) { + + is_fitted = status->isFitted(); + fKFres->SetIsFitted(n,is_fitted); + + fKFres->SetMaterialEffects(n,material_effects); + fKFres->SetNFailedHits(n,status->getNFailedPoints()); + fKFres->SetConvergency(n,0); + if (status->isFitConvergedPartially()) fKFres->SetConvergency(n,-1); + if (status->isFitConvergedFully()) fKFres->SetConvergency(n,1); + } + else { + + is_fitted = false; + fKFres->SetIsFitted(n,is_fitted); + + fKFres->SetMaterialEffects(n,material_effects); + fKFres->SetConvergency(n,0); + + fKFres->AddErrorMessage(n,"Unknown_error:_no_fit_status"); + + if (!(nem > 0)) n_errors++; + + if (fVerboseLevel > 2) { + cout << "-W- <SpdIdealV0Finder::Exec> Fitter errors: " << fKFres->GetErrorMessage(n) << endl; + } + } + + if (fVerboseLevel > 3) { + cout << " >>>>>>> <SpdIdealV0Finder::Exec> track (finish): " << i << " is fitted: " << is_fitted << endl; + } + + if (!is_fitted) { + not_fitted++; + mcMom = itrack->GetStartMomentum(); + fKFres->SetPmc(n,mcMom); + fKFres->AddErrorMessage(n,"not_fitted_track"); + delete track; + continue; + } + + if (fKFres->GetConvergency(n)) nconv_tracks++; + + mcMom = itrack->GetStartMomentum(); + + track->checkConsistency(); + + // let's try to get averaged final state + try { + recMom = track->getFittedState().getMom(); + } + catch (Exception& e) { + is_fitted = false; + } + + // ill-conditioned covariance matrix (KalmanFitterInfo::calcAverageState) + if (!is_fitted) { + fKFres->SetIsFitted(n,is_fitted); + not_fitted++; + fKFres->SetPmc(n,mcMom); + fKFres->AddErrorMessage(n,"ill-conditioned_cov._matrix_in_the_final_state"); + delete track; + continue; + } + + if (fVerboseLevel > 3) + { +// cout << " >>>>>>>>> <SpdIdealV0Finder::Exec> (finish 1): track = " + cout << " track = " + << i << " / event: " << fEvent->GetEventId() + << " mom (mc) = " << itrack->GetStartMomentumMag() + << " mom (rec) = " << recMom.Mag() + << " pdg = " << itrack->GetPdgCode() << endl; + +// cout <<" >>>>>>>>> <SpdIdealV0Finder::Exec> (finish 2): track = " << i << " / event: " << fEvent->GetEventId() +// << " mom (rec) = " << recMom.Mag() << endl; + } + + // particle charge correction FIXME + if (mcMom.Dot(recMom) < 0) { + recMom *= -1; + fKFres->AddErrorMessage(n,"Track_is_turned_out"); + + ncorrd++; + if (!(nem > 0)) n_errors++; + + if (fVerboseLevel > 2) cout << "-W- <SpdIdealV0Finder::Exec> Fitter errors: " << fKFres->GetErrorMessage(n) << endl; + } + + fKFres->SetSeedMomentum(n,fStartMomentum); + fKFres->SetSeedVertex(n,fStartVertex); + fKFres->SetSeedCov(n,fStartSeedCov); + + fKFres->SetPmc(n,mcMom); + fKFres->SetPrec(n,recMom); + + if (fKFres->GetIsGood(n)) n_good++; + + Double_t chi2 = status->getForwardChi2(); + Int_t ndf = status->getForwardNdf(); + + if (chi2 > 0 && ndf > 0) { + fKFres->SetChi2(n,chi2); + fKFres->SetNDF(n,ndf); + if (TMath::Abs(chi2) > 1e-8) fKFres->SetChi2Delta(n,(chi2-status->getBackwardChi2())/chi2); + } + +// if (fVerboseLevel > 1) + if (fVerboseLevel > 3) + { + cout << " >>>>>>> <SpdIdealV0Finder::Exec> Fitted tracks (nice/total): " + << n_good << "/" << ntotal_tracks << " = " << 0.01*Int_t(10000.*(1-n_good/Double_t(ntotal_tracks))) << " % " + << " (" << ncorrd << ") " + << " n/fitted: " << not_fitted + << "; n/converged: " << ntotal_tracks-nconv_tracks + << "; errors: " << n_errors + << "; chi2/NDF: " << status->getForwardChi2() << "/" << status->getForwardNdf() + << " => " << fKFres->GetChi2toNDF(n) << ", d(chi2) = " << fKFres->GetChi2Delta(n) << endl; + } + + track->setMcTrackId(n); // ATTENTION here n is NOT mc-track id (mc-track id = itrack->GetTrackId()) + + fTracks->Add(new SpdGFTrackW(track,n)); + } + + Exception::setEmessgflag(false); + + if (fVerboseLevel > 2) cout << "\n >>>>>>> VERTEX RECONSTRUCTION " << endl; + + //return; + + // Interaction vertex + + TVector3 v_mc = fEvent->GetVertex(); + TVector3 v_rec; + + if (fVertexFitMethod > 0) FindVertex(v_rec); + + fKFres->SetVertex(v_mc,v_rec); + + NTracks = fTracks->GetEntriesFast(); + SpdGFTrackW* t; + + for (Int_t i(0); i<NTracks; i++) + { + t = (SpdGFTrackW*)fTracks->At(i); + n = t->GetDataID(); + + MeasuredStateOnPlane s = t->GetTrack()->getFittedState(); + TMatrixDSym cov = s.get6DCov().GetSub(3,5,3,5); + + fKFres->SetMomCov(n,cov); + } + + FindDecayVertex(); // V0 vertex finder + + //fKFres->PrintData(); + //cout << "\n\n"; + + fEvent->DeleteAll(); +} + +//________________________________________________________________________________________ +genfit::Track* SpdIdealV0Finder::BuildTrack(Int_t n, genfit::Track* track) +{ + if (track) { + delete track; + track = 0; + } + + TObjArray* tracks = fEvent->GetTracks(); + if (!tracks) return 0; + + SpdIdealTrack* itrack = (SpdIdealTrack*)tracks->At(n); + if (!itrack) return 0; + + SpdIdealHit* ihit; + TrackPoint* point; + + AbsTrackRep* rep = new RKTrackRep(itrack->GetPdgCode()); + + // (1) init start state + + MeasuredStateOnPlane state(rep); + + // (2) init start position and momentum + + if (fStartSeedMethod == 1) DefineTrackStartVertexAndMom(itrack); + else if (fStartSeedMethod == 2) DefineTrackStartVertexAndMom(n,itrack); + else DefineTrackStartVertexAndMom(itrack); + + // (3) init covariance + + DefineStartVertexCovariance(); + + // set start values: state, position, momentum, covariance + + rep->setPosMomCov(state, fStartVertex, fStartMomentum, fStartSeedCov); + + // --------- create track --------- + + TVectorD seedState(6); + TMatrixDSym seedCov(6); + + rep->get6DStateCov(state, seedState, seedCov); + + track = new Track(rep, seedState, seedCov); + + // add hits to the track + + Int_t NTrackHits = itrack->GetNHits(); + + for (Int_t j(0); j<NTrackHits; j++) { + + ihit = (SpdIdealHit*)itrack->GetHit(j); + vector<AbsMeasurement*> measurements = fMeasCreator->CreateHit(ihit,GetHitRepresentation(ihit->GetDetId())); + point = new TrackPoint(measurements,track); + track->insertPoint(point); + } + + return track; +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::SetHitRepresentation(Int_t DetId, GFMeasurementType GFhitType) +{ + fHitRepresentation[DetId] = GFhitType; + +// for (auto& it1 : fHitRepresentation) { +// cout << "Size: " << fHitRepresentation.size() +// << " Detector/Hit: " << it1.first << " " << it1.second << endl; +// } +} + +//________________________________________________________________________________________ +GFMeasurementType SpdIdealV0Finder::GetHitRepresentation(Int_t DetId) const +{ + auto it = fHitRepresentation.find(DetId); + return (it != fHitRepresentation.end()) ? GFMeasurementType(it->second) : pkSpacepoint; +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::DefineTrackStartVertexAndMom(const SpdIdealTrack* track) +{ + fStartVertex = track->GetPrimVertex(); + fStartMomentum = track->GetStartMomentum(); + + fStartMomentum.SetMag(fSeedMomentum); + + if (!fSmearSeedValues) return; + + fStartVertex.SetX(gRandom->Uniform(fStartVertex.X()-fSmearingVertexDelta,fStartVertex.X()+fSmearingVertexDelta)); // cm + fStartVertex.SetY(gRandom->Uniform(fStartVertex.Y()-fSmearingVertexDelta,fStartVertex.X()+fSmearingVertexDelta)); // cm + fStartVertex.SetZ(gRandom->Uniform(fStartVertex.Z()-fSmearingVertexDelta,fStartVertex.X()+fSmearingVertexDelta)); // cm + + Double_t theta = gRandom->Gaus(fStartMomentum.Theta(),fSmearingAngleDelta*TMath::DegToRad()); + Double_t phi = gRandom->Gaus(fStartMomentum.Phi(),fSmearingAngleDelta*TMath::DegToRad()); + + fStartMomentum.SetMagThetaPhi(gRandom->Uniform(fSeedMomentum-fSmearingMomDelta,fSeedMomentum+fSmearingMomDelta),theta,phi); +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::DefineTrackStartVertexAndMom(const Int_t ntrack, const SpdIdealTrack* track) +{ + SpdIdealDataInfo* info = fEvent->FindDataInfo(kSpdIts); + + Int_t np(0); + if (info) np = info->GetTrackHits(ntrack); + + if (np < 1) cout << "-W- <SpdIdealD0Finder::TrackStartVertexAndMom> Its points (data): " << np << endl; + + TObjArray* hits = track->GetHits(); + Int_t nhits = hits->GetEntriesFast(); + SpdIdealHit* xhit; + SpdIdealSpacepointHit* hit; + + Long_t id; + + std::vector<TVector3> points; + if (np > 0) points.reserve(np); + + Int_t na = nhits; + if (fNPointsVertexUse > 0 && fNPointsVertexUse < nhits) na = fNPointsVertexUse; + + Int_t npx(0), nerr(0); + for (Int_t i(0); i<na; i++) { + xhit = (SpdIdealHit*)hits->At(i); + id = xhit->GetDetId(0); + if (id != kSpdIts) continue; + hit = static_cast<SpdIdealSpacepointHit*>(xhit); + if (!hit) continue; + if (++npx > np) nerr = 1; + points.push_back(hit->GetHit()); + } + + TVector3 p1(0,0,0), n1(0,0,1); + TVector3 p2 = points[0], n2; + + if (npx == 1) n2 = points[0]; + else { + TVector3 nn; + for (Int_t i(0); i<npx-1; i++) { + p2 += points[i+1]; + for (Int_t j = i+1; j<npx; j++) { + nn = points[j]-points[i]; + nn.SetMag(1); + n2 += nn; + } + } + p2 *= 1./npx; + } + + n2.SetMag(1); + + Double_t theta = n2.Theta(); + Double_t phi = points[0].Phi(); + + if (fSmearSeedValues) { + Double_t mmag = gRandom->Uniform(fSeedMomentum-fSmearingMomDelta,fSeedMomentum+fSmearingMomDelta); + fStartMomentum.SetMagThetaPhi(mmag,theta,phi); + } + else fStartMomentum.SetMagThetaPhi(fSeedMomentum,theta,phi); + + if (npx < 2) { + fStartVertex.SetXYZ(0,0,0); + } + else { + + fStartVertex = p2; + + Double_t c = n1.Dot(n2); + Double_t cc = 1.-c*c; + + if (cc < 1.e-12) { + cout << "-W- <SpdIdealV0Finder::TrackStartVertexAndMom> Vertex is very far from origin: " << endl; + (p2.Z() < 0) ? fStartVertex.SetXYZ(0,0,1.e9) : fStartVertex.SetXYZ(0,0,-1.e9); + return; + } + + TVector3 p0 = p2-p1; + Double_t f = (c*p0.Dot(n1)-p0.Dot(n2))/cc; + + fStartVertex += f*n2; + + fStartVertex.SetX(0); + fStartVertex.SetY(0); + } + +// cout << "\t-I- <SpdIdealKalmanFitter::TrackStartVertexAndMom>" +// << " points: " << npx << "/" << np << ", warnings: " << nerr +// << "; theta: " << track->GetStartMomentum().Theta()*TMath::RadToDeg() << " -> " << theta*TMath::RadToDeg() +// << ", phi: " << track->GetStartMomentum().Phi()*TMath::RadToDeg() << " -> " << phi*TMath::RadToDeg() +// << ", v(z): " << track->GetPrimVertex().Z() << " -> " << fStartVertex.Z() << endl; +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::DefineStartVertexCovariance() +{ + fStartSeedCov.Clear(); + fStartSeedCov.ResizeTo(6,6); + + for (Int_t i(0); i < 3; i++) fStartSeedCov(i,i) = 10.; // position + for (Int_t i(3); i < 6; i++) fStartSeedCov(i,i) = 100.; // momentum +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::FindVertex(TVector3& vertex) +{ + vertex.SetXYZ(0,0,0); + + //--------------------------------------- + // vertex fit program for CBM experiment + //--------------------------------------- + + if (!fTracks) return; + + // Iterative fit of the vertex (CDM) + //---------------------------------- + const Double_t CutChi2 = 3.5*3.5; + const Int_t MaxIter = 3; + + // Vertex state vector and covariance matrix + //------------------------------------------- + Double_t r[3] = {0,0,0}; + Double_t C[6]; + + for(Int_t i = 0; i<6; i++) C[i] = 0; + C[0] = C[2] = 5.; + C[5] = 0.25; + + // Chi^2 & NDF + //------------------------------------------- + Int_t refNDF; + Double_t refChi2; + + // Iterative fit of the vertex + //----------------------------- + for (Int_t iteration = 0; iteration < MaxIter; ++iteration) + { + // Store the vertex from the previous iteration + //--------------------------------------------- + Double_t r0[3], C0[6]; + for( Int_t i=0; i<3; i++ ) r0[i] = r[i]; + for( Int_t i=0; i<6; i++ ) C0[i] = C[i]; + + // Initialize the vertex covariance, Chi^2 & NDF + //----------------------------------------------- + C[0] = 100.; + C[1] = 0.; C[2] = 100.; + C[3] = 0.; C[4] = 0.; C[5] = 100.; + + refNDF = -3; + refChi2 = 0.0; + + Int_t NTracks = fTracks->GetEntriesFast(); + + SpdGFTrackW* wtr; + Track* track; + Int_t ntrack; + + TMatrixDSym vCov; + TVector3 vPos, vMom; + + // start loop over tracks + //----------------------- + + for (Int_t itrk(0); itrk < NTracks; ++itrk) { + + wtr = (SpdGFTrackW*)fTracks->At(itrk); + + track = wtr->GetTrack(); + ntrack = wtr->GetDataID(); + + if (!fKFres->GetIsFitted(ntrack)) continue; // FIXME + if (fKFres->GetConvergency(ntrack) != 1) continue; // FIXME + + MeasuredStateOnPlane stateF = track->getFittedState(); // copy + + Double_t mTheta = stateF.getDir().Theta(); + + // skip tracks with theta 90+-fVertexFitAngleCut [degrees] + if (fabs(mTheta-TMath::PiOver2()) < fVertexFitAngleCut*TMath::DegToRad()) continue; // FIXME + + TVector3 planePos(0.0, 0.0, r0[2]); + TVector3 planeDir(0.0, 0.0, 1.0); + + SharedPlanePtr plane(new DetPlane(planePos, planeDir)); + + stateF.getPosMomCov(vPos, vMom, vCov); // in global, before extrapolation + + // ATTENTION --- track extrapolation --- ATTENTION + try + { + stateF.extrapolateToPlane(plane); + } + catch(Exception& e) + { + fKFres->SetPrec(ntrack,vMom); + continue; + } + + stateF.getPosMomCov(vPos, vMom, vCov); // in global, after extrapolation + + if (iteration == MaxIter-1) { + + // Update track momentum and its covariance + fKFres->SetPrec(ntrack,vMom); + + // cout << "TRACK: " << itrk << endl; + // cout << "POS: " << vPos.X() << " " << vPos.Y() << " " << vPos.Z() << endl; + // cout << "MOM: " << vMom.X() << " " << vMom.Y() << " " << vMom.Z() << endl; + // cout << "pt = " << vMom.Perp() << " p = " << vMom.Mag() << endl; + + } + + TVectorD& state = stateF.getState(); // on plane, 5 + TMatrixDSym& covV = stateF.getCov(); // on plane, 5x5 + + TVector3 vMU(-state[1], -state[2], 1.0); + + Double_t vV[10] = { covV[3][3], covV[3][4], covV[4][4], + covV[1][3], covV[1][4], covV[1][1], + covV[2][3], covV[2][4], covV[2][1], + covV[2][2] }; + + Double_t a = 0, b = 0; + { + Double_t zeta[2] = { r0[0]-vPos.X(), r0[1]-vPos.Y() }; + + // Check the track Chi^2 deviation from the r0 vertex estimate + //------------------------------------------------------------- + Double_t S[3] = { (C0[2]+vV[2]), -(C0[1]+vV[1]), (C0[0]+vV[0]) }; + Double_t s = S[2]*S[0] - S[1]*S[1]; + Double_t chi2 = zeta[0]*zeta[0]*S[0] + 2*zeta[0]*zeta[1]*S[1] + + zeta[1]*zeta[1]*S[2]; + // std::cout << " chi2 = " << chi2 << std::endl; + + if ( chi2 > s*CutChi2 ) continue; + + // Fit of the vertex track slopes (a,b) to the r0 vertex estimate + //----------------------------------------------------------------- + s = vV[0]*vV[2] - vV[1]*vV[1]; + + if ( s < 1.E-20 ) continue; + + s = 1./s; + + a = vMU.X() + s*( ( vV[3]*vV[2] - vV[4]*vV[1])*zeta[0] + + (-vV[3]*vV[1] + vV[4]*vV[0])*zeta[1] ); + + b = vMU.Y() + s*( ( vV[6]*vV[2] - vV[7]*vV[1])*zeta[0] + + (-vV[6]*vV[1] + vV[7]*vV[0])*zeta[1] ); + } + + // std::cout << " a = " << a << " b = " << b << std::endl; + + // Update the vertex (r,C) with the track estimate (m,V) : + //-------------------------------------------------------- + + // Linearized measurement matrix H = { { 1, 0, -a}, { 0, 1, -b} }; + //----------------------------------------------------------------- + + // Residual zeta (measured - estimated) + //-------------------------------------- + Double_t zeta[2] = { vPos.X() - ( r[0] - a*(r[2]-r0[2]) ), + vPos.Y() - ( r[1] - b*(r[2]-r0[2]) ) }; + + // std::cout << " zeta[0] = " << zeta[0] << " zeta[1] = " << zeta[1] + // << " zeta[2] = " << zeta[2] << std::endl; + + // CHt = CH’ + //---------- + Double_t CHt[3][2] = { { C[0] - a*C[3], C[1] - b*C[3]}, + { C[1] - a*C[4], C[2] - b*C[4]}, + { C[3] - a*C[5], C[4] - b*C[5]} }; + + // S = (H*C*H’ + V )^{-1} + //------------------------- + Double_t S[3] = { vV[0] + CHt[0][0] - a*CHt[2][0], + vV[1] + CHt[1][0] - b*CHt[2][0], + vV[2] + CHt[1][1] - b*CHt[2][1] }; + + // Invert S + //---------- + { + Double_t s = S[0]*S[2] - S[1]*S[1]; + if (s < 1.E-20) continue; + s = 1./s; + Double_t S0 = S[0]; + S[0] = s*S[2]; + S[1] = -s*S[1]; + S[2] = s*S0; + } + + // Calculate Chi^2 + //----------------- + refChi2 += zeta[0]*zeta[0]*S[0] + 2*zeta[0]*zeta[1]*S[1] + + zeta[1]*zeta[1]*S[2]; + refNDF += 2; + + // std::cout << " refChi2 = " << refChi2 << " refNDF = " << refNDF << std::endl; + + // Kalman gain K = CH’*S + //------------------------ + Double_t K[3][2]; + for (Int_t i(0); i<3; ++i) { K[i][0] = CHt[i][0]*S[0] + CHt[i][1]*S[1] ; + K[i][1] = CHt[i][0]*S[1] + CHt[i][1]*S[2] ; } + + // New estimation of the vertex position r += K*zeta + //--------------------------------------------------- + for (Int_t i(0); i<3; ++i) r[i] += K[i][0]*zeta[0] + K[i][1]*zeta[1]; + + // std::cout << " trk = " << itrk << " r[0] = " << r[0] << " r[1] = " << r[1] + // << " r[2] = " << r[2] << std::endl; + + // New covariance matrix C -= K*(CH’)’ + //-------------------------------------- + C[0] -= K[0][0]*CHt[0][0] + K[0][1]*CHt[0][1]; + C[1] -= K[1][0]*CHt[0][0] + K[1][1]*CHt[0][1]; + C[2] -= K[1][0]*CHt[1][0] + K[1][1]*CHt[1][1]; + C[3] -= K[2][0]*CHt[0][0] + K[2][1]*CHt[0][1]; + C[4] -= K[2][0]*CHt[1][0] + K[2][1]*CHt[1][1]; + C[5] -= K[2][0]*CHt[2][0] + K[2][1]*CHt[2][1]; + + } // end loop over tracks + + } // end loop over iteration + + vertex.SetX(r[0]); + vertex.SetY(r[1]); + vertex.SetZ(r[2]); + + //cout << "\nrefChi2 = " << refChi2 << " refNDF = " << refNDF << endl; + + TMatrixDSym VC(3); + VC(0,0) = C[0]; VC(0,1) = C[1]; VC(0,2) = C[3]; + VC(1,0) = C[1]; VC(1,1) = C[2]; VC(1,2) = C[4]; + VC(2,0) = C[3]; VC(2,1) = C[4]; VC(2,2) = C[5]; + + if (refNDF > 0) { + fKFres->SetVertexChi2overNDF(refChi2/refNDF); + fKFres->SetVertexRECcov(VC); + } + else fKFres->ClearVertexData(); + + //VC.Print(); +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::FindDecayVertex() +{ + // set initial output values + //--------------------------- + v0_mass = -99.; + v0_massErr = -99.; + v0_pp = -99.; + v0_energy = -99.; + v0_eta = -99.; + v0_theta = -99.; + v0_phi = -99.; + v0_length = -99.; + + Int_t nTracks = fTracks->GetEntriesFast(); // number of tracks + + // set primary vertex (reconstructed or simulated) + //------------------------------------------------- + TVector3 recVtx = fKFres->GetVertexRec(); // reconstructed PV + TMatrixDSym recCov = fKFres->GetVertexRECcov(); + + TVector3 pvVtx( fEvent->GetVertex() ); // simulated PV + if (fUsedTypeOfPV > 1) pvVtx = recVtx; // set PV vertex + + // set field + //----------- + float fieldBz = (float)fField->GetField()->GetBz(pvVtx.X(), pvVtx.Y(), pvVtx.Z()); + KFParticle::SetField(fieldBz); + + // track parameters + //---------------- + SpdGFTrackW* wtr; + Track* track; + Int_t ntrack; + + TVector3 trkPos, trkMom; + TMatrixDSym trkCov; + + fKFparticles.clear(); + for (Int_t itrk(0); itrk < nTracks; ++itrk) // loop over tracks + { + wtr = (SpdGFTrackW*)fTracks->At(itrk); + + track = wtr->GetTrack(); + ntrack = wtr->GetDataID(); + + if (!fKFres->GetIsFitted(ntrack)) continue; // FIXME + if ( fKFres->GetConvergency(ntrack) != 1) continue; // FIXME + + int pdgTrk = (int)fKFres->GetTrackPdg(ntrack); + TParticlePDG* part = TDatabasePDG::Instance()->GetParticle(pdgTrk); + + // check only first or second daugter particle types + //--------------------------------------------------- + if ( fabs(pdgTrk) != fFirstDaughter && fabs(pdgTrk) != fSecondDaughter) continue; + + MeasuredStateOnPlane stateF = track->getFittedState(); // copy + stateF.getPosMomCov(trkPos, trkMom, trkCov); // get track parameters at first + // hit position + // extrapolate to primary vertex (sim or rec) + //------------------------------------------- + try + { + stateF.extrapolateToPoint(pvVtx); + } + catch(Exception& e) + { + cout << " bad track extrapolation " << endl; + continue; + } + + TMatrixDSym pvCov; + TVector3 pvPos, pvMom; + stateF.getPosMomCov(pvPos, pvMom, pvCov); // in global, after extrapolation + + // track deviation from the primary vertex + //------------------------------------------- + + // track Cov matrix in DCA point + //------------------------------- + float mS[6] = { (float)pvCov(0,0)+(float)recCov(0,0), + (float)pvCov(1,0)+(float)recCov(1,0), (float)pvCov(1,1)+(float)recCov(1,1), + (float)pvCov(2,0)+(float)recCov(2,0), (float)pvCov(2,1)+(float)recCov(2,1), + (float)pvCov(2,2)+(float)recCov(2,2) }; + // deviation track from PV + //------------------------ + float zeta[3] = { (float)(pvPos.X()-pvVtx.X()) , + (float)(pvPos.Y()-pvVtx.Y()) , + (float)(pvPos.Z()-pvVtx.Z()) }; + + InvertCholetsky3(mS); // invert matrix C => C^{-1} + + // chi2 = (R_trk - R_pv)^{T} * (C_trk + C_pv)^{-1} * (R_trk - R_pv); + //------------------------------------------------------------------- + float fChi2 = (mS[0]*zeta[0] + mS[1]*zeta[1] + mS[3]*zeta[2]) * zeta[0] + + (mS[1]*zeta[0] + mS[2]*zeta[1] + mS[4]*zeta[2]) * zeta[1] + + (mS[3]*zeta[0] + mS[4]*zeta[1] + mS[5]*zeta[2]) * zeta[2]; + + if (fChi2 < fMinChi2PV) continue; // check min topo Chi2 + + // set KF track parameters + //------------------------ + KFPTrack kfTrack; + kfTrack.SetParameters( trkPos.X(), trkPos.Y(), trkPos.Z(), + trkMom.X(), trkMom.Y(), trkMom.Z() ); + + Double_t C[21] = { trkCov(0,0), + trkCov(1,0),trkCov(1,1), + trkCov(2,0),trkCov(2,1),trkCov(2,2), + trkCov(3,0),trkCov(3,1),trkCov(3,2),trkCov(3,3), + trkCov(4,0),trkCov(4,1),trkCov(4,2),trkCov(4,3),trkCov(4,4), + trkCov(5,0),trkCov(5,1),trkCov(5,2),trkCov(5,3),trkCov(5,4),trkCov(5,5) }; + + kfTrack.SetCovarianceMatrix(C); + + kfTrack.SetNDF( track->getFitStatus()->getNdf() ); + kfTrack.SetChi2(track->getFitStatus()->getChi2()); + kfTrack.SetCharge( (part->Charge())/3); + + KFParticle p1(kfTrack, pdgTrk); + fKFparticles.push_back(p1); + } + + // check vector with daughter candidates + //-------------------------------------- + if (fKFparticles.size() >= 2) // number of KF particles >= 2 + { + for (int i=0; i<fKFparticles.size()-1; ++i) + { + for (int j=i+1; j<fKFparticles.size(); ++j) + { + if (fKFparticles[i].GetQ()*fKFparticles[j].GetQ() > 0) continue; + + if ( ( fabs(fKFparticles[i].GetPDG())==fFirstDaughter && + fabs(fKFparticles[j].GetPDG())!=fSecondDaughter ) || + ( fabs(fKFparticles[i].GetPDG())==fSecondDaughter && + fabs(fKFparticles[j].GetPDG())!=fFirstDaughter ) ) continue; + + // distance between two daughter particles + //---------------------------------------- + float dist2part = fKFparticles[i].GetDistanceFromParticle(fKFparticles[j]); + + if (dist2part > fMinDist) continue; // check distance + + // parameter 1 - array of the daughter particles + // parameter 2 - number of the daughter particles + // parameter 3 - vertex (it should be the object of the KFParticle class) + + KFPVertex vert; + vert.SetXYZ( pvVtx.X(), pvVtx.Y(), pvVtx.Z() ); + vert.SetCovarianceMatrix( (float)recCov(0,0), + (float)recCov(1,0), (float)recCov(1,1), + (float)recCov(2,0), (float)recCov(2,1), (float)recCov(2,2) ); + vert.SetNContributors(nTracks-2); + float vtxChi2 = (nTracks-2)*fKFres->GetVertexChi2overNDF(); + vert.SetChi2(vtxChi2); + KFParticle p0(vert); // set primary vertex as KFParticle + + const KFParticle pVertex = p0; + int NDaughters = 2; + const KFParticle *vDaughters[2] = { &fKFparticles[i], &fKFparticles[j] }; + + // construct deacay V0 particle without PV and mass constrain + //------------------------------------------------------------ + KFParticle K0_1; + K0_1.SetProductionVertex(pVertex); + K0_1.Construct(vDaughters,NDaughters,0,-1); + + TVector3 v1; + v1.SetXYZ(K0_1.GetX(), K0_1.GetY(), K0_1.GetZ()); // decay vertex + + float mass1 = K0_1.GetMass(); + float massErr1 = K0_1.GetErrMass(); + float mom1 = K0_1.GetP(); + float ene1 = K0_1.GetE(); + float eta1 = K0_1.GetRapidity(); + float theta1 = K0_1.GetTheta(); + float phi1 = K0_1.GetPhi(); + float length1 = (v1-pvVtx).Mag(); + + // construct decay V0 particle with PV constrain + //----------------------------------------------- + KFParticle K0_2; + K0_2.SetProductionVertex(pVertex); + K0_2.Construct(vDaughters,NDaughters,&pVertex,-1); + + v0_mass = K0_2.GetMass(); + v0_massErr = K0_2.GetErrMass(); + v0_pp = K0_2.GetP(); + v0_energy = K0_2.GetE(); + v0_eta = K0_2.GetRapidity(); + v0_theta = K0_2.GetTheta(); + v0_phi = K0_2.GetPhi(); + v0_length = K0_2.GetDecayLength(); + + if ( fConstrainToPV < 1) // without PV constrain + { + v0_mass = mass1; + v0_massErr = massErr1; + v0_pp = mom1; + v0_energy = ene1; + v0_eta = eta1; + v0_theta = theta1; + v0_phi = phi1; + v0_length = length1; + } + + // check V0 mass window + //---------------------- + if( v0_mass < fMinMass || v0_mass > fMaxMass) continue; // mass window + + fV0tree->Fill(); + } + } + } + +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::InvertCholetsky3(float a[6]) +{ + /* Inverts symmetric 3x3 matrix a using modified Choletsky decomposition. + The result is stored to the same matrix a. + param[in,out] a - 3x3 symmetric matrix + */ + + float d[3], uud, u[3][3]; + for(int i=0; i<3; i++) + { + d[i] = 0; + for(int j=0; j<3; j++) u[i][j] = 0; + } + + for(int i=0; i<3 ; i++) + { + uud = 0; + for(int j=0; j<i; j++) uud += u[j][i]*u[j][i]*d[j]; + + uud = a[i*(i+3)/2] - uud; + + if(fabs(uud)<1.e-12f) uud = 1.e-12f; + + d[i] = uud/fabs(uud); + u[i][i] = sqrt(fabs(uud)); + + for(int j=i+1; j<3; j++) + { + uud = 0; + for(int k=0; k<i; k++) uud += u[k][i]*u[k][j]*d[k]; + + uud = a[j*(j+1)/2+i] - uud; + u[i][j] = d[i]/u[i][i]*uud; + } + } + + float u1[3]; + for(int i=0; i<3; i++) + { + u1[i] = u[i][i]; + u[i][i] = 1/u[i][i]; + } + + for(int i=0; i<2; i++) + { + u[i][i+1] = - u[i][i+1]*u[i][i]*u[i+1][i+1]; + } + + for(int i=0; i<1; i++) + { + u[i][i+2] = u[i][i+1]*u1[i+1]*u[i+1][i+2]-u[i][i+2]*u[i][i]*u[i+2][i+2]; + } + + for(int i=0; i<3; i++) a[i+3] = u[i][2]*u[2][2]*d[2]; + + for(int i=0; i<2; i++) a[i+1] = u[i][1]*u[1][1]*d[1] + u[i][2]*u[1][2]*d[2]; + + a[0] = u[0][0]*u[0][0]*d[0] + u[0][1]*u[0][1]*d[1] + u[0][2]*u[0][2]*d[2]; +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::Finish() +{ + cout << "-I- <SpdIdealV0Finder::Finish>" << endl; + + CloseOutputV0file(); +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::FillParametersIn(SpdBaseParSet* params) +{ + if (!params) return; + + params->SetParameter("IdealKalmanFitter/MaterialsOpt",fMaterialsOpt); + + params->SetParameter("IdealKalmanFitter/SeedMomentum",fSeedMomentum); + params->SetParameter("IdealKalmanFitter/VertexFitMethod",fVertexFitMethod); + params->SetParameter("IdealKalmanFitter/VertexFitAngleCut",fVertexFitAngleCut); + + Int_t n = fHitRepresentation.size(); + + params->SetParameter("IdealKalmanFitter/NHRepresentations",n); + + if (n > 0) { + Int_t i(0); + for (auto& it : fHitRepresentation) { + params->SetParameter(Form("IdealKalmanFitter/HitRepDetId[%d]",i),it.first); + params->SetParameter(Form("IdealKalmanFitter/HitRepDet[%d]",i),it.second); + i++; + } + } + + params->SetParameter("IdealKalmanFitter/fStartSeedMethod",fStartSeedMethod); + params->SetParameter("IdealKalmanFitter/fSmearSeedValues",fSmearSeedValues); + + if (fSmearSeedValues) { + params->SetParameter("IdealKalmanFitter/fSmearingMomDelta",fSmearingMomDelta); + if (fStartSeedMethod == 2) { + params->SetParameter("IdealKalmanFitter/fNPointsVertexUse",fNPointsVertexUse); + } + else + { + params->SetParameter("IdealKalmanFitter/fSmearingAngleDelta",fSmearingAngleDelta); + params->SetParameter("IdealKalmanFitter/fSmearingVertexDelta",fSmearingVertexDelta); + } + } + + params->SetParameter("IdealKalmanFitter/FitterOption",fFitterOption); + + params->SetParameter("IdealKalmanFitter/FitterMaxIterations",fFitterMaxIterations); + params->SetParameter("IdealKalmanFitter/FitterMaxTrials",fFitterMaxTrials); + + params->SetParameter("IdealKalmanFitter/StoreTracks",fStoreTracks); +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::LoadParametersFrom(SpdBaseParSet* params) +{ + if (!params) return; + + fHitRepresentation.clear(); + + Int_t pi; + Double_t pd; + Bool_t pb; + + if (params->GetParameter("IdealKalmanFitter/MaterialsOpt",pi)) SetMaterialEffectsOption(pi); + + if (params->GetParameter("IdealKalmanFitter/SeedMomentum",pd)) SetSeedMomentum(pd); + if (params->GetParameter("IdealKalmanFitter/VertexFitMethod",pi)) SetVertexFindingMethod(pi); + if (params->GetParameter("IdealKalmanFitter/VertexFitAngleCut",pd)) SetVertexFindingAngleCut(pd); + + if (params->GetParameter("IdealKalmanFitter/NHRepresentations",pi)) { + if (pi > 0) { + Int_t pi2, pi3; + for (Int_t i(0); i<pi; i++) { + params->GetParameter(Form("IdealKalmanFitter/HitRepDetId[%d]",i),pi2); + params->GetParameter(Form("IdealKalmanFitter/HitRepDet[%d]",i),pi3); + fHitRepresentation[pi2] = pi3; + } + } + } + + if (params->GetParameter("IdealKalmanFitter/fStartSeedMethod",pi)) SetStartSeedMethod(pi); + if (params->GetParameter("IdealKalmanFitter/fSmearSeedValues",pb)) SetSmearSeedValues(pb); + + if (fSmearSeedValues) { + if (params->GetParameter("IdealKalmanFitter/fSmearingMomDelta",pd)) SetSmearingMomDelta(pd); + if (fStartSeedMethod == 2) { + if (params->GetParameter("IdealKalmanFitter/fNPointsVertexUse",pi)) SetNPointsVertexUse(pi); + } + else { + if (params->GetParameter("IdealKalmanFitter/fSmearingAngleDelta",pd)) SetSmearingAngleDelta(pd); + if (params->GetParameter("IdealKalmanFitter/fSmearingVertexDelta",pd)) SetSmearingVertexDelta(pd); + } + } + + if (params->GetParameter("IdealKalmanFitter/FitterOption",pi)) SetFitterOption(pi); + + if (params->GetParameter("IdealKalmanFitter/FitterMaxIterations",pi)) SetFitterMaxIterations(pi); + if (params->GetParameter("IdealKalmanFitter/FitterMaxTrials",pi)) SetFitterMaxTrials(pi); + + if (params->GetParameter("IdealKalmanFitter/StoreTracks",pb)) SetStoreTracks(pb); +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::InitV0nTuple(TString name) +{ + fV0file = new TFile(name, "RECREATE"); + fV0tree = new TTree("DecayV0Tree", "DecayV0Tree"); + + fV0tree->Branch("v0_mass", &v0_mass, "v0_mass/F" ); + fV0tree->Branch("v0_massErr", &v0_massErr, "v0_massErr/F"); + fV0tree->Branch("v0_pp", &v0_pp, "v0_pp/F" ); + fV0tree->Branch("v0_energy", &v0_energy, "v0_energy/F" ); + fV0tree->Branch("v0_eta", &v0_eta, "v0_eta/F" ); + fV0tree->Branch("v0_theta", &v0_theta, "v0_theta/F" ); + fV0tree->Branch("v0_phi", &v0_phi, "v0_phi/F" ); + fV0tree->Branch("v0_length", &v0_length, "v0_length/F" ); +} + +//________________________________________________________________________________________ +void SpdIdealV0Finder::CloseOutputV0file() +{ + fV0file->Write(); + fV0file->Close(); +} + + + diff --git a/reco/SpdIdealV0Finder.h b/reco/SpdIdealV0Finder.h new file mode 100644 index 0000000000000000000000000000000000000000..a39969177430589969138c7c1c27ba5898470809 --- /dev/null +++ b/reco/SpdIdealV0Finder.h @@ -0,0 +1,209 @@ +// $Id$ +// Author: vladimir andreevv 2020/08/29 + +#ifndef __SPDIDEALV0FINDER_H__ +#define __SPDIDEALV0FINDER_H__ + +#include <TString.h> +#include "FairTask.h" +#include "FairBaseParSet.h" +#include "SpdFieldPar.h" +#include "SpdGeoLoader.h" +#include "SpdIdealTrack.h" +#include "SpdBaseParSet.h" +#include "SpdGFMeasurementCreator.h" +#include "AbsKalmanFitter.h" + +// KFParticle +#include "KFParticle.h" +#include "KFPTrack.h" +#include "KFPVertex.h" +#include "KFParticleSIMD.h" + +#include <TTree.h> +#include <TFile.h> + +//#include <map> + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdIdealV0Finder // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdGeoLoader; +class SpdIdealTrackColl; +class SpdKFSimpleRes; +class SpdGFMeasurementCreator; +class SpdGFMagneticField; + +class SpdIdealV0Finder: public FairTask { + +public: + + SpdIdealV0Finder(); + virtual ~SpdIdealV0Finder(); + + void SetTrackingGeoModules(Bool_t add_passives = kTRUE); + + void AddModule(TString module) { fGeoModules.push_back(module); } + void AddModule(Int_t module) { fGeoModules.push_back(Form("%d",module)); } + void ClearListOfGeoModules() { fGeoModules.clear(); } + + virtual InitStatus Init(); + virtual void Exec(Option_t* opt); + virtual void Finish(); + + void DeleteGeoLoader(); + + /* SETTERS */ + + void SetVerboseLevel(Int_t level) { fVerboseLevel = level; } + + void SetMaterialEffectsOption(Int_t opt /*-1,0(default),1 */) { fMaterialsOpt = opt; } + + void SetSeedMomentum(Double_t mom /* GeV/c */) { fSeedMomentum = fabs(mom); } + void SetHitRepresentation(Int_t DetId, GFMeasurementType GFhitType); + + void SetVertexFindingMethod(Int_t method) { fVertexFitMethod = method; } + void SetVertexFindingAngleCut(Double_t acut /*deg*/) { fVertexFitAngleCut = acut; } + + void SetStartSeedMethod(Int_t method) { fStartSeedMethod = method; } + void SetSmearSeedValues(Bool_t smear) { fSmearSeedValues = smear; } + + void SetSmearingAngleDelta(Double_t angle /*deg*/) { fSmearingAngleDelta = TMath::Abs(angle); } + void SetSmearingVertexDelta(Double_t dpos /*cm*/) { fSmearingVertexDelta = TMath::Abs(dpos); } + void SetSmearingMomDelta(Double_t dp /*Gev/c*/) { fSmearingMomDelta = TMath::Abs(dp); } + void SetNPointsVertexUse(Int_t np /* < 1 = max */) { fNPointsVertexUse = np; } + + void SetFitterOption(Int_t opt) { fFitterOption = opt; } + + void SetFitterMaxIterations(Int_t niter) { fFitterMaxIterations = (niter > 2) ? niter : 4; } + void SetFitterMaxTrials(Int_t ntrials) { fFitterMaxTrials = (ntrials > 1) ? ntrials : 1; } + + void SetStoreTracks(Bool_t store = true) { fStoreTracks = store; } + + void FillParametersIn(SpdBaseParSet* params); + void LoadParametersFrom(SpdBaseParSet* params); + + /* V0 finder Setter */ + + void SetOutputFileName(TString m_outfile_name); + void SetFirstDaughter(Int_t p) { fFirstDaughter = p; } + void SetSecondDaughter(Int_t p) { fSecondDaughter = p; } + void SetUsedTypeOfPV(Int_t p) { fUsedTypeOfPV = p; } + void SetConstrainToPV(Int_t p) { fConstrainToPV = p; } + void SetMinTrackPVchi2(Double_t chi2) { fMinChi2PV = chi2; } + void SetMinDistDaughter(Double_t dist) { fMinDist = dist; } + void SetMinimumMass(Double_t m) { fMinMass = m; } + void SetMaximumMass(Double_t m) { fMaxMass = m; } + +private: + + SpdGFMagneticField* fField; //! Magnetic field + SpdGFMeasurementCreator* fMeasCreator; //! GenFit measurements creator + genfit::AbsKalmanFitter* fFitter; //! GenFit fitter + + /* methods */ + + void LoadGeometry(); + void LoadField(); + void InitFitter(); + + genfit::Track* BuildTrack(Int_t n, genfit::Track* track = 0); + + GFMeasurementType GetHitRepresentation(Int_t DetId) const; + + void DefineTrackStartVertexAndMom(const SpdIdealTrack* track); + void DefineTrackStartVertexAndMom(const Int_t ntrack, const SpdIdealTrack* track); + void DefineStartVertexCovariance(); + + void FindVertex(TVector3& vertex); + + /* V0 finder */ + + void FindDecayVertex(); // V0 vertex finder + void InvertCholetsky3(float a[6]); // a => a^{-1} + void InitV0nTuple(TString name); // V0 user nTuple + void CloseOutputV0file(); // V0 user nTuple + + /* Geometry */ + Bool_t fOwnGeoLoader; //! indicates geometry loader owning + SpdGeoLoader* fGeoLoader; //! SPD geometry + std::vector<TString> fGeoModules; //! geometry modules are to be built + + /* data memebers */ + + SpdIdealTrackColl* fEvent; //! Input data + SpdKFSimpleRes* fKFres; //! Output data + TObjArray* fTracks; //! Output tracks + + SpdBaseParSet* fParameters; + + Int_t fVerboseLevel; + + /* FIT OPTIONS */ + + Int_t fMaterialsOpt; // > 0 (+material effects, default), <=0 (no mat. effects) + + // standard + Double_t fSeedMomentum; // start track vertex momentum [GeV/c] + std::map<Int_t,Int_t> fHitRepresentation; // <Detector Id, GFMeasurementType> + + // advanced + Int_t fVertexFitMethod; // <1 (no fit); 1 (default) + Double_t fVertexFitAngleCut; // reject tracks with theta = 90+-cut, default cut = 3 [deg] + + Int_t fStartSeedMethod; // 1, 2 = default + Bool_t fSmearSeedValues; // start values smearing flag + + Double_t fSmearingMomDelta; // track start momentum smearing (+-)value, GeV/c + + Double_t fSmearingAngleDelta; // [StartSeedMethod = 1] track start angle smearing (+-)value, deg () + Double_t fSmearingVertexDelta; // [StartSeedMethod = 1] track start vertex position smearing (+-)value, cm + + Int_t fNPointsVertexUse; // [StartSeedMethod = ] number of vertex points are used to evaluate start parameters + + Int_t fFitterMaxIterations; // max. number of iteration to reach convergency + Int_t fFitterMaxTrials; // max. number of admissible track rebuilding trials to reach convergency + + Int_t fFitterOption; // method to update covariance matrix (default = 1) + + Bool_t fStoreTracks; // if true, store tracks in the output file + + TVector3 fStartMomentum; // start track vertex momentum [GeV/c] + TVector3 fStartVertex; // start track vertex position [cm] + TMatrixDSym fStartSeedCov; // covariation matrix of size (6x6) + + /* V0 variables */ + + TFile *fV0file; // ROOT file + TTree *fV0tree; // Tree + + Int_t fFirstDaughter; // first daugther + Int_t fSecondDaughter; // second daugther + Int_t fUsedTypeOfPV; // type of used PV + Int_t fConstrainToPV; // constrain to PV + Double_t fMinChi2PV; // minimum chi2 track to PV + Double_t fMinDist; // minimum distance between 2 daughter particles + Double_t fMinMass; // minimum mass for mother particle + Double_t fMaxMass; // maximum mass for mother particle + + std::vector<KFParticle> fKFparticles; + + float v0_mass; // mass od decay particle + float v0_massErr; // error of mass decay particle + float v0_pp; // momentum of decay particle + float v0_energy; // energy of decay particle + float v0_eta; // eta of decay particle + float v0_theta; // theta of decay particle + float v0_phi; // phi of decay particle + float v0_length; // decay length + + ClassDef(SpdIdealV0Finder,1) +}; + +#endif /* __SPDIDEALV0FINDER_H__ */ + diff --git a/reco/SpdRecoLinkDef.h b/reco/SpdRecoLinkDef.h index 2f6cc2df4c49af2a832b07b4544c6ba06bc552e5..e7ab85211a83ff334ae196fca125b7b371e29f1b 100644 --- a/reco/SpdRecoLinkDef.h +++ b/reco/SpdRecoLinkDef.h @@ -6,5 +6,6 @@ #pragma link off all functions; #pragma link C++ class SpdIdealKalmanFitter+; +#pragma link C++ class SpdIdealV0Finder+; #endif diff --git a/rst/CMakeLists.txt b/rst/CMakeLists.txt index beee6bb21f3d97bb8e249ba24ad49f6dfcff175e..1a4f8e66711a952929399dcf92ecce519a2ab674 100644 --- a/rst/CMakeLists.txt +++ b/rst/CMakeLists.txt @@ -36,14 +36,18 @@ set(SRCS SpdRsTContFact.cxx barrel/SpdRsTB.cxx +barrel/SpdRsTB2.cxx barrel/SpdRsTBParSet.cxx barrel/SpdRsTBPoint.cxx +barrel/SpdRsTB2Point.cxx barrel/SpdRsTBHit.cxx barrel/SpdRsTBHitProducer.cxx ecps/SpdRsTEC.cxx +ecps/SpdRsTEC2.cxx ecps/SpdRsTECParSet.cxx ecps/SpdRsTECPoint.cxx +ecps/SpdRsTEC2Point.cxx ecps/SpdRsTECHit.cxx ecps/SpdRsTECHitProducer.cxx diff --git a/rst/SpdRstLinkDef.h b/rst/SpdRstLinkDef.h index 5b0dd0f7695279197ec65191cfb0066181f7e3ef..0a9d3da09cc0ef6f2b8974141153ea4eb1b95d96 100644 --- a/rst/SpdRstLinkDef.h +++ b/rst/SpdRstLinkDef.h @@ -13,10 +13,16 @@ #pragma link C++ class SpdRsTBHit+; #pragma link C++ class SpdRsTBHitProducer+; +#pragma link C++ class SpdRsTB2+; +#pragma link C++ class SpdRsTB2Point+; + #pragma link C++ class SpdRsTECParSet+; #pragma link C++ class SpdRsTEC+; #pragma link C++ class SpdRsTECPoint+; #pragma link C++ class SpdRsTECHit+; #pragma link C++ class SpdRsTECHitProducer+; +#pragma link C++ class SpdRsTEC2+; +#pragma link C++ class SpdRsTEC2Point+; + #endif diff --git a/rst/barrel/SpdRsTB.cxx b/rst/barrel/SpdRsTB.cxx index 86affb3f0354da9feffa9be216154fd6da8c9f66..4270107f5dc0a9cd541e4440c927c755f1b35584 100644 --- a/rst/barrel/SpdRsTB.cxx +++ b/rst/barrel/SpdRsTB.cxx @@ -145,7 +145,7 @@ Bool_t SpdRsTB::ProcessHits(FairVolume* vol) fTrackID = gMC->GetStack()->GetCurrentTrackNumber(); - fVolumeID1 = kSpdEcalTB; + fVolumeID1 = kSpdRsTB; fVolumeID2 = -111111111; fVolumeID3 = -111111111; diff --git a/rst/barrel/SpdRsTB2.cxx b/rst/barrel/SpdRsTB2.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f277e8e6acdbd5d01bdade34da0a675bf89aa900 --- /dev/null +++ b/rst/barrel/SpdRsTB2.cxx @@ -0,0 +1,894 @@ +// $Id$ +// Author: artur 2018/02/01 + +//_____________________________________________________________________________ +// +// SpdRsTB2 +//_____________________________________________________________________________ + +#include "SpdRsTB2.h" + +#include "TRefArray.h" +#include "TClonesArray.h" +#include "TParticle.h" +#include "TVirtualMC.h" +#include "TGeoManager.h" +#include "TGeoBBox.h" +#include "TGeoCompositeShape.h" +#include "TGeoTube.h" +#include "TGeoMaterial.h" +#include "TGeoMedium.h" +#include "TGeoArb8.h" + +#include "TMath.h" + +#include "SpdRsTB2Point.h" +#include "SpdRsTB2GeoMapper.h" + +#include "SpdDetectorList.h" +#include "SpdStack.h" +#include "SpdMCEventHeader.h" +#include "SpdCommonGeoMapper.h" +#include "SpdGeoFactory.h" + +#include <iostream> + +using namespace std; +using namespace TMath; + +ClassImp(SpdRsTB2) + +//_____________________________________________________________________________________ +SpdRsTB2::SpdRsTB2(): + + SpdDetector("RS barrel (qsl)", kSpdRsTB, kTRUE), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fPointCollection(0), + fModule(0) +{ + SetParametersType("RsTBParSet"); + + fNDataOut = 1; + fOutDataPointObject = "SpdRsTB2Point"; + + fBaseColor = kGreen+2; // (air) + fAbsorbColor = kGreen+4; // (iron) +} + +//_____________________________________________________________________________________ +SpdRsTB2::SpdRsTB2(const char* name, Bool_t active): + + SpdDetector(name, kSpdRsTB, active), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fPointCollection(0), + fModule(0) +{ + SetParametersType("RsTBParSet"); + + fNDataOut = 1; + fOutDataPointObject = "SpdRsTB2Point"; + + fBaseColor = kGreen+2; // (air) + fAbsorbColor = kGreen+4; // (iron) +} + +//_____________________________________________________________________________________ +SpdRsTB2::~SpdRsTB2() +{ + if (fPointCollection) { + fPointCollection->Delete(); + delete fPointCollection; + fPointCollection = 0; + } +} + +//_____________________________________________________________________________________ +void SpdRsTB2::Initialize() +{ + cout << "\n*******************************************************************************" << endl; + cout << "************************* SpdRsTB2::Initialize ********************************" << endl; + cout << "*******************************************************************************\n" << endl; + + // data collections + fPointCollection = new TClonesArray(fOutDataPointObject); + + // Initialize module and fill parameters + SpdDetector::Initialize(); + + // SpdParSet* pars = GetParameters(); + // if (pars) pars->printParams(); + +} + +//_____________________________________________________________________________________ +void SpdRsTB2::Reset() +{ + fPointCollection->Clear(); +} + +//_____________________________________________________________________________________ +void SpdRsTB2::Register() +{ + if (fGeoMapper && fGeoMapper->GetGeoType() < 1) return; + + FairRootManager::Instance()->Register(fOutDataPointObject,"SpdRsTB2", + fPointCollection, kTRUE); +} + +//_____________________________________________________________________________________ +Bool_t SpdRsTB2::ProcessHits(FairVolume* vol) +{ + + //cout << "<SpdRsTB2::ProcessHits> " << gMC->CurrentVolPath() << endl; + + //Set parameters at entrance of volume. Reset ELoss. + if (gMC->IsTrackEntering()) { + fELoss = 0.; + fTime = gMC->TrackTime() * 1.e9; // ns -> s + fLength = gMC->TrackLength(); + gMC->TrackPosition(fPos); + gMC->TrackMomentum(fMom); + } + + // Sum energy loss for all steps in the active volume + fELoss += gMC->Edep(); + + // Create SpdRsTB2Point at exit of active volume + if ( gMC->IsTrackExiting() || + gMC->IsTrackStop() || + gMC->IsTrackDisappeared() ) + { + + if (!fSaveEmptyHits && fELoss == 0.) { return kFALSE; } + + fTrackID = gMC->GetStack()->GetCurrentTrackNumber(); + fSegmentLength = gMC->TrackLength() - fLength; + fTimeOut = gMC->TrackTime() * 1.e9; // ns -> s + + fVolumeID = kSpdRsTB; + fVolumePath = gMC->CurrentVolPath(); + gMC->TrackPosition(fPosOut); + gMC->TrackMomentum(fMomOut); + + //cout << "path = " << fVolumePath << endl; + + AddHit(); + + //cout << "<SpdRsTB2::AddHit> " << fPointCollection->GetEntriesFast() << endl; + + SpdStack* stack = (SpdStack*)gMC->GetStack(); + stack->AddPoint(kSpdRsTB); + } + + return kTRUE; +} + +//_____________________________________________________________________________________ +void SpdRsTB2::AddHit() +{ + static Bool_t addhit = (fOutDataPointObject == "SpdRsTB2Point") ? kTRUE : kFALSE; + + if (!addhit) return; + + TClonesArray& clref = *fPointCollection; + Int_t size = clref.GetEntriesFast(); + + new(clref[size]) SpdRsTB2Point(fTrackID,fVolumeID,fVolumePath, + TVector3(fPos.X(),fPos.Y(),fPos.Z()), + TVector3(fMom.Px(),fMom.Py(),fMom.Pz()), + TVector3(fPosOut.X(),fPosOut.Y(),fPosOut.Z()), + TVector3(fMomOut.Px(),fMomOut.Py(),fMomOut.Pz()), + fTime, fTimeOut, + fLength, fSegmentLength, fELoss); +} + +//_____________________________________________________________________________________ +void SpdRsTB2::EndOfEvent() +{ + Reset(); +} + +//_____________________________________________________________________________________ +void SpdRsTB2::FinishRun() +{ + //SpdDetector::FinishRun(); + FillNodesTableIn(GetParameters()); +} + +//_____________________________________________________________________________________ +void SpdRsTB2::ConstructGeometry() +{ + // Create detector geometry + + fMasterVolume = SpdCommonGeoMapper::Instance()->GetMasterVolume(); + + if (!fMasterVolume) { + cout << "-E- <SpdTsTEC::ConstructGeometry> No MASTER volume " << endl; + return; + } + + if (!GetMapper()) return; + + if (!fGeoMapper->InitGeometry()) return; + + //fGeoMapper->Print(""); + + Int_t geo_type = fGeoMapper->GetGeoType(); + + ConstructDetector(); + + fGeoMapper->LockGeometry(); + + cout << "\n*******************************************************************************" << endl; + cout << "********************** SpdRsTB2::ConstructGeometry ****************************" << endl; + cout << "********************** GEOMETRY TYPE: " << geo_type + << " ***************************************" << endl; + cout << "*******************************************************************************\n" << endl; +} + +//_____________________________________________________________________________________ +void SpdRsTB2::ConstructDetector() +{ + SpdParameter* par; + + SpdRsTB2GeoMapper* mapper = dynamic_cast<SpdRsTB2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + Double_t mlen = mapper->GetModuleLength(); + + Double_t hmin = mapper->GetModuleHmin(); + Double_t hmax = mapper->GetModuleHmax();; + Double_t lmin = mapper->GetModuleLmin(); + Double_t lmax = mapper->GetModuleLmax(); + + fModule = BuildModule("SideSVol", mapper->GetBaseMaterial(), + 0.5*mlen, hmin, hmax, 0.5*lmin, 0.5*lmax); + + if (!fModule) { + cout << "-E- <SpdRsTB2::ConstructGeometry> " + << "Volume " << fModule->GetName() << " cannot be created " << endl; + return; + } + + fModule->SetFillColor(kGreen); + fModule->SetLineColor(kGreen); + fModule->SetTransparency(30); + + /*-----------------------------------------------------------*/ + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t msize = mapper->GetModuleSize(); + Double_t mwidth = mapper->GetModuleWidth(); + + Int_t nLayers = mapper->GetNLayers(); + + // Add bottom layer (absrober(6.0cm) + mdt detectors(3.5cm)) + fModule->AddNode(CreateBottomLayer(msize, mwidth, mlen), 1, new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + + // Add regular layers (3.0cm absorber + 3.5cm mdt detectors) + for (Int_t i(2); i < nLayers+1; ++i) { + fModule->AddNode(CreateRegularLayer(i, msize, mwidth, mlen), i, new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + } + + // Add top absorber (6.0cm) + fModule->AddNode(CreateTopLayer(nLayers+1, msize, mwidth, mlen), nLayers+1, new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + + /*-----------------------------------------------------------*/ + + TGeoTranslation trans(0,0,0); + TGeoRotation rot; + + Double_t angle = mapper->GetSecAngle(); + Int_t nsectors = mapper->GetNSectors(); + + for (int i(1); i<=nsectors; i++) { + + fMasterVolume->AddNode(fModule,i,new TGeoCombiTrans(trans,rot)); + rot.RotateZ(angle); + } +} + +//________________________________________________________________________________ +TGeoVolume* SpdRsTB2::BuildModule(const char* name, TString mat, Double_t length, + Double_t hmin, Double_t hmax, Double_t lmin, Double_t lmax) +{ + //cout << "-I- <SpdRsTB2::BuildModule> " << length << "/" + // << hmin << "/" << hmax << "/" << lmin << "/" << lmax << endl; + + Double_t v[16]; + + v[0] = lmin; v[1] = hmin; + v[2] = -lmin; v[3] = hmin; + v[4] = -lmax; v[5] = hmax; + v[6] = lmax; v[7] = hmax; + + v[8] = lmin; v[9] = hmin; + v[10] = -lmin; v[11] = hmin; + v[12] = -lmax; v[13] = hmax; + v[14] = lmax; v[15] = hmax; + + TGeoMedium* material = FindMedium(mat,"air"); + + if (!material) { + cout << "-E- <SpdRsTB2::BuildModule> " + << "Unknown material: " << mat << endl; + return 0; + } + + TGeoVolume* vol = gGeoManager->MakeArb8(name,material,length,v); + + //AddSensitiveVolume(vol); //ATTENTION FIXME ATTENTION + + return vol; +} + +//________________________________________________________________________________ +TGeoVolume* SpdRsTB2::CreateBottomLayer(Double_t rsSize, Double_t rsThickness, Double_t rsLength) +{ + //---------------------------------------------------------------------------- + // Creates trapezoid representing bottom layer of the RS Barrel part + // (6.0cm thick iron absorber and a layer of MDT detectors) + // Parameters: 1. Size of RS from collision point (rsSize); + // 2. Thickness of RS rsThickness. + // Returns: TGeoVolume object of the layer with absorber and MDTs. + //---------------------------------------------------------------------------- + + SpdRsTB2GeoMapper* mapper = dynamic_cast<SpdRsTB2GeoMapper*>(fGeoMapper); + if (!mapper) { + cout << "-E- <SpdRsTB2::CreateBottomLayer> Unknown mapper: " << mapper->ClassName() << endl; + return 0; + } + + Double_t layerThickness = 6.0+3.5; //cm + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + + // Materials + TString mat; + + mat = mapper->GetAbsorbMaterial(); + TGeoMedium *piron = FindMedium(mat,""); + + mat = mapper->GetBaseMaterial(); + TGeoMedium *pair = FindMedium(mat,""); + + // Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t lmin = (rsSize - rsThickness)*(sqrt(2.0)-1.0); // dimensions (bottom base) + Double_t lmax = (rsSize - rsThickness + layerThickness)*(sqrt(2.0)-1.0); // dimensions (top base) + Double_t hmin = (rsSize - rsThickness); + Double_t hmax = (rsSize - rsThickness + layerThickness); + +// cout << "lmin: " << lmin << endl; +// cout << "lmax: " << lmax << endl; +// cout << "hmin: " << hmin << endl; +// cout << "hmax: " << hmax << endl; + + Double_t v_bottom[16]; + + v_bottom[0] = lmin; v_bottom[1] = hmin; + v_bottom[2] = -lmin; v_bottom[3] = hmin; + v_bottom[4] = -lmax; v_bottom[5] = hmax; + v_bottom[6] = lmax; v_bottom[7] = hmax; + + v_bottom[8] = lmin; v_bottom[9] = hmin; + v_bottom[10] = -lmin; v_bottom[11] = hmin; + v_bottom[12] = -lmax; v_bottom[13] = hmax; + v_bottom[14] = lmax; v_bottom[15] = hmax; + + TGeoArb8* Layer_SideS_Shape = new TGeoArb8("Layer_SideS_Shape", rsLength/2, v_bottom); + + Double_t Layer_Sector_Abs_dx = lmin; + Double_t Layer_Sector_Abs_dy = 6./2; + Double_t Layer_Sector_Abs_dz = rsLength/2; + + //cout << "Layer_SideS_Abs_Base_Shape: " + // << 2*Layer_Sector_Abs_dx << ", " << 2*Layer_Sector_Abs_dy << ", " << 2*Layer_Sector_Abs_dz << endl; + + TGeoBBox* Layer_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + Layer_Sector_Abs_dx, + Layer_Sector_Abs_dy, + Layer_Sector_Abs_dz); + + TGeoVolume* Layer_SideS_Vol = new TGeoVolume("LayerSideSVol", Layer_SideS_Shape, pair); + TGeoVolume* Layer_SideS_Abs_Base_Vol = new TGeoVolume("LayerSideSAbsBaseVol", Layer_SideS_Abs_Base_Shape, piron); + + Layer_SideS_Vol->AddNode(Layer_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, hmin+Layer_Sector_Abs_dy, 0, rotNoRot)); + + Double_t Layer_Envelope_startX = -1.0*lmin; + Double_t Layer_Envelope_shiftX = Layer_Envelope_startX + widthEnv/2; + Double_t Layer_length = 2*abs(Layer_Envelope_startX); + + Int_t Nenvelopes = Int_t(Layer_length/widthEnv); + + //cout << "Layer #1 length: " << Layer_length << endl; + //cout << "Number of MDT detector in Layer #1: " << Nenvelopes << endl; + + for (UInt_t i(0); i < Nenvelopes; i++) + { + Layer_SideS_Vol->AddNode(CreateMDT(rsLength-0.2), i+1, new TGeoCombiTrans("", Layer_Envelope_shiftX, hmin+6+3.5/2, 0, rotNoRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + } + + Layer_SideS_Abs_Base_Vol->SetFillColor(fAbsorbColor); + Layer_SideS_Abs_Base_Vol->SetLineColor(fAbsorbColor); + Layer_SideS_Abs_Base_Vol->SetTransparency(30); + + Layer_SideS_Vol->SetFillColor(fBaseColor); + Layer_SideS_Vol->SetLineColor(fBaseColor); + Layer_SideS_Vol->SetTransparency(30); + + return Layer_SideS_Vol; +} + +//________________________________________________________________________________ +TGeoVolume* SpdRsTB2::CreateTopLayer(Int_t layerN, Double_t rsSize, Double_t rsThickness, Double_t rsLength) +{ + //---------------------------------------------------------------------------- + // + // Creates trapezoid representing regular layer of the RS Barrel part + // (3.0cm thick iron absorber and a layer of MDT detectors) + // Parameters: 1. Number of layer in a sector + // 2. Size of RS from collision point (rsSize); + // 3. Thickness of RS rsThickness. + // Returns: TGeoVolume object of the layer with absorber and MDTs. + //---------------------------------------------------------------------------- + + SpdRsTB2GeoMapper* mapper = dynamic_cast<SpdRsTB2GeoMapper*>(fGeoMapper); + if (!mapper) { + cout << "-E- <SpdRsTB2::CreateTopLayer> Unknown mapper: " << mapper->ClassName() << endl; + return 0; + } + + Double_t layerThickness = 3.0+3.0; // cm + Double_t Sector_dy = rsLength/2.0; // cm + Double_t widthEnv = 8.5; // cm xAxis + Double_t thicknessEnv = 1.64; // cm zAxis + + // Materials + TString mat; + + mat = mapper->GetAbsorbMaterial(); + TGeoMedium *piron = FindMedium(mat,""); + + mat = mapper->GetBaseMaterial(); + TGeoMedium *pair = FindMedium(mat,""); + + // Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t lmin = (rsSize - rsThickness + 9.5 + (layerN-1)*layerThickness)*(sqrt(2.0)-1.0); // dimensions (bottom base) + Double_t lmax = (rsSize - rsThickness + 9.5 + (layerN)*layerThickness)*(sqrt(2.0)-1.0); // dimensions (top base) + Double_t hmin = (rsSize - rsThickness + 9.5 + (layerN-2)*6.5); + Double_t hmax = (rsSize - rsThickness + 9.5 + (layerN-2)*6.5 + layerThickness); + + //cout << "Layer #" << layerN << " dimensions (bottom base, lmin): [" << -lmin << "," << lmin << "]" << endl; + //cout << "Layer #" << layerN << " dimensions (bottom base, lmax): [" << -lmax << "," << lmax << "]" << endl; + //cout << "hmin: " << hmin <<endl; + //cout << "hmax: " << hmax <<endl; + + Double_t v_top[16]; + + v_top[0] = lmin; v_top[1] = hmin; + v_top[2] = -lmin; v_top[3] = hmin; + v_top[4] = -lmax; v_top[5] = hmax; + v_top[6] = lmax; v_top[7] = hmax; + + v_top[8] = lmin; v_top[9] = hmin; + v_top[10] = -lmin; v_top[11] = hmin; + v_top[12] = -lmax; v_top[13] = hmax; + v_top[14] = lmax; v_top[15] = hmax; + + TGeoArb8* Layer_SideS_Shape = new TGeoArb8("Layer_SideS_Shape", rsLength/2, v_top); + + Double_t Layer_Sector_Abs_dx = lmin; + Double_t Layer_Sector_Abs_dy = layerThickness/2; + Double_t Layer_Sector_Abs_dz = rsLength/2; + + TGeoBBox* Layer_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + Layer_Sector_Abs_dx, + Layer_Sector_Abs_dy, + Layer_Sector_Abs_dz); + + + TGeoVolume* Layer_SideS_Vol = new TGeoVolume("LayerSideSVol", Layer_SideS_Shape, pair); + TGeoVolume* Layer_SideS_Abs_Base_Vol = new TGeoVolume("LayerSideSAbsBaseVol", Layer_SideS_Abs_Base_Shape, piron); + + Layer_SideS_Vol->AddNode(Layer_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, hmin+Layer_Sector_Abs_dy, 0, rotNoRot)); + + Layer_SideS_Abs_Base_Vol->SetFillColor(fAbsorbColor); + Layer_SideS_Abs_Base_Vol->SetLineColor(fAbsorbColor); + Layer_SideS_Abs_Base_Vol->SetTransparency(30); + + Layer_SideS_Vol->SetFillColor(fBaseColor); + Layer_SideS_Vol->SetLineColor(fBaseColor); + Layer_SideS_Vol->SetTransparency(30); + + return Layer_SideS_Vol; +} + +//________________________________________________________________________________ +TGeoVolume* SpdRsTB2::CreateRegularLayer(Int_t layerN, Double_t rsSize, Double_t rsThickness, Double_t rsLength) +{ + //---------------------------------------------------------------------------- + // Creates trapezoid representing regular layer of the RS Barrel part + // (3.0cm thick iron absorber and a layer of MDT detectors) + // Parameters: 1. Number of layer in a sector + // 2. Size of RS from collision point (rsSize); + // 3. Thickness of RS rsThickness. + // Returns: TGeoVolume object of the layer with absorber and MDTs. + //---------------------------------------------------------------------------- + + SpdRsTB2GeoMapper* mapper = dynamic_cast<SpdRsTB2GeoMapper*>(fGeoMapper); + if (!mapper) { + cout << "-E- <SpdRsTB2::CreateMDT> Unknown mapper: " << mapper->ClassName() << endl; + return 0; + } + + Double_t layerThickness = 3.0+3.5; // cm + Double_t Sector_dy = rsLength/2.0; // cm + Double_t widthEnv = 8.5; // cm xAxis + Double_t thicknessEnv = 1.64; // cm zAxis + + // Materials + TString mat; + + mat = mapper->GetAbsorbMaterial(); + TGeoMedium *piron = FindMedium(mat,""); + + mat = mapper->GetBaseMaterial(); + TGeoMedium *pair = FindMedium(mat,""); + + // Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t Layer_Sector_dz = layerThickness/2; // z-coord of the layer center + Double_t Layer_Sector_dx1 = 1.0*(rsSize - rsThickness + 9.5 + (layerN-2)*layerThickness)*(sqrt(2.0)-1.0); // X-coord of the bottom base + Double_t Layer_Sector_dx2 = 1.0*(rsSize - rsThickness + 9.5 + (layerN-1)*layerThickness)*(sqrt(2.0)-1.0); // X-coord of the top base + Double_t Layer_Sector_dy = Sector_dy; // y-coord of the layer center + + //cout<<"Layer #"<< layerN << " dimensions (bottom base): [" + // << Layer_Sector_dx1*2 << " x " << Layer_Sector_dz*2 << " x " << Layer_Sector_dy*2 << "] cm" << endl; + //cout<<"Layer #"<< layerN << " dimensions (top base): [" + // << Layer_Sector_dx2*2 << " x " << Layer_Sector_dz*2 << " x " << Layer_Sector_dy*2 << "] cm" << endl; + + Double_t lmin = (rsSize - rsThickness + 9.5 + (layerN-2)*layerThickness)*(sqrt(2.0)-1.0); // dimensions (bottom base) + Double_t lmax = (rsSize - rsThickness + 9.5 + (layerN-1)*layerThickness)*(sqrt(2.0)-1.0); // dimensions (top base) + Double_t hmin = (rsSize - rsThickness + 9.5 + (layerN-2)*layerThickness); + Double_t hmax = (rsSize - rsThickness + 9.5 + (layerN-1)*layerThickness); + + //cout << "Layer #" << layerN << " dimensions (bottom base, lmin): [" << -lmin << "," << lmin << "]" << endl; + //cout << "Layer #" << layerN << " dimensions (bottom base, lmax): [" << -lmax << "," << lmax << "]" << endl; + //cout << "hmin: " << hmin << endl; + //cout << "hmax: " << hmax << endl; + + Double_t v_regular[16]; + + v_regular[0] = lmin; v_regular[1] = hmin; + v_regular[2] = -lmin; v_regular[3] = hmin; + v_regular[4] = -lmax; v_regular[5] = hmax; + v_regular[6] = lmax; v_regular[7] = hmax; + + v_regular[8] = lmin; v_regular[9] = hmin; + v_regular[10] = -lmin; v_regular[11] = hmin; + v_regular[12] = -lmax; v_regular[13] = hmax; + v_regular[14] = lmax; v_regular[15] = hmax; + + TGeoArb8* Layer_SideS_Shape = new TGeoArb8("Layer_SideS_Shape", rsLength/2, v_regular); + + Double_t Layer_Sector_Abs_dx = lmin; + Double_t Layer_Sector_Abs_dy = 3./2; + Double_t Layer_Sector_Abs_dz = rsLength/2; + + TGeoBBox* Layer_SideS_Abs_Base_Shape = new TGeoBBox("Layer_SideS_Abs_Base_Shape", + Layer_Sector_Abs_dx, Layer_Sector_Abs_dy, Layer_Sector_Abs_dz); + + + TGeoVolume* Layer_SideS_Vol = new TGeoVolume("LayerSideSVol", Layer_SideS_Shape, pair); + TGeoVolume* Layer_SideS_Abs_Base_Vol = new TGeoVolume("LayerSideSAbsBaseVol", Layer_SideS_Abs_Base_Shape, piron); + + Layer_SideS_Vol->AddNode(Layer_SideS_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, hmin+Layer_Sector_Abs_dy, 0, rotNoRot)); + + if (layerN % 2 == 0) + { + Double_t Layer_Envelope_startX = lmin; + Double_t Layer_Envelope_shiftX = Layer_Envelope_startX - widthEnv/2; + + Double_t Layer_length = 2*abs(Layer_Envelope_startX); + Int_t Nenvelopes = Int_t((Layer_length)/widthEnv); + + //cout << " Layer #" << layerN << " length: " << Layer_length << endl; + //cout << " Number of MDT detector in Layer" << layerN << ": " << Nenvelopes << endl; + + for (UInt_t i(0); i < Nenvelopes; i++) + { + Layer_SideS_Vol->AddNode(CreateMDT(493.0), i+1, new TGeoCombiTrans("", Layer_Envelope_shiftX, hmin + 3 + 3.5/2, 0, rotNoRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX - widthEnv; + } + } + else + { + Double_t Layer_Envelope_startX = -1.0*abs(lmin); + Double_t Layer_Envelope_shiftX = Layer_Envelope_startX + widthEnv/2; + + Double_t Layer_length = 2*abs(Layer_Envelope_startX); + Int_t Nenvelopes = Int_t((Layer_length)/widthEnv); + + //cout << " Layer #" << layerN << " length: " << Layer_length << endl; + //cout << " Number of MDT detector in Layer" << layerN << ": " << Nenvelopes << endl; + + for (UInt_t i(0); i < Nenvelopes; i++) + { + Layer_SideS_Vol->AddNode(CreateMDT(493.0), i+1, new TGeoCombiTrans("", Layer_Envelope_shiftX, hmin + 3 + 3.5/2, 0, rotNoRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + } + } + + Layer_SideS_Abs_Base_Vol->SetFillColor(fAbsorbColor); + Layer_SideS_Abs_Base_Vol->SetLineColor(fAbsorbColor); + Layer_SideS_Abs_Base_Vol->SetTransparency(30); + + Layer_SideS_Vol->SetFillColor(fBaseColor); + Layer_SideS_Vol->SetLineColor(fBaseColor); + Layer_SideS_Vol->SetTransparency(30); + + return Layer_SideS_Vol; +} + +//________________________________________________________________________________ +TGeoVolume* SpdRsTB2::CreateMDT(Double_t length) +{ + //---------------------------------------------------------------------------- + // Creates MDT of given length; + // Envelope Dimensions(L x W x H): length x 8.5cm x 1.64cm. + // Note: Adopted from Panda Muon System + //---------------------------------------------------------------------------- + + SpdRsTB2GeoMapper* mapper = dynamic_cast<SpdRsTB2GeoMapper*>(fGeoMapper); + if (!mapper) { + cout << "-E- <SpdRsTB2::CreateMDT> Unknown mapper: " << mapper->ClassName() << endl; + return 0; + } + + // Materials ------------------------------------------------------------------------ + + TString mat; + + mat = mapper->GetBaseMaterial(); + TGeoMedium* pair = FindMedium(mat,""); + + mat = mapper->GetActiveMaterialMDT(); + TGeoMedium* pMDTMixture = FindMedium(mat,""); + + mat = mapper->GetPassiveMaterialMDT(); + TGeoMedium* paluminium = FindMedium(mat,""); + + // Shapes and volumes --------------------------------------------------------------- + + // General dimensions + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + Double_t xSize = 1.0; + + TString transName; + Int_t Nenvelopes; + Int_t IncEnv = 0; + + // Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t empty_value = (2.0+2.0+8.5)+6.5*2; + Double_t L_MDT_Envelope = length; //493.0; + Double_t L_MDT_Envelope_sensitive = L_MDT_Envelope-empty_value; + + Int_t ind = Int_t(length*10); + + //--------------------------------------- + + TGeoBBox* Indent20_Shape = new TGeoBBox("Indent20_Shape", widthEnv/2, thicknessEnv/2, 1.0); + TGeoBBox* FEB_box_Shape = new TGeoBBox("FEBbox_Shape", widthEnv/2, thicknessEnv/2, widthEnv/2); + TGeoBBox* DeadMat_Shape = new TGeoBBox("DeadMat_Shape", 4.07, 0.515, 3.25); + + TGeoVolume* Indent20_Vol = new TGeoVolume("Indent20Vol", Indent20_Shape, pair); + TGeoVolume* FEB_box_Vol = new TGeoVolume("FEBboxVol", FEB_box_Shape, pair); + TGeoVolume* DeadMat_Vol = new TGeoVolume("DeadMatVol", DeadMat_Shape, pMDTMixture); + + //--------------------------------------- + + TGeoBBox* L_Al_A_Shape = new TGeoBBox(Form("L%d_Al_A_Shape",ind), 4.03, 0.03, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_Al_B_Shape = new TGeoBBox(Form("L%d_Al_B_Shape",ind), 0.03, 0.42, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_GasCell_Shape = new TGeoBBox(Form("L%d_GasCell_Shape",ind), 0.47, 0.46, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_Cell_Shape = new TGeoBBox(Form("L%d_Cell_Shape",ind), 0.5, 0.46, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_MDT_S_Shape = new TGeoBBox(Form("L%d_MDT_S_Shape",ind), 4.0, 0.46, L_MDT_Envelope_sensitive/2); + + TGeoVolume* L_Al_A_Vol = new TGeoVolume(Form("L%dAlAVol",ind), L_Al_A_Shape, paluminium); + TGeoVolume* L_Al_B_Vol = new TGeoVolume(Form("L%dAlBVol",ind), L_Al_B_Shape, paluminium); + TGeoVolume* L_GasCell_Vol = new TGeoVolume(Form("L%dGasCellVol",ind), L_GasCell_Shape, pMDTMixture); + TGeoVolume* L_Cell_Vol = new TGeoVolume(Form("L%dCellVol",ind), L_Cell_Shape, pMDTMixture); + TGeoVolume* L_MDT_S_Vol = new TGeoVolume(Form("L%dMDTSVol",ind), L_MDT_S_Shape, pMDTMixture); + + //--------------------------------------- + + TGeoBBox* L_Envelope_Shape = new TGeoBBox(Form("L%d_Envelope_Shape",ind), widthEnv/2, thicknessEnv/2, L_MDT_Envelope/2); + + TGeoVolume* L_Envelope_Vol = new TGeoVolume(Form("L%dEnvelopeVol",ind), L_Envelope_Shape, pair); + + // Structure ----------------------------------------------------------------- + + // GasCell and Al_B in Cell + L_Cell_Vol->AddNode(L_GasCell_Vol, 1, new TGeoCombiTrans("", -0.03, 0, 0, rotNoRot)); + L_Cell_Vol->AddNode(L_Al_B_Vol, 1, new TGeoCombiTrans("", 0.47, -0.04, 0, rotNoRot)); + + // Cells in MDT_S + const Int_t NCells = 8; + for (UInt_t i(0); i < NCells; i++) + { + transName.Form("trans_cell_%d", i); + TGeoCombiTrans* trans1 = new TGeoCombiTrans(transName.Data(), -4.0 + xSize/2. + (Double_t)i*xSize, 0, 0., rotNoRot); + trans1->RegisterYourself(); + L_MDT_S_Vol->AddNode(L_Cell_Vol, i+1, trans1); + } + + L_Envelope_Vol->AddNode(Indent20_Vol, 1, new TGeoCombiTrans("", 0, 0, L_MDT_Envelope/2 - 1.0, rotNoRot)); + L_Envelope_Vol->AddNode(Indent20_Vol, 2, new TGeoCombiTrans("", 0, 0, 1.0 - L_MDT_Envelope/2, rotNoRot)); + L_Envelope_Vol->AddNode(FEB_box_Vol, 1, new TGeoCombiTrans("", 0, 0, L_MDT_Envelope/2-2.0-8.5*0.5, rotNoRot)); + L_Envelope_Vol->AddNode(DeadMat_Vol, 1, new TGeoCombiTrans("", 0, 0, ((L_MDT_Envelope-(2.0+2.0+8.5))-6.5)/2-widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(DeadMat_Vol, 2, new TGeoCombiTrans("", 0, 0,-((L_MDT_Envelope-(2.0+2.0+8.5))-6.5)/2-widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_Al_A_Vol, 1, new TGeoCombiTrans("", 0, -0.36, -widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_Al_B_Vol, 1, new TGeoCombiTrans("", -4.0, 0.09, -widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_MDT_S_Vol, 1, new TGeoCombiTrans("", 0.03, 0.13, -widthEnv/2, rotNoRot)); + + L_Envelope_Vol->SetFillColor(kGreen+1); + L_Envelope_Vol->SetLineColor(kGreen+1); + L_Envelope_Vol->SetTransparency(30); + + AddSensitiveVolume(L_GasCell_Vol); //ATTENTION FIXME ATTENTION + + return L_Envelope_Vol; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +SpdGeoMapper* SpdRsTB2::GetMapper() +{ + if (fGeoMapper) return fGeoMapper; + + SpdGeoFactory* factory = SpdGeoFactory::Instance(); + + // search for mapper + fGeoMapper = factory->SearchForMapper("SpdRsTB2GeoMapper"); + + if (!fGeoMapper) fGeoMapper = factory->Mapper("SpdRsTB2GeoMapper"); + + return fGeoMapper; +} + +//_____________________________________________________________________________ +Bool_t SpdRsTB2::LoadParsFrom(SpdParSet* params) +{ + if (!params) return kFALSE; + + if (!SpdDetector::LoadParsFrom(params)) return kFALSE; + + TString mapper; + params->GetParameter("Mapper",mapper); + fGeoMapper = SpdGeoFactory::Instance()->Mapper(mapper); + if (fGeoMapper) fGeoMapper->LoadParametersFrom(params); + + fOutDataPointObject = "unknown"; + + if (fNDataOut < 1) return kTRUE; + + params->GetParameter("Detector/NOutData_1",fOutDataPointObject); + + return kTRUE; +} + +//_____________________________________________________________________________________ +TString SpdRsTB2::GetDataOut(Int_t n) const +{ + if (n < 0 || n >= fNDataOut) return "unknown"; + return fOutDataPointObject; +} + + +//_____________________________________________________________________________________ +TClonesArray* SpdRsTB2::GetCollection(Int_t iColl) const +{ + return (iColl == 0) ? fPointCollection : 0; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +Double_t SpdRsTB2::GetCapacity() const +{ + //return (fModule) ? fModule->GetShape()->Capacity() : 0; + return 0.; +} + +//_____________________________________________________________________________________ +Double_t SpdRsTB2::GetMass() const +{ + return (fModule) ? GetCapacity()*GetDensity() : 0; +} + +//_____________________________________________________________________________________ +Double_t SpdRsTB2::GetDensity() const +{ + return (fModule) ? fModule->GetMaterial()->GetDensity() : 0; +} + +//_____________________________________________________________________________________ +TString SpdRsTB2::GetMaterialName() const // private +{ + return (fModule) ? fModule->GetMaterial()->GetName() : ""; +} + +//_____________________________________________________________________________ +void SpdRsTB2::Print(Option_t*) const +{ + SpdDetector::Print(""); + + if (!fGeoMapper) return; + + TString divider('-',150); + + cout << "\n"; + + fGeoMapper->Print(""); + + cout << "\n"; + cout <<"\tCapacity (total): " << GetCapacity()*1e-6 << " [m^3] " << endl; + cout <<"\tMass (total): " << GetMass()*1e-3 << " [kg] " << endl; + cout <<"\tDensity (averaged): " << GetDensity() << " [g/cm^3] " << endl; + cout << "\n"; + + cout << "\n" << divider.Data() << "\n"; + + printf("%6s %4s %15s %14s %14s %14s \n\n", + "Type","N","Material","Dens [g/cm^3]","Volume [m^3]","Mass [kg]" + ); + + if (!fModule) { + cout << "\n"; + return; + } + + printf("%6d %4d %15s %14.6f %14.6f %14.6f \n", + 1, 1, GetMaterialName().Data(), + GetDensity(), GetCapacity()*1e-6, GetMass()*1e-3); + + cout << divider.Data() << "\n"; + + printf("%6s %35s %14.3e %14.3e \n","TOTAL:","",GetCapacity()*1e-6,GetMass()*1e-3); + + cout << divider.Data() << "\n"; + + cout << "\n"; +} + + diff --git a/rst/barrel/SpdRsTB2.h b/rst/barrel/SpdRsTB2.h new file mode 100644 index 0000000000000000000000000000000000000000..0ec6976293caa0a073081e7c2cf24044562f361e --- /dev/null +++ b/rst/barrel/SpdRsTB2.h @@ -0,0 +1,103 @@ + +#ifndef __SPDRSTB2_H__ +#define __SPDRSTB2_H__ + +#include <TLorentzVector.h> +#include <TString.h> + +#include "SpdDetector.h" + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdRsTB2 // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class FairVolume; +class TClonesArray; + +class SpdRsTB2: public SpdDetector { + +public: + + SpdRsTB2(const char* Name, Bool_t Active); + SpdRsTB2(); + + virtual ~SpdRsTB2(); + + virtual void Initialize(); + virtual void Reset(); + virtual void Register(); + + virtual Bool_t ProcessHits(FairVolume* v = 0); + + virtual TString GetDataOut(Int_t n) const; + virtual TClonesArray* GetCollection(Int_t iColl) const; + + virtual Double_t GetCapacity() const; // cm^3 + virtual Double_t GetMass() const; // g + virtual Double_t GetDensity() const; // g/cm^3 + + virtual SpdGeoMapper* GetMapper(); + + virtual void ConstructGeometry(); + + virtual void EndOfEvent(); + virtual void FinishRun(); + + virtual Bool_t LoadParsFrom(SpdParSet* params); + + virtual void Print(Option_t*) const; + +private: + + void AddHit(); + + /* Track information to be stored until the track leaves the active volume. */ + + Int_t fTrackID; //! track index + Int_t fVolumeID; //! volume id (Detector Id) + TString fVolumePath; //! full path to current volume + TLorentzVector fPos; //! position at entrance + TLorentzVector fMom; //! momentum at entrance + TLorentzVector fPosOut; //! position at exit + TLorentzVector fMomOut; //! momentum at exit + Double32_t fTime; //! time + Double32_t fTimeOut; //! time at exit + Double32_t fLength; //! length + Double32_t fSegmentLength; //! length of segment + Double32_t fELoss; //! energy loss + + /* containers for data */ + + TString fOutDataPointObject; //! + TClonesArray* fPointCollection; //! + + SpdRsTB2(const SpdRsTB2&); + SpdRsTB2& operator=(const SpdRsTB2&); + + /* GEOMETRY */ + + TGeoVolume* fModule; //! + + TGeoVolume* BuildModule(const Char_t* name, TString mat, + Double_t length, Double_t hmin, Double_t hmax, Double_t lmin, Double_t lmax); + + TGeoVolume* CreateBottomLayer(Double_t rsSize, Double_t rsThickness, Double_t rsLength); + TGeoVolume* CreateTopLayer(Int_t layerN, Double_t rsWidth, Double_t rsThickness, Double_t rsLength); + TGeoVolume* CreateRegularLayer(Int_t layerN, Double_t rsSize, Double_t rsThickness, Double_t rsLength); + TGeoVolume* CreateMDT(Double_t length); + + void ConstructDetector(); + + TString GetMaterialName() const; + + Int_t fBaseColor; // (air) + Int_t fAbsorbColor; // (iron) + + ClassDef(SpdRsTB2,1) +}; + +#endif /* __SPDRSTB2_H__ */ diff --git a/rst/barrel/SpdRsTB2Point.cxx b/rst/barrel/SpdRsTB2Point.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ca19810183d42115ce295c7396f36748361e3cc8 --- /dev/null +++ b/rst/barrel/SpdRsTB2Point.cxx @@ -0,0 +1,78 @@ +// $Id$ +// Author: artur 2018/02/01 + +#include "SpdRsTB2Point.h" + +#include <iostream> + +using std::cout; +using std::endl; + +ClassImp(SpdRsTB2Point) + +//_____________________________________________________________________________________ +SpdRsTB2Point::SpdRsTB2Point():FairMCPoint(),fHitGeoPath("") +{ + +} + +//_____________________________________________________________________________________ +SpdRsTB2Point::SpdRsTB2Point(Int_t trackID, Int_t detID, + TVector3 pos, TVector3 mom, Double_t tof, + Double_t length, Double_t eLoss) +:FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), +fHitGeoPath("") +{ + +} + +//_____________________________________________________________________________________ +SpdRsTB2Point::SpdRsTB2Point(Int_t trackID, Int_t detID, TString hpath, + TVector3 pos, TVector3 mom, Double_t tof, + Double_t length, Double_t eLoss) +:FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), +fHitGeoPath(hpath) +{ + +} + +//_____________________________________________________________________________________ +SpdRsTB2Point::SpdRsTB2Point(Int_t trackID, Int_t detID, TString hpath, + TVector3 pos, TVector3 mom, TVector3 posOut, TVector3 momOut, + Double_t tof, Double_t tofOut, + Double_t length, Double_t segmentlength, Double_t eLoss) +:FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), +fHitGeoPath(hpath), +fPosOut(posOut), +fMomOut(momOut), +fTimeOut(tofOut), +fSegmentLength(segmentlength) +{ + +} + +//_____________________________________________________________________________________ +SpdRsTB2Point::~SpdRsTB2Point() +{ + +} + +//_____________________________________________________________________________________ +void SpdRsTB2Point::Print(const Option_t* opt) const +{ + cout << "<SpdRsTB2Point::Print> " << endl; + cout << "\n"; + cout << " Track/DetectorID: " << fTrackID << "/" << fDetectorID << endl; + cout << " Hit node path: " << fHitGeoPath << endl; + cout << " Position In, Time: " << fX << ", " << fY << ", " << fZ << " [cm] " + << fTime << " [ns] " << endl; + cout << " Position Out: " << fPosOut.X() << ", " << fPosOut.Y() << ", " << fPosOut.Z() << " [cm] " << endl; + cout << " Momentum In: " << fPx << ", " << fPy << ", " << fPz << " [GeV]" << endl; + cout << " Momentum Out: " << fMomOut.X() << ", " << fMomOut.Y() << ", " << fMomOut.Z() << " [GeV]" << endl; + cout << " Energy loss: " << fELoss*1.0e06 << " keV " << endl; + cout << "\n"; +} + + + + diff --git a/rst/barrel/SpdRsTB2Point.h b/rst/barrel/SpdRsTB2Point.h new file mode 100644 index 0000000000000000000000000000000000000000..c57b9182712c12d0daba95350ffb14f8741481dc --- /dev/null +++ b/rst/barrel/SpdRsTB2Point.h @@ -0,0 +1,86 @@ +// $Id$ +// Author: artur 2018/02/01 +// +// added new variables for points + +#ifndef __SPDRSTB2POINT_H__ +#define __SPDRSTB2POINT_H__ + +#include "FairMCPoint.h" +#include <TString.h> + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdRsTB2Point2 // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdRsTB2Point : public FairMCPoint { + +public: + + /** Constructor with arguments + *@param trackID Index of MCTrack + *@param detID Detector ID + *@param hpath Hit node full geopath + *@param pos Ccoordinates at entrance to active volume [cm] + *@param mom Momentum of track at entrance [GeV] + *@param posOut Coordinates at exit to active volume [cm] + *@param momOut Momentum of track at exit [GeV] + *@param tof Time since event start [ns] + *@param length Track length since creation [cm] + *@param ELoss Energy deposit [GeV] + **/ + + SpdRsTB2Point(); + + SpdRsTB2Point(Int_t trackID, Int_t detID, + TVector3 pos, TVector3 mom, + Double_t tof, Double_t length, Double_t ELoss); + + SpdRsTB2Point(Int_t trackID, Int_t detID, TString hpath, + TVector3 pos, TVector3 mom, + Double_t tof, Double_t length, Double_t ELoss); + + SpdRsTB2Point(Int_t trackID, Int_t detID, TString hpath, + TVector3 pos, TVector3 mom, TVector3 posOut, TVector3 momOut, + Double_t tof, Double_t tofOut, + Double_t length, Double_t segmentlength, Double_t ELoss); + + SpdRsTB2Point(const SpdRsTB2Point& point) { *this = point; }; + + virtual ~SpdRsTB2Point(); + + /** Accessors **/ + inline TVector3 GetPosIn() const { return TVector3(fX, fY, fZ); } + inline TVector3 GetMomIn() const { return TVector3(fPx, fPy, fPz); } + inline TVector3 GetPosOut() const { return fPosOut; } + inline TVector3 GetMomOut() const { return fMomOut; } + inline Double_t GetSegmentLength() const { return fSegmentLength; } + inline Double_t GetTimeIn() const { return fTime; } + inline Double_t GetTimeOut() const { return fTimeOut; } + + inline void SetHitGeoPath(TString hpath) { fHitGeoPath = hpath; } + + inline TString GetHitGeoPath() const { return fHitGeoPath; } + + virtual void Print(const Option_t* opt) const; + +protected: + + TVector3 fPosOut; + TVector3 fMomOut; + Double32_t fTimeOut; // Time since event start at exit of detector [ns] + Double_t fSegmentLength; // Trajectory segment length inside the detector, [cm] + +private: + + TString fHitGeoPath; + + ClassDef(SpdRsTB2Point,1) + +}; + +#endif /* __SPDRSTB2POINT_H__ */ diff --git a/rst/ecps/SpdRsTEC2.cxx b/rst/ecps/SpdRsTEC2.cxx new file mode 100644 index 0000000000000000000000000000000000000000..21e70d313f61920c0904045f558bf45485daa726 --- /dev/null +++ b/rst/ecps/SpdRsTEC2.cxx @@ -0,0 +1,868 @@ +// $Id$ +// Author: artur 2018/02/01 + +//_____________________________________________________________________________ +// +// SpdRsTEC2 +//_____________________________________________________________________________ + +#include "SpdRsTEC2.h" + +#include "TRefArray.h" +#include "TClonesArray.h" +#include "TParticle.h" +#include "TVirtualMC.h" +#include "TGeoManager.h" +#include "TGeoBBox.h" +#include "TGeoPgon.h" +#include "TGeoCompositeShape.h" +#include "TGeoTube.h" +#include "TGeoMaterial.h" +#include "TGeoMedium.h" +#include "TMath.h" + +#include "SpdRsTEC2Point.h" +#include "SpdRsTEC2GeoMapper.h" + +#include "SpdDetectorList.h" +#include "SpdStack.h" +#include "SpdMCEventHeader.h" +#include "SpdCommonGeoMapper.h" +#include "SpdGeoFactory.h" + +#include <iostream> + +using namespace std; +using namespace TMath; + +ClassImp(SpdRsTEC2) + +//_____________________________________________________________________________________ +SpdRsTEC2::SpdRsTEC2(): + + SpdDetector("RS endcaps (qsl)", kSpdRsTEC, kTRUE), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fPointCollection(0), + fModule(0) +{ + SetParametersType("RsTECParSet"); + + fNDataOut = 1; + fOutDataPointObject = "SpdRsTEC2Point"; + + fBaseColor = kGreen+1; // (air) + fAbsorbColor = kGreen+3; // (iron) +} + +//_____________________________________________________________________________________ +SpdRsTEC2::SpdRsTEC2(const char* name, Bool_t active): + + SpdDetector(name, kSpdRsTEC, active), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fPointCollection(0), + fModule(0) +{ + SetParametersType("RsTECParSet"); + + fNDataOut = 1; + fOutDataPointObject = "SpdRsTEC2Point"; + + fBaseColor = kGreen+1; // (air) + fAbsorbColor = kGreen+3; // (iron) + +} + +//_____________________________________________________________________________________ +SpdRsTEC2::~SpdRsTEC2() +{ + if (fPointCollection) { + fPointCollection->Delete(); + delete fPointCollection; + fPointCollection = 0; + } +} + +//_____________________________________________________________________________________ +void SpdRsTEC2::Initialize() +{ + cout << "\n*******************************************************************************" << endl; + cout << "************************* SpdRsTEC2::Initialize *******************************" << endl; + cout << "*******************************************************************************\n" << endl; + + // data collections + fPointCollection = new TClonesArray(fOutDataPointObject); + + // Initialize module and fill parameters + SpdDetector::Initialize(); + + // SpdParSet* pars = GetParameters(); + // if (pars) pars->printParams(); +} + +//_____________________________________________________________________________________ +void SpdRsTEC2::Reset() +{ + fPointCollection->Clear(); +} + +//_____________________________________________________________________________________ +void SpdRsTEC2::Register() +{ + if (fGeoMapper && fGeoMapper->GetGeoType() < 1) return; + + FairRootManager::Instance()->Register(fOutDataPointObject,"SpdRsTEC2", + fPointCollection, kTRUE); +} + +//_____________________________________________________________________________________ +Bool_t SpdRsTEC2::ProcessHits(FairVolume* vol) +{ + //cout << "<SpdRsTEC2::ProcessHits> " << gMC->CurrentVolPath() << endl; + + //Set parameters at entrance of volume. Reset ELoss. + if (gMC->IsTrackEntering()) { + fELoss = 0.; + fTime = gMC->TrackTime() * 1.e9; // ns -> s + fLength = gMC->TrackLength(); + gMC->TrackPosition(fPos); + gMC->TrackMomentum(fMom); + } + + // Sum energy loss for all steps in the active volume + fELoss += gMC->Edep(); + + // Create SpdRsTEC2Point at exit of active volume + if ( gMC->IsTrackExiting() || + gMC->IsTrackStop() || + gMC->IsTrackDisappeared() ) + { + if (!fSaveEmptyHits && fELoss == 0.) { return kFALSE; } + + fTrackID = gMC->GetStack()->GetCurrentTrackNumber(); + fSegmentLength = gMC->TrackLength() - fLength; + fTimeOut = gMC->TrackTime() * 1.e9; // ns -> s + + fVolumeID = kSpdRsTEC; + fVolumePath = gMC->CurrentVolPath(); + gMC->TrackPosition(fPosOut); + gMC->TrackMomentum(fMomOut); + + //cout << "path = " << gMC->CurrentVolPath() << endl; + + AddHit(); + + //cout << "<SpdRsTEC2::AddHit> " << fPointCollection->GetEntriesFast() << endl; + + SpdStack* stack = (SpdStack*)gMC->GetStack(); + stack->AddPoint(kSpdRsTEC); + } + + return kTRUE; +} + +//_____________________________________________________________________________________ +void SpdRsTEC2::AddHit() +{ + static Bool_t addhit = (fOutDataPointObject == "SpdRsTEC2Point") ? kTRUE : kFALSE; + + if (!addhit) return; + + TClonesArray& clref = *fPointCollection; + Int_t size = clref.GetEntriesFast(); + + new(clref[size]) SpdRsTEC2Point(fTrackID,fVolumeID,fVolumePath, + TVector3(fPos.X(),fPos.Y(),fPos.Z()), + TVector3(fMom.Px(),fMom.Py(),fMom.Pz()), + TVector3(fPosOut.X(),fPosOut.Y(),fPosOut.Z()), + TVector3(fMomOut.Px(),fMomOut.Py(),fMomOut.Pz()), + fTime, fTimeOut, + fLength, fSegmentLength, fELoss); +} + +//_____________________________________________________________________________________ +void SpdRsTEC2::EndOfEvent() +{ + Reset(); +} + +//_____________________________________________________________________________________ +void SpdRsTEC2::FinishRun() +{ + //SpdDetector::FinishRun(); + FillNodesTableIn(GetParameters()); +} + +//_____________________________________________________________________________________ +void SpdRsTEC2::ConstructGeometry() +{ + // Create detector geometry + + fMasterVolume = SpdCommonGeoMapper::Instance()->GetMasterVolume(); + + if (!fMasterVolume) { + cout << "-E- <SpdTsTEC2::ConstructGeometry> No MASTER volume " << endl; + return; + } + + if (!GetMapper()) return; + + if (!fGeoMapper->InitGeometry()) return; + + //fGeoMapper->Print(""); + + Int_t geo_type = fGeoMapper->GetGeoType(); + + ConstructDetector(); + + fGeoMapper->LockGeometry(); + + cout << "\n*******************************************************************************" << endl; + cout << "********************** SpdRsTEC2::ConstructGeometry ***************************" << endl; + cout << "********************** GEOMETRY TYPE: " << geo_type + << " ***************************************" << endl; + cout << "*******************************************************************************\n" << endl; +} + +//_____________________________________________________________________________________ +void SpdRsTEC2::ConstructDetector() +{ + + SpdParameter* par; + SpdRsTEC2GeoMapper* mapper = dynamic_cast<SpdRsTEC2GeoMapper*>(fGeoMapper); + if (!mapper) return; + + Int_t nsectors = mapper->GetNSectors(); //8; + Double_t rsInnerRadius = mapper->GetModuleInnerRadius(); //20.0/2; + Double_t rsOuterRadius = mapper->GetModuleOuterRadius(); //628.8/2.; + Double_t rsThickness = mapper->GetModuleThickness(); //139.0; + + fModule = BuildModule("ECVol", mapper->GetBaseMaterial(), + nsectors, rsInnerRadius, rsOuterRadius, rsThickness); + + if (!fModule) + { + cout << "-E- <SpdRsTEC2::ConstructGeometry> " + << "Volume " << fModule->GetName() << " cannot be created " << endl; + return; + } + + fModule->SetFillColor(kGreen); + fModule->SetLineColor(kGreen); + fModule->SetTransparency(40); + + /*-----------------------------------------------------------*/ + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Int_t nLayers = mapper->GetNLayers(); + + // Add bottom layer (absrober(6.0cm) + mdt detectors(3.5cm)) + fModule->AddNode(CreateFirstLayer(rsInnerRadius, rsOuterRadius, 0.5*rsThickness), 1, + new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + + // Add regular layers (3.0cm absorber + 3.5cm mdt detectors) + for (Int_t i=2; i < nLayers+1; ++i) { + fModule->AddNode(CreateRegularLayer(i, rsInnerRadius, rsOuterRadius, 0.5*rsThickness), i, + new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + } + + // Add top absorber (6.0cm) + fModule->AddNode(CreateLastLayer(nLayers+1, rsInnerRadius, rsOuterRadius, 0.5*rsThickness), nLayers+1, + new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); + + /*-----------------------------------------------------------*/ + + Double_t mindist = mapper->GetDist(); + Double_t angle = mapper->GetSecAngleOver2(); //pi/8 + + Double_t shift = mindist+0.5*rsThickness; // z-shift + + TGeoTranslation trans; + TGeoRotation rot; + + rot.RotateZ(45+angle); + trans.SetTranslation(0,0,shift); + fMasterVolume->AddNode(fModule,1,new TGeoCombiTrans(trans, rot)); + + trans.SetTranslation(0,0,-shift); + rot.RotateX(180); + fMasterVolume->AddNode(fModule,2,new TGeoCombiTrans(trans, rot)); +} + +//_____________________________________________________________________________________ +TGeoVolume* SpdRsTEC2::BuildModule(const char* name, TString mat, + Int_t nsectors, Double_t rsInnerRadius, Double_t rsOuterRadius, Double_t rsThickness) +{ + + TGeoMedium* material = FindMedium(mat,"air"); + + if (!material) { + cout << "-E- <SpdRsTEC2::BuildModule> " + << "Unknown material: " << mat << endl; + return 0; + } + + TGeoVolume* vol = gGeoManager->MakePgon(name, material, 0, 360, nsectors, 2); + TGeoPgon* pgon = (TGeoPgon*)vol->GetShape(); + pgon->DefineSection(0, -0.5*rsThickness, rsInnerRadius, rsOuterRadius); + pgon->DefineSection(1, 0.5*rsThickness, rsInnerRadius, rsOuterRadius); + + return vol; +} + +//_____________________________________________________________________________________ +TGeoVolume* SpdRsTEC2::CreateFirstLayer(Double_t rsInnerRadius, Double_t rsOuterRadius, Double_t rsThickness) +{ + // + // Creates polygon representing bottom layer of the RS EC part + // (6.0cm thick iron absorber and a layer of MDT detectors) + // Parameters: 1. Inner radius of RS from collision point / tube radius (rsInnerRadius) + // 2. Outer radius of RS from collision point (rsOuterRadius) + // 3. Thickness of RS EC rsThickness + // Returns: TGeoVolume object of the layer with absorber and MDTs. + // + SpdRsTEC2GeoMapper* mapper = dynamic_cast<SpdRsTEC2GeoMapper*>(fGeoMapper); + if (!mapper) { + cout << "-E- <SpdRsTEC2::CreateFirstLayer> Unknown mapper: " << mapper->ClassName() << endl; + return 0; + } + + Double_t layerThickness = 6.0+3.5; //cm + + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + + TString mat; + + mat = mapper->GetBaseMaterial(); + TGeoMedium* pair = FindMedium(mat,""); + + mat = mapper->GetAbsorbMaterial(); + TGeoMedium *piron = FindMedium(mat,""); + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + TGeoRotation* rotMDTRot = new TGeoRotation("rotMDTRot", 45./2, 90, 0); + rotMDTRot->RegisterYourself(); + + TGeoPgon* Layer_EC_Shape = new TGeoPgon("Layer_EC_Shape", 0, 360, 8, 2); + Layer_EC_Shape->DefineSection(0, -rsThickness, rsInnerRadius, rsOuterRadius); + Layer_EC_Shape->DefineSection(1, -rsThickness+layerThickness, rsInnerRadius, rsOuterRadius); + + //cout << "1 layer: " << -rsThickness << " " << -rsThickness + layerThickness << endl; + + TGeoVolume* Layer_EC_Vol = new TGeoVolume("LayerECVol", Layer_EC_Shape, pair); + + TGeoPgon* Layer_EC_Abs_Base_Shape = new TGeoPgon("Layer_EC_Abs_Base_Shape", 0, 360, 8, 2); + Layer_EC_Abs_Base_Shape->DefineSection(0, -rsThickness, rsInnerRadius, rsOuterRadius); + Layer_EC_Abs_Base_Shape->DefineSection(1, -rsThickness+6.0, rsInnerRadius, rsOuterRadius); + + TGeoVolume* Layer_EC_Abs_Base_Vol = new TGeoVolume("LayerECAbsBaseVol", Layer_EC_Abs_Base_Shape, piron); + Layer_EC_Vol->AddNode(Layer_EC_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); // + + + Int_t Nenvelopes = Int_t((rsOuterRadius-rsInnerRadius)/widthEnv); + Double_t shift = 0.5*(rsOuterRadius - rsInnerRadius - Nenvelopes*widthEnv); + + Double_t minMDTsize = (rsOuterRadius)*(sqrt(2.0)-1.0); // min size of MDT + Int_t Nenvelopes_MDTvar = Int_t((rsOuterRadius-minMDTsize)/widthEnv); // number of MDTs with varying sizes + + Double_t Layer_Envelope_startX = -rsOuterRadius+shift; + Double_t Layer_Envelope_shiftX = Layer_Envelope_startX + widthEnv/2; + + + Double_t rotX = TMath::Cos(((Double_t)1)*TMath::ACos(-1.0)/8.0); + Double_t rotY = TMath::Sin(((Double_t)1)*TMath::ACos(-1.0)/8.0); + + Double_t smMDT = minMDTsize; + Int_t NumberOfMDT = 1; + for (UInt_t i(0); i<Nenvelopes_MDTvar; i++) + { + Layer_EC_Vol->AddNode(CreateMDT(int(2*smMDT)), NumberOfMDT, + new TGeoCombiTrans("", Layer_Envelope_shiftX*rotX, Layer_Envelope_shiftX*rotY, -rsThickness+6.0+3.5/2, rotMDTRot)); + + smMDT = Layer_Envelope_shiftX + (rsOuterRadius + minMDTsize); // y = x + b + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + NumberOfMDT++; + } + + for (UInt_t i=Nenvelopes_MDTvar; i<Nenvelopes; i++) + { + Layer_EC_Vol->AddNode(CreateMDT(2*(rsOuterRadius-10)), NumberOfMDT, new TGeoCombiTrans("", Layer_Envelope_shiftX*rotX, Layer_Envelope_shiftX*rotY, -rsThickness+6.0+3.5/2, rotMDTRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + NumberOfMDT++; + + } + + Layer_Envelope_shiftX = -(Layer_Envelope_shiftX - widthEnv); + for (UInt_t i=Nenvelopes_MDTvar; i<Nenvelopes; i++) + { + Layer_EC_Vol->AddNode(CreateMDT(2*(rsOuterRadius-10)), NumberOfMDT, new TGeoCombiTrans("", Layer_Envelope_shiftX*rotX, Layer_Envelope_shiftX*rotY, -rsThickness+6.0+3.5/2, rotMDTRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + NumberOfMDT++; + } + + for (UInt_t i=0; i<Nenvelopes_MDTvar; i++) + { + smMDT = -Layer_Envelope_shiftX-widthEnv + (rsOuterRadius + minMDTsize); // y = -x + b + Layer_EC_Vol->AddNode(CreateMDT(int(2*smMDT)), NumberOfMDT, new TGeoCombiTrans("", Layer_Envelope_shiftX*rotX, Layer_Envelope_shiftX*rotY, -rsThickness+6.0+3.5/2, rotMDTRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + NumberOfMDT++; + } + + Layer_EC_Abs_Base_Vol->SetFillColor(fAbsorbColor); + Layer_EC_Abs_Base_Vol->SetLineColor(fAbsorbColor); + Layer_EC_Abs_Base_Vol->SetTransparency(40); + + Layer_EC_Vol->SetFillColor(fBaseColor); + Layer_EC_Vol->SetLineColor(fBaseColor); + Layer_EC_Vol->SetTransparency(40); + + return Layer_EC_Vol; +} + +//_____________________________________________________________________________________ +TGeoVolume* SpdRsTEC2::CreateRegularLayer(Int_t layerN, Double_t rsInnerRadius, Double_t rsOuterRadius, Double_t rsThickness) +{ + // + // Creates trapezoid representing regular layer of the RS EC part + // (3.0cm thick iron absorber and a layer of MDT detectors) + // Parameters: 1. Number of layer in a sector + // 2. Inner radius of RS from collision point / tube radius (rsInnerRadius) + // 3. Outer radius of RS from collision point (rsOuterRadius) + // 4. Thickness of RS EC rsThickness + // Returns: TGeoVolume object of the layer with absorber and MDTs. + // + SpdRsTEC2GeoMapper* mapper = dynamic_cast<SpdRsTEC2GeoMapper*>(fGeoMapper); + if (!mapper) { + cout << "-E- <SpdRsTEC2::CreateRegularLayer> Unknown mapper: " << mapper->ClassName() << endl; + return 0; + } + + TString mat; + + mat = mapper->GetBaseMaterial(); + TGeoMedium* pair = FindMedium(mat,""); + + mat = mapper->GetAbsorbMaterial(); + TGeoMedium *piron = FindMedium(mat,""); + + Double_t layerThickness = 3.0+3.5; //cm + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + TGeoRotation* rotMDTRot = new TGeoRotation("rotMDTRot", 45./2, 90, 0); // + rotMDTRot->RegisterYourself(); + + Double_t shiftZ = -rsThickness + 9.5 + (layerN-2)*layerThickness; + + TGeoPgon* Layer_EC_Shape = new TGeoPgon("Layer_EC_Shape", 0, 360, 8, 2); + Layer_EC_Shape->DefineSection(0, shiftZ, rsInnerRadius, rsOuterRadius); + Layer_EC_Shape->DefineSection(1, shiftZ + layerThickness, rsInnerRadius, rsOuterRadius); + + //cout << layerN << " layer: " << shiftZ << " " << shiftZ + layerThickness << endl; + + TGeoVolume* Layer_EC_Vol = new TGeoVolume("LayerECVol", Layer_EC_Shape, pair); + + + TGeoPgon* Layer_EC_Abs_Base_Shape = new TGeoPgon("Layer_EC_Abs_Base_Shape", 0, 360, 8, 2); + Layer_EC_Abs_Base_Shape->DefineSection(0, shiftZ, rsInnerRadius, rsOuterRadius); + Layer_EC_Abs_Base_Shape->DefineSection(1, shiftZ + 3, rsInnerRadius, rsOuterRadius); + + TGeoVolume* Layer_EC_Abs_Base_Vol = new TGeoVolume("LayerECAbsBaseVol", Layer_EC_Abs_Base_Shape, piron); + Layer_EC_Vol->AddNode(Layer_EC_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); // + + + Int_t Nenvelopes = Int_t((rsOuterRadius-rsInnerRadius)/widthEnv); + Double_t shift = 0.5*(rsOuterRadius - rsInnerRadius - Nenvelopes*widthEnv); + + Double_t minMDTsize = (rsOuterRadius)*(sqrt(2.0)-1.0); // min size of MDT + Int_t Nenvelopes_MDTvar = Int_t((rsOuterRadius-minMDTsize)/widthEnv); // number of MDTs with varying sizes + + Double_t Layer_Envelope_startX; + + if (layerN % 2 == 0) { Layer_Envelope_startX = -rsOuterRadius+shift; } + else + { + shift = shift + 0.5; //shift for half of the size MPD cell + Layer_Envelope_startX = -rsOuterRadius+shift; + } + + + Double_t rotX = TMath::Cos(((Double_t)1)*TMath::ACos(-1.0)/8.0); + Double_t rotY = TMath::Sin(((Double_t)1)*TMath::ACos(-1.0)/8.0); + + Double_t Layer_Envelope_shiftX = Layer_Envelope_startX + widthEnv/2; + + Double_t smMDT = minMDTsize; + Int_t NumberOfMDT = 1; + for (UInt_t i=0; i<Nenvelopes_MDTvar; i++) + { + Layer_EC_Vol->AddNode(CreateMDT(int(2*smMDT)), NumberOfMDT, new TGeoCombiTrans("", Layer_Envelope_shiftX*rotX, Layer_Envelope_shiftX*rotY, shiftZ+3.0+3.5/2, rotMDTRot)); + + smMDT = Layer_Envelope_shiftX + (rsOuterRadius + minMDTsize); // y = x + b + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + NumberOfMDT++; + } + + for (UInt_t i=Nenvelopes_MDTvar; i<Nenvelopes; i++) + { + + Layer_EC_Vol->AddNode(CreateMDT(2*(rsOuterRadius-10)), NumberOfMDT, new TGeoCombiTrans("", Layer_Envelope_shiftX*rotX, Layer_Envelope_shiftX*rotY, shiftZ+3.0+3.5/2, rotMDTRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + NumberOfMDT++; + + } + + Layer_Envelope_shiftX = -(Layer_Envelope_shiftX - widthEnv); + for (UInt_t i=Nenvelopes_MDTvar; i<Nenvelopes; i++) + { + + Layer_EC_Vol->AddNode(CreateMDT(2*(rsOuterRadius-10)), NumberOfMDT, new TGeoCombiTrans("", Layer_Envelope_shiftX*rotX, Layer_Envelope_shiftX*rotY, shiftZ+3.0+3.5/2, rotMDTRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + NumberOfMDT++; + } + + for (UInt_t i=0; i<Nenvelopes_MDTvar; i++) + { + + smMDT = -Layer_Envelope_shiftX-widthEnv + (rsOuterRadius + minMDTsize); // y = -x + b + Layer_EC_Vol->AddNode(CreateMDT(int(2*smMDT)), NumberOfMDT, new TGeoCombiTrans("", Layer_Envelope_shiftX*rotX, Layer_Envelope_shiftX*rotY, shiftZ+3.0+3.5/2, rotMDTRot)); + Layer_Envelope_shiftX = Layer_Envelope_shiftX + widthEnv; + NumberOfMDT++; + } + + Layer_EC_Abs_Base_Vol->SetFillColor(fAbsorbColor); + Layer_EC_Abs_Base_Vol->SetLineColor(fAbsorbColor); + Layer_EC_Abs_Base_Vol->SetTransparency(40); + + Layer_EC_Vol->SetFillColor(fBaseColor); + Layer_EC_Vol->SetLineColor(fBaseColor); + Layer_EC_Vol->SetTransparency(40); + + return Layer_EC_Vol; +} + +//_____________________________________________________________________________________ +TGeoVolume* SpdRsTEC2::CreateLastLayer(Int_t layerN, Double_t rsInnerRadius, Double_t rsOuterRadius, Double_t rsThickness) +{ + // + // Creates trapezoid representing top layer of the RS EC part + // (6.0cm thick iron absorber and no layer of MDT detectors) + // Parameters: 1. Number of layer in a sector + // 2. Inner radius of RS from collision point / tube radius (rsInnerRadius) + // 3. Outer radius of RS from collision point (rsOuterRadius) + // 4. Thickness of RS EC rsThickness + // Returns: TGeoVolume object of the layer with absorber and MDTs. + // + SpdRsTEC2GeoMapper* mapper = dynamic_cast<SpdRsTEC2GeoMapper*>(fGeoMapper); + if (!mapper) { + cout << "-E- <SpdRsTEC2::CreateLastLayer> Unknown mapper: " << mapper->ClassName() << endl; + return 0; + } + + TString mat; + + mat = mapper->GetBaseMaterial(); + TGeoMedium* pair = FindMedium(mat,""); + + mat = mapper->GetAbsorbMaterial(); + TGeoMedium *piron = FindMedium(mat,""); + + Double_t layerThickness = 6.0; //cm + + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t shiftZ = -rsThickness + 9.5 + (layerN-2)*6.5; + + TGeoPgon* Layer_EC_Shape = new TGeoPgon("Layer_EC_Shape", 0, 360, 8, 2); + Layer_EC_Shape->DefineSection(0, shiftZ, rsInnerRadius, rsOuterRadius); + Layer_EC_Shape->DefineSection(1, shiftZ + layerThickness, rsInnerRadius, rsOuterRadius); + + //cout<<"Last layer: " << shiftZ << " " << shiftZ + layerThickness << endl; + + TGeoVolume* Layer_EC_Vol = new TGeoVolume("LayerECVol", Layer_EC_Shape, pair); + + + TGeoPgon* Layer_EC_Abs_Base_Shape = new TGeoPgon("Layer_EC_Abs_Base_Shape", 0, 360, 8, 2); + Layer_EC_Abs_Base_Shape->DefineSection(0, shiftZ, rsInnerRadius, rsOuterRadius); + Layer_EC_Abs_Base_Shape->DefineSection(1, shiftZ + layerThickness, rsInnerRadius, rsOuterRadius); + + TGeoVolume* Layer_EC_Abs_Base_Vol = new TGeoVolume("LayerECAbsBaseVol", Layer_EC_Abs_Base_Shape, piron); + Layer_EC_Vol->AddNode(Layer_EC_Abs_Base_Vol, 1, new TGeoCombiTrans("", 0, 0, 0, rotNoRot)); // + + Layer_EC_Abs_Base_Vol->SetFillColor(fAbsorbColor); + Layer_EC_Abs_Base_Vol->SetLineColor(fAbsorbColor); + Layer_EC_Abs_Base_Vol->SetTransparency(40); + + Layer_EC_Vol->SetFillColor(fBaseColor); + Layer_EC_Vol->SetLineColor(fBaseColor); + Layer_EC_Vol->SetTransparency(40); + + return Layer_EC_Vol; +} + +//_____________________________________________________________________________________ +TGeoVolume* SpdRsTEC2::CreateMDT(Double_t length) +{ + // + // Creates MDT of given length; + // Envelope Dimensions(L x W x H): length x 8.5cm x 1.64cm. + // Note: Adopted from Panda Muon System + // + SpdRsTEC2GeoMapper* mapper = dynamic_cast<SpdRsTEC2GeoMapper*>(fGeoMapper); + if (!mapper) { + cout << "-E- <SpdRsTEC2::CreateMDT> Unknown mapper: " << mapper->ClassName() << endl; + return 0; + } + + TString mat; + + mat = mapper->GetBaseMaterial(); + TGeoMedium* pair = FindMedium(mat,""); + + mat = mapper->GetActiveMaterialMDT(); + TGeoMedium* pMDTMixture = FindMedium(mat,""); + + mat = mapper->GetPassiveMaterialMDT(); + TGeoMedium* paluminium = FindMedium(mat,""); + + // Shapes and volumes --------------------------------------------------------------- + // General dimensions + Double_t widthEnv = 8.5; //cm xAxis + Double_t thicknessEnv = 1.64; //cm zAxis + Double_t xSize = 1.0; + + TString transName; + Int_t Nenvelopes; + Int_t IncEnv = 0; + + //Matrices + TGeoRotation* rotNoRot = new TGeoRotation("rotNoRot", 0., 0., 0.); + rotNoRot->RegisterYourself(); + + Double_t empty_value = (2.0+2.0+8.5)+6.5*2; + Double_t L_MDT_Envelope = length; //493.0; + Double_t L_MDT_Envelope_sensitive = L_MDT_Envelope-empty_value; + + + Int_t ind = int(length*10); + + //Shapes + TGeoBBox* Indent20_Shape = new TGeoBBox("Indent20_Shape", widthEnv/2, thicknessEnv/2, 1.0); + TGeoBBox* FEB_box_Shape = new TGeoBBox("FEBbox_Shape", widthEnv/2, thicknessEnv/2, widthEnv/2); + TGeoBBox* DeadMat_Shape = new TGeoBBox("DeadMat_Shape", 4.07, 0.515, 3.25); + + TGeoVolume* Indent20_Vol = new TGeoVolume("Indent20Vol", Indent20_Shape, pair); + TGeoVolume* FEB_box_Vol = new TGeoVolume("FEBboxVol", FEB_box_Shape, pair); + TGeoVolume* DeadMat_Vol = new TGeoVolume("DeadMatVol", DeadMat_Shape, pMDTMixture); + + //--------------------------------------- + + TGeoBBox* L_Al_A_Shape = new TGeoBBox(Form("L%d_Al_A_Shape",ind), 4.03, 0.03, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_Al_B_Shape = new TGeoBBox(Form("L%d_Al_B_Shape",ind), 0.03, 0.42, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_GasCell_Shape = new TGeoBBox(Form("L%d_GasCell_Shape",ind), 0.47, 0.46, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_Cell_Shape = new TGeoBBox(Form("L%d_Cell_Shape",ind), 0.5, 0.46, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_MDT_S_Shape = new TGeoBBox(Form("L%d_MDT_S_Shape",ind), 4.0, 0.46, L_MDT_Envelope_sensitive/2); + TGeoBBox* L_Envelope_Shape = new TGeoBBox(Form("L%d_Envelope_Shape",ind), widthEnv/2, thicknessEnv/2, L_MDT_Envelope/2); + + //Volumes + TGeoVolume* L_Al_A_Vol = new TGeoVolume(Form("L%dAlAVol",ind), L_Al_A_Shape, paluminium); + TGeoVolume* L_Al_B_Vol = new TGeoVolume(Form("L%dAlBVol",ind), L_Al_B_Shape, paluminium); + TGeoVolume* L_GasCell_Vol = new TGeoVolume(Form("L%dGasCellVol",ind), L_GasCell_Shape, pMDTMixture); + TGeoVolume* L_Cell_Vol = new TGeoVolume(Form("L%dCellVol",ind), L_Cell_Shape, pMDTMixture); + TGeoVolume* L_MDT_S_Vol = new TGeoVolume(Form("L%dMDTSVol",ind), L_MDT_S_Shape, pMDTMixture); + TGeoVolume* L_Envelope_Vol = new TGeoVolume(Form("L%dEnvelopeVol",ind), L_Envelope_Shape, pair); + + // Volume hierarchy ----------------------------------------------------------------- + //Structure + //GasCell and Al_B in Cell + L_Cell_Vol->AddNode(L_GasCell_Vol, 1, + new TGeoCombiTrans("", -0.03, 0, 0, rotNoRot)); + L_Cell_Vol->AddNode(L_Al_B_Vol, 1, + new TGeoCombiTrans("", 0.47, -0.04, 0, rotNoRot)); + + //8 Cells in MDT_S + const Int_t NCells = 8; + for (UInt_t i(0); i<NCells; i++) { + transName.Form("trans_cell_%d", i); + TGeoCombiTrans* trans1 = new TGeoCombiTrans(transName.Data(), -4.0 + xSize/2. + (Double_t)i*xSize, 0, 0., rotNoRot); + trans1->RegisterYourself(); + L_MDT_S_Vol->AddNode(L_Cell_Vol, i+1, trans1); + } + + L_Envelope_Vol->AddNode(Indent20_Vol, 1, + new TGeoCombiTrans("", 0, 0, L_MDT_Envelope/2 - 1.0, rotNoRot)); + L_Envelope_Vol->AddNode(Indent20_Vol, 2, + new TGeoCombiTrans("", 0, 0, 1.0 - L_MDT_Envelope/2, rotNoRot)); + L_Envelope_Vol->AddNode(FEB_box_Vol, 1, + new TGeoCombiTrans("", 0, 0, L_MDT_Envelope/2-2.0-8.5*0.5, rotNoRot)); + L_Envelope_Vol->AddNode(DeadMat_Vol, 1, + new TGeoCombiTrans("", 0, 0, ((L_MDT_Envelope-(2.0+2.0+8.5))-6.5)/2-widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(DeadMat_Vol, 2, + new TGeoCombiTrans("", 0, 0, -((L_MDT_Envelope-(2.0+2.0+8.5))-6.5)/2-widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_Al_A_Vol, 1, + new TGeoCombiTrans("", 0, -0.36, -widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_Al_B_Vol, 1, + new TGeoCombiTrans("", -4.0, 0.09, -widthEnv/2, rotNoRot)); + L_Envelope_Vol->AddNode(L_MDT_S_Vol, 1, + new TGeoCombiTrans("", 0.03, 0.13, -widthEnv/2, rotNoRot)); + + L_Envelope_Vol->SetFillColor(kGreen+1); + L_Envelope_Vol->SetLineColor(kGreen+1); + L_Envelope_Vol->SetTransparency(30); + + AddSensitiveVolume(L_GasCell_Vol); //ATTENTION FIXME ATTENTION + + return L_Envelope_Vol; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +SpdGeoMapper* SpdRsTEC2::GetMapper() +{ + if (fGeoMapper) return fGeoMapper; + + SpdGeoFactory* factory = SpdGeoFactory::Instance(); + + // search for mapper + fGeoMapper = factory->SearchForMapper("SpdRsTEC2GeoMapper"); + + // create default mapper + if (!fGeoMapper) fGeoMapper = factory->Mapper("SpdRsTEC2GeoMapper"); + + return fGeoMapper; +} + +//_____________________________________________________________________________ +Bool_t SpdRsTEC2::LoadParsFrom(SpdParSet* params) +{ + if (!params) return kFALSE; + + if (!SpdDetector::LoadParsFrom(params)) return kFALSE; + + TString mapper; + params->GetParameter("Mapper",mapper); + fGeoMapper = SpdGeoFactory::Instance()->Mapper(mapper); + if (fGeoMapper) fGeoMapper->LoadParametersFrom(params); + + fOutDataPointObject = "unknown"; + + if (fNDataOut < 1) return kTRUE; + + params->GetParameter("Detector/NOutData_1",fOutDataPointObject); + + return kTRUE; +} + +//_____________________________________________________________________________________ +TString SpdRsTEC2::GetDataOut(Int_t n) const +{ + if (n < 0 || n >= fNDataOut) return "unknown"; + return fOutDataPointObject; +} + + +//_____________________________________________________________________________________ +TClonesArray* SpdRsTEC2::GetCollection(Int_t iColl) const +{ + return (iColl == 0) ? fPointCollection : 0; +} + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________________ +Double_t SpdRsTEC2::GetCapacity() const +{ + // return (fModule) ? fModule->GetShape()->Capacity() : 0; + return 0; +} + +//_____________________________________________________________________________________ +Double_t SpdRsTEC2::GetMass() const +{ + return (fModule) ? GetCapacity()*GetDensity() : 0; +} + +//_____________________________________________________________________________________ +Double_t SpdRsTEC2::GetDensity() const +{ + return (fModule) ? fModule->GetMaterial()->GetDensity() : 0; +} + +//_____________________________________________________________________________________ +TString SpdRsTEC2::GetMaterialName() const // private +{ + return (fModule) ? fModule->GetMaterial()->GetName() : ""; +} + +//_____________________________________________________________________________ +void SpdRsTEC2::Print(Option_t*) const +{ + SpdDetector::Print(""); + + if (!fGeoMapper) return; + + TString divider('-',150); + + cout << "\n"; + + fGeoMapper->Print(""); + + cout << "\n"; + cout <<"\tCapacity (total): " << GetCapacity()*1e-6 << " [m^3] " << endl; + cout <<"\tMass (total): " << GetMass()*1e-3 << " [kg] " << endl; + cout <<"\tDensity (averaged): " << GetDensity() << " [g/cm^3] " << endl; + cout << "\n"; + + cout << "\n" << divider.Data() << "\n"; + printf("%6s %4s %15s %14s %14s %14s \n\n", + "Type","N","Material","Dens [g/cm^3]","Volume [m^3]","Mass [kg]" + ); + + if (!fModule) { + cout << "\n"; + return; + } + + printf("%6d %4d %15s %14.6f %14.6f %14.6f \n", + 1, 1, GetMaterialName().Data(), + GetDensity(), GetCapacity()*1e-6, GetMass()*1e-3); + + cout << divider.Data() << "\n"; + + printf("%6s %35s %14.3e %14.3e \n","TOTAL:","",GetCapacity()*1e-6,GetMass()*1e-3); + + cout << divider.Data() << "\n"; + + cout << "\n"; + +} + + diff --git a/rst/ecps/SpdRsTEC2.h b/rst/ecps/SpdRsTEC2.h new file mode 100644 index 0000000000000000000000000000000000000000..75d4d3aba36643d5427f9f9409a324b55a547757 --- /dev/null +++ b/rst/ecps/SpdRsTEC2.h @@ -0,0 +1,102 @@ + +#ifndef __SPDRSTEC2_H__ +#define __SPDRSTEC2_H__ + +#include <TLorentzVector.h> +#include <TString.h> + +#include "SpdDetector.h" + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdRsTEC2 // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class FairVolume; +class TClonesArray; + +class SpdRsTEC2: public SpdDetector { + +public: + + SpdRsTEC2(const char* Name, Bool_t Active); + SpdRsTEC2(); + + virtual ~SpdRsTEC2(); + + virtual void Initialize(); + virtual void Reset(); + virtual void Register(); + + virtual Bool_t ProcessHits(FairVolume* v = 0); + + virtual TString GetDataOut(Int_t n) const; + virtual TClonesArray* GetCollection(Int_t iColl) const; + + virtual Double_t GetCapacity() const; // cm^3 + virtual Double_t GetMass() const; // g + virtual Double_t GetDensity() const; // g/cm^3 + + virtual SpdGeoMapper* GetMapper(); + + virtual void ConstructGeometry(); + + virtual void EndOfEvent(); + virtual void FinishRun(); + + virtual Bool_t LoadParsFrom(SpdParSet* params); + + virtual void Print(Option_t*) const; + +private: + + void AddHit(); + + /* Track information to be stored until the track leaves the active volume. */ + + Int_t fTrackID; //! track index + Int_t fVolumeID; //! volume id (detector id) + TString fVolumePath; //! full path to current volume + TLorentzVector fPos; //! position at entrance + TLorentzVector fMom; //! momentum at entrance + TLorentzVector fPosOut; //! position at exit + TLorentzVector fMomOut; //! momentum at exit + Double32_t fTime; //! time + Double32_t fTimeOut; //! time at exit + Double32_t fLength; //! length + Double32_t fSegmentLength; //! length of segment + Double32_t fELoss; //! energy loss + + /* containers for data */ + + TString fOutDataPointObject; //! + TClonesArray* fPointCollection; //! + + SpdRsTEC2(const SpdRsTEC2&); + SpdRsTEC2& operator=(const SpdRsTEC2&); + + /* GEOMETRY */ + + TGeoVolume* fModule; //! + + TGeoVolume* BuildModule(const char* name, TString mat, + Int_t nsectors, Double_t rsInnerRadius, Double_t rsOuterRadius, Double_t rsThickness); + TGeoVolume* CreateFirstLayer(Double_t rsInnerRadius, Double_t rsOuterRadius, Double_t rsThickness); + TGeoVolume* CreateRegularLayer(Int_t layerN, Double_t rsInnerRadius, Double_t rsOuterRadius, Double_t rsThickness); + TGeoVolume* CreateLastLayer(Int_t layerN, Double_t rsInnerRadius, Double_t rsOuterRadius, Double_t rsThickness); + TGeoVolume* CreateMDT(Double_t length); + + void ConstructDetector(); + + TString GetMaterialName() const; + + Int_t fBaseColor; // (air) + Int_t fAbsorbColor; // (iron) + + ClassDef(SpdRsTEC2,1) +}; + +#endif /* __SPDRSTEC2_H__ */ diff --git a/rst/ecps/SpdRsTEC2Point.cxx b/rst/ecps/SpdRsTEC2Point.cxx new file mode 100644 index 0000000000000000000000000000000000000000..bda212272684050bb6d5ec929737e84a6a2d99f6 --- /dev/null +++ b/rst/ecps/SpdRsTEC2Point.cxx @@ -0,0 +1,78 @@ +// $Id$ +// Author: alver 2020/07/16 + +#include "SpdRsTEC2Point.h" + +#include <iostream> + +using std::cout; +using std::endl; + +ClassImp(SpdRsTEC2Point) + +//_____________________________________________________________________________________ +SpdRsTEC2Point::SpdRsTEC2Point():FairMCPoint(),fHitGeoPath("") +{ + +} + +//_____________________________________________________________________________________ +SpdRsTEC2Point::SpdRsTEC2Point(Int_t trackID, Int_t detID, + TVector3 pos, TVector3 mom, Double_t tof, + Double_t length, Double_t eLoss) +:FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), +fHitGeoPath("") +{ + +} + +//_____________________________________________________________________________________ +SpdRsTEC2Point::SpdRsTEC2Point(Int_t trackID, Int_t detID, TString hpath, + TVector3 pos, TVector3 mom, Double_t tof, + Double_t length, Double_t eLoss) +:FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), +fHitGeoPath("") +{ + +} + +//_____________________________________________________________________________________ +SpdRsTEC2Point::SpdRsTEC2Point(Int_t trackID, Int_t detID, TString hpath, + TVector3 pos, TVector3 mom, TVector3 posOut, TVector3 momOut, + Double_t tof, Double_t tofOut, + Double_t length, Double_t segmentlength, Double_t eLoss) +:FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss), +fHitGeoPath(hpath), +fPosOut(posOut), +fMomOut(momOut), +fTimeOut(tofOut), +fSegmentLength(segmentlength) +{ + +} + +//_____________________________________________________________________________________ +SpdRsTEC2Point::~SpdRsTEC2Point() +{ + +} + +//_____________________________________________________________________________________ +void SpdRsTEC2Point::Print(const Option_t* opt) const +{ + cout << "<SpdRsTECPoint::Print> " << endl; + cout << "\n"; + cout << " Track/DetectorID: " << fTrackID << "/" << fDetectorID << endl; + cout << " Hit node path: " << fHitGeoPath << endl; + cout << " Position, Time In: " << fX << ", " << fY << ", " << fZ << " [cm] " + << fTime << " [ns] " << endl; + cout << " Position, Time Out: " << fPosOut.X() << ", " << fPosOut.Y() << ", " << fPosOut.Z() << " [cm] " << fTimeOut << " [ns] " << endl; + cout << " Momentum In: " << fPx << ", " << fPy << ", " << fPz << " [GeV]" << endl; + cout << " Momentum Out: " << fMomOut.X() << ", " << fMomOut.Y() << ", " << fMomOut.Z() << " [GeV]" << endl; + cout << " Energy loss: " << fELoss*1.0e06 << " keV " << endl; + cout << "\n"; +} + + + + diff --git a/rst/ecps/SpdRsTEC2Point.h b/rst/ecps/SpdRsTEC2Point.h new file mode 100644 index 0000000000000000000000000000000000000000..6aed9b7d11d5854d41ff4f5f729c2994fdb57e24 --- /dev/null +++ b/rst/ecps/SpdRsTEC2Point.h @@ -0,0 +1,84 @@ +// $Id$ +// Author: alver 2020/07/16 + +#ifndef __SPDRSTEC2POINT_H__ +#define __SPDRSTEC2POINT_H__ + +#include "FairMCPoint.h" +#include <TString.h> + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdRsTEC2Point // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdRsTEC2Point : public FairMCPoint { + +public: + + /** Constructor with arguments + *@param trackID Index of MCTrack + *@param detID Detector ID + *@param modID Module ID + *@param submodID SubModule ID + *@param pos Ccoordinates at entrance to active volume [cm] + *@param mom Momentum of track at entrance [GeV] + *@param posOut Coordinates at exit to active volume [cm] + *@param momOut Momentum of track at exit [GeV] + *@param tof Time since event start [ns] + *@param length Track length since creation [cm] + *@param ELoss Energy deposit [GeV] + **/ + + SpdRsTEC2Point(); + + SpdRsTEC2Point(Int_t trackID, Int_t detID, + TVector3 pos, TVector3 mom, + Double_t tof, Double_t length, Double_t ELoss); + + SpdRsTEC2Point(Int_t trackID, Int_t detID, TString hpath, + TVector3 pos, TVector3 mom, + Double_t tof, Double_t length, Double_t ELoss); + + SpdRsTEC2Point(Int_t trackID, Int_t detID, TString hpath, + TVector3 pos, TVector3 mom, TVector3 posOut, TVector3 momOut, + Double_t tof, Double_t tofOut, + Double_t length, Double_t segmentlength, Double_t ELoss); + + SpdRsTEC2Point(const SpdRsTEC2Point& point) { *this = point; }; + + virtual ~SpdRsTEC2Point(); + + inline void SetHitGeoPath(TString hpath) { fHitGeoPath = hpath; } + + inline TString GetHitGeoPath() const { return fHitGeoPath; } + + virtual void Print(const Option_t* opt) const; + + /** Accessors **/ + inline TVector3 GetPosIn() const { return TVector3(fX, fY, fZ); } + inline TVector3 GetMomIn() const { return TVector3(fPx, fPy, fPz); } + inline TVector3 GetPosOut() const { return fPosOut; } + inline TVector3 GetMomOut() const { return fMomOut; } + inline Double_t GetSegmentLength() const { return fSegmentLength; } + inline Double_t GetTimeIn() const { return fTime; } + inline Double_t GetTimeOut() const { return fTimeOut; } +protected: + + TVector3 fPosOut; + TVector3 fMomOut; + Double32_t fTimeOut; // Time since event start at exit of detector [ns] + Double_t fSegmentLength; // Trajectory segment length inside the detector, [cm] + +private: + + TString fHitGeoPath; + + ClassDef(SpdRsTEC2Point,1) + +}; /* __SPDRSTEC2POINT_H__ */ + +#endif diff --git a/scripts/run.pbs b/scripts/run.pbs deleted file mode 100644 index 8b9347542df0689618a507bc980cb3ed710aa79c..0000000000000000000000000000000000000000 --- a/scripts/run.pbs +++ /dev/null @@ -1,46 +0,0 @@ -#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -# SPDROOT FRAMEWORK -#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -#PBS -l cput=01:00:00 -#PBS -l walltime=01:00:00 - -EVENTS=1 - -#set output directory (SCRATCH) -#OUTDIR=/scrc/u/avt/Projects/DATA/SIMU/spd -OUTDIR=$PBS_O_WORKDIR - -#choosing output server -SOUT=lxpub01 - -#full path to folder spdroot were installed (AFS) -SPDROOTPATH=/afs/jinr.ru/user/a/avt/spdroot - -#set input macro path (AFS) -SPDMACROPATH=$SPDROOTPATH - -#----------------------------------------- - -cd $TMPDIR -cp $SPDMACROPATH/macro/run_sim.C . -cp $SPDROOTPATH/build/config.sh . - -if test ! -e $TMPDIR/run_sim.C ; then - echo "ERROR: no $TMPDIR/run_sim.C" - ret=1 -fi -if test ! -e $TMPDIR/config.sh ; then - echo "ERROR: no $TMPDIR/config.sh" - ret=1 -fi - -#[ ret > 0 ]; exit 1 - -source config.sh - -root -b -q "run_sim.C($EVENTS)" - -scp -p2 *.root $SOUT:$OUTDIR/ - - diff --git a/scripts/spdrun.nx b/scripts/spdrun.nx deleted file mode 100644 index 8bdf147c7172d23aaf54f45c810c0ec0f6e43691..0000000000000000000000000000000000000000 --- a/scripts/spdrun.nx +++ /dev/null @@ -1,34 +0,0 @@ -#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -# SPDROOT FRAMEWORK -# -# the macro is provided only for scratch using (i.e. from /scrc/u/...) -#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -#set number of RUNS -NRUN=3 - -#the files needed in current directory -PBSSCRIPT=spdrun.pbs -SPDMACRO=run_sim.C - -CDIR=$PWD - -PBSSCRIPTPATH=$CDIR -SPDMACROPATH=$CDIR - -#----------------------------------------- - -for ((i=1; i <= NRUN; i++)) -do - mkdir $CDIR/xrun_$i - cd $CDIR/xrun_$i - - cp $PBSSCRIPTPATH/$PBSSCRIPT . - cp $SPDMACROPATH/$SPDMACRO . - - qsub $PBSSCRIPT - - #rm -f arun.pbs - - cd $CDIR -done \ No newline at end of file diff --git a/scripts/spdrun.pbs b/scripts/spdrun.pbs deleted file mode 100644 index 83e45f32a695d184389bbc1600d9c17635fad722..0000000000000000000000000000000000000000 --- a/scripts/spdrun.pbs +++ /dev/null @@ -1,48 +0,0 @@ -#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -# SPDROOT FRAMEWORK -# -# the macro is provided only for scratch using (i.e. from /scrc/u/...) -#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -#PBS -l cput=99:00:00 -#PBS -l walltime=99:00:00 - -#set number of events in the RUN -EVENTS=1 - -#full path to folder spdroot were installed (AFS) -SPDROOTPATH=/afs/jinr.ru/user/a/avt/spdroot - -#choosing output server -SOUT=lxpub01 - -#set output directory (current directory, SCRATCH) -OUTDIR=$PBS_O_WORKDIR - -#set input macro path (current directory, SCRATCH) -SPDMACROPATH=$OUTDIR - -#----------------------------------------- - -cd $TMPDIR -scp -p2 $SOUT:$SPDMACROPATH/run_sim.C . -cp $SPDROOTPATH/build/config.sh . - -if test ! -e $TMPDIR/run_sim.C ; then - echo "ERROR: no $TMPDIR/run_sim.C" - ret=1 -fi -if test ! -e $TMPDIR/config.sh ; then - echo "ERROR: no $TMPDIR/config.sh" - ret=1 -fi - -#[ ret > 0 ]; exit 1 - -source config.sh - -root -b -q "run_sim.C($EVENTS)" - -scp -p2 *.root $SOUT:$OUTDIR/ - - diff --git a/spddata/CMakeLists.txt b/spddata/CMakeLists.txt index 9ac8329af746da2482e26ad51ab73eb829c4393b..ae358a79619f95db720f9407ab1395ebb880a69a 100644 --- a/spddata/CMakeLists.txt +++ b/spddata/CMakeLists.txt @@ -33,7 +33,7 @@ mcdata/SpdPrimGenData.cxx params/SpdParameter.cxx params/SpdFieldPar.cxx -params/SpdPassiveGeoPar.cxx +params/SpdPassiveGeoParSet.cxx params/SpdBaseParSet.cxx params/SpdParSet.cxx params/SpdPrimGenParSet.cxx @@ -50,11 +50,32 @@ kfdata/SpdKFSimpleRes.cxx ) -# Set(HEADERS -# -# SpdDetectorList.h -# -# ) +Set(HEADERS + +IdealTrackData/SpdIdealDataInfo.h +IdealTrackData/SpdIdealHit.h +IdealTrackData/SpdIdealSpacepointHit.h +IdealTrackData/SpdIdealTrackColl.h +IdealTrackData/SpdIdealTrack.h +IdealTrackData/SpdIdealWirepointHit.h +kfdata/SpdKFSimpleRes.h +mcdata/SpdMCEventHeader.h +mcdata/SpdMCTrack.h +mcdata/SpdPrimGenData.h +params/SpdBaseParSet.h +params/SpdFieldPar.h +params/SpdParameter.h +params/SpdParSetContFact.h +params/SpdParSet.h +params/SpdPassiveGeoParSet.h +params/SpdPrimGenParSet.h +RWdata.h +SpdDetectorList.h +SpdGeopathParser.h +#TrackData/SpdTrackCand.h +#TrackData/SpdTrackCandHit.h +#TrackData/SpdTrack.h +) Set(LINKDEF SpdDataLinkDef.h) Set(LIBRARY_NAME SpdData) diff --git a/spddata/IdealTrackData/SpdIdealDataInfo.cxx b/spddata/IdealTrackData/SpdIdealDataInfo.cxx index 8cdb1244a7477b9e5d06bdb1f3a8ed45877dc40e..18fd3f65bcceffe663e26f4bd8c9d2eb9802c3f0 100644 --- a/spddata/IdealTrackData/SpdIdealDataInfo.cxx +++ b/spddata/IdealTrackData/SpdIdealDataInfo.cxx @@ -45,11 +45,11 @@ Int_t SpdIdealDataInfo::GetNHits() const //_____________________________________________________________________________ void SpdIdealDataInfo::PrintInfo(TString opt) const { - if (opt == "short") { cout << "-I- <SpdIdealDataInfo::PrintInfo> " << fName << ", " << fTitle << "; module: " << fDetId << "; hit type: " << fHitType - << "; tracks/hits: " << GetNTracks() << "/" << GetNHits() << endl; + << "; tracks/hits: " << GetNTracks() << "/" << GetNHits() + << endl; return; } diff --git a/spddata/IdealTrackData/SpdIdealHit.cxx b/spddata/IdealTrackData/SpdIdealHit.cxx index 2a4ceb2fb5b038a9f98f1e1d2f87b6e56d2a3511..c4e42903f7ffa1bbbaa9612ef1b925b6326981a8 100644 --- a/spddata/IdealTrackData/SpdIdealHit.cxx +++ b/spddata/IdealTrackData/SpdIdealHit.cxx @@ -18,8 +18,8 @@ using std::endl; ClassImp(SpdIdealHit) //_____________________________________________________________________________ -SpdIdealHit::SpdIdealHit():FairTimeStamp(), -fEdep(0.),fInfoNum(-1),fMotherPointNum(-1) +SpdIdealHit::SpdIdealHit():FairTimeStamp(),fSpecifity('n'), +fEdep(0.),fId(-1),fInfoNum(-1),fMotherPointNum(-1),fResolution(-1,-1,-1) { fDetId.assign(IDSIZE,0); } @@ -38,35 +38,56 @@ void SpdIdealHit::Clear() fTimeStamp = -1.; fTimeStampError = -1.; + fId = -1; fInfoNum = -1; fMotherPointNum = -1; + fTrackId.clear(); + fDetId.assign(IDSIZE,0); + + fResolution.SetXYZ(-1,-1,-1); } //_____________________________________________________________________________ void SpdIdealHit::SetDetId(Int_t i, Long_t id) { - if ( !(i < 0) && i < IDSIZE) fDetId[i] = id; + if (i < 0) return; + + if (i < IDSIZE) fDetId[i] = id; + else { + fDetId.resize(i+1,0); + fDetId[i] = id; + } } //_____________________________________________________________________________ Long_t SpdIdealHit::GetDetId(Int_t i) const { - return ( !(i < 0) && i < IDSIZE) ? fDetId[i]: Int_t(kSpdUndefined); + if (i < 0) return Int_t(kSpdUndefined); + if (i < IDSIZE) return fDetId[i]; + if (i < fDetId.size()) return fDetId[i]; + return Int_t(kSpdUndefined); } //_____________________________________________________________________________ -void SpdIdealHit::PrintHit(Bool_t print_point) const +void SpdIdealHit::PrintHit(Bool_t print_point, Bool_t print_res) const { - cout << "\t-I- <" << this->ClassName() << "::PrintHit>" << "\n"; - cout << "\tDetector id: " << fDetId[0] << " " << fDetId[1] << " " << fDetId[2] << endl; + cout << "\t<" << this->ClassName() << "::PrintHit>" << "\n\n"; + cout << "\tHit unique ID: " << fId << endl; + cout << "\tDetector id: "; for (Int_t i(0); i<fDetId.size(); i++) { cout << fDetId[i] << " "; } cout << endl; + cout << "\tTrack id: "; for (Int_t i(0); i<fTrackId.size(); i++) { cout << fTrackId[i] << " "; } cout << endl; cout << "\tInfo, mcpoint: " << fInfoNum << ", " << fMotherPointNum << endl; cout << "\tEdep, Time: " << fEdep << " [GeV], " << fTimeStamp << " [ns] " << endl; + cout << "\tSpecifity: " << fSpecifity << endl; if (print_point) { cout << "\tPoint(x,y,z): " - << GetPointX() << ", " << GetPointY() << ", " << GetPointZ() << " [cm] " << endl; + << fPoint.X() << ", " << fPoint.Y() << ", " << fPoint.Z() << " [cm] " << endl; + } + if (print_res) { + cout << "\tResolution: " + << fResolution.X() << ", " << fResolution.Y() << ", " << fResolution.Z() << " [cm] " << endl; } cout << "\n"; } diff --git a/spddata/IdealTrackData/SpdIdealHit.h b/spddata/IdealTrackData/SpdIdealHit.h index 9a1566d2beb197b8bc17f19fe2403d50a3f58dea..66b9cb43e1799e6d585e96b8b37e72df55dd2885 100644 --- a/spddata/IdealTrackData/SpdIdealHit.h +++ b/spddata/IdealTrackData/SpdIdealHit.h @@ -34,42 +34,85 @@ public: virtual ~SpdIdealHit(); void Clear(); + + // unable/disable methods (set/get) + virtual void DisableHit(Bool_t disable) { fSpecifity = 'd'; } + virtual Bool_t IsHitDisabled() { return (fSpecifity == 'd'); } /* setters */ - void SetDetId(Int_t i, Long_t id); - void SetEdep(Double_t edep) { fEdep = edep; } - void SetInfoNum(Int_t n) { fInfoNum = n; } - void SetMotherPointNum(Int_t n) { fMotherPointNum = n; } + virtual void SetDetId(Int_t i, Long_t id); + virtual void SetSpecifity(Char_t spec) { fSpecifity = spec; } + + void SetEdep(Double_t edep) { fEdep = edep; } + void SetId(Int_t id) { fId = id; } + void SetInfoNum(Int_t n) { fInfoNum = n; } + void SetMotherPointNum(Int_t n) { fMotherPointNum = n; } + + void AddTrackId(Int_t id) { fTrackId.push_back(id); } - virtual void SetPoint(Double_t /*x*/, Double_t /*y*/, Double_t /*z*/) {} - virtual void SetPoint(TVector3 /*point*/) {} + virtual void SetPoint(Double_t x, Double_t y, Double_t z) { fPoint.SetXYZ(x,y,z); } + virtual void SetPoint(TVector3 point) { fPoint = point; } + + virtual void SetHit(Double_t /*x*/, Double_t /*y*/, Double_t /*z*/) { } + virtual void SetHit(TVector3 /*hit*/) { } + + virtual void SetResolution(Double_t r1, Double_t r2, Double_t r3) { fResolution.SetXYZ(r1,r2,r3); } + virtual void SetResolution(TVector3 res) { fResolution = res; } /* getters */ - Long_t GetDetId(Int_t i) const; - Double_t GetEdep() const { return fEdep; } - Int_t GetInfoNum() const { return fInfoNum; } + virtual Int_t GetDetId() const { return Int_t(fDetId[0]); } + virtual Long_t GetDetId(Int_t i) const; + virtual Char_t GetSpecifity() const { return fSpecifity; } + + Double_t GetEdep() const { return fEdep; } + Int_t GetId() const { return fId; } + Int_t GetInfoNum() const { return fInfoNum; } Int_t GetMotherPointNum() const { return fMotherPointNum; } + + virtual Bool_t GetPoint(TVector3& point) const { point = fPoint; return true; } + virtual TVector3 GetPoint() const { return fPoint; } - virtual Double_t GetPointX() const { return 0.; } - virtual Double_t GetPointY() const { return 0.; } - virtual Double_t GetPointZ() const { return 0.; } + Int_t GetNTrakcs() const { return fTrackId.size(); } + Int_t GetTrackId(Int_t i = 0) const { return (fTrackId.empty()) ? -1 : fTrackId[i]; } - virtual void GetPoint(TVector3& point) const { point.SetXYZ(GetPointX(),GetPointY(),GetPointZ()); } - virtual TVector3 GetPoint() const { return TVector3(GetPointX(),GetPointY(),GetPointZ()); } + Double_t GetPointX() const { return fPoint.X(); } + Double_t GetPointY() const { return fPoint.Y(); } + Double_t GetPointZ() const { return fPoint.Z(); } + + virtual Bool_t GetHit(TVector3& /*hit*/) const { return false; } - virtual void PrintHit(Bool_t print_point = kTRUE) const; + virtual TVector3 GetResolution() const { return fResolution; } -private: - - std::vector<Long_t> fDetId; // geo. module id, detector id, subdectector id + virtual Double_t GetResolution1() const { return fResolution.X(); } + virtual Double_t GetResolution2() const { return fResolution.Y(); } + virtual Double_t GetResolution3() const { return fResolution.Z(); } + virtual void PrintHit(Bool_t print_point = true, Bool_t print_res = false) const; + +protected: + + std::vector<Long_t> fDetId; // mc-digit: geo. module id, detector id, [subdectector id, submodule id, ... ] + Double_t fEdep; // energy deposit, GeV - Int_t fInfoNum; // SpdIdealDataInfo number in SpdIdealTrackColl + Int_t fId; // hit unique id + Int_t fInfoNum; // SpdIdealDataInfo number (see SpdIdealTrackColl or SpdIEvent) Int_t fMotherPointNum; // mother mc-point number + std::vector<Int_t> fTrackId; // tracks (id's) to which the hit belong + + // Additional parameter "specifity", for example: + // 'f'(failed), 'd'(disabled), 'n'(undefined) + // spacepoint-like: 'p'(simple point),'m'(MAPS),'s'(DSSD), ... + // wirepoint-like: 'p'(simple point),'w'(wire) + // ... + Char_t fSpecifity; + + TVector3 fPoint; // mc-point coordinates + TVector3 fResolution; // hit resolution + ClassDef(SpdIdealHit,1) }; diff --git a/spddata/IdealTrackData/SpdIdealSpacepointHit.cxx b/spddata/IdealTrackData/SpdIdealSpacepointHit.cxx index fe0ebdf8838a861a288ab8bba2abca6a4b0dd1e3..5b590a9a39e91bc54830a6fea3ce39700301d434 100644 --- a/spddata/IdealTrackData/SpdIdealSpacepointHit.cxx +++ b/spddata/IdealTrackData/SpdIdealSpacepointHit.cxx @@ -8,10 +8,15 @@ #include "SpdIdealSpacepointHit.h" +#include <iostream> + +using std::cout; +using std::endl; + ClassImp(SpdIdealSpacepointHit) //_____________________________________________________________________________ -SpdIdealSpacepointHit::SpdIdealSpacepointHit():SpdIdealHit(),fSpecifity('n'), +SpdIdealSpacepointHit::SpdIdealSpacepointHit():SpdIdealHit(), fLn(1),fLu(1,0,0),fLv(0,1,0) { } @@ -25,6 +30,49 @@ TVector3 SpdIdealSpacepointHit::GetN(Bool_t unit) const return N; } +//_____________________________________________________________________________ +Double_t SpdIdealSpacepointHit::GetHitU() const +{ + TVector3 u = fLu.Unit(); + TVector3 p = fHit - fDetPos; + return p.Dot(u); +} + +//_____________________________________________________________________________ +Double_t SpdIdealSpacepointHit::GetHitV() const +{ + TVector3 v = fLv.Unit(); + TVector3 p = fHit - fDetPos; + return p.Dot(v); +} + +//_____________________________________________________________________________ +Double_t SpdIdealSpacepointHit::GetHitN() const +{ + TVector3 n = GetN(kTRUE); + TVector3 p = fHit - fDetPos; + return p.Dot(n); +} + +//_____________________________________________________________________________ +void SpdIdealSpacepointHit::GetHitUV(Double_t& xu, Double_t& xv) const +{ + TVector3 p = fHit - fDetPos; + TVector3 u = fLu.Unit(), v = fLv.Unit(); + xu = p.Dot(u); + xv = p.Dot(v); +} + +//_____________________________________________________________________________ +void SpdIdealSpacepointHit::GetHitUVN(Double_t& xu, Double_t& xv, Double_t& xn) const +{ + TVector3 p = fHit - fDetPos; + TVector3 u = fLu.Unit(), v = fLv.Unit(), n = GetN(kTRUE); + xu = p.Dot(u); + xv = p.Dot(v); + xn = p.Dot(n); +} + //_____________________________________________________________________________ Double_t SpdIdealSpacepointHit::GetPointU() const { @@ -69,25 +117,41 @@ void SpdIdealSpacepointHit::GetPointUVN(Double_t& xu, Double_t& xv, Double_t& xn } //_____________________________________________________________________________ -void SpdIdealSpacepointHit::PrintHit(Bool_t print_point) const +void SpdIdealSpacepointHit::PrintHit(Bool_t print_point, Bool_t print_res) const { - SpdIdealHit::PrintHit(print_point); + cout << "\t<" << this->ClassName() << "::PrintHit>" << "\n\n"; + cout << "\tHit unique ID: " << fId << endl; + cout << "\tDetector id: "; for (Int_t i(0); i<fDetId.size(); i++) { cout << fDetId[i] << " "; } cout << endl; + cout << "\tTrack id: "; for (Int_t i(0); i<fTrackId.size(); i++) { cout << fTrackId[i] << " "; } cout << endl; + cout << "\tInfo, mcpoint: " << fInfoNum << ", " << fMotherPointNum << endl; + cout << "\tEdep, Time: " << fEdep << " [GeV], " << fTimeStamp << " [ns] " << endl; + cout << "\tSpecifity: " << fSpecifity << endl; - printf("\tSpecifity: '%c'\n", fSpecifity); + if (print_point) { + cout << "\n"; + cout << "\tPoint(x,y,z): " + << fPoint.X() << ", " << fPoint.Y() << ", " << fPoint.Z() << " [cm] " << endl; + cout << "\tHit(x,y,z): " + << fHit.X() << ", " << fHit.Y() << ", " << fHit.Z() << " [cm] " << endl; + } + if (print_res) { + cout << "\tResolution: " + << fResolution.X()*1e4 << ", " << fResolution.Y()*1e4 << ", " << fResolution.Z()*1e4 << " [mkm] " << endl; + } - TVector3 v; + TVector3 v; - printf("\n"); - v = GetU(); - printf("\tu: [%8.3f, %8.3f, %8.3f] l(u) = %8.3f [cm]\n",v.X(),v.Y(),v.Z(),GetLu()); - v = GetV(); - printf("\tv: [%8.3f, %8.3f, %8.3f] l(v) = %8.3f [cm]\n",v.X(),v.Y(),v.Z(),GetLv()); - v = GetN(); - printf("\tn: [%8.3f, %8.3f, %8.3f] l(n) = %8.3f [cm]\n",v.X(),v.Y(),v.Z(),GetLn()); + printf("\n"); + v = GetU(); + printf("\tu: [%8.3f, %8.3f, %8.3f] l(u) = %8.3f [cm]\n",v.X(),v.Y(),v.Z(),GetLu()); + v = GetV(); + printf("\tv: [%8.3f, %8.3f, %8.3f] l(v) = %8.3f [cm]\n",v.X(),v.Y(),v.Z(),GetLv()); + v = GetN(); + printf("\tn: [%8.3f, %8.3f, %8.3f] l(n) = %8.3f [cm]\n",v.X(),v.Y(),v.Z(),GetLn()); - printf("\n"); - printf("\tdet: [%8.3f, %8.3f, %8.3f] Dr = %8.3f [cm]\n",fDetPos.X(),fDetPos.Y(),fDetPos.Z(), - fDetPos.XYvector().Mod()); - printf("\n"); + printf("\n"); + printf("\tdet: [%8.3f, %8.3f, %8.3f] Dr = %8.3f [cm]\n",fDetPos.X(),fDetPos.Y(),fDetPos.Z(), + fDetPos.XYvector().Mod()); + printf("\n"); } diff --git a/spddata/IdealTrackData/SpdIdealSpacepointHit.h b/spddata/IdealTrackData/SpdIdealSpacepointHit.h index 24ec6fe323af7a8485ca9bff82c0c6c61c585dca..79b20db5aac77dde7b01085cd8dc8e190f53c1b5 100644 --- a/spddata/IdealTrackData/SpdIdealSpacepointHit.h +++ b/spddata/IdealTrackData/SpdIdealSpacepointHit.h @@ -21,13 +21,19 @@ public: SpdIdealSpacepointHit(); virtual ~SpdIdealSpacepointHit() {} - /* setters */ - - virtual void SetPoint(Double_t x, Double_t y, Double_t z) { fPoint.SetXYZ(x,y,z); } - virtual void SetPoint(TVector3 point) { fPoint = point; } - - void SetSpecifity(Char_t spec) { fSpecifity = spec; } + /* ========== SETTERS ========== */ + // hit + virtual void SetHit(Double_t x, Double_t y, Double_t z) { fHit.SetXYZ(x,y,z); } + virtual void SetHit(TVector3 hit) { fHit = hit; } + + void SetResolutionUVN(Double_t ru, Double_t rv, Double_t rn) { fResolution.SetXYZ(ru,rv,rn); } + void SetResolutionUV(Double_t ru, Double_t rv) { fResolution.SetXYZ(ru,rv,-1); } + void SetResolutionU(Double_t ru) { fResolution.SetX(ru); } + void SetResolutionV(Double_t rv) { fResolution.SetY(rv); } + void SetResolutionN(Double_t rn) { fResolution.SetZ(rn); } + + // detector void SetU(TVector3 x, Double_t mag = -1); void SetV(TVector3 x, Double_t mag = -1); @@ -42,24 +48,32 @@ public: void SetDetPos(Double_t x, Double_t y, Double_t z) { fDetPos.SetXYZ(x,y,z); } void SetDetPos(TVector3 pos) { fDetPos = pos; } - /* getters */ + /* ========== GETTERS ========== */ - Double_t GetPointU() const; - Double_t GetPointV() const; - Double_t GetPointN() const; + Double_t GetResolutionU() const { return fResolution.X(); } + Double_t GetResolutionV() const { return fResolution.Y(); } + Double_t GetResolutionN() const { return fResolution.Z(); } - void GetPointUV(Double_t& xu, Double_t& xv) const; - void GetPointUVN(Double_t& xu, Double_t& xv, Double_t& xn) const; + // hit + virtual Bool_t GetHit(TVector3& hit) const { hit = fHit; return true; } + TVector3 GetHit() const { return fHit; } + + Double_t GetHitU() const; // u coordinate (local CS) + Double_t GetHitV() const; // v coordinate (local CS) + Double_t GetHitN() const; // n coordinate (local CS) - virtual Double_t GetPointX() const { return fPoint.X(); } - virtual Double_t GetPointY() const { return fPoint.Y(); } - virtual Double_t GetPointZ() const { return fPoint.Z(); } + void GetHitUV(Double_t& xu, Double_t& xv) const; + void GetHitUVN(Double_t& xu, Double_t& xv, Double_t& xn) const; - virtual void GetPoint(TVector3& point) const { point = fPoint; } - virtual TVector3 GetPoint() const { return fPoint; } + // point + Double_t GetPointU() const; // u coordinate (local РЎS) + Double_t GetPointV() const; // v coordinate (local РЎS) + Double_t GetPointN() const; // n coordinate (local РЎS) - Char_t GetSpecifity() { return fSpecifity; } + void GetPointUV(Double_t& xu, Double_t& xv) const; + void GetPointUVN(Double_t& xu, Double_t& xv, Double_t& xn) const; + // detector TVector3 GetU(Bool_t unit = kTRUE) const { return (unit) ? fLu.Unit() : fLu; } TVector3 GetV(Bool_t unit = kTRUE) const { return (unit) ? fLv.Unit() : fLv; } TVector3 GetN(Bool_t unit = kTRUE) const; @@ -70,19 +84,22 @@ public: TVector3 GetDetPos() const { return fDetPos; } - virtual void PrintHit(Bool_t print_point = kTRUE) const; + Double_t GetDetPosX() const { return fDetPos.X(); } + Double_t GetDetPosY() const { return fDetPos.Y(); } + Double_t GetDetPosZ() const { return fDetPos.Z(); } + + virtual void PrintHit(Bool_t print_point = true, Bool_t print_res = true) const; private: // hit - TVector3 fPoint; - Char_t fSpecifity; // for example, 'n'(unknown),'p'(point),'m'(MAPS),'s'(DSSD), ... + TVector3 fHit; // hit coordinates (global S.C.) // detector - Double_t fLn; - TVector3 fLu; - TVector3 fLv; - TVector3 fDetPos; + Double_t fLn; // n = [u x v] + TVector3 fLu; // u -direction + TVector3 fLv; // v- direction + TVector3 fDetPos; // detector position ClassDef(SpdIdealSpacepointHit,1) }; diff --git a/spddata/IdealTrackData/SpdIdealWirepointHit.cxx b/spddata/IdealTrackData/SpdIdealWirepointHit.cxx index 30728cbf7d71b148cb888481912df269d8ae85a3..848f30623f76a199977013f6c687de4aa370a468 100644 --- a/spddata/IdealTrackData/SpdIdealWirepointHit.cxx +++ b/spddata/IdealTrackData/SpdIdealWirepointHit.cxx @@ -22,18 +22,22 @@ SpdIdealWirepointHit::~SpdIdealWirepointHit() { } +//***************************************************************************/ +//******************************** HIT **************************************/ +//***************************************************************************/ + //___________________________________________________________________________ Double_t SpdIdealWirepointHit::GetRdrift() const { - TVector3 dir = GetWireDirection(); - TVector3 l = (fPoint-fWirePoint1).Cross(dir); - return l.Mag(); + TVector3 WireDirection = GetWireDirection(); + TVector3 r = (fHit-fWirePoint1).Cross(WireDirection); + return r.Mag(); } //___________________________________________________________________________ Double_t SpdIdealWirepointHit::GetZwire() const { TVector3 WireDirection = GetWireDirection(); - return fabs(WireDirection.Dot(fPoint-fWirePoint1)); + return fabs(WireDirection.Dot(fHit-fWirePoint1)); } //___________________________________________________________________________ @@ -42,31 +46,100 @@ Int_t SpdIdealWirepointHit::GetLRtype() const TVector3 WireDirection = GetWireDirection(false); TVector3 U = fDirInPoint.Cross(WireDirection); TVector3 l = GetPointOnWire(); - Double_t v = U.Dot(l-fPoint); + Double_t v = U.Dot(l-fHit); if (fabs(v) < 1.e-6) return 0; return (v > 0) ? 1 : -1; } //___________________________________________________________________________ TVector3 SpdIdealWirepointHit::GetPointOnWire() const +{ + TVector3 WireDirection = GetWireDirection(); + return fWirePoint1 + WireDirection.Dot(fHit-fWirePoint1)*WireDirection; +} + +//___________________________________________________________________________ +TVector3 SpdIdealWirepointHit::GetDriftDirR() const +{ + TVector3 p = GetPointOnWire(); + return fHit - p; +} + +//___________________________________________________________________________ +TVector3 SpdIdealWirepointHit::GetWireDirZ() const +{ + TVector3 WireDirection = GetWireDirection(); + return WireDirection.Dot(fHit-fWirePoint1)*WireDirection; +} + +//***************************************************************************/ +//****************************** POINT **************************************/ +//***************************************************************************/ + +//___________________________________________________________________________ +Double_t SpdIdealWirepointHit::GetPointRdrift() const +{ + TVector3 WireDirection = GetWireDirection(); + TVector3 r = (fPoint-fWirePoint1).Cross(WireDirection); + return r.Mag(); +} +//___________________________________________________________________________ +Double_t SpdIdealWirepointHit::GetPointZwire() const +{ + TVector3 WireDirection = GetWireDirection(); + return fabs(WireDirection.Dot(fPoint-fWirePoint1)); +} + +//___________________________________________________________________________ +Int_t SpdIdealWirepointHit::GetPointLRtype() const +{ + TVector3 WireDirection = GetWireDirection(false); + TVector3 U = fDirInPoint.Cross(WireDirection); + TVector3 l = GetPointOnWire(); + Double_t v = U.Dot(l-fPoint); + if (fabs(v) < 1.e-6) return 0; + return (v > 0) ? 1 : -1; +} + +//___________________________________________________________________________ +TVector3 SpdIdealWirepointHit::GetPointPointOnWire() const { TVector3 WireDirection = GetWireDirection(); return fWirePoint1 + WireDirection.Dot(fPoint-fWirePoint1)*WireDirection; } - + +//___________________________________________________________________________ +TVector3 SpdIdealWirepointHit::GetPointDriftDirR() const +{ + TVector3 p = GetPointOnWire(); + return fPoint - p; +} + +//___________________________________________________________________________ +TVector3 SpdIdealWirepointHit::GetPointWireDirZ() const +{ + TVector3 WireDirection = GetWireDirection(); + return WireDirection.Dot(fPoint-fWirePoint1)*WireDirection; +} + //_____________________________________________________________________________ -void SpdIdealWirepointHit::PrintHit(Bool_t print_point) const +void SpdIdealWirepointHit::PrintHit(Bool_t print_point, Bool_t print_res) const { - SpdIdealHit::PrintHit(kFALSE); + SpdIdealHit::PrintHit(false,false); if (print_point) { printf("\tpoint: [%8.3f, %8.3f, %8.3f] [cm]\n",fPoint.X(),fPoint.Y(),fPoint.Z()); + printf("\thit: [%8.3f, %8.3f, %8.3f] [cm]\n",fHit.X(),fHit.Y(),fHit.Z()); printf("\tdir(point): [%8.3f, %8.3f, %8.3f] [cm]\n",fDirInPoint.X(),fDirInPoint.Y(),fDirInPoint.Z()); } - + if (print_res) { + printf("\tresolution: [%8.0f, %8.0f, %8.0f] [mkm]\n",fResolution.X()*1e4 ,fResolution.Y()*1e4 ,fResolution.Z()*1e4); + } + printf("\n"); - - printf("\tHit: z,r,s [%8.3f, %8.3f, %8.3f] [cm] lr = %8d\n",GetZwire(),GetRdrift(),GetSegLen(),GetLRtype()); + + printf("\tPoint: r,z,s [%8.3f, %8.3f, %8.3f] [cm] lr = %-8d\n",GetPointRdrift(),GetPointZwire(),GetSegLen(),GetPointLRtype()); + printf("\tHit: r,z,s [%8.3f, %8.3f, %8.3f] [cm] lr = %-8d\n",GetRdrift(),GetZwire(),GetSegLen(),GetLRtype()); printf("\tWire: L,Theta,Phi [%8.3f, %8.3f, %8.3f] [cm] r = %8.3f [cm]\n",GetWireLength(), GetWireTheta(),GetWirePhi(),GetWireMaxRadius()); diff --git a/spddata/IdealTrackData/SpdIdealWirepointHit.h b/spddata/IdealTrackData/SpdIdealWirepointHit.h index 471d94440a3d734f3ecc3873a7ae98f161362616..bedd23f5f8c6320c85d7cdaa333a525cdb0b77da 100644 --- a/spddata/IdealTrackData/SpdIdealWirepointHit.h +++ b/spddata/IdealTrackData/SpdIdealWirepointHit.h @@ -23,11 +23,16 @@ public: virtual ~SpdIdealWirepointHit(); /* ========== SETTERS ========== */ - + // hit - virtual void SetPoint(Double_t x, Double_t y, Double_t z) { fPoint.SetXYZ(x,y,z); } - virtual void SetPoint(TVector3 point) { fPoint = point; } - + virtual void SetHit(Double_t x, Double_t y, Double_t z) { fHit.SetXYZ(x,y,z); } + virtual void SetHit(TVector3 hit) { fHit = hit; } + + void SetResolutionRZ(Double_t rr, Double_t rz) { fResolution.SetXYZ(rr,rz,-1); } + void SetResolutionR(Double_t rr) { fResolution.SetX(rr); } + void SetResolutionZ(Double_t rz) { fResolution.SetY(rz); } + + // point additional (hit) void SetDirInPoint(Double_t lx, Double_t ly, Double_t lz) { fDirInPoint.SetXYZ(lx,ly,lz); } void SetDirInPoint(Double_t l, Double_t nx, Double_t ny, Double_t nz) { fDirInPoint.SetXYZ(nx,ny,nz); fDirInPoint.SetMag(l); } void SetDirInPoint(TVector3 dir, Double_t s) { fDirInPoint = dir; dir.SetMag(1); fSegLength = s; } @@ -37,28 +42,38 @@ public: // detector void SetWireMaxRadius(Double_t R) { fWireMaxRadius = fabs(R); } void SetWire(TVector3& point1, TVector3& point2) { fWirePoint1 = point1; fWirePoint2 = point2; } - void SetWire(TVector3& point, TVector3& dir, Double_t l) { fWirePoint1 = point-0.5*l*dir; fWirePoint2 = point+0.5*l*dir; } + void SetWire(TVector3& point, TVector3& dir, Double_t halfl) { fWirePoint1 = point-halfl*dir; fWirePoint2 = point+halfl*dir; } /* ========== GETTERS ========== */ - // hit - virtual Double_t GetPointX() const { return fPoint.X(); } - virtual Double_t GetPointY() const { return fPoint.Y(); } - virtual Double_t GetPointZ() const { return fPoint.Z(); } - - virtual void GetPoint(TVector3& point) const { point = fPoint; } - virtual TVector3 GetPoint() const { return fPoint; } - void GetDirInPoint(TVector3& dir) const { dir = fDirInPoint; } TVector3 GetDirInPoint() const { return fDirInPoint; } - Double_t GetSegLen() const { return fSegLength; } // track segment length - Double_t GetRdrift() const; // drift radius - Double_t GetZwire() const; // coordinate along the wire + + Double_t GetResolutionR() const { return fResolution.X(); } + Double_t GetResolutionZ() const { return fResolution.Y(); } + + // hit + virtual Bool_t GetHit(TVector3& hit) const { hit = fHit; return true; } + TVector3 GetHit() const { return fHit; } + + Double_t GetRdrift() const; // hit drift radius + Double_t GetZwire() const; // hit coordinate along the wire Int_t GetLRtype() const; // hit type: -1(left), +1(right), 0(undefined) (to resolove left/right ambiguity) - TVector3 GetPointOnWire() const; // hit projection on wire - + TVector3 GetPointOnWire() const; // hit projection on wire + TVector3 GetDriftDirR() const; // hit radial component in the wire CS (orthohonal to the wire) + TVector3 GetWireDirZ() const; // hit z componentin in the wire CS (along the wire) + + // point + Double_t GetPointRdrift() const; // point drift radius + Double_t GetPointZwire() const; // point coordinate along the wire + Int_t GetPointLRtype() const; // point hit type: -1(left), +1(right), 0(undefined) (to resolove left/right ambiguity) + + TVector3 GetPointPointOnWire() const; // point projection on wire + TVector3 GetPointDriftDirR() const; // point radial component in the wire CS (orthohonal to the wire) + TVector3 GetPointWireDirZ() const; // point z component in the wire CS (along the wire) + // detector Double_t GetWireMaxRadius() const { return fWireMaxRadius; } TVector3 GetWirePoint1() const { return fWirePoint1; } @@ -72,20 +87,22 @@ public: TVector3 GetWirePosition() const { return 0.5*(fWirePoint1+fWirePoint2); } TVector3 GetWireDirection(Bool_t norm = true) const { return (norm) ? (fWirePoint2-fWirePoint1).Unit() : (fWirePoint2-fWirePoint1); } - - virtual void PrintHit(Bool_t print_point = kTRUE) const; + + virtual void PrintHit(Bool_t print_point = true, Bool_t print_res = true) const; private: - // hit - TVector3 fPoint; - TVector3 fDirInPoint; - Double_t fSegLength; + // hit + TVector3 fHit; // hit coordinates (global S.C.) + + // additional point chars + TVector3 fDirInPoint; // track direction in mc-point + Double_t fSegLength; // track segment length // detector - Double_t fWireMaxRadius; - TVector3 fWirePoint1; - TVector3 fWirePoint2; + Double_t fWireMaxRadius; // max. drift radius + TVector3 fWirePoint1; // first end of the wire + TVector3 fWirePoint2; // second end of the wire ClassDef(SpdIdealWirepointHit,1) }; diff --git a/spddata/SpdDataLinkDef.h b/spddata/SpdDataLinkDef.h index 0e365050127d1a7ec1bc337155c3a890e94964f5..b79b446b3e8ce415fb937723e9919041a4f6384a 100644 --- a/spddata/SpdDataLinkDef.h +++ b/spddata/SpdDataLinkDef.h @@ -14,7 +14,7 @@ #pragma link C++ class SpdParameter+; #pragma link C++ class SpdFieldPar+; #pragma link C++ class SpdParSetContFact+; -#pragma link C++ class SpdPassiveGeoPar+; +#pragma link C++ class SpdPassiveGeoParSet+; #pragma link C++ class SpdBaseParSet+; #pragma link C++ class SpdParSet+; #pragma link C++ class SpdPrimGenParSet+; diff --git a/spddata/SpdGeopathParser.cxx b/spddata/SpdGeopathParser.cxx index 4233246ade6cde01ac7d792d4a5d872e853c131c..3188de1139c3644d9742fc3e8d42de95afa918e4 100644 --- a/spddata/SpdGeopathParser.cxx +++ b/spddata/SpdGeopathParser.cxx @@ -76,14 +76,14 @@ Int_t SpdGeopathParser::ParsePath(const TString& path) name = name(i+1,name.Length()); fPath[fPathLevel].second = name.Atoi(); -// cout << "<SpdGeopathParser::ParsePath> " << path << " :: " << fPathLevel -// << " | " << fPath[fPathLevel].first -// << " | " << fPath[fPathLevel].second<< endl; + //cout << "<SpdGeopathParser::ParsePath> " << path << " :: " << fPathLevel + // << " | " << fPath[fPathLevel].first + // << " | " << fPath[fPathLevel].second<< endl; fPathLevel++; } - //cout << "<SpdGeopathParser::ParsePath> " << GetCurrentPathString() << endl; + //cout << "-I- <SpdGeopathParser::ParsePath> " << GetCurrentPathString() << " Geometry level: " << fPathLevel << endl; return fPathLevel; } @@ -95,11 +95,13 @@ TString SpdGeopathParser::GetCurrentPathString() const TString path; SPDGEOPATH::const_iterator it = fPath.begin(); - Int_t n(0); + Int_t n(1); for (; it != fPath.end(); it++) { path += Form("/%s_%d",it->first.Data(),it->second); - if (n++ == fPathLevel) return path; + if (n == fPathLevel) break; + n++; } + return path; } diff --git a/spddata/SpdGeopathParser.h b/spddata/SpdGeopathParser.h index 15c12e9543d706cbfeaecb3d75152873968517b9..7a945b9a686a0884fe826baea22eea5619e6d0d6 100644 --- a/spddata/SpdGeopathParser.h +++ b/spddata/SpdGeopathParser.h @@ -16,7 +16,7 @@ // // /////////////////////////////////////////////////////////////////////////////// -typedef std::vector< std::pair<TString,Int_t> > SPDGEOPATH; +typedef std::vector< std::pair< TString,Int_t> > SPDGEOPATH; class SpdGeopathParser: public TObject { diff --git a/spddata/kfdata/SpdKFSimpleRes.cxx b/spddata/kfdata/SpdKFSimpleRes.cxx index 4af88d64ef3bc5d6f4b54ccf979f5ce4a0223171..98ab02d0116bfbbc456305874597f37ba07b99aa 100644 --- a/spddata/kfdata/SpdKFSimpleRes.cxx +++ b/spddata/kfdata/SpdKFSimpleRes.cxx @@ -129,6 +129,25 @@ Int_t SpdKFSimpleRes::GetNTracks(Bool_t without_errors, Bool_t converged, Bool_t return n; } +//_____________________________________________________________________________ +Double_t SpdKFSimpleRes::GetMomRes(Bool_t without_errors, Bool_t converged) const +{ + Double_t res(0.), m; + Int_t n(0); + + for (Int_t i(0); i<fTracks.size(); i++) { + if (!fTracks[i].IsFitted) continue; + if (converged && fTracks[i].Convergency != 1) continue; + if (without_errors && fTracks[i].ErrorFlag != 0) continue; + m = fTracks[i].MomentumMC.Mag(); + if (!(m > 0)) continue; + res += TMath::Abs(m-fTracks[i].MomentumREC.Mag())/m; + n++; + } + + return (n > 1) ? res/n : 0.; +} + //_____________________________________________________________________________ Double_t SpdKFSimpleRes::GetMomResN(Int_t& nres, Bool_t without_errors, Bool_t converged) const { @@ -151,7 +170,7 @@ Double_t SpdKFSimpleRes::GetMomResN(Int_t& nres, Bool_t without_errors, Bool_t c } //_____________________________________________________________________________ -Double_t SpdKFSimpleRes::GetMomRes(Bool_t without_errors, Bool_t converged) const +Double_t SpdKFSimpleRes::GetMomTRes(Bool_t without_errors, Bool_t converged) const { Double_t res(0.), m; Int_t n(0); @@ -160,15 +179,36 @@ Double_t SpdKFSimpleRes::GetMomRes(Bool_t without_errors, Bool_t converged) cons if (!fTracks[i].IsFitted) continue; if (converged && fTracks[i].Convergency != 1) continue; if (without_errors && fTracks[i].ErrorFlag != 0) continue; - m = fTracks[i].MomentumMC.Mag(); + m = fTracks[i].MomentumMC.Perp(); if (!(m > 0)) continue; - res += TMath::Abs(m-fTracks[i].MomentumREC.Mag())/m; + res += TMath::Abs(m-fTracks[i].MomentumREC.Perp())/m; n++; } return (n > 1) ? res/n : 0.; } +//_____________________________________________________________________________ +Double_t SpdKFSimpleRes::GetMomTResN(Int_t& nres, Bool_t without_errors, Bool_t converged) const +{ + nres = 0; + + if (!fTracks.size() < 1) return 0.; + + Double_t res(0), m; + for (Int_t i(0); i<fTracks.size(); i++) { + if (!fTracks[i].IsFitted) continue; + if (converged && fTracks[i].Convergency != 1) continue; + if (without_errors && fTracks[i].ErrorFlag != 0) continue; + m = fTracks[i].MomentumMC.Perp(); + if (!(m > 0)) continue; + res += TMath::Abs(m-fTracks[i].MomentumREC.Perp())/m; + nres++; + } + + return (nres > 1) ? res/nres : 0.; +} + //_____________________________________________________________________________ Int_t SpdKFSimpleRes::GetRes(Double_t& rp, Double_t& rpt, Double_t& rpz, Double_t& rtheta, Double_t& rphi, Bool_t without_errors, Bool_t converged) const @@ -403,9 +443,9 @@ void SpdKFSimpleRes::PrintData(Int_t opt) const } printf("\n%5s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n\n", - "N","chi2/ndf","|dp|/s","px(mc)","px(rec)","dpx","sigma(x)","|dpx|/sx", - "py(mc)","py(rec)","dpy","sigma(y)","|dpy|/sy", - "pz(mc)","pz(rec)","dpz","sigma(z)","|dpz|/sz"); + "N","chi2/ndf","|dp|/s","px(mc)","px(rec)","dpx ","sigma(x)","|dpx|/sx", + "py(mc)","py(rec)","dpy ","sigma(y)","|dpy|/sy", + "pz(mc)","pz(rec)","dpz ","sigma(z)","|dpz|/sz"); for (Int_t i(0); i<ntracks; i++) { printf("%5d %8.3f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f\n", @@ -418,9 +458,15 @@ void SpdKFSimpleRes::PrintData(Int_t opt) const } printf("\n averaged values : \n"); - printf("\n |dp/p| (fitted): %8.3f [%%] (%d)",GetMomRes(false,false)*100,GetNTracks(false,false)); - printf("\n |dp/p| (fitted + converged): %8.3f [%%] (%d)",GetMomRes(false,true)*100,GetNTracks(false,true)); - printf("\n |dp/p| (fitted + converged + noerrors): %8.3f [%%] (%d)",GetMomRes(true,true)*100,GetNTracks(true,true)); + printf("\n |dp/p| (fitted): %8.3f [%%] (%d)",GetMomRes(false,false)*100,GetNTracks(false,false)); + printf("\n |dp/p| (fitted + converged): %8.3f [%%] (%d)",GetMomRes(false,true)*100,GetNTracks(false,true)); + printf("\n |dp/p| (fitted + converged + noerrors): %8.3f [%%] (%d)",GetMomRes(true,true)*100,GetNTracks(true,true)); + + printf("\n"); + + printf("\n |dpt/pt| (fitted): %8.3f [%%] (%d)",GetMomTRes(false,false)*100,GetNTracks(false,false)); + printf("\n |dpt/pt| (fitted + converged): %8.3f [%%] (%d)",GetMomTRes(false,true)*100,GetNTracks(false,true)); + printf("\n |dpt/pt| (fitted + converged + noerrors): %8.3f [%%] (%d)",GetMomTRes(true,true)*100,GetNTracks(true,true)); printf("\n\n"); } diff --git a/spddata/kfdata/SpdKFSimpleRes.h b/spddata/kfdata/SpdKFSimpleRes.h index 2e0888a29bb10cada07e2de64e5639af199fde70..d4f5f57cab2d055f5f4632f86d96aaf352bb099d 100644 --- a/spddata/kfdata/SpdKFSimpleRes.h +++ b/spddata/kfdata/SpdKFSimpleRes.h @@ -177,6 +177,7 @@ public: Int_t GetNThits(Int_t i) const { return (FindTrack(i)) ? (fTracks[i].NTBhits + fTracks[i].NTEChits) : 0; } Int_t GetNTBhits(Int_t i) const { return (FindTrack(i)) ? fTracks[i].NTBhits : 0; } Int_t GetNTEChits(Int_t i) const { return (FindTrack(i)) ? fTracks[i].NTEChits : 0; } + Int_t GetNTThits(Int_t i) const { return (FindTrack(i)) ? (fTracks[i].NVhits + fTracks[i].NTBhits + fTracks[i].NTEChits) : 0; } // convergency + errors Bool_t GetIsGood(Int_t i) const; @@ -233,6 +234,10 @@ public: Double_t GetMomRes(Bool_t without_errors = true, Bool_t converged = true) const; Double_t GetMomResN(Int_t& nres, Bool_t without_errors = true, Bool_t converged = true) const; + // resolution: return AVERAGED |dpt/pt| (fitted tracks only) + Double_t GetMomTRes(Bool_t without_errors = true, Bool_t converged = true) const; + Double_t GetMomTResN(Int_t& nres, Bool_t without_errors = true, Bool_t converged = true) const; + // resolution: return number of tracks & AVERAGED values (fitted tracks only) Int_t GetRes(Double_t& rp, Double_t& rpt, Double_t& rpz, Double_t& rtheta, Double_t& rphi, Bool_t without_errors = true, Bool_t converged = true) const; // !ATTENTION! NOT IMPLEMENTED YET! (return 0) diff --git a/spddata/params/SpdParSetContFact.cxx b/spddata/params/SpdParSetContFact.cxx index 4cab5256a1cc27c3b719da58118dba27c466723f..bdadcded708905a359536947c5b0cf4c9b2f014f 100644 --- a/spddata/params/SpdParSetContFact.cxx +++ b/spddata/params/SpdParSetContFact.cxx @@ -7,7 +7,7 @@ #include "SpdBaseParSet.h" #include "SpdParSet.h" #include "SpdPrimGenParSet.h" -#include "SpdPassiveGeoPar.h" +#include "SpdPassiveGeoParSet.h" ClassImp(SpdParSetContFact) @@ -45,7 +45,7 @@ void SpdParSetContFact::setAllContainers() containers->Add(p); - p = new FairContainer("PassiveGeoPar", + p = new FairContainer("PassiveGeoParSet", "Spd Passive Geo Parameters", "TestDefaultContext"); @@ -79,10 +79,10 @@ FairParSet* SpdParSetContFact::createContainer(FairContainer* c) c->GetTitle(), c->getContext()); } - else if (strcmp(name,"PassiveGeoPar") == 0) { - p = new SpdPassiveGeoPar(c->getConcatName().Data(), - c->GetTitle(), - c->getContext()); + else if (strcmp(name,"PassiveGeoParSet") == 0) { + p = new SpdPassiveGeoParSet(c->getConcatName().Data(), + c->GetTitle(), + c->getContext()); } else if (strcmp(name,"PrimGenParSet") == 0) { p = new SpdPrimGenParSet(c->getConcatName().Data(), diff --git a/spddata/params/SpdPassiveGeoPar.cxx b/spddata/params/SpdPassiveGeoParSet.cxx similarity index 75% rename from spddata/params/SpdPassiveGeoPar.cxx rename to spddata/params/SpdPassiveGeoParSet.cxx index c490ae68f2d1b2e8f97ca29dcaf5b30e59a43b56..9e32488aea8a715d8a30cc08a403296b50de41cb 100644 --- a/spddata/params/SpdPassiveGeoPar.cxx +++ b/spddata/params/SpdPassiveGeoParSet.cxx @@ -3,10 +3,10 @@ //_____________________________________________________________________________ // -// SpdPassiveGeoPar +// SpdPassiveGeoParSet //_____________________________________________________________________________ -#include "SpdPassiveGeoPar.h" +#include "SpdPassiveGeoParSet.h" #include "FairParamList.h" #include "TObjArray.h" @@ -15,18 +15,18 @@ using std::cout; using std::endl; -ClassImp(SpdPassiveGeoPar) +ClassImp(SpdPassiveGeoParSet) //_____________________________________________________________________________________ -SpdPassiveGeoPar::SpdPassiveGeoPar(const char* name, const char* title, const char* context): +SpdPassiveGeoParSet::SpdPassiveGeoParSet(const char* name, const char* title, const char* context): FairParGenericSet(name,title,context),fParams(0) { - //std::cout << "<SpdPassiveGeoPar::SpdPassiveGeoPar> CREATE CONTAINER" << std::endl; + //std::cout << "<SpdPassiveGeoParSet::SpdPassiveGeoParSet> CREATE CONTAINER" << std::endl; fParams = new TObjArray(); } //_____________________________________________________________________________________ -SpdPassiveGeoPar::~SpdPassiveGeoPar() +SpdPassiveGeoParSet::~SpdPassiveGeoParSet() { FairParGenericSet::clear(); @@ -38,32 +38,32 @@ SpdPassiveGeoPar::~SpdPassiveGeoPar() } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::clear() +void SpdPassiveGeoParSet::clear() { if (fParams) fParams->Delete(); } //_____________________________________________________________________________________ -Bool_t SpdPassiveGeoPar::GetParameter(const Text_t* par_name, Int_t& value) +Bool_t SpdPassiveGeoParSet::GetParameter(const Text_t* par_name, Int_t& value) { return SpdParameter::GetParameter(fParams,par_name,value); } //_____________________________________________________________________________________ -Bool_t SpdPassiveGeoPar::GetParameter(const Text_t* par_name, Double_t& value) +Bool_t SpdPassiveGeoParSet::GetParameter(const Text_t* par_name, Double_t& value) { return SpdParameter::GetParameter(fParams,par_name,value); } //_____________________________________________________________________________________ -Bool_t SpdPassiveGeoPar::GetParameter(const Text_t* par_name, TString& value) +Bool_t SpdPassiveGeoParSet::GetParameter(const Text_t* par_name, TString& value) { value = SpdParameter::GetParameter(fParams,par_name); return !value.IsWhitespace(); } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::SetParameter(const Text_t* par_name, Int_t value) +void SpdPassiveGeoParSet::SetParameter(const Text_t* par_name, Int_t value) { SpdParameter* par = GetParameter(par_name); if (par) par->SetValue(value); @@ -71,7 +71,7 @@ void SpdPassiveGeoPar::SetParameter(const Text_t* par_name, Int_t value) } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::SetParameter(const Text_t* par_name, Double_t value) +void SpdPassiveGeoParSet::SetParameter(const Text_t* par_name, Double_t value) { SpdParameter* par = GetParameter(par_name); if (par) par->SetValue(value); @@ -79,7 +79,7 @@ void SpdPassiveGeoPar::SetParameter(const Text_t* par_name, Double_t value) } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::SetParameter(const Text_t* par_name, const Char_t* value) +void SpdPassiveGeoParSet::SetParameter(const Text_t* par_name, const Char_t* value) { SpdParameter* par = GetParameter(par_name); if (par) *par = value; @@ -87,7 +87,7 @@ void SpdPassiveGeoPar::SetParameter(const Text_t* par_name, const Char_t* value) } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::SetParameters(TObjArray* pars) +void SpdPassiveGeoParSet::SetParameters(TObjArray* pars) { if (!pars) return; @@ -103,7 +103,7 @@ void SpdPassiveGeoPar::SetParameters(TObjArray* pars) } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::FillParameters(TObjArray* pars) +void SpdPassiveGeoParSet::FillParameters(TObjArray* pars) { if (!pars) return; @@ -119,43 +119,43 @@ void SpdPassiveGeoPar::FillParameters(TObjArray* pars) } //_____________________________________________________________________________________ -Bool_t SpdPassiveGeoPar::FindParameter(const Text_t* par_name) +Bool_t SpdPassiveGeoParSet::FindParameter(const Text_t* par_name) { if (!fParams) return kFALSE; return fParams->FindObject(par_name); } //_____________________________________________________________________________________ -SpdParameter* SpdPassiveGeoPar::GetParameter(const Text_t* par_name) +SpdParameter* SpdPassiveGeoParSet::GetParameter(const Text_t* par_name) { if (!fParams) return 0; return (SpdParameter*)fParams->FindObject(par_name); } //_____________________________________________________________________________________ -Int_t SpdPassiveGeoPar::GetNParameters() +Int_t SpdPassiveGeoParSet::GetNParameters() { return fParams ? fParams->GetEntries() : 0; } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::putParams(FairParamList* l) +void SpdPassiveGeoParSet::putParams(FairParamList* l) { if (!l || !fParams) return; l->addObject("Passive geometry parameters",fParams); } //_____________________________________________________________________________________ -Bool_t SpdPassiveGeoPar::getParams(FairParamList* l) +Bool_t SpdPassiveGeoParSet::getParams(FairParamList* l) { if (!l || !fParams) return kFALSE; return (l->fillObject("Passive geometry parameters",fParams)) ? kTRUE : kFALSE; } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::print(Int_t opt) +void SpdPassiveGeoParSet::print(Int_t opt) { - cout << "<SpdPassiveGeoPar::print>" << endl; + cout << "<SpdPassiveGeoParSet::print>" << endl; cout << "Number of parameters = " << GetNParameters() << " " << endl; cout << endl; @@ -170,10 +170,10 @@ void SpdPassiveGeoPar::print(Int_t opt) } //_____________________________________________________________________________________ -void SpdPassiveGeoPar::printParams() +void SpdPassiveGeoParSet::printParams() { cout << "---------------------------------------------\n"; - cout << "<SpdPassiveGeoPar::printParams> Name: "<< GetName() << "\n"; + cout << "<SpdPassiveGeoParSet::printParams> Name: "<< GetName() << "\n"; if (!paramContext.IsNull()) { cout << "Context/Purpose: " << paramContext << endl; } if (!author.IsNull()) { cout << "Author: " << author << endl; } if (!description.IsNull()) { cout << "Description: " << description << endl; } diff --git a/spddata/params/SpdPassiveGeoPar.h b/spddata/params/SpdPassiveGeoParSet.h similarity index 81% rename from spddata/params/SpdPassiveGeoPar.h rename to spddata/params/SpdPassiveGeoParSet.h index 11089a02b08f44cc7fa48ee76ac0c5c28c57dab6..71c135e6ad3bd6aa513ac13dd628a32802aa3f6c 100644 --- a/spddata/params/SpdPassiveGeoPar.h +++ b/spddata/params/SpdPassiveGeoParSet.h @@ -1,15 +1,15 @@ // $Id$ // Author: artur 2018/01/23 -#ifndef __SPDPASSIVEGEOPAR_H__ -#define __SPDPASSIVEGEOPAR_H__ +#ifndef __SPDPASSIVEGEOPARSET_H__ +#define __SPDPASSIVEGEOPARSET_H__ #include "FairParGenericSet.h" #include "SpdParameter.h" //////////////////////////////////////////////////////////////////////////////// // // -// SpdPassiveGeoPar // +// SpdPassiveGeoParSet // // // // <brief class description> // // // @@ -18,15 +18,15 @@ class FairParamList; class TObjArray; -class SpdPassiveGeoPar : public FairParGenericSet { +class SpdPassiveGeoParSet : public FairParGenericSet { public: - SpdPassiveGeoPar(const char* name = "SpdPassiveGeoPar", - const char* title = "SpdPassive Geometry Parameters", + SpdPassiveGeoParSet(const char* name = "SpdPassiveGeoParSet", + const char* title = "Spd Passive Geometry Parameters Set", const char* context = "TestDefaultContext"); - ~SpdPassiveGeoPar(); + ~SpdPassiveGeoParSet(); virtual void clear(); virtual void printParams(); @@ -56,7 +56,7 @@ private: TObjArray* fParams; - ClassDef(SpdPassiveGeoPar,1) + ClassDef(SpdPassiveGeoParSet,1) }; #endif diff --git a/spddisplay/CMakeLists.txt b/spddisplay/CMakeLists.txt index 74eb61c3cc54c4cbd30a3b335afbcbcc1cbd5ead..3acd2a5766c88dc865ed61585366bba40aba89d7 100644 --- a/spddisplay/CMakeLists.txt +++ b/spddisplay/CMakeLists.txt @@ -32,6 +32,13 @@ SpdMCTracks.cxx ) +set(HEADERS +SpdEveEventViewer.h +SpdEventManager.h +SpdFairEventManager.h +SpdMCTracks.h +) + Set(LINKDEF SpdDisplayLinkDef.h) Set(LIBRARY_NAME SpdDisplay) Set(DEPENDENCIES Base EventDisplay SpdData SpdField) diff --git a/spdgenerators/CMakeLists.txt b/spdgenerators/CMakeLists.txt index 9bddfc61bf1ad645d9feb42b7185bf3dd39c2028..a92bc49c9f2762f8d217e86d0bb937d89ff387fa 100644 --- a/spdgenerators/CMakeLists.txt +++ b/spdgenerators/CMakeLists.txt @@ -7,6 +7,7 @@ set(INCLUDE_DIRECTORIES ${SYSTEM_INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES} ${PYTHIA8_INCLUDE_DIR} +${Geant4_INCLUDE_DIR} ${SIMPATH}/include ${CMAKE_SOURCE_DIR}/FtfEvtGen/ ${CMAKE_SOURCE_DIR}/FtfEvtGen/include @@ -24,6 +25,7 @@ set(LINK_DIRECTORIES ${ROOT_LIBRARY_DIR} ${FAIRROOT_LIBRARY_DIR} ${SIMPATH}/lib +${GEANT4_LIBRARY_DIR} ) link_directories( ${LINK_DIRECTORIES}) @@ -42,6 +44,24 @@ SpdFtfGenerator.cxx SpdIsotropicGenerator.cxx SpdPrimaryGenerator.cxx SpdPythia8Generator.cxx +SpdUrqmdGenerator.cxx +) + +set(HEADERS +SpdDecayer.h +SpdEvtBaseGenerator.h +SpdFtfGenerator.h +SpdGenerator.h +SpdIsotropicGenerator.h +SpdMultiParticleGenerator.h +SpdParticleGenerator.h +SpdPrimaryGenerator.h +SpdPrimGenFactory.h +SpdPythia6Decayer.h +SpdPythia6Generator.h +SpdPythia6.h +SpdPythia8Generator.h +SpdUrqmdGenerator.h ) set(LINKDEF GenLinkDef.h) diff --git a/spdgenerators/FtfEvtGen/common.mk b/spdgenerators/FtfEvtGen/common.mk index ecfb8eca3b898a8a717554191e7889baa3c373a2..da4f1d0fdd01a98296488f8cc92159dd6d4cbefc 100644 --- a/spdgenerators/FtfEvtGen/common.mk +++ b/spdgenerators/FtfEvtGen/common.mk @@ -42,8 +42,9 @@ F77FLAGS = -fPIC CPPFLAGS += -Iinclude -CPPFLAGS += -I$(CLHEP_INCLUDE_DIR) -CPPFLAGS += -I$(GEANT4_INCLUDE_DIR) +#CPPFLAGS += -I$(CLHEP_INCLUDE_DIR) +#CPPFLAGS += -I$(GEANT4_INCLUDE_DIR) +CPPFLAGS += -I$(Geant4_INCLUDE_DIRS) #LDFLAGS += -L$(CLHEP_LIB_DIR) #LDFLAGS += -L$(CLHEP_LIBRARY_DIR) #LDLIBS += -l$(CLHEP_LIB) @@ -55,7 +56,9 @@ GLIBS = $(ROOTGLIBS) -lEG -lTreePlayer -lMinuit FTFLIB = -L$(LIBDIR) -lFtfEvtGen -LDLIBS += -L$(GEANT4_LIBRARY_DIR) -lG4clhep -lG4global -lG4geometry -lG4physicslists -lG4materials -lG4processes -lG4track -lG4particles -lEG $(GLIBS) +#LDLIBS += -L$(GEANT4_LIBRARY_DIR) -lG4clhep -lG4global -lG4geometry -lG4physicslists -lG4materials -lG4processes -lG4track -#lG4particles -lEG $(GLIBS) + +LDLIBS += -L$(SIMPATH)/lib -lG4clhep -lG4global -lG4geometry -lG4physicslists -lG4materials -lG4processes -lG4track -lG4particles -lEG $(GLIBS) # Static pattern rule for object file dependency on sources: $(OBJDIR)/%.o: %.cc diff --git a/spdgenerators/GenLinkDef.h b/spdgenerators/GenLinkDef.h index e38061f94c0243b0edcfb2277b36eb78c60245d5..a808a2bb3268c2d3f79ea713a95893a281f5ef5a 100644 --- a/spdgenerators/GenLinkDef.h +++ b/spdgenerators/GenLinkDef.h @@ -13,6 +13,7 @@ #pragma link C++ class SpdPythia8Generator+; #pragma link C++ class SpdIsotropicGenerator+; #pragma link C++ class SpdFtfGenerator+; +#pragma link C++ class SpdUrqmdGenerator+; #pragma link C++ class SpdDecayer+; #pragma link C++ class SpdPythia6Decayer+; diff --git a/spdgenerators/SpdGenerator.cxx b/spdgenerators/SpdGenerator.cxx index 4dad68388fef8bdb04853efe72a6e2facb2e5157..ed9e11084807530a5ea8b25ae7bc39025cfb5c23 100644 --- a/spdgenerators/SpdGenerator.cxx +++ b/spdgenerators/SpdGenerator.cxx @@ -90,6 +90,7 @@ Bool_t SpdGenerator::AddTrack(FairPrimaryGenerator* primGen, Bool_t AddToStack, Double_t e, Double_t time, Double_t weight) { if (fEvent != 0) { + Int_t n = fEvent->GetEntriesFast(); TParticle* part = new ((*fEvent)[n]) TParticle(pdg, num, parent_num, AddToStack, -1, -1, px, py, pz, e, vx, vy, vz, time); @@ -106,7 +107,7 @@ Bool_t SpdGenerator::AddTrack(FairPrimaryGenerator* primGen, Bool_t AddToStack, Int_t DataTrackId = -1; if (fGenData) { - + if (!primGen) StackTrackId = AddToStack; TParticle* part = new TParticle(pdg, num, parent_num, StackTrackId, @@ -129,10 +130,11 @@ Bool_t SpdGenerator::AddTrack(FairPrimaryGenerator* primGen, Bool_t AddToStack, delete part; } + if (primGen && AddToStack) { - + SpdPrimaryGenerator* gen = dynamic_cast<SpdPrimaryGenerator*>(primGen); - + if (gen) StackTrackId = gen->GetCurrentTrackId(); primGen->AddTrack(pdg, px, py, pz, vx, vy, vz, DataTrackId, diff --git a/spdgenerators/SpdIsotropicGenerator.cxx b/spdgenerators/SpdIsotropicGenerator.cxx index 6b61c3d1f0ace88752fee9e3ce8458fb1a96b637..0489647b740588c7d117f1940ef3ab82afbea1e3 100644 --- a/spdgenerators/SpdIsotropicGenerator.cxx +++ b/spdgenerators/SpdIsotropicGenerator.cxx @@ -257,7 +257,7 @@ void SpdIsotropicGenerator::Initialize(Int_t pdg, Double_t kenergy, Int_t np) TParticlePDG *part = TDatabasePDG::Instance()->GetParticle(pdg); if (!part) { - cout << "-E- <SpdIsotropicGenerator::Init> Unknown particle: " << pdg << endl; + cout << "-E- <SpdIsotropicGenerator::Initialize> Unknown particle: " << pdg << endl; return; } diff --git a/spdgenerators/SpdPrimaryGenerator.cxx b/spdgenerators/SpdPrimaryGenerator.cxx index 2e018d413ef7a61f4120a8f7ea50bdd3f169b549..e645538c683b36348e39dee0a27a41e081f87d50 100644 --- a/spdgenerators/SpdPrimaryGenerator.cxx +++ b/spdgenerators/SpdPrimaryGenerator.cxx @@ -565,6 +565,8 @@ Bool_t SpdPrimaryGenerator::FillParsIn(SpdPrimGenParSet* params) if (fExternalDecayer) params->SetParameter("DecayerStorageIndex", fExternalDecayer->GetStorageIndex(),0); + + return kTRUE; } //_____________________________________________________________________________ diff --git a/spdgenerators/SpdPythia6Decayer.cxx b/spdgenerators/SpdPythia6Decayer.cxx index e46fc5f983849f9fb20b642400e8ae5d65db1f69..5a423f6f32dc2537ca7c833556008b0c7955a1d0 100644 --- a/spdgenerators/SpdPythia6Decayer.cxx +++ b/spdgenerators/SpdPythia6Decayer.cxx @@ -11,6 +11,8 @@ #include <TParticle.h> #include <TRandom3.h> #include <TMath.h> +#include <TDatabasePDG.h> +#include <TParticlePDG.h> #include <TPythia6.h> @@ -108,7 +110,9 @@ void SpdPythia6Decayer::Decay(Int_t idpart, TLorentzVector* p) { // Decay a particle of type IDPART (PDG code) and momentum P. - //cout << "-I- <SpdPythia6Decayer::Decay> Particle (pdg): " << idpart << endl; + //cout << "-I- <SpdPythia6Decayer::Decay> Particle (pdg): " + // << TDatabasePDG::Instance()->GetParticle(idpart)->GetName() + // << " (" << idpart << ")" << endl; if (!fInit) Init(); @@ -120,7 +124,7 @@ void SpdPythia6Decayer::Decay(Int_t idpart, TLorentzVector* p) TPythia6::Instance()->GetPrimaries(); fParticlePdg = idpart; - + fCycle++; if (fDecayer) fDecayer->FillDecay(idpart,p); @@ -129,8 +133,7 @@ void SpdPythia6Decayer::Decay(Int_t idpart, TLorentzVector* p) //______________________________________________________________________________ Int_t SpdPythia6Decayer::ImportParticles(TClonesArray *particles) { - // Get the decay products into the passed PARTICLES TClonesArray of - // TParticles + // Get the decay products into the passed PARTICLES TClonesArray of TParticles Int_t np = TPythia6::Instance()->ImportParticles(fParticles,"All"); @@ -151,13 +154,13 @@ Int_t SpdPythia6Decayer::ImportParticles(TClonesArray *particles) fParticles->Clear(); -// cout << "-I- <SpdPythia6Decayer::ImportParticles> Particle (pdg): " << fParticlePdg -// << " add: " << npp << "/" << np << endl; + //cout << "-I- <SpdPythia6Decayer::ImportParticles> Particle (pdg): " << fParticlePdg + // << " add: " << npp << "/" << np << " Particles list: " << endl; -// for (Int_t i(0); i<npp; i++) { -// p = (TParticle*)parts.At(i); -// p->Print(); -// } + //for (Int_t i(0); i<npp; i++) { + // p = (TParticle*)parts.At(i); + // p->Print(); + //} if (fDecayer) fDecayer->FillParticles(&parts); @@ -189,13 +192,119 @@ Bool_t SpdPythia6Decayer::LoadParsFrom(SpdPrimGenParSet* params, Int_t index) //______________________________________________________________________________ Float_t SpdPythia6Decayer::GetLifetime(Int_t pdg) { - Int_t kc = TPythia6::Instance()->Pycomp(TMath::Abs(pdg)); + Int_t kc = TPythia6::Instance()->Pycomp(TMath::Abs(pdg)); Float_t t = TPythia6::Instance()->GetPMAS(kc,4) * 3.3333e-12; - cout << "pdg = " << pdg << " t = " << t << endl; - exit(1); + //cout << "pdg = " << pdg << " t = " << t << endl; return t; } +//______________________________________________________________________________ +void SpdPythia6Decayer::SelectForcedDecay(Int_t particle, Int_t channel) +{ + std::map< Int_t, std::set<Int_t> >::iterator it = fSelectedDecays.find(particle); + if (it == fSelectedDecays.end()) { + std::set<Int_t> channels; + channels.insert(channel); + fSelectedDecays[particle] = channels; + } + else it->second.insert(channel); +} + +//______________________________________________________________________________ +void SpdPythia6Decayer::ForceSelectedDecays() +{ + if (fSelectedDecays.empty()) { + cout << "-W- <SpdPythia6Decayer::ForceSelectedDecays> Decays list is empty, nothing has been done. " << endl; + return; + } + + std::map< Int_t, std::set<Int_t> >::const_iterator it = fSelectedDecays.begin(); + std::set< Int_t >::const_iterator its; + + TPythia6* pythia = TPythia6::Instance(); + + Int_t pdg, channel; + Int_t kc, ifirst, ilast; + + for (; it != fSelectedDecays.end(); it++) + { + pdg = it->first; + + if (!TDatabasePDG::Instance()->GetParticle(pdg)) { + cout << "-W- <SpdPythia6Decayer::ForceSelectedDecays> [TDatabasePDG] unknown particle: " + << pdg << endl; + continue; + } + + kc = pythia->Pycomp(pdg); + ifirst = pythia->GetMDCY(kc,2); + ilast = ifirst + pythia->GetMDCY(kc,3)-1; + + its = it->second.begin(); + + fBraPart[kc] = 1.; + + cout << "\n-I- <SpdPythia6Decayer::ForceSelectedDecays> particle: " << pdg << " " << endl; + channel = 0; + for (Int_t ch = ifirst; ch <= ilast; ch++) { + channel++; + if (channel == *its) { + pythia->SetMDME(ch,1,1); + cout << "\t force channel: " << channel << endl; + its++; + + } + else { + pythia->SetMDME(ch,1,0); + fBraPart[kc] -= pythia->GetBRAT(ch); + } + } + } +} + +//______________________________________________________________________________ +void SpdPythia6Decayer::PrintParticleDecayChannels(Int_t particle /*pdg number*/) +{ + TPythia6* pythia = TPythia6::Instance(); + + Int_t kc = pythia->Pycomp(particle); + + pythia->SetMDCY(kc,1,1); + + Int_t ifirst = pythia->GetMDCY(kc,2); + Int_t ilast = ifirst + pythia->GetMDCY(kc,3)-1; + + TDatabasePDG* db = TDatabasePDG::Instance(); + TParticlePDG* p = db->GetParticle(particle); + + if (!p) { + cout << "-W- <SpdPythia6Decayer::PrintParticleDecayBranching> [TDatabasePDG] unknown particle: " + << particle << endl; + return; + } + + cout << "\n-I- <SpdPythia6Decayer::PrintParticleDecayBranching> Particle (pdg): " + << p->GetName() << " (" << particle << ") Life time [s]: " << GetLifetime(particle) << endl; + + Double_t brsum(0); + + // Loop over decay channels + Int_t n(0), pdg; + for (Int_t channel = ifirst; channel <= ilast; channel++) { + cout << "channel: " << ++n << "; particles: "; + for (Int_t i = 1; i <= 5; i++) { + pdg = pythia->GetKFDP(channel,i); + if (pdg == 0) continue; + p = db->GetParticle(pdg); + if (p) cout << p->GetName() << " (" << pdg << ") " << " "; + else cout << "unknown" << " (" << pdg << ") " << "; "; + } + cout << " branch ratio: " << pythia->GetBRAT(channel) << endl; + brsum += pythia->GetBRAT(channel); + } + + cout << "Braching (sum): " << brsum << endl; +} diff --git a/spdgenerators/SpdPythia6Decayer.h b/spdgenerators/SpdPythia6Decayer.h index b9a08927ddeae29220ea29ff825b7124ae76886c..aad6e871ae95136f43a71eb8f452afe60ad131b4 100644 --- a/spdgenerators/SpdPythia6Decayer.h +++ b/spdgenerators/SpdPythia6Decayer.h @@ -5,6 +5,11 @@ #define __SPDPYTHIA6DECAYER_H__ #include <TPythia6Decayer.h> +#include <map> +#include <set> + +//using std::map; +//using std::set; //////////////////////////////////////////////////////////////////////////////// // // @@ -49,6 +54,11 @@ public: virtual Float_t GetLifetime(Int_t pdg); + void PrintParticleDecayChannels(Int_t particle /*pdg number*/); + void SelectForcedDecay(Int_t particle, Int_t channel); + void ForceSelectedDecays(); + void ClearSelectedDecays() { fSelectedDecays.clear(); } + protected: Int_t fParticlePdg; //! current particle id @@ -60,6 +70,8 @@ protected: Bool_t fInit; SpdDecayer* fDecayer; + std::map< Int_t, std::set<Int_t> > fSelectedDecays; + ClassDef(SpdPythia6Decayer,1) }; diff --git a/spdgenerators/SpdPythia6Generator.cxx b/spdgenerators/SpdPythia6Generator.cxx index 2737e0195c64ac8d11791d179e596270fbbb7345..40622dba3704ab25e3fb8f3862707c92b4b14d9d 100644 --- a/spdgenerators/SpdPythia6Generator.cxx +++ b/spdgenerators/SpdPythia6Generator.cxx @@ -290,7 +290,7 @@ Bool_t SpdPythia6Generator::GenerateDirectly(FairPrimaryGenerator* primGen) static const Float_t tmin = 1e-20; static const Float_t kmin = 1e-9; - static const Int_t Nattempt_max = 1000; + static const Int_t Nattempt_max = 100000; TClonesArray* ps; TMCParticle *part; @@ -488,6 +488,10 @@ Bool_t SpdPythia6Generator::GenerateDirectly(FairPrimaryGenerator* primGen) if (addpart) pnn.insert(*it); } + /* !ATTENTION! CHECK EVENT !ATTENTION!*/ + + //if (!IsAcceptableEvent(ps,pnn,true)) continue; + /* CHECK SELECTED PARTICLES */ for (it = pnn.begin(); it != pnn.end(); it++) { @@ -657,13 +661,19 @@ bool SpdPythia6Generator::IsAcceptableParticle(Int_t pdg, Bool_t edump) const return kFALSE; } - if (ptype.Contains("Charmed")) { - if (fVerboseLevel > -2 && fVgenopt > 0) { - cout << "-W- <SpdPythia6Generator::IsAcceptableParticle> Unacceptable particle: " - << pdg << " (" << ptype << ") " << endl; - } - return kFALSE; - } +// if (ptype.Contains("Charmed")) { +// if (fVerboseLevel > -2 && fVgenopt > 0) { +// cout << "-W- <SpdPythia6Generator::IsAcceptableParticle> Unacceptable particle: " +// << pdg << " (" << ptype << ") " << endl; +// } +// return kFALSE; +// } + +// if (ptype.Contains("Charmed")) { +// cout << "-I- <SpdPythia6Generator::IsAcceptableParticle> Charmed particle: " +// << pdgpart->GetName() << " " << pdg << " (" << ptype << ") " << endl; +// return kTRUE; +// } if (ptype.Contains("Meson")) return kTRUE; if (ptype.Contains("Baryon")) return kTRUE; @@ -678,6 +688,34 @@ bool SpdPythia6Generator::IsAcceptableParticle(Int_t pdg, Bool_t edump) const return kFALSE; } +//_____________________________________________________________________________ +bool SpdPythia6Generator::IsAcceptableEvent(TClonesArray* plist, const std::set<Int_t>& psel, Bool_t edump) const +{ + std::set<Int_t>::const_iterator it; + TMCParticle* part; + TParticlePDG* pdgpart; + Int_t pdg(0); + TString ptype; + + Bool_t is_ok = kFALSE; + + for (it = psel.begin(); it != psel.end(); it++) { + part = (TMCParticle*)plist->At(*it); + pdg = part->GetKF(); + pdgpart = TDatabasePDG::Instance()->GetParticle(pdg); + if (!pdgpart) return kFALSE; + ptype = pdgpart->ParticleClass(); + if (ptype.Contains("Charmed")) { is_ok = kTRUE; break; } + } + + if (is_ok && edump) { + cout << "-I- <SpdPythia6Generator::IsAcceptableEvent> Accept event with particle: " + << pdgpart->GetName() << " " << pdg << " (" << ptype << ") " << endl; + } + + return is_ok; +} + //_____________________________________________________________________________ void SpdPythia6Generator::ClearTest() { diff --git a/spdgenerators/SpdPythia6Generator.h b/spdgenerators/SpdPythia6Generator.h index 1531d38e8c61d5b4663434eeb04c947d32156b32..dd94b2887470689f30dba3faab3a5c1a5c99671b 100644 --- a/spdgenerators/SpdPythia6Generator.h +++ b/spdgenerators/SpdPythia6Generator.h @@ -6,6 +6,7 @@ #include <TRandom3.h> #include <map> +#include <set> #include "SpdPythia6.h" #include "SpdGenerator.h" @@ -123,7 +124,8 @@ private: void InitSeeds(); bool IsAcceptableParticle(Int_t pdg, Bool_t edump) const; - + bool IsAcceptableEvent(TClonesArray* plist, const std::set<Int_t>& psel, Bool_t edump) const; + TString fFrame; // frame of the experiment TString fBeam; // beam particle TString fTarget; // target particle diff --git a/spdgenerators/SpdUrqmdGenerator.cxx b/spdgenerators/SpdUrqmdGenerator.cxx new file mode 100644 index 0000000000000000000000000000000000000000..171f3751948b0e700091fe1b7c54335fd6e54d9f --- /dev/null +++ b/spdgenerators/SpdUrqmdGenerator.cxx @@ -0,0 +1,489 @@ +// ------------------------------------------------------------------------- +// ----- SpdUrqmdGenerator source file ----- +// ----- Created 24/06/04 by V. Friese ----- +// ------------------------------------------------------------------------- +#include "SpdUrqmdGenerator.h" + +#include "FairPrimaryGenerator.h" +#include "FairMCEventHeader.h" +//#include "constants.h" + +#include "TMCProcess.h" +#include "TObjArray.h" +#include "TPDGCode.h" +#include "TParticle.h" +#include "TRandom.h" +#include "TString.h" +#include "TVirtualMCStack.h" +#include "TLorentzVector.h" +#include "TDatabasePDG.h" +#include "TParticlePDG.h" +#include <iostream> +#include <cstring> + +#include <stdio.h> + +using namespace std; +using namespace TMath; + +//const Double_t kProtonMass = 0.938271998; + + +// ----- Default constructor ------------------------------------------ + +SpdUrqmdGenerator::SpdUrqmdGenerator() +: SpdGenerator("SPD URQMD Generator"), +fInputFile(NULL), +fParticleTable(), +fFileName(NULL), +fPhiMin(0.), +fPhiMax(0.), +fEventPlaneSet(kFALSE) { +} +// ------------------------------------------------------------------------ + + + +// ----- Standard constructor ----------------------------------------- + +SpdUrqmdGenerator::SpdUrqmdGenerator(const char* fileName) +: SpdGenerator("SPD URQMD Generator"), + fInputFile(NULL), + fParticleTable(), + fFileName(fileName), + fPhiMin(0.), + fPhiMax(0.), + fEventPlaneSet(kFALSE), + fParticles(0), + fVerbose(0), + fKeepEvent(kFALSE) { + // fFileName = fileName; + cout << "-I SpdUrqmdGenerator: Opening input file " << fFileName << endl; + fInputFile = gzopen(fFileName, "rb"); + if (!fInputFile) { + Fatal("SpdUrqmdGenerator", "Cannot open input file."); + exit(1); + } + cout << "done!" << endl; + ReadConversionTable(); +} +// ------------------------------------------------------------------------ + + + +// ----- Destructor --------------------------------------------------- + +SpdUrqmdGenerator::~SpdUrqmdGenerator() { + // cout<<"Enter Destructor of SpdUrqmdGenerator"<<endl; + if (fInputFile) { +#ifdef GZIP_SUPPORT + gzclose(fInputFile); +#else + fclose(fInputFile); +#endif + fInputFile = NULL; + } + fParticleTable.clear(); + // cout<<"Leave Destructor of SpdUrqmdGenerator"<<endl; + if (fParticles) { + fParticles->Delete(); + delete fParticles; + } +} +// ------------------------------------------------------------------------ + +void SpdUrqmdGenerator::ResetEvent() +{ + if (fParticles) + fParticles->Clear(); +} + +void SpdUrqmdGenerator::SetKeepEvent(Bool_t v) +{ + if (v) { + if (!fParticles) fParticles = new TClonesArray("TParticle"); + else fParticles->Delete(); + } + else { + if (fParticles) { + fParticles->Delete(); + delete fParticles; + fParticles = 0; + } + } + + fKeepEvent = v; +} +// ----- Public method ReadEvent -------------------------------------- + +Bool_t SpdUrqmdGenerator::ReadEvent(FairPrimaryGenerator* primGen) { + + // ---> Check for input file + if (!fInputFile) { + cout << "-E SpdUrqmdGenerator: Input file not open! " << endl; + return kFALSE; + } + + // ---> Check for primary generator + //if (!primGen) { + // cout << "-E- SpdUrqmdGenerator::ReadEvent: " + // << "No PrimaryGenerator!" << endl; + // return kFALSE; + //} + + // ---> Define event variables to be read from file + int evnr = 0, ntracks = 0, aProj = 0, zProj = 0, aTarg = 0, zTarg = 0; + float b = 0., ekin = 0.; + + int ityp = 0, i3 = 0, ichg = 0, pid = 0; + float ppx = 0., ppy = 0., ppz = 0., m = 0.; + + // ---> Read and check first event header line from input file + char read[200]; +#ifdef GZIP_SUPPORT + gzgets(fInputFile, read, 200); // line 1 +#else + fgets(read, 200, fInputFile); +#endif + Int_t urqmdVersion = 0; + sscanf(read, "UQMD version: %d 1000 %d output_file 14", &urqmdVersion, &urqmdVersion); + cout << "URQMD VERSION USED = " << urqmdVersion << endl; +#ifdef GZIP_SUPPORT + if (gzeof(fInputFile)) { + cout << "-I SpdUrqmdGenerator : End of input file reached." << endl; + gzclose(fInputFile); +#else + if ( feof(fInputFile) ) { + cout << "-I SpdUrqmdGenerator : End of input file reached." << endl; + fclose(fInputFile); +#endif + fInputFile = NULL; + return kFALSE; + } + if (read[0] != 'U') { + cout << "-E SpdUrqmdGenerator: Wrong event header" << endl; + return kFALSE; + } + + // ---> Read rest of event header +#ifdef GZIP_SUPPORT + gzgets(fInputFile, read, 200); // line 2 + sscanf(read, "projectile: (mass, char) %d %d target: (mass, char) %d %d", + &aProj, &zProj, &aTarg, &zTarg); // line 2 + gzgets(fInputFile, read, 200); // line 3 + gzgets(fInputFile, read, 36); // line 4 + gzgets(fInputFile, read, 200); // line 4 + sscanf(read, "%f", &b); // line 4 + gzgets(fInputFile, read, 39); // line 5 + gzgets(fInputFile, read, 200); // line 5 + sscanf(read, "%e", &ekin); // line 5 + gzgets(fInputFile, read, 7); // line 6 + gzgets(fInputFile, read, 200); // line 6 + sscanf(read, "%d", &evnr); // line 6 + + for (Int_t iline = 0; iline < ((urqmdVersion == 30400) ? 11 : 8); iline++) + gzgets(fInputFile, read, 200); + + gzgets(fInputFile, read, 200); // line 18 + sscanf(read, "%d", &ntracks); // line 18 + gzgets(fInputFile, read, 200); // line 19 +#else + fgets(read, 26, fInputFile); + fscanf(fInputFile, "%d", &aProj); + fscanf(fInputFile, "%d", &zProj); + fgets(read, 25, fInputFile); + fscanf(fInputFile, "%d", &aTarg); + fscanf(fInputFile, "%d", &zTarg); + fgets(read, 200, fInputFile); + fgets(read, 200, fInputFile); + fgets(read, 36, fInputFile); + fscanf(fInputFile, "%f", &b); + fgets(read, 200, fInputFile); + fgets(read, 39, fInputFile); + fscanf(fInputFile, "%e", &ekin); + fgets(read, 200, fInputFile); + fgets(read, 7, fInputFile); + fscanf(fInputFile, "%d", &evnr); + fgets(read, 200, fInputFile); + for (int iline=0; iline<8; iline++) { fgets(read, 200,fInputFile); } + fscanf(fInputFile, "%d", &ntracks); + fgets(read, 200, fInputFile); + fgets(read, 200, fInputFile); +#endif + + // ---> Calculate beta and gamma for Lorentztransformation + TDatabasePDG* pdgDB = TDatabasePDG::Instance(); + TParticlePDG* kProton = pdgDB->GetParticle(2212); + Double_t kProtonMass = kProton->Mass(); + + Double_t eBeam = ekin + kProtonMass; + Double_t pBeam = TMath::Sqrt(eBeam * eBeam - kProtonMass * kProtonMass); + Double_t betaCM = pBeam / (eBeam + kProtonMass); + Double_t gammaCM = TMath::Sqrt(1. / (1. - betaCM * betaCM)); + + cout << "-I SpdUrqmdGenerator: Event " << evnr << ", b = " << b + << " fm, multiplicity " << ntracks << ", ekin: " << ekin << endl; + + + Double_t phi = 0.; + // ---> Generate rotation angle + if (fEventPlaneSet) { + phi = gRandom->Uniform(fPhiMin, fPhiMax); + } + + // Set event id and impact parameter in MCEvent if not yet done + + if(primGen){ + FairMCEventHeader* event = primGen->GetEvent(); + if (event && (!event->IsSet())) { + event->SetEventID(evnr); + event->SetB(b); + event->MarkSet(kTRUE); + event->SetRotZ(phi); + } + } + + Int_t itr = 0; + // ---> Loop over tracks in the current event + for (int itrack = 0; itrack < ntracks; itrack++) { + if(fVerbose > 1) cout << "Read track " << itrack << endl; + // Read momentum and PID from file +#ifdef GZIP_SUPPORT + gzgets(fInputFile, read, 81); + gzgets(fInputFile, read, 200); + sscanf(read, "%e %e %e %e %d %d %d", &ppx, &ppy, &ppz, &m, &ityp, &i3, &ichg); +#else + fgets(read, 81, fInputFile); + fscanf(fInputFile, "%e", &ppx); + fscanf(fInputFile, "%e", &ppy); + fscanf(fInputFile, "%e", &ppz); + fscanf(fInputFile, "%e", &m); + fscanf(fInputFile, "%d", &ityp); + fscanf(fInputFile, "%d", &i3); + fscanf(fInputFile, "%d", &ichg); + fgets(read, 200, fInputFile); +#endif + + // Convert UrQMD type and charge to unique pid identifier + if (ityp >= 0) { + pid = 1000 * (ichg + 2) + ityp; + } else { + pid = -1000 * (ichg + 2) + ityp; + } + + // Convert Unique PID into PDG particle code + if (fParticleTable.find(pid) == fParticleTable.end()) { + cout << "-W SpdUrqmdGenerator: PID " << ityp << " charge " + << ichg << " not found in table (" << pid << ")" << endl; + continue; + } + Int_t pdgID = fParticleTable[pid]; + + // CM system + Double_t mass = Double_t(m); + Double_t px = Double_t(ppx); + Double_t py = Double_t(ppy); + Double_t pz = Double_t(ppz); + Double_t e = sqrt(mass * mass + px * px + py * py + pz * pz); + // transform to laboratory + // if (gCoordinateSystem == sysLaboratory) + // pz = gammaCM * (pz + betaCM * e); + Double_t ee = sqrt(mass * mass + px * px + py * py + pz * pz); + + if (fEventPlaneSet) { + Double_t pt = Sqrt(px * px + py * py); + Double_t azim = ATan2(py, px); + azim += phi; + px = pt * Cos(azim); + py = pt * Sin(azim); + } + + TLorentzVector pp; + pp.SetPx(px); + pp.SetPy(py); + pp.SetPz(pz); + pp.SetE(ee); + + if (fKeepEvent && fParticles) { + Int_t np = fParticles->GetEntriesFast(); + TParticle* particle = new ((*fParticles)[np]) TParticle(); + particle->SetPdgCode(pdgID); + particle->SetProductionVertex(0, 0, 0, 0); + + if(fVerbose) + cout << " PDG " << pdgID << " " << px << " " << py << " " << pz << endl; + + TParticlePDG* pdgpart = TDatabasePDG::Instance()->GetParticle(pdgID); + if (pdgpart) { + Double_t pdgmass = pdgpart->Mass(); + Double_t te = TMath::Sqrt(px*px + py*py + pz*pz + pdgmass*pdgmass); + particle->SetMomentum(px, py, pz, te); + } + else { + particle->SetMomentum(px, py, pz, -1); + } + } + + + + + // Give track to PrimaryGenerator (for FairGenerator only!) + // if(primGen) + // { + // //primGen->AddTrack(pdgID, px, py, pz, 0., 0., 0.); + // } + + AddTrack(primGen, 1, pdgID , itr++, -1, px, py, pz); + + } + + return kTRUE; +} +// ------------------------------------------------------------------------ + + +// ----- Public method ReadEvent -------------------------------------- + +Bool_t SpdUrqmdGenerator::SkipEvents(Int_t count) { + if (count <= 0) { + return kTRUE; + } + + for (Int_t ii = 0; ii < count; ii++) { + // ---> Check for input file + if (!fInputFile) { + cout << "-E SpdUrqmdGenerator: Input file not open! " << endl; + return kFALSE; + } + + // ---> Define event variables to be read from file + int evnr = 0, ntracks = 0, aProj = 0, zProj = 0, aTarg = 0, zTarg = 0; + float b = 0., ekin = 0.; + + // ---> Read and check first event header line from input file + char read[200]; +#ifdef GZIP_SUPPORT + gzgets(fInputFile, read, 200); // line 1 +#else + fgets(read, 200, fInputFile); +#endif + Int_t urqmdVersion = 0; + sscanf(read, "UQMD version: %d 1000 %d output_file 14", &urqmdVersion, &urqmdVersion); + cout << "URQMD VERSION USED = " << urqmdVersion << endl; + +#ifdef GZIP_SUPPORT + if (gzeof(fInputFile)) { + cout << "-I SpdUrqmdGenerator : End of input file reached." << endl; + gzclose(fInputFile); +#else + if ( feof(fInputFile) ) { + cout << "-I SpdUrqmdGenerator : End of input file reached." << endl; + fclose(fInputFile); +#endif + fInputFile = NULL; + return kFALSE; + } + if (read[0] != 'U') { + cout << "-E SpdUrqmdGenerator: Wrong event header" << endl; + return kFALSE; + } + + // ---> Read rest of event header +#ifdef GZIP_SUPPORT + gzgets(fInputFile, read, 200); // line 2 + sscanf(read, "projectile: (mass, char) %d %d target: (mass, char) %d %d", + &aProj, &zProj, &aTarg, &zTarg); // line 2 + gzgets(fInputFile, read, 200); // line 3 + gzgets(fInputFile, read, 36); // line 4 + gzgets(fInputFile, read, 200); // line 4 + sscanf(read, "%f", &b); // line 4 + gzgets(fInputFile, read, 39); // line 5 + gzgets(fInputFile, read, 200); // line 5 + sscanf(read, "%e", &ekin); // line 5 + gzgets(fInputFile, read, 7); // line 6 + gzgets(fInputFile, read, 200); // line 6 + sscanf(read, "%d", &evnr); // line 6 + + for (Int_t iline = 0; iline < ((urqmdVersion == 30400) ? 11 : 8); iline++) + gzgets(fInputFile, read, 200); + + gzgets(fInputFile, read, 200); // line 15 + sscanf(read, "%d", &ntracks); // line 15 + gzgets(fInputFile, read, 200); // line 16 +#else + fgets(read, 26, fInputFile); + fscanf(fInputFile, "%d", &aProj); + fscanf(fInputFile, "%d", &zProj); + fgets(read, 25, fInputFile); + fscanf(fInputFile, "%d", &aTarg); + fscanf(fInputFile, "%d", &zTarg); + fgets(read, 200, fInputFile); + fgets(read, 200, fInputFile); + fgets(read, 36, fInputFile); + fscanf(fInputFile, "%f", &b); + fgets(read, 200, fInputFile); + fgets(read, 39, fInputFile); + fscanf(fInputFile, "%e", &ekin); + fgets(read, 200, fInputFile); + fgets(read, 7, fInputFile); + fscanf(fInputFile, "%d", &evnr); + fgets(read, 200, fInputFile); + for (int iline=0; iline<8; iline++) { fgets(read, 200,fInputFile); } + fscanf(fInputFile, "%d", &ntracks); + fgets(read, 200, fInputFile); + fgets(read, 200, fInputFile); +#endif + + cout << "-I SpdUrqmdGenerator: Event " << evnr << " skipped!" << endl; + + // ---> Loop over tracks in the current event + for (int itrack = 0; itrack < ntracks; itrack++) { + + // Read momentum and PID from file +#ifdef GZIP_SUPPORT + gzgets(fInputFile, read, 200); +#else + fgets(read, 81, fInputFile); + fgets(read, 200, fInputFile); +#endif + } + } + return kTRUE; +} +// ------------------------------------------------------------------------ + +// ----- Private method ReadConverisonTable --------------------------- + +void SpdUrqmdGenerator::ReadConversionTable() { + + TString work = getenv("VMCWORKDIR"); + TString fileName = work + "/input/urqmd_pdg.dat"; + ifstream* pdgconv = new ifstream(fileName.Data()); + + Int_t index = 0; + Int_t pdgId = 0; + + while (!pdgconv->eof()) { + index = pdgId = 0; + *pdgconv >> index >> pdgId; + fParticleTable[index] = pdgId; + } + + pdgconv->close(); + delete pdgconv; + + cout << "-I SpdUrqmdGenerator: Particle table for conversion from " + << "UrQMD loaded" << endl; + +} +// ------------------------------------------------------------------------ + +void SpdUrqmdGenerator::SetEventPlane(Double_t phiMin, Double_t phiMax) { + fPhiMin = phiMin; + fPhiMax = phiMax; + fEventPlaneSet = kTRUE; +} + + + +ClassImp(SpdUrqmdGenerator); diff --git a/spdgenerators/SpdUrqmdGenerator.h b/spdgenerators/SpdUrqmdGenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..4cdfdd5541caa740ba8c61de2a9e1530a3985a41 --- /dev/null +++ b/spdgenerators/SpdUrqmdGenerator.h @@ -0,0 +1,109 @@ +// ------------------------------------------------------------------------- +// ----- SpdUrqmdGenerator header file ----- +// ----- Created 11/06/04 by V. Friese / D.Bertini ----- +// ------------------------------------------------------------------------- + + +/** SpdUrqmdGenerator.h + *@ author V.Friese <v.friese@gsi.de> + *@author D.Bertini <d.bertini@gsi.de> + * + The SpdUrqmdGenerator reads the output file 14 (ftn14) from UrQMD. The UrQMD + calculation has to be performed in the CM system of the collision; Lorentz + transformation into the lab is performed by this class. + Derived from FairGenerator. +**/ +#define GZIP_SUPPORT // version with gz support + +#ifndef SPDURQMDGENERATOR_H +#define SPDURQMDGENERATOR_H + +#include "SpdGenerator.h" + +#include <fstream> +#include <map> + +#include "TClonesArray.h" + +#ifdef GZIP_SUPPORT +#ifndef __CINT__ +#include <zlib.h> +#endif +#endif + +class TVirtualMCStack; +class FairPrimaryGenerator; + +class SpdUrqmdGenerator : public SpdGenerator +{ + public: + + /** Default constructor without arguments should not be used. **/ + SpdUrqmdGenerator(); + + + /** Standard constructor. + * @param fileName The input file name + **/ + SpdUrqmdGenerator(const char* fileName); + + + /** Destructor. **/ + ~SpdUrqmdGenerator(); + + virtual Bool_t Init() { return kTRUE; } //FIXME!!! + + /** Reads on event from the input file and pushes the tracks onto + ** the stack. Abstract method in base class. + ** @param pStack pointer to the stack + ** @param ver not used + **/ + Bool_t ReadEvent(FairPrimaryGenerator* primGen); + + //Skip some events in file + Bool_t SkipEvents(Int_t count); + + void SetEventPlane(Double_t phiMin, Double_t phiMax); //FIXME!!! + + inline const TClonesArray* GetEvent() const { return fParticles; } + void SetKeepEvent(Bool_t v); + void ResetEvent(); + + void SetVerboseLevel(Int_t vl) {fVerbose = vl;} //FIXME!!! + + private: + +#ifdef GZIP_SUPPORT + #ifndef __CINT__ + gzFile fInputFile; //! Input file + #endif +#else + FILE* fInputFile; //! Input file +#endif + + std::map<Int_t,Int_t> fParticleTable; //! Map from UrQMD PID to PDGPID + + Double32_t fPhiMin, fPhiMax; // Limits of event plane angle //FIXME!!! + Bool_t fEventPlaneSet; // Flag whether event plane angle is used //FIXME!!! + + const Char_t* fFileName; //! Input file name + + /** Private method ReadConversionTable. Reads the conversion table + from UrQMD particle code to PDG particle code and fills the + conversion map. Is called from the constructor. **/ + void ReadConversionTable(); + + TClonesArray* fParticles; // local storage + Bool_t fKeepEvent; + Int_t fVerbose; //FIXME!!! + + SpdUrqmdGenerator(const SpdUrqmdGenerator&); + SpdUrqmdGenerator& operator=(const SpdUrqmdGenerator&); + + ClassDef(SpdUrqmdGenerator,1); + +}; + +#endif + + diff --git a/spdgeometry/CMakeLists.txt b/spdgeometry/CMakeLists.txt index deb2e89d166e2b6f4b58d928378244983a88f0ac..64721d117bf2c683ba36dc41aaef72b55fd85b27 100644 --- a/spdgeometry/CMakeLists.txt +++ b/spdgeometry/CMakeLists.txt @@ -44,10 +44,14 @@ set(SRCS ./tst/SpdTsTECGeoBuilder.cxx ./ecalt/SpdEcalTBGeoMapper.cxx +./ecalt/SpdEcalTB2GeoMapper.cxx ./ecalt/SpdEcalTECGeoMapper.cxx +./ecalt/SpdEcalTEC2GeoMapper.cxx ./rst/SpdRsTBGeoMapper.cxx +./rst/SpdRsTB2GeoMapper.cxx ./rst/SpdRsTECGeoMapper.cxx +./rst/SpdRsTEC2GeoMapper.cxx ./sol/SpdTsSBGeoMapper.cxx ./sol/SpdTsSBGeoBuilder.cxx @@ -63,6 +67,35 @@ SpdGeoFactory.cxx SpdGeoLoader.cxx ) +set(HEADERS +ecalt/SpdEcalTB2GeoMapper.h +ecalt/SpdEcalTBGeoMapper.h +ecalt/SpdEcalTEC2GeoMapper.h +ecalt/SpdEcalTECGeoMapper.h +its/SpdItsGeoBuilder.h +its/SpdItsGeoMapperX.h +its/SpdItsVolPars.h +rst/SpdRsTB2GeoMapper.h +rst/SpdRsTBGeoMapper.h +rst/SpdRsTEC2GeoMapper.h +rst/SpdRsTECGeoMapper.h +sol/SpdEcalSBGeoMapper.h +sol/SpdEcalSECGeoMapper.h +sol/SpdRsSBGeoMapper.h +sol/SpdRsSECGeoMapper.h +sol/SpdTsSBGeoBuilder.h +sol/SpdTsSBGeoMapper.h +sol/SpdTsSECGeoMapper.h +SpdGeoFactory.h +SpdGeoLoader.h +tst/SpdTsBVolPars.h +tst/SpdTsECVolPars.h +tst/SpdTsTBGeoBuilder.h +tst/SpdTsTBGeoMapper.h +tst/SpdTsTECGeoBuilder.h +tst/SpdTsTECGeoMapper.h +) + set(LINKDEF SpdGeometryLinkDef.h) set(LIBRARY_NAME SpdGeometry) diff --git a/spdgeometry/SpdGeoFactory.cxx b/spdgeometry/SpdGeoFactory.cxx index bc8e953b296c26c523cb2800339a869d1b5fccb2..7254332aa8d93d65f72991afd7f254f6c2b38d02 100644 --- a/spdgeometry/SpdGeoFactory.cxx +++ b/spdgeometry/SpdGeoFactory.cxx @@ -12,12 +12,16 @@ #include "SpdItsGeoMapperX.h" #include "SpdEcalTBGeoMapper.h" +#include "SpdEcalTB2GeoMapper.h" #include "SpdEcalTECGeoMapper.h" +#include "SpdEcalTEC2GeoMapper.h" #include "SpdEcalSBGeoMapper.h" #include "SpdEcalSECGeoMapper.h" #include "SpdRsTBGeoMapper.h" +#include "SpdRsTB2GeoMapper.h" #include "SpdRsTECGeoMapper.h" +#include "SpdRsTEC2GeoMapper.h" #include "SpdRsSBGeoMapper.h" #include "SpdRsSECGeoMapper.h" @@ -78,55 +82,55 @@ SpdGeoMapper* SpdGeoFactory::SearchForMapper(DetectorId id) switch (id) { case kSpdIts : { - mapper = SpdItsGeoMapperX::Instance()->GetMapper(); + mapper = SpdItsGeoMapperX::GetMapper(); break; } case kSpdEcalTB : { - mapper = SpdEcalTBGeoMapper::Instance()->GetMapper(); + mapper = SpdEcalTBGeoMapper::GetMapper(); break; } case kSpdEcalTEC : { - mapper = SpdEcalTECGeoMapper::Instance()->GetMapper(); + mapper = SpdEcalTECGeoMapper::GetMapper(); break; } case kSpdTsTB : { - mapper = SpdTsTBGeoMapper::Instance()->GetMapper(); + mapper = SpdTsTBGeoMapper::GetMapper(); break; } case kSpdTsTEC : { - mapper = SpdTsTECGeoMapper::Instance()->GetMapper(); + mapper = SpdTsTECGeoMapper::GetMapper(); break; } case kSpdRsTB : { - mapper = SpdRsTBGeoMapper::Instance()->GetMapper(); + mapper = SpdRsTBGeoMapper::GetMapper(); break; } case kSpdRsTEC : { - mapper = SpdRsTECGeoMapper::Instance()->GetMapper(); + mapper = SpdRsTECGeoMapper::GetMapper(); break; } case kSpdEcalSB : { - mapper = SpdEcalSBGeoMapper::Instance()->GetMapper(); + mapper = SpdEcalSBGeoMapper::GetMapper(); break; } case kSpdEcalSEC : { - mapper = SpdEcalSECGeoMapper::Instance()->GetMapper(); + mapper = SpdEcalSECGeoMapper::GetMapper(); break; } case kSpdTsSB : { - mapper = SpdTsSBGeoMapper::Instance()->GetMapper(); + mapper = SpdTsSBGeoMapper::GetMapper(); break; } case kSpdTsSEC : { - mapper = SpdTsSECGeoMapper::Instance()->GetMapper(); + mapper = SpdTsSECGeoMapper::GetMapper(); break; } case kSpdRsSB : { - mapper = SpdRsSBGeoMapper::Instance()->GetMapper(); + mapper = SpdRsSBGeoMapper::GetMapper(); break; } case kSpdRsSEC : { - mapper = SpdRsSECGeoMapper::Instance()->GetMapper(); + mapper = SpdRsSECGeoMapper::GetMapper(); break; } @@ -141,21 +145,27 @@ SpdGeoMapper* SpdGeoFactory::SearchForMapper(TString classname) { SpdGeoMapper* mapper = 0; - if (classname == "SpdItsGeoMapperX") mapper = SpdItsGeoMapperX::GetMapper(); + //cout << "-I <SpdGeoFactory::SearchForMapper> " << classname << endl; - else if (classname == "SpdEcalTBGeoMapper") mapper = SpdEcalTBGeoMapper::GetMapper(); - else if (classname == "SpdEcalTECGeoMapper") mapper = SpdEcalTECGeoMapper::GetMapper(); - else if (classname == "SpdTsTBGeoMapper") mapper = SpdTsTBGeoMapper::GetMapper(); - else if (classname == "SpdTsTECGeoMapper") mapper = SpdTsTECGeoMapper::GetMapper(); - else if (classname == "SpdRsTBGeoMapper") mapper = SpdRsTBGeoMapper::GetMapper(); - else if (classname == "SpdRsTECGeoMapper") mapper = SpdRsTECGeoMapper::GetMapper(); + if (classname == "SpdItsGeoMapperX") mapper = SpdItsGeoMapperX::GetMapper(); - else if (classname == "SpdEcalSBGeoMapper") mapper = SpdEcalSBGeoMapper::GetMapper(); - else if (classname == "SpdEcalSECGeoMapper") mapper = SpdEcalSECGeoMapper::GetMapper(); - else if (classname == "SpdTsSBGeoMapper") mapper = SpdTsSBGeoMapper::GetMapper(); - else if (classname == "SpdTsSECGeoMapper") mapper = SpdTsSECGeoMapper::GetMapper(); - else if (classname == "SpdRsSBGeoMapper") mapper = SpdRsSBGeoMapper::GetMapper(); - else if (classname == "SpdRsSECGeoMapper") mapper = SpdRsSECGeoMapper::GetMapper(); + else if (classname == "SpdEcalTBGeoMapper") mapper = SpdEcalTBGeoMapper::GetMapper(); + else if (classname == "SpdEcalTB2GeoMapper") mapper = SpdEcalTB2GeoMapper::GetMapper(); + else if (classname == "SpdEcalTECGeoMapper") mapper = SpdEcalTECGeoMapper::GetMapper(); + else if (classname == "SpdEcalTEC2GeoMapper") mapper = SpdEcalTEC2GeoMapper::GetMapper(); + else if (classname == "SpdTsTBGeoMapper") mapper = SpdTsTBGeoMapper::GetMapper(); + else if (classname == "SpdTsTECGeoMapper") mapper = SpdTsTECGeoMapper::GetMapper(); + else if (classname == "SpdRsTBGeoMapper") mapper = SpdRsTBGeoMapper::GetMapper(); + else if (classname == "SpdRsTB2GeoMapper") mapper = SpdRsTB2GeoMapper::GetMapper(); + else if (classname == "SpdRsTECGeoMapper") mapper = SpdRsTECGeoMapper::GetMapper(); + else if (classname == "SpdRsTEC2GeoMapper") mapper = SpdRsTEC2GeoMapper::GetMapper(); + + else if (classname == "SpdEcalSBGeoMapper") mapper = SpdEcalSBGeoMapper::GetMapper(); + else if (classname == "SpdEcalSECGeoMapper") mapper = SpdEcalSECGeoMapper::GetMapper(); + else if (classname == "SpdTsSBGeoMapper") mapper = SpdTsSBGeoMapper::GetMapper(); + else if (classname == "SpdTsSECGeoMapper") mapper = SpdTsSECGeoMapper::GetMapper(); + else if (classname == "SpdRsSBGeoMapper") mapper = SpdRsSBGeoMapper::GetMapper(); + else if (classname == "SpdRsSECGeoMapper") mapper = SpdRsSECGeoMapper::GetMapper(); return mapper; } @@ -165,21 +175,25 @@ SpdGeoMapper* SpdGeoFactory::Mapper(TString classname) { SpdGeoMapper* mapper = 0; - if (classname == "SpdItsGeoMapperX") mapper = SpdItsGeoMapperX::Instance(); + if (classname == "SpdItsGeoMapperX") mapper = SpdItsGeoMapperX::Instance(); - else if (classname == "SpdEcalTBGeoMapper") mapper = SpdEcalTBGeoMapper::Instance(); - else if (classname == "SpdEcalTECGeoMapper") mapper = SpdEcalTECGeoMapper::Instance(); - else if (classname == "SpdTsTBGeoMapper") mapper = SpdTsTBGeoMapper::Instance(); - else if (classname == "SpdTsTECGeoMapper") mapper = SpdTsTECGeoMapper::Instance(); - else if (classname == "SpdRsTBGeoMapper") mapper = SpdRsTBGeoMapper::Instance(); - else if (classname == "SpdRsTECGeoMapper") mapper = SpdRsTECGeoMapper::Instance(); + else if (classname == "SpdEcalTBGeoMapper") mapper = SpdEcalTBGeoMapper::Instance(); + else if (classname == "SpdEcalTB2GeoMapper") mapper = SpdEcalTB2GeoMapper::Instance(); + else if (classname == "SpdEcalTECGeoMapper") mapper = SpdEcalTECGeoMapper::Instance(); + else if (classname == "SpdEcalTEC2GeoMapper") mapper = SpdEcalTEC2GeoMapper::Instance(); + else if (classname == "SpdTsTBGeoMapper") mapper = SpdTsTBGeoMapper::Instance(); + else if (classname == "SpdTsTECGeoMapper") mapper = SpdTsTECGeoMapper::Instance(); + else if (classname == "SpdRsTBGeoMapper") mapper = SpdRsTBGeoMapper::Instance(); + else if (classname == "SpdRsTB2GeoMapper") mapper = SpdRsTB2GeoMapper::Instance(); + else if (classname == "SpdRsTECGeoMapper") mapper = SpdRsTECGeoMapper::Instance(); + else if (classname == "SpdRsTEC2GeoMapper") mapper = SpdRsTEC2GeoMapper::Instance(); - else if (classname == "SpdEcalSBGeoMapper") mapper = SpdEcalSBGeoMapper::Instance(); - else if (classname == "SpdEcalSECGeoMapper") mapper = SpdEcalSECGeoMapper::Instance(); - else if (classname == "SpdTsSBGeoMapper") mapper = SpdTsSBGeoMapper::Instance(); - else if (classname == "SpdTsSECGeoMapper") mapper = SpdTsSECGeoMapper::Instance(); - else if (classname == "SpdRsSBGeoMapper") mapper = SpdRsSBGeoMapper::Instance(); - else if (classname == "SpdRsSECGeoMapper") mapper = SpdRsSECGeoMapper::Instance(); + else if (classname == "SpdEcalSBGeoMapper") mapper = SpdEcalSBGeoMapper::Instance(); + else if (classname == "SpdEcalSECGeoMapper") mapper = SpdEcalSECGeoMapper::Instance(); + else if (classname == "SpdTsSBGeoMapper") mapper = SpdTsSBGeoMapper::Instance(); + else if (classname == "SpdTsSECGeoMapper") mapper = SpdTsSECGeoMapper::Instance(); + else if (classname == "SpdRsSBGeoMapper") mapper = SpdRsSBGeoMapper::Instance(); + else if (classname == "SpdRsSECGeoMapper") mapper = SpdRsSECGeoMapper::Instance(); return mapper; } @@ -192,22 +206,22 @@ SpdGeoBuilder* SpdGeoFactory::SearchForBuilder(DetectorId id) switch (id) { case kSpdIts : { - builder = SpdItsGeoBuilder::Instance()->GetBuilder(); + builder = SpdItsGeoBuilder::GetBuilder(); break; } case kSpdTsTB : { - builder = SpdTsTBGeoBuilder::Instance()->GetBuilder(); + builder = SpdTsTBGeoBuilder::GetBuilder(); break; } case kSpdTsTEC : { - builder = SpdTsTECGeoBuilder::Instance()->GetBuilder(); + builder = SpdTsTECGeoBuilder::GetBuilder(); break; } case kSpdTsSB : { - builder = SpdTsSBGeoBuilder::Instance()->GetBuilder(); + builder = SpdTsSBGeoBuilder::GetBuilder(); break; } diff --git a/spdgeometry/SpdGeoFactory.h b/spdgeometry/SpdGeoFactory.h index e30a0a3fa589fc785fb0375ae0509376624ed3d8..58af0f1f239936da7c69704c4593239d4e77240a 100644 --- a/spdgeometry/SpdGeoFactory.h +++ b/spdgeometry/SpdGeoFactory.h @@ -28,13 +28,13 @@ public: static SpdGeoFactory* Instance(); - virtual SpdGeoMapper* SearchForMapper(DetectorId id); // search for mapper for the detector of a such id + virtual SpdGeoMapper* SearchForMapper(DetectorId id); // search for default mapper for the detector of a such id virtual SpdGeoMapper* SearchForMapper(TString classname); // search for mapper of a such type - virtual SpdGeoMapper* Mapper(TString classname); // get mapper (or create if doesn't exist) of a such type + virtual SpdGeoMapper* Mapper(TString classname); // get mapper (or create if doesn't exist!) of a such type - virtual SpdGeoBuilder* SearchForBuilder(DetectorId id); // search for builder for the detector of a such id + virtual SpdGeoBuilder* SearchForBuilder(DetectorId id); // search for default builder for the detector of a such id virtual SpdGeoBuilder* SearchForBuilder(TString classname); // search for builder of a such type - virtual SpdGeoBuilder* Builder(TString classname); // get builder (or create if doesn't exist) of a such type + virtual SpdGeoBuilder* Builder(TString classname); // get builder (or create if doesn't exist!) of a such type virtual SpdNodesIdTable* GetNodesIdTable(TString classname); diff --git a/spdgeometry/SpdGeoLoader.cxx b/spdgeometry/SpdGeoLoader.cxx index 81267a900e0dd417da46015b9d5a7d1ca7638bc0..95f6b5a7b59ee0caa9e221071dca5eae090654c9 100644 --- a/spdgeometry/SpdGeoLoader.cxx +++ b/spdgeometry/SpdGeoLoader.cxx @@ -12,6 +12,7 @@ #include <TFile.h> #include "FairBaseParSet.h" +#include "SpdPassiveGeoParSet.h" #include "SpdGeoLoader.h" #include "SpdGeoFactory.h" @@ -25,12 +26,36 @@ using std::cout; using std::endl; +TString SpdGeoLoader::fTopGeoFile = ""; +TString SpdGeoLoader::fMediaFile = ""; +Bool_t SpdGeoLoader::fUnsetMaterials = false; +Bool_t SpdGeoLoader::fResetMediaFromPars = true; +Bool_t SpdGeoLoader::fResetPassivesMedia = false; + +//------------------------------------------------------ +void SpdGeoLoader::ForceTopGeoFile(TString fname) { fTopGeoFile = fname; } +//------------------------------------------------------ +void SpdGeoLoader::ForceMediaFile(TString fname) { fMediaFile = fname; } +//------------------------------------------------------ +void SpdGeoLoader::UnsetMaterials(Bool_t m) { fUnsetMaterials = m; } +//------------------------------------------------------ +void SpdGeoLoader::ResetMediaFromParams(Bool_t r) { fResetMediaFromPars = r; } +//------------------------------------------------------ +void SpdGeoLoader::ResetPassivesMedia(Bool_t r) { fResetPassivesMedia = r; } + +SpdGeoLoader* SpdGeoLoader::fInstance = 0; + ClassImp(SpdGeoLoader) //_____________________________________________________________________________ -SpdGeoLoader::SpdGeoLoader():fIsInit(kFALSE),fParFile(0) +SpdGeoLoader::SpdGeoLoader():fIsInit(false),fLockGeom(false),fParFile(0) { - + if (fInstance) { + cout << "-F- <SpdGeoLoader::SpdGeoLoader> Fatal error. " + << "Singleton object has already been created." << endl; + exit; + } + fInstance = this; } //_____________________________________________________________________________ @@ -39,7 +64,16 @@ SpdGeoLoader::~SpdGeoLoader() if (fParFile) { fParFile->Close(); delete fParFile; + fParFile = 0; } + + fTopGeoFile = ""; + fMediaFile = ""; + fUnsetMaterials = false; + fResetMediaFromPars = true; + fResetPassivesMedia = false; + + fInstance = 0; } //_____________________________________________________________________________ @@ -55,18 +89,27 @@ Bool_t SpdGeoLoader::LoadGeometry() nmodules += SpdCommonGeoMapper::Instance()->GetNPassives(); if (nmodules == 0) { - cout << "-W- <SpdGeoLoader::LoadGeometry> No modules are loaded " << endl; + cout << "-W- <SpdGeoLoader::LoadBaseGeometry> No modules have been loaded " << endl; return fIsInit; } - cout << "-I- <SpdGeoLoader::LoadGeometry> Load SPD geometry " << endl; + cout << "-I- <SpdGeoLoader::LoadGeometry> Load SPD geometry; number of modules: " << nmodules << endl; + + if (gGeoManager) delete gGeoManager; /*!ATTENTION! DELETE CURRENT GEOMETRY !ATTENTION!*/ - if (gGeoManager) delete gGeoManager; + SpdPassiveGeoParSet* paspars = GetPassiveParameters(); - SpdCommonGeoMapper::Instance()->OpenGeometry(); + if (!fMediaFile.IsWhitespace()) SpdCommonGeoMapper::Instance()->OpenGeometry(fMediaFile); + else { + if (paspars->GetParameter("Global/MediaFileName",fMediaFile)) SpdCommonGeoMapper::Instance()->OpenGeometry(fMediaFile); + else SpdCommonGeoMapper::Instance()->OpenGeometry(); + } + fMediaFile = SpdCommonGeoMapper::Instance()->GetActualMediaFileName(); - FairModule* Cave = new SpdCave(); - Cave->SetGeometryFileName("cave.geo"); + SpdCave* Cave = new SpdCave(); + Cave->LoadParsFrom(paspars); + if (!fTopGeoFile.IsWhitespace()) Cave->SetGeometryFileName(fTopGeoFile); + fTopGeoFile = Cave->GetActualGeometryFileName(); Cave->ConstructGeometry(); Int_t nmod, nm(0); @@ -107,16 +150,7 @@ Bool_t SpdGeoLoader::LoadGeometry(TString parfile) } if (parfile.IsWhitespace()) { - cout << "-I- <SpdGeoLoader::LoadGeometry> Define \"empty\" geometry (the TOP volume only)" << endl; - - SpdCommonGeoMapper::Instance()->OpenGeometry(); - - FairModule* Cave = new SpdCave(); - Cave->SetGeometryFileName("cave.geo"); - Cave->ConstructGeometry(); - - fIsInit = kTRUE; - + cout << "-W- <SpdGeoLoader::LoadGeometry> Geometry is not defined " << endl; return fIsInit; } @@ -134,10 +168,21 @@ Bool_t SpdGeoLoader::LoadGeometry(TString parfile) cout << "-I- <SpdGeoLoader::LoadGeometry> Load SPD geometry from: " << parfile << endl; - SpdCommonGeoMapper::Instance()->OpenGeometry(); + if (gGeoManager) delete gGeoManager; /*!ATTENTION! DELETE CURRENT GEOMETRY !ATTENTION!*/ + + SpdPassiveGeoParSet* paspars = GetPassiveParameters(); - FairModule* Cave = new SpdCave(); - Cave->SetGeometryFileName("cave.geo"); + if (!fMediaFile.IsWhitespace()) SpdCommonGeoMapper::Instance()->OpenGeometry(fMediaFile); + else { + if (paspars->GetParameter("Global/MediaFileName",fMediaFile)) SpdCommonGeoMapper::Instance()->OpenGeometry(fMediaFile); + else SpdCommonGeoMapper::Instance()->OpenGeometry(); + } + fMediaFile = SpdCommonGeoMapper::Instance()->GetActualMediaFileName(); + + SpdCave* Cave = new SpdCave(); + Cave->LoadParsFrom(paspars); + if (!fTopGeoFile.IsWhitespace()) Cave->SetGeometryFileName(fTopGeoFile); + fTopGeoFile = Cave->GetActualGeometryFileName(); Cave->ConstructGeometry(); // load full set of modules (passive and active) @@ -173,13 +218,18 @@ Bool_t SpdGeoLoader::LoadGeometry(TString parfile) } //_____________________________________________________________________________ - Bool_t SpdGeoLoader::LoadModule(Int_t id) + Bool_t SpdGeoLoader::LoadModule(Int_t id, Bool_t unsetmat) { if (!fIsInit) { cout << "-W- <SpdGeoLoader::LoadModule> Geometry is not initialized" << endl; return kFALSE; } + if (fLockGeom) { + cout << "-W- <SpdGeoLoader::LoadModule> Geomery is locked, disable protection to add module " << endl; + return kFALSE; + } + if (id == Int_t(kSpdUndefined)) { cout << "-W- <SpdGeoLoader::LoadModule> Module is undefined" << endl; return kFALSE; @@ -199,8 +249,19 @@ Bool_t SpdGeoLoader::LoadGeometry(TString parfile) } if (SpdCommonGeoMapper::IsActive(id)) { - SpdParSet* pars = GetParameters(id); - ((SpdDetector*)module)->LoadParsFrom(pars); + SpdParSet* pars = GetActiveParameters(id); + SpdDetector* active = (SpdDetector*)module; + active->LoadParsFrom(pars); + SpdGeoMapper* mapper = active->GetMapper(); + if (fResetMediaFromPars) mapper->ResetMediaFromParams(); + if (unsetmat || fUnsetMaterials) mapper->UnsetMaterials(false,"base"); + } + else { + SpdPassiveGeoParSet* pars = GetPassiveParameters(); + SpdPassiveModule* passive = (SpdPassiveModule*)module; + if (fResetPassivesMedia) passive->ResetMaterials(); + if (unsetmat || fUnsetMaterials) passive->UnsetMaterials("vacuum"); + passive->Print(""); } cout << "-I- <SpdGeoLoader::LoadModule> Construct module of id: " << id << endl; @@ -213,12 +274,17 @@ Bool_t SpdGeoLoader::LoadGeometry(TString parfile) } //_____________________________________________________________________________ -Bool_t SpdGeoLoader::LoadModule(TString name) +Bool_t SpdGeoLoader::LoadModule(TString name, Bool_t unsetmat) { if (!fIsInit) { cout << "-W- <SpdGeoLoader::LoadModule> Geometry is not initialized" << endl; return kFALSE; } + + if (fLockGeom) { + cout << "-W- <SpdGeoLoader::LoadModule> Geomery is locked, disable protection to add module " << endl; + return kFALSE; + } std::map<TString,Int_t>::const_iterator it = fModulesId.find(name); if (it != fModulesId.end()) return LoadModule(it->second); @@ -231,14 +297,14 @@ Bool_t SpdGeoLoader::LoadModule(TString name) if (mname == "all" || mname == "total" || mname == "passives" || mname == "passive") { Int_t nmod; SpdPassiveModule** mod = SpdCommonGeoMapper::Instance()->GetListOfPassives(nmod); - for (Int_t i(0); i<nmod; i++) load = LoadModule(mod[i]->GetId()); + for (Int_t i(0); i<nmod; i++) load = LoadModule(mod[i]->GetId(),unsetmat); delete [] mod; } if (mname == "all" || mname == "total" || mname == "actives" || mname == "active") { Int_t ndet; SpdDetector** det = SpdCommonGeoMapper::Instance()->GetListOfDetectors(ndet); - for (Int_t i(0); i<ndet; i++) load = LoadModule(det[i]->GetDetId()); + for (Int_t i(0); i<ndet; i++) load = LoadModule(det[i]->GetDetId(),unsetmat); delete [] det; } @@ -276,26 +342,47 @@ Bool_t SpdGeoLoader::IsModuleActive(Int_t id) const } //_____________________________________________________________________________ -SpdParSet* SpdGeoLoader::GetParameters(Int_t id) +SpdPassiveGeoParSet* SpdGeoLoader::GetPassiveParameters() +{ + TFile* g = gFile; + + SpdPassiveGeoParSet* pars = 0; + if (fParFile) { + pars = (SpdPassiveGeoParSet*)fParFile->Get("PassiveGeoParSet"); + } + else { + FairRuntimeDb* rtdb = FairRun::Instance()->GetRuntimeDb(); + pars = (SpdPassiveGeoParSet*)rtdb->getContainer("PassiveGeoParSet"); + ((FairParSet*)pars)->init(); + } + + gFile = g; + if (g) g->cd(); + + return pars; +} + +//_____________________________________________________________________________ +SpdParSet* SpdGeoLoader::GetActiveParameters(Int_t id) { if (!fIsInit) { - cout << "-W- <SpdGeoLoader::GetParameters> Geometry is not initialized" << endl; + cout << "-W- <SpdGeoLoader::GetActiveParameters> Geometry is not initialized" << endl; return 0; } if (!IsGeometryModule(id)) { - cout << "-W- <SpdGeoLoader::GetParameters> Module of id = " << id << " is not actual " << endl; + cout << "-W- <SpdGeoLoader::GetActiveParameters> Module of id = " << id << " is not actual " << endl; return 0; } if (SpdCommonGeoMapper::IsPassive(id)) { - cout << "-W- <SpdGeoLoader::GetParameters> This module is \"passive\": " << id << endl; + cout << "-W- <SpdGeoLoader::GetActiveParameters> This module is \"passive\": " << id << endl; return 0; } SpdDetector* det = SpdCommonGeoMapper::Instance()->SearchForActive(id); if (!det) { - cout << "-W- <SpdGeoLoader::LoadModule> No module of id = " << id << endl; + cout << "-W- <SpdGeoLoader::GetActiveParameters> No module of id = " << id << endl; return 0; } @@ -312,6 +399,7 @@ SpdParSet* SpdGeoLoader::GetParameters(Int_t id) ((FairParSet*)pars)->init(); } + gFile = g; if (g) g->cd(); return pars; @@ -327,6 +415,26 @@ FairModule* SpdGeoLoader::GetModule(Int_t id) return SpdCommonGeoMapper::Instance()->SearchForModule(id); } +//_____________________________________________________________________________ +SpdDetector* SpdGeoLoader::GetActive(Int_t id) +{ + if (!IsModuleActual(id)) { + cout << "-W- <SpdGeoLoader::GetActive> Module of id = " << id << " is not actual " << endl; + return 0; + } + return SpdCommonGeoMapper::Instance()->SearchForActive(id); +} + +//_____________________________________________________________________________ +SpdPassiveModule* SpdGeoLoader::GetPassive(Int_t id) +{ + if (!IsModuleActual(id)) { + cout << "-W- <SpdGeoLoader::GetPassive> Module of id = " << id << " is not actual " << endl; + return 0; + } + return SpdCommonGeoMapper::Instance()->SearchForPassive(id); +} + //_____________________________________________________________________________ SpdGeoMapper* SpdGeoLoader::GetMapper(Int_t id) { @@ -361,6 +469,13 @@ void SpdGeoLoader::PrintGeometry() const cout << "-I- <SpdGeoLoader::PrintGeometry> Modules [actual/total]: " << GetNActualModules() << "/" << GetNTotalModules() << endl; + cout << endl; + cout << "Cave geometry: " << fTopGeoFile << endl; + cout << "Media file: " << fMediaFile << endl; + cout << "Unset materials: " << ((fUnsetMaterials) ? "true" : "false") << endl; + cout << "Pars. materials: " << ((fResetMediaFromPars) ? "true" : "false") << endl; + cout << endl; + if (GetNTotalModules() < 1) return; printf("--------------------------------------------------\n"); @@ -381,13 +496,21 @@ void SpdGeoLoader::PrintActualGeometry() const { cout << "-I- <SpdGeoLoader::PrintActualGeometry> Modules [actual/total]: " << GetNActualModules() << "/" << GetNTotalModules() << endl; - - if (GetNActualModules() < 1) return; + + cout << endl; + cout << "Cave geometry: " << fTopGeoFile << endl; + cout << "Media file: " << fMediaFile << endl; + cout << "Is geometry locked: " << fLockGeom << endl; + cout << "Unset materials: " << ((fUnsetMaterials) ? "true" : "false") << endl; + cout << "Reset materials: " << ((fResetMediaFromPars) ? "true" : "false") << endl; + cout << endl; printf("--------------------------------------------------\n"); printf("%5s | %5s | \"%s\"\n","N","Id","Name"); printf("--------------------------------------------------\n"); + if (GetNActualModules() < 1) return; + Int_t n(0); std::map<TString,Int_t>::const_iterator it = fModulesId.begin(); diff --git a/spdgeometry/SpdGeoLoader.h b/spdgeometry/SpdGeoLoader.h index 4499763ae4de23aa9f80ea4a313e9d3ec4d15bb6..936bea34fb4d403781fad2153849d6235fc235cd 100644 --- a/spdgeometry/SpdGeoLoader.h +++ b/spdgeometry/SpdGeoLoader.h @@ -13,8 +13,11 @@ class TFile; class SpdParSet; +class SpdPassiveGeoParSet; class FairBaseParSet; class FairModule; +class SpdDetector; +class SpdPassiveModule; class SpdGeoMapper; class SpdGeoBuilder; @@ -33,12 +36,18 @@ public: SpdGeoLoader(); virtual ~SpdGeoLoader(); - Bool_t LoadGeometry(TString parfile); // file name or "" (TOP level geometry only) + static SpdGeoLoader* Instance() { return fInstance; } + + Bool_t LoadGeometry(TString parfile); + Bool_t LoadGeometry(); // use this method if parameters already have been loaded via runtime database - Bool_t LoadModule(Int_t id); - Bool_t LoadModule(TString name); // module name, "all", "passives", "actives" + Bool_t LoadModule(Int_t id, Bool_t unsetmat = false); + Bool_t LoadModule(TString name, Bool_t unsetmat = false); // name = module name, "all", "passives", "actives" + + void LockGeometry(Bool_t lock = true) { fLockGeom = lock; } // if true, prevent loading new modules via LoadModule /* Getters */ + Bool_t IsGeometryLocked() const { return fLockGeom; } Int_t GetNTotalModules() const { return fModulesId.size(); } Int_t GetNActualModules() const { return fModules.size(); } @@ -50,10 +59,21 @@ public: Bool_t IsModuleActual(Int_t id) const; Bool_t IsModuleActive(Int_t id) const; - SpdParSet* GetParameters(Int_t id); - FairModule* GetModule(Int_t id); - SpdGeoMapper* GetMapper(Int_t id); - SpdGeoBuilder* GetBuilder(Int_t id); + SpdPassiveGeoParSet* GetPassiveParameters(); + SpdParSet* GetActiveParameters(Int_t id); + FairModule* GetModule(Int_t id); + SpdPassiveModule* GetPassive(Int_t id); + SpdDetector* GetActive(Int_t id); + SpdGeoMapper* GetMapper(Int_t id); + SpdGeoBuilder* GetBuilder(Int_t id); + + /* Setters (static) */ + + static void ForceTopGeoFile(TString fname); // TOP (cave) geometry changing + static void ForceMediaFile(TString fname); // Media file changing + static void UnsetMaterials(Bool_t m = false); + static void ResetMediaFromParams(Bool_t r = true); + static void ResetPassivesMedia(Bool_t r = false); /* Draw/Print */ @@ -62,18 +82,23 @@ public: void PrintGeometry() const; void PrintActualGeometry() const; - /* specials */ - - Bool_t LoadGeometry(); - protected: Bool_t fIsInit; + Bool_t fLockGeom; TFile* fParFile; std::map<TString,Int_t> fModulesId; // module [name <-> id] std::set<Int_t> fModules; // list of modules were constructed - + + static TString fTopGeoFile; // default: "cave.geo" + static TString fMediaFile; // default: "media.geo" + static Bool_t fUnsetMaterials; // default: false + static Bool_t fResetMediaFromPars; // default: true + static Bool_t fResetPassivesMedia; // default: false + + static SpdGeoLoader* fInstance; + ClassDef(SpdGeoLoader,1) }; diff --git a/spdgeometry/SpdGeometryLinkDef.h b/spdgeometry/SpdGeometryLinkDef.h index 059629da03153c52cfa07ba512e8932de6f14927..455e3ec3f023f3298c2becb1f18149b9fcb20ffc 100644 --- a/spdgeometry/SpdGeometryLinkDef.h +++ b/spdgeometry/SpdGeometryLinkDef.h @@ -29,12 +29,16 @@ #pragma link C++ class SpdItsGeoMapperX+; #pragma link C++ class SpdEcalTBGeoMapper+; +#pragma link C++ class SpdEcalTB2GeoMapper+; #pragma link C++ class SpdEcalTECGeoMapper+; +#pragma link C++ class SpdEcalTEC2GeoMapper+; #pragma link C++ class SpdEcalSBGeoMapper+; #pragma link C++ class SpdEcalSECGeoMapper+; #pragma link C++ class SpdRsTBGeoMapper+; +#pragma link C++ class SpdRsTB2GeoMapper+; #pragma link C++ class SpdRsTECGeoMapper+; +#pragma link C++ class SpdRsTEC2GeoMapper+; #pragma link C++ class SpdRsSBGeoMapper+; #pragma link C++ class SpdRsSECGeoMapper+; diff --git a/spdgeometry/ecalt/SpdEcalTB2GeoMapper.cxx b/spdgeometry/ecalt/SpdEcalTB2GeoMapper.cxx new file mode 100644 index 0000000000000000000000000000000000000000..88dfcd7f1238f0b3b7ed47d2b92482df39e2659a --- /dev/null +++ b/spdgeometry/ecalt/SpdEcalTB2GeoMapper.cxx @@ -0,0 +1,737 @@ +// $Id$ +// Author: andre/artur 2020/07/31 + +//_____________________________________________________________________________ +// +// SpdEcalTB2GeoMapper +//_____________________________________________________________________________ + +#include "SpdEcalTB2GeoMapper.h" +#include "SpdCommonGeoMapper.h" + +#include <TMath.h> + +#include <iostream> + +using std::cout; +using std::endl; + +using namespace TMath; + +ClassImp(SpdEcalTB2GeoMapper) + +SpdEcalTB2GeoMapper* SpdEcalTB2GeoMapper::fInstance = 0; + +SpdEcalTB2GeoMapper* SpdEcalTB2GeoMapper::Instance() +{ return (fInstance) ? fInstance : new SpdEcalTB2GeoMapper(); } + +SpdEcalTB2GeoMapper* SpdEcalTB2GeoMapper::GetMapper() +{ return fInstance; } + +//_____________________________________________________________________________ +SpdEcalTB2GeoMapper::SpdEcalTB2GeoMapper():SpdGeoMapper("EcalTB") +{ + if (fInstance) { + Fatal("SpdEcalTB2GeoMapper", "Singleton instance already exists."); + return; + } + + fInstance = this; + + fParams = new TObjArray(); + fGeoVolPars = new TObjArray(); + fGeoTable = new SpdGeoTable(); + + fMasterVolName = SpdCommonGeoMapper::Instance()->GetMasterVolumeName(); + + fGeoType = SpdCommonGeoMapper::Instance()->GetEcalTBDefGeoType(); +} + +//_____________________________________________________________________________ +SpdEcalTB2GeoMapper::SpdEcalTB2GeoMapper(TString prefix):SpdGeoMapper(prefix) +{ + if (fInstance) { + Fatal("SpdEcalTB2GeoMapper", "Singleton instance already exists."); + return; + } + + fInstance = this; + + fParams = new TObjArray(); + fGeoVolPars = new TObjArray(); + fGeoTable = new SpdGeoTable(); + + fMasterVolName = SpdCommonGeoMapper::Instance()->GetMasterVolumeName(); + + fGeoType = SpdCommonGeoMapper::Instance()->GetEcalTBDefGeoType(); +} + +//_____________________________________________________________________________ +SpdEcalTB2GeoMapper::~SpdEcalTB2GeoMapper() +{ + +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::AddParameterFromCommon(TString parname, Int_t accessFunc(SpdCommonGeoMapper*), Bool_t reinit) +{ + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + SpdParameter* par = GetParameter(parname); + if (par) { if (reinit) *par = accessFunc(mapper); } + else fParams->Add(new SpdParameter(parname, accessFunc(mapper))); +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::AddParameterFromCommon(TString parname, Double_t accessFunc(SpdCommonGeoMapper*), Bool_t reinit) +{ + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + SpdParameter* par = GetParameter(parname); + if (par) { if (reinit) *par = accessFunc(mapper); } + else fParams->Add(new SpdParameter(parname, accessFunc(mapper))); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Values from CommonGeoMapper: +// +// EcalBarrelNSectors: number of sectors in barrel +// EcalBarrelLength [cm]: length of barrel part +// SectorClearance [cm]: minimum distance between modules of different sectors +// EcalBarrelRadius [cm]: shortest distance from Z axis to ECAL barrel basket +// EcalTBWidth2 [cm]: (meaningful only for EcalBarrelForceCellSize == false) the radial size of barrel basket. +// All modules are contained within the basket. Size and shape of modules is varied accordingly +// +// Some default values: +// +// EcalTBNBasketsZ: number of baskets in barrel in Z direction [default: 2] +// +// EcalBarrelForceCellSize (bool): +// - if TRUE, cell sizes are forced to be as defined with +// EcalCellPhiInnerSize/EcalCellPhiOuterSize/EcalCellThetaInnerSize/EcalCellThetaOuterSize; +// - if FALSE, cell sizes are calculated automatically to +// 1) minimize empty spaces between modules, and +// 2) to be as close to the defined variables +// EcalCellPhiInnerSize/EcalCellPhiOuterSize/EcalCellThetaInnerSize/EcalCellThetaOuterSize as possible +// +// EcalBarrelTrimModuleLength (bool): +// - if TRUE, the module length is calculated so that the module is fitted inside the basket; +// - if FALSE, the module size is fixed and defined by EcalModuleNLayers +// +// EcalCellPhiInnerSize [cm]: П†-size of inner size of barrel cell +// (if EcalBarrelForceCellSize is false, this defines rough dimensions) [default: 5.5] +// +// EcalCellPhiOuterSize [cm]: П†-size of outer size of barrel cell +// (if EcalBarrelForceCellSize is false, chosen automatically to minimize empty space) [default: 7.0] +// +// EcalCellThetaInnerSize [cm]: Оё(Z)-size of inner size of barrel cell +// (if EcalBarrelForceCellSize is false, this defines rough dimensions) [default: 5.5] +// +// EcalCellThetaOuterSize [cm]: Оё(Z)-size of outer size of barrel cell +// (if EcalBarrelForceCellSize is false, this defines rough dimensions) [default: 5.5] +// +// EcalBasketClearance [cm]: minimum distance between modules of different Z-baskets [default: 0.5] +// +// EcalModuleClearance [cm]: clearance between modules (2x2 cells) [default: 0.1] +// +// EcalCellClearance [cm]: clerance between cells in a module [default: 0.05] +// +// EcalModuleNLayers: (meaningful only for EcalBarrelForceCellSize == true or EcalBarrelTrimModuleLength == FALSE) +// number of layers in a module (same for barrel and endcap parts), [default: 200]. +// In case of EcalBarrelForceCellSize == FALSE and EcalBarrelTrimModuleLength == TRUE, for each module, +// maximum number of layers is calculated, for which the module stays within the basket. +// +// EcalAbsorberThickness [cm]: thickness of absorber layer (material hardcoded as lead) [default: 0.05] +// +// EcalScintThickness [cm]: thickness of scintillator layer (material hardcoded as polystyrene(?)) [default: 0.15] +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________ +Bool_t SpdEcalTB2GeoMapper::InitGeometry(Int_t gtype, Bool_t reinit) +{ + //cout << "-I- <SpdEcalTB2GeoMapper::InitGeometry> " << endl; + + if (fLockGeometry) { + cout << "-E- <SpdEcalTB2GeoMapper::InitGeometry> Geometry is locked " << endl; + return kFALSE; + } + + if (!fParams) return kFALSE; + if (fGeoTable) fGeoTable->Clear(); + if (fGeoVolPars) fGeoVolPars->Clear(); + + if (!CheckGeoType(gtype,"EcalTBGeoType")) return kFALSE; + + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + + AddParameterFromCommon("EcalBarrelNSectors", [](SpdCommonGeoMapper* m) {return m->GetNGeoSectors();}, reinit); + AddParameterFromCommon("EcalBarrelLength", [](SpdCommonGeoMapper* m) {return m->GetEcalTBLen2();}, reinit); + AddParameterFromCommon("EcalBarrelOuterSize", [](SpdCommonGeoMapper* m) {return m->GetEcalTBSize2();}, reinit); + AddParameterFromCommon("EcalBarrelWidth", [](SpdCommonGeoMapper* m) {return m->GetEcalTBWidth2();}, reinit); + AddParameterFromCommon("EcalTBWidth2", [](SpdCommonGeoMapper* m) {return m->GetEcalTBWidth2();}, reinit); + AddParameterFromCommon("SectorClearance", [](SpdCommonGeoMapper* m) {return m->GetSectorClearance();}, reinit); + + //sanity check of parameters + //barrelLength/2 should not be larger than distance to endcaps + + SpdParameter* par; + + Int_t nsectors(-1); + par = GetParameter("EcalBarrelNSectors"); + if (par) par->Value(nsectors); + if (nsectors != -1 && nsectors < 3) { + cout << "-F- <SpdEcalTB2GeoMapper::InitGeometry> " + << "Cannot map ECAL geometry: nsectors should be >=3 (recommended >= 6)" << endl; + exit(1); + } + + Double_t thetaInnerSize(-1.), thetaOuterSize(-1.); + Bool_t forceSize(false); + + par = GetParameter("EcalCellThetaInnerSize"); if (par) par->Value(thetaInnerSize); + par = GetParameter("EcalCellThetaOuterSize"); if (par) par->Value(thetaOuterSize); + par = GetParameter("EcalBarrelForceCellSize"); if (par) par->Value(forceSize); + + if (thetaInnerSize != -1. && thetaOuterSize != -1. && par && thetaInnerSize != thetaOuterSize && forceSize) { + cout << "-F- <SpdEcalTB2GeoMapper::InitGeometry> " + << "Cannot map ECAL geometry: theta(Z) inner size != theta(Z) outer size (while forced size): " + << "projective geometry support is not implemented yet!" << endl; + exit(1); + } + + if (thetaInnerSize != -1. && thetaOuterSize != -1. && thetaInnerSize != thetaOuterSize) { + cout << "-W- <SpdEcalTB2GeoMapper::InitGeometry> " + << "theta(Z) inner size != theta(Z) outer size (size not forced): " + << "as a guideline for theta (Z) size is chosen as inner size = " << thetaInnerSize << " cm" << endl; + } + + Double_t phiInnerSize(-1.), phiOuterSize(-1.); + + par = GetParameter("EcalCellPhiInnerSize"); if (par) par->Value(phiInnerSize); + par = GetParameter("EcalCellPhiOuterSize"); if (par) par->Value(phiOuterSize); + par = GetParameter("EcalBarrelForceCellSize"); + + if (phiInnerSize != -1. && phiOuterSize != -1. && par && phiInnerSize > phiOuterSize && forceSize) { + cout << "-F- <SpdEcalTB2GeoMapper::InitGeometry> " + << "Cannot map ECAL geometry: phi inner size > phi outer size (while forcing size): " + << "this gives undefined behaviour and is not recommended" << endl; + exit(1); + } + + SpdParameter* par2; + + Int_t nLayers(-1); + Bool_t trimModule(false); + + par = GetParameter("EcalModuleNLayers"); if (par) par->Value(nLayers); + par = GetParameter("EcalBarrelForceCellSize"); + par2 = GetParameter("EcalBarrelTrimModuleLength"); if (par2) par2->Value(trimModule); + + if (nLayers != -1 && par && par2 && !forceSize && trimModule) { + cout << "-W- <SpdEcalTB2GeoMapper::InitGeometry> Automatical selection of cell size is chosen " + << "(EcalBarrelForceCellSize = false && EcalBarrelTrimModuleLength == true): " + << "number of layers in each module will be calculated automatically! " + << "(setting EcalModuleNLayers is meaningless) " << endl; + } + + if (nLayers != -1 && par && !par2 && !forceSize) { + cout << "-W- <SpdEcalTB2GeoMapper::InitGeometry> Automatical selection of cell size is chosen " + << "(EcalBarrelForceCellSize = false && EcalBarrelTrimModuleLength == true (by default)): " + << "number of layers in each module will be calculated automatically! " + << "(setting EcalModuleNLayers is meaningless) " << endl; + } + + if (nLayers != -1 && !par && !par2) { + cout << "-W- <SpdEcalTB2GeoMapper::InitGeometry> Automatical selection of cell size is chosen " + << "(EcalBarrelForceCellSize = false (by default) && EcalBarrelTrimModuleLength == true (by default)): " + << "number of layers in each module will be calculated automatically! " + << "(setting EcalModuleNLayers is meaningless) " << endl; + } + + if (nLayers != -1 && !par && par2 && trimModule) { + cout << "-W- <SpdEcalTB2GeoMapper::InitGeometry> Automatical selection of cell size is chosen " + << "(EcalBarrelForceCellSize = false (by default) && EcalBarrelTrimModuleLength == true): " + << "number of layers in each module will be calculated automatically! " + << "(setting EcalModuleNLayers is meaningless) " << endl; + } + + Double_t moduleLength(-1.); + + par = GetParameter("EcalTBWidth2"); if (par) par->Value(moduleLength); + par = GetParameter("EcalBarrelTrimModuleLength"); + + if (par && moduleLength != -1. && moduleLength != mapper->GetEcalTBWidth2() && !trimModule) { + cout << "-W- <SpdEcalTB2GeoMapper::InitGeometry> : manual selection of cell length is chosen " + << "(EcalBarrelTrimModuleLength = false): cell length is calculated using " + << "EcalModuleNLayers/EcalAbsorberThickness/EcalScintThickness " + << "(changing EcalTBWidth2 WILL NOT change simulation) " << endl; + } + if (!par && moduleLength != -1. && moduleLength != mapper->GetEcalTBWidth2()) { + cout << "-W- <SpdEcalTB2GeoMapper::InitGeometry> : manual selection of cell length is chosen " + << "(EcalBarrelTrimModuleLength = false): cell length is calculated using " + << "EcalModuleNLayers/EcalAbsorberThickness/EcalScintThickness " + << "(changing EcalTBWidth2 WILL NOT change simulation) " << endl; + } + + par = GetParameter("EcalTBNBasketsZ"); + if (par) { if (reinit) *par = 2; } + else { fParams->Add(new SpdParameter("EcalTBNBasketsZ", 2)); } + + par = GetParameter("EcalCellPhiInnerSize"); + if (par) { if (reinit) *par = 5.5; } + else { fParams->Add(new SpdParameter("EcalCellPhiInnerSize", 5.5)); } + + par = GetParameter("EcalCellPhiOuterSize"); + if (par) { if (reinit) *par = 7.0; } + else { fParams->Add(new SpdParameter("EcalCellPhiOuterSize", 7.0)); } + + par = GetParameter("EcalCellThetaInnerSize"); + if (par) { if (reinit) *par = 5.5; } + else { fParams->Add(new SpdParameter("EcalCellThetaInnerSize", 5.5)); } + + par = GetParameter("EcalCellThetaOuterSize"); + if (par) { if (reinit) *par = 5.5; } + else { fParams->Add(new SpdParameter("EcalCellThetaOuterSize", 5.5)); } + + par = GetParameter("EcalBasketClearance"); + if (par) { if (reinit) *par = 0.5; } + else { fParams->Add(new SpdParameter("EcalBasketClearance", 0.5)); } + + par = GetParameter("EcalModuleClearance"); + if (par) { if (reinit) *par = 0.1; } + else { fParams->Add(new SpdParameter("EcalModuleClearance", 0.1)); } + + par = GetParameter("EcalCellClearance"); + if (par) { if (reinit) *par = 0.05; } + else { fParams->Add(new SpdParameter("EcalCellClearance", 0.05)); } + + par = GetParameter("EcalBarrelMaxTheta"); + if (par) { if (reinit) *par = 0.0; } + else { fParams->Add(new SpdParameter("EcalBarrelMaxTheta", 0.0)); } + + par = GetParameter("EcalModuleNLayers"); + if (par) { if (reinit) *par = 200; } + else { fParams->Add(new SpdParameter("EcalModuleNLayers", 200)); } + + par = GetParameter("EcalAbsorberThickness"); + if (par) { if (reinit) *par = 0.05; } + else { fParams->Add(new SpdParameter("EcalAbsorberThickness", 0.05)); } + + par = GetParameter("EcalScintThickness"); + if (par) { if (reinit) *par = 0.15; } + else { fParams->Add(new SpdParameter("EcalScintThickness", 0.15)); } + + par = GetParameter("EcalBarrelForceCellSize"); + if (par) { if (reinit) *par = false; } + else { fParams->Add(new SpdParameter("EcalBarrelForceCellSize", false)); } + + par = GetParameter("EcalBarrelTrimModuleLength"); + if (par) { if (reinit) *par = false; } + else { fParams->Add(new SpdParameter("EcalBarrelTrimModuleLength", false)); } + + par = GetParameter("EcalBarrelBaseMedium"); + if (par) { if (reinit) *par = "air"; } + else { fParams->Add(new SpdParameter("EcalBarrelBaseMedium", "air")); } + + par = GetParameter("EcalBarrelAbsorberMedium"); + if (par) { if (reinit) *par = "lead"; } + else { fParams->Add(new SpdParameter("EcalBarrelAbsorberMedium", "lead")); } + + par = GetParameter("EcalBarrelScintMedium"); + if (par) { if (reinit) *par = "FscScint"; } + else { fParams->Add(new SpdParameter("EcalBarrelScintMedium", "FscScint")); } + + return kTRUE; +} + +/* + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ++++++++++++++++++++++++++++++++ GETTERS ++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + +//_____________________________________________________________________________ +TString SpdEcalTB2GeoMapper::GetBaseMedium() const +{ + const SpdParameter* par = GetParameter("EcalBarrelBaseMedium"); + const Char_t* value = par->Value(); + return TString(value); +} + +//_____________________________________________________________________________ +TString SpdEcalTB2GeoMapper::GetAbsorberMedium() const +{ + const SpdParameter* par = GetParameter("EcalBarrelAbsorberMedium"); + const Char_t* value = par->Value(); + return TString(value); +} + +//_____________________________________________________________________________ +TString SpdEcalTB2GeoMapper::GetScintMedium() const +{ + const SpdParameter* par = GetParameter("EcalBarrelScintMedium"); + const Char_t* value = par->Value(); + return TString(value); +} + +//_____________________________________________________________________________ +Bool_t SpdEcalTB2GeoMapper::IsForceCellSize() const +{ + const SpdParameter* par = GetParameter("EcalBarrelForceCellSize"); + Bool_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Bool_t SpdEcalTB2GeoMapper::IsTrimModuleLength() const +{ + const SpdParameter* par = GetParameter("EcalBarrelTrimModuleLength"); + Bool_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Int_t SpdEcalTB2GeoMapper::GetNLayers() const +{ + const SpdParameter* par = GetParameter("EcalModuleNLayers"); + Int_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetBarrelModuleRadialSize() const +{ + const SpdParameter* par = GetParameter("EcalTBWidth2"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetBarrelWidth() const +{ + const SpdParameter* par = GetParameter("EcalBarrelWidth"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetBarrelOuterSize() const +{ + const SpdParameter* par = GetParameter("EcalBarrelOuterSize"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetLayerInnerSizeTheta() const +{ + const SpdParameter* par = GetParameter("EcalCellThetaInnerSize"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetLayerInnerSizePhi() const +{ + const SpdParameter* par = GetParameter("EcalCellPhiInnerSize"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetLayerOuterSizeTheta() const +{ + const SpdParameter* par = GetParameter("EcalCellThetaOuterSize"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetLayerOuterSizePhi() const +{ + const SpdParameter* par = GetParameter("EcalCellPhiOuterSize"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetLayer1SizeZ() const +{ + const SpdParameter* par = GetParameter("EcalAbsorberThickness"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetLayer2SizeZ() const +{ + const SpdParameter* par = GetParameter("EcalScintThickness"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetBarrelLength() const +{ + const SpdParameter* par = GetParameter("EcalBarrelLength"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetBarrelMaxTheta() const +{ + const SpdParameter* par = GetParameter("EcalBarrelMaxTheta"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetBasketClearance() const +{ + const SpdParameter* par = GetParameter("EcalBasketClearance"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetCellClearance() const +{ + const SpdParameter* par = GetParameter("EcalCellClearance"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetModuleClearance() const +{ + const SpdParameter* par = GetParameter("EcalModuleClearance"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTB2GeoMapper::GetSectorClearance() const +{ + const SpdParameter* par = GetParameter("SectorClearance"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Int_t SpdEcalTB2GeoMapper::GetNSectors() const +{ + const SpdParameter* par = GetParameter("EcalBarrelNSectors"); + Int_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +/* + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ++++++++++++++++++++++++++++++++ SETTERS ++++++++++++++++++++++++++++++++++++++ + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetForceInsideBasket(Bool_t value) +{ + SpdParameter* par = GetParameter("EcalBarrelTrimModuleLength"); + if (!par) fParams->Add(new SpdParameter("EcalBarrelTrimModuleLength",value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetForceInsideBasket> Overwriting parameter \"EcalBarrelTrimModuleLength\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetForceCellSize(Bool_t value) +{ + SpdParameter* par = GetParameter("EcalBarrelForceCellSize"); + if (!par) fParams->Add(new SpdParameter("EcalBarrelForceCellSize", value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetForceCellSize> Overwriting parameter \"EcalBarrelForceCellSize\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetCellZSize(Double_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTB2GeoMapper::SetCellZSize> Cell z size should be > 0" << endl; + exit(1); + } + + if (value > SpdCommonGeoMapper::Instance()->GetEcalTBLen2()) { + cout << "-W- <SpdEcalTB2GeoMapper::SetCellSize> " + << "cell z size is more than barrel length, " + << "recommended decreasing cell z size " << endl; + } + + SpdParameter* par = GetParameter("EcalCellThetaInnerSize"); + if (!par) fParams->Add(new SpdParameter("EcalCellThetaInnerSize", value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetCellZSize> Overwriting parameter \"EcalCellThetaInnerSize\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetCellInnerPhiSize(Double_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTB2GeoMapper::SetCellInnerPhiSize> Cell phi size should be > 0" << endl; + exit(1); + } + + if (value > SpdCommonGeoMapper::Instance()->GetEcalTBSize2()) { + cout << "-W- <SpdEcalTB2GeoMapper::SetCellInnerPhiSize> " + << "Cell phi inner size is more than barrel outer radius, " + << "recommended decreasing cell phi inner size " << endl; + } + + SpdParameter* par = GetParameter("EcalCellPhiInnerSize"); + if (!par) fParams->Add(new SpdParameter("EcalCellPhiInnerSize", value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetCellInnerPhiSize> Overwriting parameter \"EcalCellPhiInnerSize\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetCellOuterPhiSize(Double_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTB2GeoMapper::SetCellOuterPhiSize> Cell phi size should be > 0" << endl; + exit(1); + } + + if (value > SpdCommonGeoMapper::Instance()->GetEcalTBSize2()) { + cout << "-W- <SpdEcalTB2GeoMapper::SetCellOuterPhiSize> " + << "Cell phi inner size is more than barrel outer radius, " + << "recommended decreasing cell phi inner size " << endl; + } + + SpdParameter* par = GetParameter("EcalCellPhiOuterSize"); + if (!par) fParams->Add(new SpdParameter("EcalCellPhiOuterSize",value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetCellOuterPhiSize> Overwriting parameter \"EcalCellPhiOuterSize\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetNLayers(Int_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTB2GeoMapper::SetNLayers> Number of layers should be > 0" << endl; + exit(1); + } + + SpdParameter* par = GetParameter("EcalModuleNLayers"); + if (!par) fParams->Add(new SpdParameter("EcalModuleNLayers", value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetNLayers> Overwriting parameter \"EcalModuleNLayers\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetAbsorberLayerThickness(Double_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTB2GeoMapper::SetAbsorberLayerThickness> Absorber layer thickness should be > 0" << endl; + exit(1); + } + + SpdParameter* par = GetParameter("EcalAbsorberThickness"); + if (!par) fParams->Add(new SpdParameter("EcalAbsorberThickness", value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetAbsorberLayerThickness> Overwriting parameter \"EcalAbsorberThickness\"" << endl; + } + +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetScintLayerThickness(Double_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTB2GeoMapper::SetScintLayerThickness> Scintillator layer thickness should be > 0" << endl; + exit(1); + } + + SpdParameter* par = GetParameter("EcalScintThickness"); + if (!par) fParams->Add(new SpdParameter("EcalScintThickness", value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetScintLayerThickness> Overwriting parameter \"EcalScintThickness\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetCellClearance(Double_t value) +{ + if (value < 0) { + cout << "-F- <SpdEcalTB2GeoMapper::SetCellClearance> Cell clearance should be >= 0" << endl; + exit(1); + } + + SpdParameter* par = GetParameter("EcalCellClearance"); + if (!par) fParams->Add(new SpdParameter("EcalCellClearance",value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetCellClearance> Overwriting parameter \"EcalCellClearance\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::SetModuleClearance(Double_t value) +{ + if (value < 0) { + cout << "-F- <SpdEcalTB2GeoMapper::SetModuleClearance> Module clearance should be >= 0" << endl; + exit(1); + } + + SpdParameter* par = GetParameter("EcalModuleClearance"); + if (!par) fParams->Add(new SpdParameter("EcalModuleClearance",value)); + else { + *par = value; + cout << "-W- <SpdEcalTB2GeoMapper::SetModuleClearance> Overwriting parameter \"EcalModuleClearance\"" << endl; + } +} + +//_____________________________________________________________________________ +void SpdEcalTB2GeoMapper::Print(Option_t*) const +{ + cout << "-I- <SpdEcalTB2GeoMapper::Print>" << "\n\n"; + SpdGeoMapper::Print(""); +} + + + + + + + + diff --git a/spdgeometry/ecalt/SpdEcalTB2GeoMapper.h b/spdgeometry/ecalt/SpdEcalTB2GeoMapper.h new file mode 100644 index 0000000000000000000000000000000000000000..ea5c30d726a2fe369826c772a5e5711c25aab9de --- /dev/null +++ b/spdgeometry/ecalt/SpdEcalTB2GeoMapper.h @@ -0,0 +1,100 @@ +// $Id$ +// Author: andre/artur 2020/07/31 + +#ifndef __SPDECALTB2GEOMAPPER_H__ +#define __SPDECALTB2GEOMAPPER_H__ + +#include <TObjArray.h> + +#include "SpdGeoMapper.h" +#include "SpdCommonGeoMapper.h" + +class TString; + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdEcalTB2GeoMapper // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdEcalTB2GeoMapper: public SpdGeoMapper { + +public: + + SpdEcalTB2GeoMapper(); + SpdEcalTB2GeoMapper(TString prefix); + + virtual ~SpdEcalTB2GeoMapper(); + + static SpdEcalTB2GeoMapper* Instance(); + static SpdEcalTB2GeoMapper* GetMapper(); + + virtual Bool_t InitGeometry(Int_t gtype = -1, Bool_t reinit = kFALSE); + + /* Getters */ + + Int_t GetNLayers() const; + Int_t GetNSectors() const; + + Double_t GetBarrelLength() const; + Double_t GetBarrelMaxTheta() const; + Double_t GetBarrelWidth() const; + Double_t GetBarrelOuterSize() const; + + Double_t GetSectorClearance() const; + Double_t GetBasketClearance() const; + Double_t GetModuleClearance() const; + Double_t GetCellClearance() const; + + Double_t GetBarrelModuleRadialSize() const; + + Double_t GetLayerInnerSizeTheta() const; + Double_t GetLayerInnerSizePhi() const; + Double_t GetLayerOuterSizeTheta() const; + Double_t GetLayerOuterSizePhi() const; + Double_t GetLayer1SizeZ() const; + Double_t GetLayer2SizeZ() const; + + Bool_t IsForceCellSize() const; + Bool_t IsTrimModuleLength() const; + + TString GetBaseMedium() const; + TString GetAbsorberMedium() const; + TString GetScintMedium() const; + + /* Setters */ + void SetForceInsideBasket(Bool_t value); + void SetForceCellSize(Bool_t value); + + void SetCellZSize(Double_t value); + void SetCellInnerPhiSize(Double_t value); + void SetCellOuterPhiSize(Double_t value); + + void SetNLayers(Int_t value); + + void SetAbsorberLayerThickness(Double_t value); + void SetScintLayerThickness(Double_t value); + + void SetCellClearance(Double_t value); + void SetModuleClearance(Double_t value); + + virtual void Print(Option_t*) const; + +protected: + + /* data members */ + static SpdEcalTB2GeoMapper* fInstance; + + TString fMasterVolName; + + void AddParameterFromCommon(TString parname, Int_t accessFunc(SpdCommonGeoMapper*), Bool_t reinit); + void AddParameterFromCommon(TString parname, Double_t accessFunc(SpdCommonGeoMapper*), Bool_t reinit); + + ClassDef(SpdEcalTB2GeoMapper,1) +}; + +#endif /* __SPDECALTB2GEOMAPPER_H__ */ + + diff --git a/spdgeometry/ecalt/SpdEcalTEC2GeoMapper.cxx b/spdgeometry/ecalt/SpdEcalTEC2GeoMapper.cxx new file mode 100644 index 0000000000000000000000000000000000000000..dc921483e6cbe896e9d6f9c648af91d43473cdeb --- /dev/null +++ b/spdgeometry/ecalt/SpdEcalTEC2GeoMapper.cxx @@ -0,0 +1,457 @@ +// $Id$ +// Author: andre/artur 2020/07/31 + +//_____________________________________________________________________________ +// +// SpdEcalTEC2GeoMapper +//_____________________________________________________________________________ + +#include "SpdEcalTEC2GeoMapper.h" +#include "SpdCommonGeoMapper.h" +#include <TString.h> +#include <TMath.h> +#include <iostream> + +using std::cout; +using std::endl; + +using namespace TMath; + +ClassImp(SpdEcalTEC2GeoMapper) + +SpdEcalTEC2GeoMapper* SpdEcalTEC2GeoMapper::fInstance = 0; + +SpdEcalTEC2GeoMapper* SpdEcalTEC2GeoMapper::Instance() +{ return (fInstance) ? fInstance : new SpdEcalTEC2GeoMapper(); } + +SpdEcalTEC2GeoMapper* SpdEcalTEC2GeoMapper::GetMapper() +{ return fInstance; } + +//_____________________________________________________________________________ +SpdEcalTEC2GeoMapper::SpdEcalTEC2GeoMapper():SpdGeoMapper("EcalTEC") +{ + if (fInstance) { + Fatal("SpdEcalTEC2GeoMapper", "Singleton instance already exists."); + return; + } + + fInstance = this; + + fParams = new TObjArray(); + fGeoVolPars = new TObjArray(); + fGeoTable = new SpdGeoTable(); + + fMasterVolName = SpdCommonGeoMapper::Instance()->GetMasterVolumeName(); + + fGeoType = SpdCommonGeoMapper::Instance()->GetEcalTECDefGeoType(); +} + +//_____________________________________________________________________________ +SpdEcalTEC2GeoMapper::SpdEcalTEC2GeoMapper(TString prefix):SpdGeoMapper(prefix) +{ + if (fInstance) { + Fatal("SpdEcalTEC2GeoMapper", "Singleton instance already exists."); + return; + } + + fInstance = this; + + fParams = new TObjArray(); + fGeoVolPars = new TObjArray(); + fGeoTable = new SpdGeoTable(); + + fMasterVolName = SpdCommonGeoMapper::Instance()->GetMasterVolumeName(); + + fGeoType = SpdCommonGeoMapper::Instance()->GetEcalTECDefGeoType(); +} + +//_____________________________________________________________________________ +SpdEcalTEC2GeoMapper::~SpdEcalTEC2GeoMapper() +{ + +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::UnsetMaterials(Bool_t precise, TString option) +{ + if (fLockGeometry) { + cout << "-E- <SpdEcalTEC2GeoMapper::UnsetMaterials> Geometry is locked " << endl; + return; + } +} + +//_____________________________________________________________________________ +Bool_t SpdEcalTEC2GeoMapper::IsGeoTypeDefined(Int_t gtype) const +{ + return (gtype > 0 && gtype < 2); +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::AddParameterFromCommon(TString parname, Int_t accessFunc(SpdCommonGeoMapper*), Bool_t reinit) +{ + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + SpdParameter* par = GetParameter(parname); + if (par) { if (reinit) *par = accessFunc(mapper); } + else fParams->Add(new SpdParameter(parname, accessFunc(mapper))); +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::AddParameterFromCommon(TString parname, Double_t accessFunc(SpdCommonGeoMapper*), Bool_t reinit) +{ + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + SpdParameter* par = GetParameter(parname); + if (par) { if (reinit) *par = accessFunc(mapper); } + else fParams->Add(new SpdParameter(parname, accessFunc(mapper))); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Values from CommonGeoMapper: +// +// EcalTECMinDist1 [cm]: fabs(Z) of the front face of endcap cell +// (distance bewteen Z = 0 plane and endcap front face plane) +// +// Endcap is made in octagonal shape with a hole. It has two parameters: +// +// EcalTECSize [cm]: distance between center of endcap and the middle of octagon edge +// EcalTECWidth [cm]: distance between centers of edges of middle and outer octagon (for same П†) +// EcalTECThickness [cm]: thickness of endcap cell (first-level geometry) +// +// Some default values +// +// EcalECModuleClearance [cm]: clearance between modules (2x2 cells) (default: 0.1) +// EcalECCellClearance [cm]: clerance between cells in a module (default: 0.05) +// EcalECCellSize [cm]: X/Y size of endcap cell (default: 5.5) +// EcalECAbsorberThickness [cm]: thickness of absorber layer (material hardcoded as lead) (default: 0.05) +// EcalECScintThickness [cm]: thickness of scintillator layer (material hardcoded as polystyrene(?)) (default: 0.15) +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +//_____________________________________________________________________________ +Bool_t SpdEcalTEC2GeoMapper::InitGeometry(Int_t gtype, Bool_t reinit) +{ + //cout << "-I- <SpdEcalTEC2GeoMapper::InitGeometry> " << endl; + + if (fLockGeometry) { + cout << "-E- <SpdEcalTEC2GeoMapper::InitGeometry> Geometry is locked " << endl; + return kFALSE; + } + + if (!fParams) return kFALSE; + + if (!CheckGeoType(gtype,"EcalTECGeoType")) return kFALSE; + + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + + SpdParameter* par; + + /* set BASE material */ + + par = GetParameter("EcalECBaseMedium"); + if (par) { if (reinit) *par = mapper->GetEcalTECBaseMaterial(); } + else fParams->Add(new SpdParameter("EcalECBaseMedium",mapper->GetEcalTECBaseMaterial())); + + /* set BASE dimensions */ + + AddParameterFromCommon("EcalTECMinDist1", [](SpdCommonGeoMapper* m) { return m->GetEcalTECMinDist1(); }, reinit); + AddParameterFromCommon("EcalTECSize", [](SpdCommonGeoMapper* m) { return m->GetEcalTECSize(); }, reinit); + AddParameterFromCommon("EcalTECWidth", [](SpdCommonGeoMapper* m) { return m->GetEcalTECWidth(); }, reinit); + AddParameterFromCommon("EcalTECThickness", [](SpdCommonGeoMapper* m) { return m->GetEcalTECThickness(); }, reinit); + +// par = GetParameter("EcalTECMinDist1"); +// if (par) { if (reinit) *par = mapper->GetEcalTECMinDist1(); } +// else { fParams->Add(new SpdParameter("EcalTECMinDist1",mapper->GetEcalTECMinDist1())); } +// +// par = GetParameter("EcalTECSize"); +// if (par) { if (reinit) *par = mapper->GetEcalTECSize(); } +// else { fParams->Add(new SpdParameter("EcalTECSize",mapper->GetEcalTECSize())); } +// +// par = GetParameter("EcalTECWidth"); +// if (par) { if (reinit) *par = mapper->GetEcalTECWidth(); } +// else { fParams->Add(new SpdParameter("EcalTECWidth",mapper->GetEcalTECWidth())); } +// +// par = GetParameter("EcalTECThickness"); +// if (par) { if (reinit) *par = mapper->GetEcalTECThickness(); } +// else { fParams->Add(new SpdParameter("EcalTECThickness",mapper->GetEcalTECThickness())); } + + //sanity check of parameters + //barrelLength/2 should not be larger than distance to endcaps + + Double_t endcapSize(-1), endcapWidth(-2); + + par = GetParameter("EcalTECSize"); + if (par) par->Value(endcapSize); + + par = GetParameter("EcalTECWidth"); + if (par) par->Value(endcapWidth); + + if (endcapSize < 0 || endcapWidth < 0 || endcapSize < endcapWidth) { + cout << "-F- <SpdEcalTEC2GeoMapper::InitGeometry> " + << " Cannot map ECAL geometry! ECAL endcap size < ECAL endcap width: doesn't make sense! " <<endl; + exit(1); + } + + /* define materials */ + TString material; + + material = "lead"; + par = GetParameter("EcalECAbsorberMedium"); + if (par) { if (reinit) *par = material; } + else fParams->Add(new SpdParameter("EcalECAbsorberMedium",material)); + + material = "FscScint"; + par = GetParameter("EcalECScintMedium"); + if (par) { if (reinit) *par = material; } + else { fParams->Add(new SpdParameter("EcalECScintMedium",material)); } + + /* define dimensions */ + + par = GetParameter("EcalECModuleClearance"); + if (par) { if (reinit) *par = 0.1;} + else { fParams->Add(new SpdParameter("EcalECModuleClearance", 0.1)); } + + par = GetParameter("EcalECCellClearance"); + if (par) { if (reinit) *par = 0.05; } + else { fParams->Add(new SpdParameter("EcalECCellClearance", 0.05)); } + + par = GetParameter("EcalECCellSize"); + if (par) { if (reinit) *par = 5.5; } + else { fParams->Add(new SpdParameter("EcalECCellSize", 5.5)); } + + par = GetParameter("EcalECAbsorberThickness"); + if (par) { if (reinit) *par = 0.05; } + else { fParams->Add(new SpdParameter("EcalECAbsorberThickness", 0.05)); } + + par = GetParameter("EcalECScintThickness"); + if (par) { if (reinit) *par = 0.15; } + else { fParams->Add(new SpdParameter("EcalECScintThickness", 0.15)); } + + return kTRUE; +} + +//_____________________________________________________________________________ +TString SpdEcalTEC2GeoMapper::GetBaseMedium() const +{ + const SpdParameter* par = GetParameter("EcalECBaseMedium"); + const Char_t* value = par->Value(); + return TString(value); +} + +//_____________________________________________________________________________ +TString SpdEcalTEC2GeoMapper::GetAbsorberMedium() const +{ + const SpdParameter* par = GetParameter("EcalECAbsorberMedium"); + const Char_t* value = par->Value(); + return TString(value); +} + +//_____________________________________________________________________________ +TString SpdEcalTEC2GeoMapper::GetScintMedium() const +{ + const SpdParameter* par = GetParameter("EcalECScintMedium"); + const Char_t* value = par->Value(); + return TString(value); +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetEndcapSize() const +{ + const SpdParameter* par = GetParameter("EcalTECSize"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetEndcapWidth() const +{ + const SpdParameter* par = GetParameter("EcalTECWidth"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetEndcapThickness() const +{ + const SpdParameter* par = GetParameter("EcalTECThickness"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetEndcapMinDist() const +{ + const SpdParameter* par = GetParameter("EcalTECMinDist1"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetLayer1SizeZ() const +{ + const SpdParameter* par = GetParameter("EcalECAbsorberThickness"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetLayer2SizeZ() const +{ + const SpdParameter* par = GetParameter("EcalECScintThickness"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetCellSize() const +{ + const SpdParameter* par = GetParameter("EcalECCellSize"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetCellClearance() const +{ + const SpdParameter* par = GetParameter("EcalECCellClearance"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +Double_t SpdEcalTEC2GeoMapper::GetModuleClearance() const +{ + const SpdParameter* par = GetParameter("EcalECModuleClearance"); + Double_t lmax = 0; + if (par) par->Value(lmax); + return lmax; +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::SetCellSize(Double_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTEC2GeoMapper::SetCellSize> cell size should be > 0" << endl; + exit(1); + } + + if (value > SpdCommonGeoMapper::Instance()->GetEcalTECSize()) { + cout << "-W- <SpdEcalTEC2GeoMapper::SetCellSize> Cell size of " + << value << " cm is more than the endcap size (" + << SpdCommonGeoMapper::Instance()->GetEcalTECSize() + << " cm), decreasing cell size is recommended " << endl; + } + + SpdParameter* par = GetParameter("EcalECCellSize"); + if (!par) fParams->Add(new SpdParameter("EcalECCellSize", value)); + else { + cout << "-I- <SpdEcalTEC2GeoMapper::SetCellSize> Overwriting parameter \"EcalECCellSize\" " << endl; + *par = value; + } +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::SetAbsorberLayerThickness(Double_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTEC2GeoMapper::SetAbsorberLayerThickness> Absorber layer thickness should be > 0" << endl; + exit(1); + } + + if (value > SpdCommonGeoMapper::Instance()->GetEcalTECThickness()/2) { + cout << "-W- <SpdEcalTEC2GeoMapper::SetAbsorberLayerThickness> Absorber layer thickness of " + << value << " cm is more than half of the endcap thickness (" + << SpdCommonGeoMapper::Instance()->GetEcalTECThickness()/2 + << " cm), decreasing layer width is recommended " << endl; + } + + SpdParameter* par = GetParameter("EcalECAbsorberThickness"); + if (!par) fParams->Add(new SpdParameter("EcalECAbsorberThickness", value)); + else { + cout << "-I- <SpdEcalTEC2GeoMapper::SetAbsorberLayerThickness> Overwriting parameter \"EcalECAbsorberThickness\" " << endl; + *par = value; + } +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::SetScintLayerThickness(Double_t value) +{ + if (value <= 0) { + cout << "-F- <SpdEcalTEC2GeoMapper::SetScintLayerThickness> Scintillator layer thickness should be > 0" << endl; + exit(1); + } + + if (value > SpdCommonGeoMapper::Instance()->GetEcalTECThickness()/2) { + cout << "-W- <SpdEcalTEC2GeoMapper::SetScintLayerThickness> Scintillator layer thickness of " + << value << " cm is more than half of the endcap thickness (" + << SpdCommonGeoMapper::Instance()->GetEcalTECThickness()/2 + << " cm), decreasing layer width is recommended " <<endl; + } + + SpdParameter* par = GetParameter("EcalECScintThickness"); + if (!par) fParams->Add(new SpdParameter("EcalECScintThickness", value)); + else { + cout << "-I- <SpdEcalTEC2GeoMapper::SetModuleClearance> Overwriting parameter \"EcalECScintThickness\" " << endl; + *par = value; + } +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::SetCellClearance(Double_t value) +{ + if (value < 0) { + cout << "-F- <SpdEcalTEC2GeoMapper::SetModuleClearance> Cell clearance should be >= 0" << endl; + exit(1); + } + + SpdParameter* par = GetParameter("EcalECCellClearance"); + if (!par) fParams->Add(new SpdParameter("EcalECCellClearance", value)); + else { + cout << "-I- <SpdEcalTEC2GeoMapper::SetModuleClearance> Overwriting parameter \"EcalECCellClearance\" " << endl; + *par = value; + } +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::SetModuleClearance(Double_t value) +{ + if (value < 0) { + cout << "-F- <SpdEcalTEC2GeoMapper::SetModuleClearance> Module clearance should be >= 0" << endl; + exit(1); + } + + SpdParameter* par = GetParameter("EcalECModuleClearance"); + if (!par) fParams->Add(new SpdParameter("EcalECModuleClearance", value)); + else { + cout << "-I- <SpdEcalTEC2GeoMapper::SetModuleClearance> Overwriting parameter \"EcalECModuleClearance\" " << endl; + *par = value; + } +} + +//_____________________________________________________________________________ +void SpdEcalTEC2GeoMapper::Print(Option_t*) const +{ + cout << "-I- <SpdEcalTEC2GeoMapper::Print>" << "\n\n"; + SpdGeoMapper::Print(""); +} + + + + + + + + + + + + + + diff --git a/spdgeometry/ecalt/SpdEcalTEC2GeoMapper.h b/spdgeometry/ecalt/SpdEcalTEC2GeoMapper.h new file mode 100644 index 0000000000000000000000000000000000000000..32d0fbeac708c4f4c208b26ec7e944b0fe6ee0b2 --- /dev/null +++ b/spdgeometry/ecalt/SpdEcalTEC2GeoMapper.h @@ -0,0 +1,80 @@ +// $Id$ +// Author: andre/artur 2020/07/31 + +#ifndef __SPDECALTEC2ECGEOMAPPER_H__ +#define __SPDECALTEC2ECGEOMAPPER_H__ + +#include <TObjArray.h> + +#include "SpdGeoMapper.h" +#include "SpdCommonGeoMapper.h" + +class TString; + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdEcalTEC2GeoMapper // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + + +class SpdEcalTEC2GeoMapper: public SpdGeoMapper { + +public: + + SpdEcalTEC2GeoMapper(); + SpdEcalTEC2GeoMapper(TString prefix); + + virtual ~SpdEcalTEC2GeoMapper(); + + static SpdEcalTEC2GeoMapper* Instance(); + static SpdEcalTEC2GeoMapper* GetMapper(); + + virtual Bool_t InitGeometry(Int_t gtype = -1, Bool_t reinit = kFALSE); + + /* getters */ + virtual Bool_t IsGeoTypeDefined(Int_t gtype) const; + + Double_t GetLayer1SizeZ() const; + Double_t GetLayer2SizeZ() const; + Double_t GetCellSize() const; + Double_t GetCellClearance() const; + Double_t GetModuleClearance() const; + Double_t GetEndcapMinDist() const; + Double_t GetEndcapThickness() const; + Double_t GetEndcapSize() const; + Double_t GetEndcapWidth() const; + + TString GetBaseMedium() const; + TString GetAbsorberMedium() const; + TString GetScintMedium() const; + + /* getters */ + virtual void UnsetMaterials(Bool_t precise = kTRUE, TString option = "base"); + + void SetCellSize(Double_t value); + void SetAbsorberLayerThickness(Double_t value); + void SetScintLayerThickness(Double_t value); + void SetCellClearance(Double_t value); + void SetModuleClearance(Double_t value); + + virtual void Print(Option_t*) const; + +protected: + + /* data members */ + static SpdEcalTEC2GeoMapper* fInstance; + + TString fMasterVolName; + + void AddParameterFromCommon(TString parname, Int_t accessFunc(SpdCommonGeoMapper*), Bool_t reinit); + void AddParameterFromCommon(TString parname, Double_t accessFunc(SpdCommonGeoMapper*), Bool_t reinit); + + ClassDef(SpdEcalTEC2GeoMapper,1) +}; + +#endif /* __SPDECALTEC2ECGEOMAPPER_H__ */ + + diff --git a/spdgeometry/its/SpdItsGeoBuilder.cxx b/spdgeometry/its/SpdItsGeoBuilder.cxx index 3e28dacf7895cb9a04d3451ef0b2b3fe5ab1473f..b67e7cbad1b757289c9be934a7c8dc67cbaec764 100644 --- a/spdgeometry/its/SpdItsGeoBuilder.cxx +++ b/spdgeometry/its/SpdItsGeoBuilder.cxx @@ -163,12 +163,21 @@ TGeoVolume* SpdItsGeoBuilder::BuildVolume(const SpdGeoVolPars* vpars) TGeoMedium* med = GetMedia(vpars->GetMedia()); - if (vpars->GetMedia() != med->GetName()) { + if (vpars->GetMedia() != med->GetName()) + { + static Bool_t media_is_changed = false; + if (!media_is_changed) { + cout << "-W- <SpdTsTBGeoBuilder::BuildVolume> +++++ ALL MATERIALS ARE SET AS -> " + << med->GetName() << " +++++ " << endl; + } + media_is_changed = true; + cout << "-W- <SpdItsGeoBuilder::BuildVolume> " << " Volume's \"" << vpars->GetName() << "\" " - << " media is changed : " << vpars->GetMedia() + << " media has been changed : " << vpars->GetMedia() <<" -> " << med->GetName() << endl; - //const_cast<SpdGeoVolPars*>(vpars)->SetActivity(0); // WARNING + + //const_cast<SpdGeoVolPars*>(vpars)->SetActivity(0); // WARNING } const_cast<SpdGeoVolPars*>(vpars)->SetMedia(med->GetName()); // WARNING @@ -321,14 +330,14 @@ Bool_t SpdItsGeoBuilder::GlobalToLocalP(const Double_t* gpnt, Double_t* lpnt) Bool_t SpdItsGeoBuilder::LocalToGlobalP(const Double_t* lpnt, Double_t* gpnt) { if (fVid < 0) return SpdGeoBuilder::LocalToGlobalP(lpnt,gpnt); - + SpdGeoVVolume* vvol = GetNodeVVolume(); if (!vvol) return kFALSE; TGeoNavigator* ntor = gGeoManager->GetCurrentNavigator(); if (!ntor) return kFALSE; - Double_t ploc[3] = {ploc[0], ploc[1], ploc[2]}; + Double_t ploc[3] = {lpnt[0], lpnt[1], lpnt[2]}; vvol->LocalToMaster(fVid,ploc[0],ploc[1],ploc[2]); ntor->LocalToMaster(ploc,gpnt); @@ -339,4 +348,4 @@ Bool_t SpdItsGeoBuilder::LocalToGlobalP(const Double_t* lpnt, Double_t* gpnt) - \ No newline at end of file + diff --git a/spdgeometry/its/SpdItsGeoMapperX.cxx b/spdgeometry/its/SpdItsGeoMapperX.cxx index 9aa8629423cf75ec0cd7e075984218d9e6ea1889..a830aa34ae0580ce8b61043d7ee900891e1a2253 100644 --- a/spdgeometry/its/SpdItsGeoMapperX.cxx +++ b/spdgeometry/its/SpdItsGeoMapperX.cxx @@ -332,7 +332,14 @@ void SpdItsGeoMapperX::UnsetMaterials(Bool_t precise, TString option) cout << "-E- <SpdItsGeoMapperX::UnsetMaterials> Geometry is locked " << endl; return; } - fUnsetMedia = "vacuumX"; + + if (option.IsWhitespace()) { fUnsetMedia = "vacuumX"; } + else if (option == "base") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX"; } + else if (option == "vacuum") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX"; } + else if (option == "air") { fUnsetMedia = "airX"; } + else { fUnsetMedia = option; } + + //cout << "-I- <SpdItsGeoMapperX::UnsetMaterials> Material: " << fUnsetMedia << endl; } //_____________________________________________________________________________ diff --git a/spdgeometry/its/SpdItsGeoMapperX.h b/spdgeometry/its/SpdItsGeoMapperX.h index bf92bac10c44829115aea18a38b83f1df416bda1..d2f90cc3650e34cec0ce0dc9c6462619ad772e26 100644 --- a/spdgeometry/its/SpdItsGeoMapperX.h +++ b/spdgeometry/its/SpdItsGeoMapperX.h @@ -35,7 +35,7 @@ public: virtual Bool_t InitGeometry(Int_t gtype = -1, Bool_t reinit = kFALSE); - virtual void UnsetMaterials(Bool_t precise = kTRUE, TString option = "base"); + virtual void UnsetMaterials(Bool_t precise = kTRUE, TString option = "base"); virtual Bool_t IsGeoTypeDefined(Int_t gtype) const; diff --git a/spdgeometry/rst/SpdRsTB2GeoMapper.cxx b/spdgeometry/rst/SpdRsTB2GeoMapper.cxx new file mode 100644 index 0000000000000000000000000000000000000000..980208e67d851537e1f51d8e5c08e58bc8f4b494 --- /dev/null +++ b/spdgeometry/rst/SpdRsTB2GeoMapper.cxx @@ -0,0 +1,330 @@ +// $Id$ +// Author: artur 2018/02/01 + +//_____________________________________________________________________________ +// +// SpdRsTB2GeoMapper +//_____________________________________________________________________________ + +#include "SpdRsTB2GeoMapper.h" +#include "SpdCommonGeoMapper.h" +#include <TMath.h> + +#include <iostream> + +using std::cout; +using std::endl; + +using namespace TMath; + +ClassImp(SpdRsTB2GeoMapper) + +SpdRsTB2GeoMapper* SpdRsTB2GeoMapper::fInstance = 0; + +SpdRsTB2GeoMapper* SpdRsTB2GeoMapper::Instance() +{ return (fInstance) ? fInstance : new SpdRsTB2GeoMapper(); } + +SpdRsTB2GeoMapper* SpdRsTB2GeoMapper::GetMapper() +{ return fInstance; } + +//_____________________________________________________________________________ +SpdRsTB2GeoMapper::SpdRsTB2GeoMapper():SpdGeoMapper("RsTB") +{ + if (fInstance) { + Fatal("SpdRsTB2GeoMapper", "Singleton instance already exists."); + return; + } + + fInstance = this; + + fParams = new TObjArray(); + + fGeoType = SpdCommonGeoMapper::Instance()->GetRsTBDefGeoType(); +} + +//_____________________________________________________________________________ +SpdRsTB2GeoMapper::SpdRsTB2GeoMapper(TString prefix):SpdGeoMapper(prefix) +{ + if (fInstance) { + Fatal("SpdRsTB2GeoMapper", "Singleton instance already exists."); + return; + } + + fInstance = this; + + fParams = new TObjArray(); + + fGeoType = SpdCommonGeoMapper::Instance()->GetRsTBDefGeoType(); +} + +//_____________________________________________________________________________ +SpdRsTB2GeoMapper::~SpdRsTB2GeoMapper() +{ + +} + +//_____________________________________________________________________________ +void SpdRsTB2GeoMapper::UnsetMaterials(Bool_t precise, TString option) +{ + if (fLockGeometry) { + cout << "-E- <SpdRsTB2GeoMapper::UnsetMaterials> Geometry is locked " << endl; + return; + } + + if (option.IsWhitespace()) { fUnsetMedia = "vacuumX"; } + else if (option == "base") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX"; } + else if (option == "vacuum") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX"; } + else if (option == "air") { fUnsetMedia = "airX"; } + else { fUnsetMedia = option; } +} + +// **************************************************************************** +// ********************* GETTERS (BEGIN) ************************************** +// **************************************************************************** + +//_____________________________________________________________________________ +TString SpdRsTB2GeoMapper::GetBaseMaterial() const +{ + const SpdParameter* par = GetParameter("RsTBBaseMaterial"); + return (par) ? par->Value() : ""; +} + +//_____________________________________________________________________________ +TString SpdRsTB2GeoMapper::GetAbsorbMaterial() const +{ + const SpdParameter* par = GetParameter("RsTBAbsorbMaterial"); + return (par) ? par->Value() : ""; +} + +//_____________________________________________________________________________ +TString SpdRsTB2GeoMapper::GetPassiveMaterialMDT() const +{ + const SpdParameter* par = GetParameter("RsTBPassiveMaterialMDT"); + return (par) ? par->Value() : ""; +} + +//_____________________________________________________________________________ +TString SpdRsTB2GeoMapper::GetActiveMaterialMDT() const +{ + const SpdParameter* par = GetParameter("RsTBActiveMaterialMDT"); + return (par) ? par->Value() : ""; +} + +//_____________________________________________________________________________ +Double_t SpdRsTB2GeoMapper::GetModuleLength() const +{ + const SpdParameter* par = GetParameter("RsTBLen"); + Double_t len = 0; + if (par) par->Value(len); + return len; +} + +//_____________________________________________________________________________ +Double_t SpdRsTB2GeoMapper::GetModuleSize() const +{ + const SpdParameter* par = GetParameter("RsTBSize"); + Double_t size = 0; + if (par) par->Value(size); + return size; +} + +//_____________________________________________________________________________ +Double_t SpdRsTB2GeoMapper::GetModuleWidth() const +{ + const SpdParameter* par = GetParameter("RsTBWidth"); + Double_t width = 0; + if (par) par->Value(width); + return width; +} + +//_____________________________________________________________________________ +Int_t SpdRsTB2GeoMapper::GetNLayers() const +{ + const SpdParameter* par = GetParameter("RsTBNLayers"); + Int_t nlayers = 0; + if (par) par->Value(nlayers); + return nlayers; +} + +//_____________________________________________________________________________ +Double_t SpdRsTB2GeoMapper::GetModuleHmin() const +{ + const SpdParameter* par = GetParameter("RsTBHmin"); + Double_t h = 0; + if (par) par->Value(h); + return h; +} + +//_____________________________________________________________________________ +Double_t SpdRsTB2GeoMapper::GetModuleHmax() const +{ + const SpdParameter* par = GetParameter("RsTBHmax"); + Double_t h = 0; + if (par) par->Value(h); + return h; +} + +//_____________________________________________________________________________ +Double_t SpdRsTB2GeoMapper::GetModuleLmin() const +{ + const SpdParameter* par = GetParameter("RsTBLmin"); + Double_t l = 0; + if (par) par->Value(l); + return l; +} + +//_____________________________________________________________________________ +Double_t SpdRsTB2GeoMapper::GetModuleLmax() const +{ + const SpdParameter* par = GetParameter("RsTBLmax"); + Double_t l = 0; + if (par) par->Value(l); + return l; +} + +//_____________________________________________________________________________ +Int_t SpdRsTB2GeoMapper::GetNSectors() const +{ + Int_t nsec; + const SpdParameter* par = GetParameter("RsTBNSectors"); + if (!par) return 0; + par->Value(nsec); + return nsec; +} + +//_____________________________________________________________________________ +Double_t SpdRsTB2GeoMapper::GetSecAngle() const +{ + Int_t nsec = GetNSectors(); + return (nsec > 0) ? 360./nsec: 0; +} + +//_____________________________________________________________________________ +Bool_t SpdRsTB2GeoMapper::IsGeoTypeDefined(Int_t gtype) const +{ + return (gtype > 0 && gtype < 3); +} + +// **************************************************************************** +// ********************* GETTERS (END) **************************************** +// **************************************************************************** + +//_____________________________________________________________________________ +Bool_t SpdRsTB2GeoMapper::InitGeometry(Int_t gtype, Bool_t reinit) +{ + if (fLockGeometry) { + cout << "-E- <SpdRsTB2GeoMapper::InitGeometry> Geometry is locked " << endl; + return kFALSE; + } + + if (!fParams) return kFALSE; + + if (!CheckGeoType(gtype,"RsTBGeoType")) return kFALSE; + + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + + SpdParameter* par; + + // ATTENTION Number of sectors -> FIXED! + const Int_t NUMBER_OF_SECTORS = 8; + par = GetParameter("RsTBNSectors"); + if (par) { if (reinit) *par = NUMBER_OF_SECTORS; } + else { fParams->Add(new SpdParameter("RsTBNSectors",NUMBER_OF_SECTORS)); } + + par = GetParameter("RsTBBaseMaterial"); + if (par) { if (reinit) *par = mapper->GetRsTBBaseMaterial(); } + else { fParams->Add(new SpdParameter("RsTBBaseMaterial",mapper->GetRsTBBaseMaterial())); } + + //cout << "-I- <SpdRsTB2GeoMapper::InitGeometry> reinit: " << reinit << endl; + + SetParameters(reinit); + + return kTRUE; +} + +//_____________________________________________________________________________ +void SpdRsTB2GeoMapper::SetParameters(Bool_t reinit) // private +{ + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + + SpdParameter* par; + + /* define module size */ + + par = GetParameter("RsTBLen"); + if (par) { if (reinit) *par = mapper->GetRsTBLen2(); } + else { fParams->Add(new SpdParameter("RsTBLen",mapper->GetRsTBLen2())); } + + Double_t size = mapper->GetRsTBSize2(); + par = GetParameter("RsTBSize"); + if (par) { if (reinit) *par = size; } + else { fParams->Add(new SpdParameter("RsTBSize",size)); } + + Double_t width = mapper->GetRsTBWidth2(); + par = GetParameter("RsTBWidth"); + if (par) { if (reinit) *par = width; } + else { fParams->Add(new SpdParameter("RsTBWidth",width)); } + + /* define materials */ + + TString material; + + material = "iron"; + par = GetParameter("RsTBAbsorbMaterial"); + if (par) { if (reinit) *par = material; } + else { fParams->Add(new SpdParameter("RsTBAbsorbMaterial",material)); } + + material = "aluminium"; + par = GetParameter("RsTBPassiveMaterialMDT"); + if (par) { if (reinit) *par = material; } + else { fParams->Add(new SpdParameter("RsTBPassiveMaterialMDT",material)); } + + material = "MDTMixture"; + par = GetParameter("RsTBActiveMaterialMDT"); + if (par) { if (reinit) *par = material; } + else { fParams->Add(new SpdParameter("RsTBActiveMaterialMDT",material)); } + + /* define secondary parameters */ + + Double_t angle = 0.5*GetSecAngle()*DegToRad(); + + Double_t hmin = size - width; + par = GetParameter("RsTBHmin"); + if (par) { *par = hmin; } + else { fParams->Add(new SpdParameter("RsTBHmin",hmin,1)); } + + Double_t hmax = size; + par = GetParameter("RsTBHmax"); + if (par) { *par = hmax; } + else { fParams->Add(new SpdParameter("RsTBHmax",hmax,1)); } + + Double_t lmin = 2.*hmin*Tan(angle); + par = GetParameter("RsTBHLmin"); + if (par) { *par = lmin; } + else { fParams->Add(new SpdParameter("RsTBLmin",lmin,2)); } + + Double_t lmax = 2.*hmax*Tan(angle); + par = GetParameter("RsTBLmax"); + if (par) { *par = lmax; } + else { fParams->Add(new SpdParameter("RsTBLmax",lmax,2)); } + + //---------------------------------------------------------------- + // Number of layers calcluation within RS thickness: + // (Thickness - top absorber - bottom absorber/mdt)/LayerThickness + 1(bottom layer) + + Int_t nLayers = Int_t((width - 6. - 9.5)/6.5) + 1; + par = GetParameter("RsTBNLayers"); + if (par) { *par = nLayers; } + else { fParams->Add(new SpdParameter("RsTBNLayers",nLayers,2)); } +} + +//_____________________________________________________________________________ +void SpdRsTB2GeoMapper::Print(Option_t*) const +{ + cout << "-I- <SpdRsTB2GeoMapper::Print>" << "\n\n"; + SpdGeoMapper::Print(""); +} + + + + diff --git a/spdgeometry/rst/SpdRsTB2GeoMapper.h b/spdgeometry/rst/SpdRsTB2GeoMapper.h new file mode 100644 index 0000000000000000000000000000000000000000..ba2b95670a86307f9799c2962cae14d6cc26f1a7 --- /dev/null +++ b/spdgeometry/rst/SpdRsTB2GeoMapper.h @@ -0,0 +1,71 @@ +// $Id$ +// Author: artur 2018/02/01 + +#ifndef __SPDRSTB2GEOMAPPER_H__ +#define __SPDRSTB2GEOMAPPER_H__ + +#include <TObjArray.h> + +#include "SpdGeoMapper.h" + +class TString; + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdRsTB2GeoMapper // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdRsTB2GeoMapper: public SpdGeoMapper { + +public: + + SpdRsTB2GeoMapper(); + SpdRsTB2GeoMapper(TString prefix); + + virtual ~SpdRsTB2GeoMapper(); + + static SpdRsTB2GeoMapper* Instance(); + static SpdRsTB2GeoMapper* GetMapper(); + + virtual Bool_t InitGeometry(Int_t gtype = -1, Bool_t reinit = kFALSE); + + virtual void UnsetMaterials(Bool_t precise = kTRUE, TString option = "base"); + + TString GetBaseMaterial() const; + TString GetAbsorbMaterial() const; + TString GetPassiveMaterialMDT() const; + TString GetActiveMaterialMDT() const; + + Double_t GetModuleLength() const; + Double_t GetModuleSize() const; + Double_t GetModuleWidth() const; + Int_t GetNLayers() const; + + Double_t GetModuleHmin() const; + Double_t GetModuleHmax() const; + Double_t GetModuleLmin() const; + Double_t GetModuleLmax() const; + + virtual Bool_t IsGeoTypeDefined(Int_t gtype) const; + + virtual void Print(Option_t*) const; + + Int_t GetNSectors() const; + Double_t GetSecAngle() const; // deg + +private: + + /* data members */ + static SpdRsTB2GeoMapper* fInstance; + + void SetParameters(Bool_t reinit); + + ClassDef(SpdRsTB2GeoMapper,1) +}; + +#endif /* __SPDRSTB2GEOMAPPER_H__ */ + + diff --git a/spdgeometry/rst/SpdRsTEC2GeoMapper.cxx b/spdgeometry/rst/SpdRsTEC2GeoMapper.cxx new file mode 100644 index 0000000000000000000000000000000000000000..23ed1ddcd43c445ce51f4c1735163b25b6b795af --- /dev/null +++ b/spdgeometry/rst/SpdRsTEC2GeoMapper.cxx @@ -0,0 +1,310 @@ +// $Id$ +// Author: alver 2020/07/17 + +//_____________________________________________________________________________ +// +// SpdRsTEC2GeoMapper +//_____________________________________________________________________________ + +#include "SpdRsTEC2GeoMapper.h" +#include "SpdCommonGeoMapper.h" + +#include <TMath.h> + +#include <iostream> + +using std::cout; +using std::endl; + +using namespace TMath; + +ClassImp(SpdRsTEC2GeoMapper) + +SpdRsTEC2GeoMapper* SpdRsTEC2GeoMapper::fInstance = 0; + +SpdRsTEC2GeoMapper* SpdRsTEC2GeoMapper::Instance() +{ return (fInstance) ? fInstance : new SpdRsTEC2GeoMapper(); } + +SpdRsTEC2GeoMapper* SpdRsTEC2GeoMapper::GetMapper() +{ return fInstance; } + +//_____________________________________________________________________________ +SpdRsTEC2GeoMapper::SpdRsTEC2GeoMapper():SpdGeoMapper("RsTEC") +{ + if (fInstance) { + Fatal("SpdRsTEC2GeoMapper", "Singleton instance already exists."); + return; + } + + fInstance = this; + + fParams = new TObjArray(); + + fGeoType = SpdCommonGeoMapper::Instance()->GetRsTECDefGeoType(); +} + +//_____________________________________________________________________________ +SpdRsTEC2GeoMapper::SpdRsTEC2GeoMapper(TString prefix):SpdGeoMapper(prefix) +{ + if (fInstance) { + Fatal("SpdRsTEC2GeoMapper", "Singleton instance already exists."); + return; + } + + fInstance = this; + + fParams = new TObjArray(); + + fGeoType = SpdCommonGeoMapper::Instance()->GetRsTECDefGeoType(); +} + +//_____________________________________________________________________________ +SpdRsTEC2GeoMapper::~SpdRsTEC2GeoMapper() +{ + +} + +//_____________________________________________________________________________ +void SpdRsTEC2GeoMapper::UnsetMaterials(Bool_t precise, TString option) +{ + if (fLockGeometry) { + cout << "-E- <SpdRsTEC2GeoMapper::UnsetMaterials> Geometry is locked " << endl; + return; + } + + if (option.IsWhitespace()) { fUnsetMedia = "vacuumX"; } + else if (option == "base") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX"; } + else if (option == "vacuum") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX"; } + else if (option == "air") { fUnsetMedia = "airX"; } + else { fUnsetMedia = option; } + + SpdParameter* par; + + par = GetParameter("RsTEC2BaseMaterial"); + if (!par) { fParams->Add(new SpdParameter("RsTECBaseMaterial",fUnsetMedia)); } + else { *par = fUnsetMedia; } + + par = GetParameter("RsTECAbsorbMaterial"); + if (!par) { fParams->Add(new SpdParameter("RsTECAbsorbMaterial",fUnsetMedia)); } + else { *par = fUnsetMedia; } + + par = GetParameter("RsTECPassiveMaterialMDT"); + if (!par) { fParams->Add(new SpdParameter("RsTECPassiveMaterialMDT",fUnsetMedia)); } + else { *par = fUnsetMedia; } + + par = GetParameter("RsTECActiveMaterialMDT"); + if (!par) { fParams->Add(new SpdParameter("RsTECActiveMaterialMDT",fUnsetMedia)); } + else { *par = fUnsetMedia; } +} + +// **************************************************************************** +// ********************* GETTERS (BEGIN) ************************************** +// **************************************************************************** + +//_____________________________________________________________________________ +TString SpdRsTEC2GeoMapper::GetBaseMaterial() const +{ + const SpdParameter* par = GetParameter("RsTECBaseMaterial"); + return (par) ? par->Value() : ""; +} + +//_____________________________________________________________________________ +TString SpdRsTEC2GeoMapper::GetAbsorbMaterial() const +{ + const SpdParameter* par = GetParameter("RsTECAbsorbMaterial"); + return (par) ? par->Value() : ""; +} + +//_____________________________________________________________________________ +TString SpdRsTEC2GeoMapper::GetPassiveMaterialMDT() const +{ + const SpdParameter* par = GetParameter("RsTECPassiveMaterialMDT"); + return (par) ? par->Value() : ""; +} + +//_____________________________________________________________________________ +TString SpdRsTEC2GeoMapper::GetActiveMaterialMDT() const +{ + const SpdParameter* par = GetParameter("RsTECActiveMaterialMDT"); + return (par) ? par->Value() : ""; +} + +//_____________________________________________________________________________ +Int_t SpdRsTEC2GeoMapper::GetNSectors() const +{ + Int_t nsec; + const SpdParameter* par = GetParameter("RsTECNSectors"); + if (!par) return 0; + par->Value(nsec); + return nsec; +} + + +//_____________________________________________________________________________ +Double_t SpdRsTEC2GeoMapper::GetSecAngleOver2() const +{ + Int_t nsec = GetNSectors(); + return (nsec > 0) ? 180./nsec: 0; +} + +//_____________________________________________________________________________ +Double_t SpdRsTEC2GeoMapper::GetModuleInnerRadius() const +{ + const SpdParameter* par = GetParameter("RsTECHmin"); + Double_t l = 0; + if (par) par->Value(l); + return l; +} + +//_____________________________________________________________________________ +Double_t SpdRsTEC2GeoMapper::GetModuleOuterRadius() const +{ + const SpdParameter* par = GetParameter("RsTECSize"); + Double_t l = 0; + if (par) par->Value(l); + return l; +} + +//_____________________________________________________________________________ +Double_t SpdRsTEC2GeoMapper::GetModuleThickness() const +{ + const SpdParameter* par = GetParameter("RsTECThickness"); + Double_t l = 0; + if (par) par->Value(l); + return l; +} + +//_____________________________________________________________________________ +Double_t SpdRsTEC2GeoMapper::GetDist() const +{ + const SpdParameter* par = GetParameter("RsTECMinDist1"); + Double_t l = 0; + if (par) par->Value(l); + return l; +} + +//_____________________________________________________________________________ +Int_t SpdRsTEC2GeoMapper::GetNLayers() const +{ + const SpdParameter* par = GetParameter("RsTECNLayers"); + Int_t nlayers = 0; + if (par) par->Value(nlayers); + return nlayers; +} + +//_____________________________________________________________________________ +Bool_t SpdRsTEC2GeoMapper::IsGeoTypeDefined(Int_t gtype) const +{ + return (gtype > 0 && gtype < 3); +} + +// **************************************************************************** +// ********************* GETTERS (END) **************************************** +// **************************************************************************** +// +//_____________________________________________________________________________ +Bool_t SpdRsTEC2GeoMapper::InitGeometry(Int_t gtype, Bool_t reinit) +{ + if (fLockGeometry) { + cout << "-E- <SpdRsTEC2GeoMapper::InitGeometry> Geometry is locked " << endl; + return kFALSE; + } + + if (!fParams) return kFALSE; + + if (!CheckGeoType(gtype,"RsTECGeoType")) return kFALSE; + + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + + SpdParameter* par; + + // ATTENTION Number of sectors -> FIXED! + const Int_t NUMBER_OF_SECTORS = 8; + par = GetParameter("RsTECNSectors"); + if (par) { if (reinit) *par = NUMBER_OF_SECTORS; } + else { fParams->Add(new SpdParameter("RsTECNSectors", NUMBER_OF_SECTORS)); } + + par = GetParameter("RsTECBaseMaterial"); + if (par) { if (reinit) *par = mapper->GetRsTECBaseMaterial(); } + else { fParams->Add(new SpdParameter("RsTECBaseMaterial",mapper->GetRsTECBaseMaterial())); } + + //cout << "-I- <SpdRsTEC2GeoMapper::InitGeometry> reinit: " << reinit << endl; + + SetParameters(reinit); + + return kTRUE; +} + +//_____________________________________________________________________________ +void SpdRsTEC2GeoMapper::SetParameters(Bool_t reinit) // private +{ + static SpdCommonGeoMapper* mapper = SpdCommonGeoMapper::Instance(); + + SpdParameter* par; + + par = GetParameter("RsTECMinDist"); + if (par) { if (reinit) *par = mapper->GetRsTECMinDist1(); } + else { fParams->Add(new SpdParameter("RsTECMinDist1",mapper->GetRsTECMinDist1())); } + + Double_t size = mapper->GetRsTECSize(); + par = GetParameter("RsTECSize"); + if (par) { if (reinit) *par = size; } + else { fParams->Add(new SpdParameter("RsTECSize",size)); } + + Double_t width = mapper->GetRsTECWidth(); + par = GetParameter("RsTECWidth"); + if (par) { if (reinit) *par = width; } + else { fParams->Add(new SpdParameter("RsTECWidth",width)); } + + Double_t thickness = mapper->GetRsTECThickness(); + par = GetParameter("RsTECThickness"); + if (par) { if (reinit) *par = thickness; } + else { fParams->Add(new SpdParameter("RsTECThickness",thickness)); } + + /* define secondary parameters */ + + Double_t hmin = size - width; + par = GetParameter("RsTECHmin"); + if (par) { *par = hmin; } + else { fParams->Add(new SpdParameter("RsTECHmin",hmin,1)); } + + + /* define materials */ + + TString material; + material = "iron"; + par = GetParameter("RsTECAbsorbMaterial"); + if (par) { if (reinit) *par = material; } + else { fParams->Add(new SpdParameter("RsTECAbsorbMaterial",material)); } + + material = "aluminium"; + par = GetParameter("RsTECPassiveMaterialMDT"); + if (par) { if (reinit) *par = material; } + else { fParams->Add(new SpdParameter("RsTECPassiveMaterialMDT",material)); } + + material = "MDTMixture"; + par = GetParameter("RsTECActiveMaterialMDT"); + if (par) { if (reinit) *par = material; } + else { fParams->Add(new SpdParameter("RsTECActiveMaterialMDT",material)); } + + //---------------------------------------------------------------- + // Number of layers calcluation within RS thickness: + // (Thickness - top absorber - bottom absorber/mdt)/LayerThickness + 1(bottom layer) + + Int_t nLayers = Int_t((thickness - 6. - 9.5)/6.5) + 1; + par = GetParameter("RsTECNLayers"); + if (par) { *par = nLayers; } + else { fParams->Add(new SpdParameter("RsTECNLayers",nLayers,2)); } + +} + +//_____________________________________________________________________________ +void SpdRsTEC2GeoMapper::Print(Option_t*) const +{ + cout << "-I- <SpdRsTEC2GeoMapper::Print>" << "\n\n"; + SpdGeoMapper::Print(""); +} + + + + diff --git a/spdgeometry/rst/SpdRsTEC2GeoMapper.h b/spdgeometry/rst/SpdRsTEC2GeoMapper.h new file mode 100644 index 0000000000000000000000000000000000000000..6ecf99a322c7c2455b3979782df07e3a5fe8d866 --- /dev/null +++ b/spdgeometry/rst/SpdRsTEC2GeoMapper.h @@ -0,0 +1,66 @@ +// $Id$ +// Author: alver 2020/07/17 + +#ifndef __SPDRSTEC2GEOMAPPER_H__ +#define __SPDRSTEC2GEOMAPPER_H__ + +#include <TObjArray.h> + +#include "SpdGeoMapper.h" + +class TString; + +//////////////////////////////////////////////////////////////////////////////// +// // +// SpdRsTEC2GeoMapper // +// // +// <brief class description> // +// // +//////////////////////////////////////////////////////////////////////////////// + +class SpdRsTEC2GeoMapper: public SpdGeoMapper { + +public: + + SpdRsTEC2GeoMapper(); + SpdRsTEC2GeoMapper(TString prefix); + + virtual ~SpdRsTEC2GeoMapper(); + + static SpdRsTEC2GeoMapper* Instance(); + static SpdRsTEC2GeoMapper* GetMapper(); + + virtual Bool_t InitGeometry(Int_t gtype = -1, Bool_t reinit = kFALSE); + + virtual void UnsetMaterials(Bool_t precise = kTRUE, TString option = "base"); + + virtual Bool_t IsGeoTypeDefined(Int_t gtype) const; + + virtual void Print(Option_t*) const; + + Int_t GetNSectors() const; + Double_t GetSecAngleOver2() const; // deg + Double_t GetModuleInnerRadius() const; + Double_t GetModuleOuterRadius() const; + Double_t GetModuleThickness() const; + Double_t GetDist() const; + Int_t GetNLayers() const; + + TString GetBaseMaterial() const; + TString GetAbsorbMaterial() const; + TString GetPassiveMaterialMDT() const; + TString GetActiveMaterialMDT() const; + +private: + + /* data members */ + static SpdRsTEC2GeoMapper* fInstance; + + void SetParameters(Bool_t reinit); + + ClassDef(SpdRsTEC2GeoMapper,1) +}; + +#endif /* __SPDRSTEC2GEOMAPPER_H__ */ + + diff --git a/spdgeometry/tst/SpdTsBVolPars.cxx b/spdgeometry/tst/SpdTsBVolPars.cxx index a720f50a73edb4e828afdcdf5fa5d6b1cb3ab1cb..6a33377c34111e8470bc33719762e9e72e8a1a8a 100644 --- a/spdgeometry/tst/SpdTsBVolPars.cxx +++ b/spdgeometry/tst/SpdTsBVolPars.cxx @@ -25,7 +25,7 @@ ClassImp(SpdTsBStraw) ClassImp(SpdTsBStrawLayer) ClassImp(SpdTsBStrawModule) -Double_t SpdTsBStraw::fMinStrawSize = 40.; //cm +Double_t SpdTsBStraw::fMinStrawSize = 10.; //cm Double_t SpdTsBStrawLayer::fMinLayerSize = 0.1; //cm //////////////////////////////////////////////////////////////////////////////// @@ -309,6 +309,7 @@ Bool_t SpdTsBStrawLayer::MakePacking() SpdTsBStraw::GetMinStrawSize(), fPackingStrawShift, fPackingStrawAngle, fPackingStrawWidth, fPackingStrawGap); + return kTRUE; } //_____________________________________________________________________________ diff --git a/spdgeometry/tst/SpdTsECVolPars.cxx b/spdgeometry/tst/SpdTsECVolPars.cxx index 6942c252c1a0e57db696a1ac41fae33e0c33124c..18f46021484678fba0357fa86982b46aef6d3fd7 100644 --- a/spdgeometry/tst/SpdTsECVolPars.cxx +++ b/spdgeometry/tst/SpdTsECVolPars.cxx @@ -27,7 +27,7 @@ ClassImp(SpdTsECStrawModule) ClassImp(SpdTsECStrawModuleArb) ClassImp(SpdTsECStrawModulePgon) -Double_t SpdTsECStraw::fMinStrawSize = 40.; //cm +Double_t SpdTsECStraw::fMinStrawSize = 10.; //cm //////////////////////////////////////////////////////////////////////////////// // // diff --git a/spdgeometry/tst/SpdTsTBGeoBuilder.cxx b/spdgeometry/tst/SpdTsTBGeoBuilder.cxx index 80cb947bf61c630e754062db06cb9ea950c0264c..8050a43642e83d1bbca2f33da3501fbe17d33b25 100644 --- a/spdgeometry/tst/SpdTsTBGeoBuilder.cxx +++ b/spdgeometry/tst/SpdTsTBGeoBuilder.cxx @@ -151,6 +151,7 @@ Bool_t SpdTsTBGeoBuilder::IsGeometryChanged() // public if (fCheckedVolumes.empty()) return kFALSE; std::map< TString, Int_t >::const_iterator it = fCheckedVolumes.begin(); for (; it != fCheckedVolumes.end(); it++) { if (it->second > 0) return kTRUE; } + return kTRUE; } //_____________________________________________________________________________ @@ -327,11 +328,20 @@ TGeoVolume* SpdTsTBGeoBuilder::BuildVolume(const SpdGeoVolPars* vpars) TGeoMedium* med = GetMedia(vpars->GetMedia()); - if (vpars->GetMedia() != med->GetName()) { - cout << "-W- <SpdTsTBGeoBuilder::BuildVolume> " - << " Volume's \"" << vpars->GetName() << "\" " - << " media is changed : " << vpars->GetMedia() - <<" -> " << med->GetName() << endl; + if (vpars->GetMedia() != med->GetName()) + { + static Bool_t media_is_changed = false; + if (!media_is_changed) { + cout << "-W- <SpdTsTBGeoBuilder::BuildVolume> +++++ ALL MATERIALS ARE SET AS -> " + << med->GetName() << " +++++ " << endl; + } + media_is_changed = true; + + //cout << "-W- <SpdTsTBGeoBuilder::BuildVolume> " + // << " Volume's \"" << vpars->GetName() << "\" " + // << " media has been changed : " << vpars->GetMedia() + // <<" -> " << med->GetName() << endl; + //const_cast<SpdGeoVolPars*>(vpars)->SetActivity(0); // WARNING } diff --git a/spdgeometry/tst/SpdTsTBGeoMapper.cxx b/spdgeometry/tst/SpdTsTBGeoMapper.cxx index 3e11fe09afdbb92bae276e7d7db03e20e5ebe2ab..5d320dedb9000b2b7ce13574152548fe99bfa73e 100644 --- a/spdgeometry/tst/SpdTsTBGeoMapper.cxx +++ b/spdgeometry/tst/SpdTsTBGeoMapper.cxx @@ -96,7 +96,12 @@ void SpdTsTBGeoMapper::UnsetMaterials(Bool_t precise, TString option) cout << "-E- <SpdTsTBGeoMapper::UnsetMaterials> Geometry is locked " << endl; return; } - (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuum"; + + if (option.IsWhitespace()) { fUnsetMedia = "vacuumX1"; } + else if (option == "base") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX1"; } + else if (option == "vacuum") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX1"; } + else if (option == "air") { fUnsetMedia = "airX1"; } + else { fUnsetMedia = option; } } //_____________________________________________________________________________ @@ -710,8 +715,18 @@ void SpdTsTBGeoMapper::SetParameters_2(Bool_t reinit) // private if (par) { *par = hmin2; } else { fParams->Add(new SpdParameter("TsTBHmin2",hmin2,1)); } + Double_t rmin2 = hmin2; + par = GetParameter("TsTBRmin2"); + if (par) { *par = rmin2; } + else { fParams->Add(new SpdParameter("TsTBRmin2",rmin2,1)); } + + Double_t rmax2 = size2/Cos(angle); + par = GetParameter("TsTBRmax2"); + if (par) { *par = rmax2; } + else { fParams->Add(new SpdParameter("TsTBRmax2",rmax2,1)); } + Double_t lmin2 = 2*(hmin2*Tan(angle) - clearance21); // < 0 ? - par = GetParameter("TsTBHLmin2"); + par = GetParameter("TsTBLmin2"); if (par) { *par = lmin2; } else { fParams->Add(new SpdParameter("TsTBLmin2",lmin2,2)); } diff --git a/spdgeometry/tst/SpdTsTECGeoBuilder.cxx b/spdgeometry/tst/SpdTsTECGeoBuilder.cxx index 8a17e78e53212da8dad8c0ac3dd4b1c21df75035..908e53c5bb355331552b1d0edac5a40d1d61f843 100644 --- a/spdgeometry/tst/SpdTsTECGeoBuilder.cxx +++ b/spdgeometry/tst/SpdTsTECGeoBuilder.cxx @@ -154,11 +154,20 @@ TGeoVolume* SpdTsTECGeoBuilder::BuildVolume(const SpdGeoVolPars* vpars) TGeoMedium* med = GetMedia(vpars->GetMedia()); - if (vpars->GetMedia() != med->GetName()) { - cout << "-W- <SpdTsTECGeoBuilder::BuildVolume> " - << " Volume's \"" << vpars->GetName() << "\" " - << " media is changed : " << vpars->GetMedia() - <<" -> " << med->GetName() << endl; + if (vpars->GetMedia() != med->GetName()) + { + static Bool_t media_is_changed = false; + if (!media_is_changed) { + cout << "-W- <SpdTsTBGeoBuilder::BuildVolume> +++++ ALL MATERIALS ARE SET AS -> " + << med->GetName() << " +++++ " << endl; + } + media_is_changed = true; + + //cout << "-W- <SpdTsTECGeoBuilder::BuildVolume> " + // << " Volume's \"" << vpars->GetName() << "\" " + // << " media has been changed : " << vpars->GetMedia() + // <<" -> " << med->GetName() << endl; + //const_cast<SpdGeoVolPars*>(vpars)->SetActivity(0); // WARNING } diff --git a/spdgeometry/tst/SpdTsTECGeoMapper.cxx b/spdgeometry/tst/SpdTsTECGeoMapper.cxx index fc5796e4210f7c2a734778d0457950f39ed5f912..b1e1866ae2467feafed76f1bf5b36e194e0b3215 100644 --- a/spdgeometry/tst/SpdTsTECGeoMapper.cxx +++ b/spdgeometry/tst/SpdTsTECGeoMapper.cxx @@ -192,8 +192,13 @@ void SpdTsTECGeoMapper::UnsetMaterials(Bool_t precise, TString option) if (fLockGeometry) { cout << "-E- <SpdTsTECGeoMapper::UnsetMaterials> Geometry is locked " << endl; return; - } - (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuum"; + } + + if (option.IsWhitespace()) { fUnsetMedia = "vacuumX2"; } + else if (option == "base") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX2"; } + else if (option == "vacuum") { (precise) ? fUnsetMedia = "vacuum2" : fUnsetMedia = "vacuumX2"; } + else if (option == "air") { fUnsetMedia = "airX2"; } + else { fUnsetMedia = option; } } //_____________________________________________________________________________ @@ -1698,9 +1703,22 @@ void SpdTsTECGeoMapper::SetGeometryPars(Int_t g) AddBackwardModule(8,0,0); AddBackwardModule(8,0,0); + RecalculateDistance(); + } + if (g == 2) + { + SetParameters(7,1,1); + SetParameters(8,2,1); + + AddForwardModule(7,0,0); + AddForwardModule(7,0,0); + + AddBackwardModule(8,0,0); + AddBackwardModule(8,0,0); + RecalculateDistance(); } - else if (g == 2) + else if (g == 3) { SetDefaultModulePars(1,1,-1); // set module length < 0 SetDefaultModulePars(2,1,-1); // set module length < 0 @@ -1711,7 +1729,7 @@ void SpdTsTECGeoMapper::SetGeometryPars(Int_t g) AddForwardModule(1,0,0); AddBackwardModule(2,0,0); } - else if (g == 3) + else if (g == 4) { SetDefaultModulePars( 9, 1, 24); // set number of layers = 24 SetDefaultModulePars(10, 1, 24); // set number of layers = 24 @@ -1722,7 +1740,7 @@ void SpdTsTECGeoMapper::SetGeometryPars(Int_t g) AddIdentModules( 1, 9, 3); AddIdentModules(-1, 10, 3); } - else if (g == 4) + else if (g == 5) { SetParameters(5); SetParameters(6); diff --git a/spdgeometry/tst/SpdTsTECGeoMapper.h b/spdgeometry/tst/SpdTsTECGeoMapper.h index bb1ea3fd0ce832782a338665d2c065819e074dc3..c9206eedd53b3c44d00b4d585586b986190ab2ee 100644 --- a/spdgeometry/tst/SpdTsTECGeoMapper.h +++ b/spdgeometry/tst/SpdTsTECGeoMapper.h @@ -34,7 +34,7 @@ public: virtual Bool_t InitGeometry(Int_t gtype = -1, Bool_t reinit = kFALSE); - virtual void UnsetMaterials(Bool_t precise = kTRUE, TString option = "base"); + virtual void UnsetMaterials(Bool_t precise = kTRUE, TString option = "base"); virtual Bool_t IsGeoTypeDefined(Int_t gtype) const; diff --git a/spdroot.py b/spdroot.py new file mode 100755 index 0000000000000000000000000000000000000000..66708e3f82b0e849c2ee643d4ee137948bbc6098 --- /dev/null +++ b/spdroot.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import sys +import os + +var = os.environ['VMCWORKDIR'] + +rootlogon = var+"/macro/rootlogon.C" +rootlogoff = var+"/macro/rootlogoff.C" + +os.system("root -l -q -b " + " " + rootlogon + " " + sys.argv[1] + " " + rootlogoff) diff --git a/tst/barrel/SpdTsTB.cxx b/tst/barrel/SpdTsTB.cxx index 82a761b6ef4d1d05d25a8f006a8932cc74a32904..6ace7988f101addf738405f85d46647606f369c4 100644 --- a/tst/barrel/SpdTsTB.cxx +++ b/tst/barrel/SpdTsTB.cxx @@ -114,7 +114,9 @@ void SpdTsTB::Initialize() //_____________________________________________________________________________________ void SpdTsTB::Reset() { + //Int_t nt = fPointCollection->GetEntriesFast(); if (fPointCollection) fPointCollection->Clear(); + //cout << "<SpdTsTB::Reset> " << nt << ", " << fPointCollection->GetEntriesFast() << endl; } //_____________________________________________________________________________________ @@ -326,11 +328,7 @@ Bool_t SpdTsTB::LoadParsFrom(SpdParSet* params) //_____________________________________________________________________________________ TString SpdTsTB::GetDataOut(Int_t n) const { - cout << "<SpdTsTB::GetDataOut> " << n << endl; - if (n < 0 || n >= fNDataOut) { - return "unknown"; - } - cout << "<SpdTsTB::GetDataOut> " << n << " object: " << fOutDataPointObject << endl; + if (n < 0 || n >= fNDataOut) return "unknown"; return fOutDataPointObject; } diff --git a/tst/ecps/SpdTsTEC.cxx b/tst/ecps/SpdTsTEC.cxx index 0f409acaa0d2b8f892bc8ddd443ca8a6964f4adb..4b37a70272da6cef78ecec55eaf2949b1da5d761 100644 --- a/tst/ecps/SpdTsTEC.cxx +++ b/tst/ecps/SpdTsTEC.cxx @@ -102,7 +102,7 @@ void SpdTsTEC::Initialize() cout << "*******************************************************************************\n" << endl; // data collections - fPointCollection = new TClonesArray(fOutDataPointObject); + fPointCollection = new TClonesArray(fOutDataPointObject,10000); // Initialize module and fill parameters SpdDetector::Initialize(); @@ -114,7 +114,9 @@ void SpdTsTEC::Initialize() //_____________________________________________________________________________________ void SpdTsTEC::Reset() { + //Int_t nt = fPointCollection->GetEntriesFast(); if (fPointCollection) fPointCollection->Clear(); + //cout << "<SpdTsTEC::Reset> " << nt << ", " << fPointCollection->GetEntriesFast() << endl; } //_____________________________________________________________________________________