diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3ae49e3d184..d8f51e2c59c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,6 +6,7 @@ /StRoot/PWGTools @nigmatkulov @zsweger @marrbnl @lbavinh /StRoot/RTS @akioogawa @jml985 @tonko-lj /StRoot/StAnalysisMaker @fisyak @R-Witt @iraklic +/StRoot/*KFP* @fisyak @R-Witt @iraklic /StRoot/StAnalysisUtilities/StHistUtil* @genevb /StRoot/StAssociationMaker/EMC @kkauder @rkunnawa @Navagyan /StRoot/StBFChain @genevb @plexoos @klendathu2k @fisyak @R-Witt @iraklic diff --git a/StRoot/KFParticle/.includes_for_export.flg b/StRoot/KFParticle/.includes_for_export.flg new file mode 100644 index 00000000000..f71036d21ab --- /dev/null +++ b/StRoot/KFParticle/.includes_for_export.flg @@ -0,0 +1 @@ +All include files of this directory for export diff --git a/StRoot/KFParticle/KFPEmcCluster.cxx b/StRoot/KFParticle/KFPEmcCluster.cxx new file mode 100644 index 00000000000..47707af84da --- /dev/null +++ b/StRoot/KFParticle/KFPEmcCluster.cxx @@ -0,0 +1,190 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "KFPEmcCluster.h" +#include + +void KFPEmcCluster::SetParameter(const float32_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+SimdLen) < Size()) + reinterpret_cast(fP[iP][iTr]) = value; + else + { + int32_v index = int32_v::indicesSequence(); + index = select(index<(Size() - iTr), index, 0); + (reinterpret_cast(fP[iP][iTr])).gather(reinterpret_cast(&value), index); + } +} +void KFPEmcCluster::SetCovariance(const float32_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+SimdLen) < Size()) + reinterpret_cast(fC[iC][iTr]) = value; + else + { + int32_v index = int32_v::indicesSequence(); + index = select(index<(Size() - iTr), index, 0); + (reinterpret_cast(fC[iC][iTr])).gather(reinterpret_cast(&value), index); + } +} + +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(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fP[iP][iElement]); + vec.gather(&(track.fP[iP][0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fP[iP][iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fC[iC][iElement]); + vec.gather(&(track.fC[iC][0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fC[iC][iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fId[iElement]); + vec.gather(&(track.fId[0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fId[iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement) + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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_int& 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 float32_v& value, int iP, int iTr); + void SetCovariance(const float32_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 + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFPINPUTDATA_H +#define KFPINPUTDATA_H + +#include "KFPTrackVector.h" +#include "KFParticle.h" + +#include +#include +#include + +/** @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(float32_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(float32_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> nTracks; + fTracks[iSet].Resize(nTracks); + + for(int iP=0; iP<6; iP++) + { + float value; + for(int iTr=0; iTr> value; + fTracks[iSet].SetParameter(value, iP, iTr); + } + } + + for(int iC=0; iC<21; iC++) + { + float value; + for(int iTr=0; iTr> value; + fTracks[iSet].SetCovariance(value, iC, iTr); + } + } + + int tmpInt; + for(int iTr=0; iTr> tmpInt; + fTracks[iSet].SetId(tmpInt, iTr); + } + + for(int iTr=0; iTr> tmpInt; + fTracks[iSet].SetPDG(tmpInt, iTr); + } + + for(int iTr=0; iTr> tmpInt; + fTracks[iSet].SetQ(tmpInt, iTr); + } + + for(int iTr=0; iTr> 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(data[NInputSets+1]); + field = fBz; + + int offset = NInputSets+2; + + for(int iSet=0; iSet(data[offset + iPV]); + tmpFloat = fPV[iPV].Parameter(iP); + } + offset += fPV.size(); + } + + for(int iC=0; iC<6; iC++) + { + for(unsigned int iPV=0; iPV(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(data[NInputSets+1]); + fBz = field; + + fPV.resize(data[NInputSets]); + + for(int iP=0; iP<3; iP++) + { + for(unsigned int iPV=0; iPV(data[offset + iPV]); + fPV[iPV].Parameter(iP) = tmpFloat; + } + offset += fPV.size(); + } + + for(int iC=0; iC<6; iC++) + { + for(unsigned int iPV=0; iPV(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& 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 fPV; ///< Vector with primary vertices. + float fBz; ///< Constant homogenious one-component magnetic field Bz. +} __attribute__((aligned(sizeof(float32_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(float32_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(float32_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(float32_v)))); ///< Input data for KF Particle Finder \see KFPInputData. + KFPLinkedList* next; ///< Link to the nex object in the linked list. +} __attribute__((aligned(sizeof(float32_v)))); + +#endif diff --git a/StRoot/KFParticle/KFPSimd/.clang-format b/StRoot/KFParticle/KFPSimd/.clang-format new file mode 100644 index 00000000000..fde267ed5d6 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/.clang-format @@ -0,0 +1,142 @@ +# BasedOnStyle: Linux Kernal Coding styles +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 11. +# +# For more information, see: +# +# Documentation/process/clang-format.rst +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +--- +Language: Cpp +IndentAccessModifiers: false +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: false +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +BreakTemplateDeclarationsStyle: Leave +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false + +ForEachMacros: + - 'for_each_event' + - 'for_each_event_tps' + - 'for_each_free_mem_range' + - 'for_each_hstate' + - 'for_each_if' + +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Left +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: c++17 +TabWidth: 8 +UseTab: Never diff --git a/StRoot/KFParticle/KFPSimd/.gitignore b/StRoot/KFParticle/KFPSimd/.gitignore new file mode 100644 index 00000000000..49c277c6676 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/.gitignore @@ -0,0 +1,7 @@ +/*.exe +/Tests/**/*.exe +/Tests/**/*.log +/Tests/**/*.out +/Tests/**/*.s +/Tests/**/*.o +Extra/ diff --git a/StRoot/KFParticle/KFPSimd/COPYING b/StRoot/KFParticle/KFPSimd/COPYING new file mode 100644 index 00000000000..f288702d2fa --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/StRoot/KFParticle/KFPSimd/SSE/constants.h b/StRoot/KFParticle/KFPSimd/SSE/constants.h new file mode 100644 index 00000000000..d88aed03c76 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/SSE/constants.h @@ -0,0 +1,23 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran; +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_SSE_CONSTANTS_H +#define SIMD_SSE_CONSTANTS_H + +#include + +namespace KFP { +namespace SIMD { + +constexpr int SimdSize{16}; +constexpr int SimdLen{4}; + +} // namespace SIMD +} // namespace KFP + +#endif // !SIMD_SSE_CONSTANTS_H diff --git a/StRoot/KFParticle/KFPSimd/SSE/float32.h b/StRoot/KFParticle/KFPSimd/SSE/float32.h new file mode 100644 index 00000000000..69f77a6e1ac --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/SSE/float32.h @@ -0,0 +1,368 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran; +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_SSE_FLOAT32_H +#define SIMD_SSE_FLOAT32_H + +#include "../Utils/macros.h" +#include "../Utils/tag.h" +#include "int32.h" +#include "mask32.h" +#include "constants.h" + +#include +#include +#include + +namespace KFP { +namespace SIMD { + +class Float32_128 +{ +public: + typedef float value_type; + typedef __m128 simd_type; + static constexpr Tag tag{ Tag::SSE }; + + // ------------------------------------------------------ + // Constructors + // ------------------------------------------------------ + // Default constructor: + Float32_128() { + m_data = _mm_setzero_ps(); + } + Float32_128(UninitializeTag) {} + // Constructor to broadcast the same value into all elements: + Float32_128(float val) + { + m_data = _mm_set1_ps(val); + } + Float32_128(const __m128& val_simd) + { + m_data = val_simd; + } + Float32_128(const float* val_ptr) + { + m_data = _mm_loadu_ps(val_ptr); + } + Float32_128(const Float32_128& class_simd) = default; + + // Assignment constructors: + Float32_128& operator=(float val) + { + m_data = _mm_set1_ps(val); + return *this; + } + Float32_128& operator=(const __m128& val_simd) + { + m_data = val_simd; + return *this; + } + Float32_128& operator=(const Float32_128& class_simd) = default; + + // ------------------------------------------------------ + // Load and Store + // ------------------------------------------------------ + // Member function to load from array (unaligned) + KFP_SIMD_INLINE Float32_128& loadUnaligned(const float* val_ptr) + { + m_data = _mm_loadu_ps(val_ptr); + return *this; + } + // Member function to load from array (aligned) + KFP_SIMD_INLINE Float32_128& load(const float* val_ptr) + { + m_data = _mm_load_ps(val_ptr); + return *this; + } + // Member function to store into array (unaligned) + KFP_SIMD_INLINE void storeUnaligned(float* val_ptr) const + { + _mm_storeu_ps(val_ptr, m_data); + } + // Member function storing into array (aligned) + KFP_SIMD_INLINE void store(float* val_ptr) const + { + _mm_store_ps(val_ptr, m_data); + } + + // ------------------------------------------------------ + // Gather and Scatter + // ------------------------------------------------------ + KFP_SIMD_INLINE Float32_128& gather(const float* val_ptr, const Int32_128& index) + { + alignas(SimdSize) std::int32_t + indices[SimdLen]{}; // Helper indices array + index.store(indices); + m_data = _mm_setr_ps( + val_ptr[indices[0]], val_ptr[indices[1]], + val_ptr[indices[2]], val_ptr[indices[3]] + ); + return *this; + } + KFP_SIMD_INLINE void scatter(float* val_ptr, const Int32_128& index) const + { + alignas(SimdSize) float + data[SimdLen]{}; // Helper data array + store(data); + + alignas(SimdSize) std::int32_t + indices[SimdLen]{}; // Helper indices array + index.store(indices); + + val_ptr[indices[0]] = data[0]; + val_ptr[indices[1]] = data[1]; + val_ptr[indices[2]] = data[2]; + val_ptr[indices[3]] = data[3]; + } + + // ------------------------------------------------------ + // Data member accessors + // ------------------------------------------------------ + KFP_SIMD_INLINE __m128& simd() + { + return m_data; + } + KFP_SIMD_INLINE const __m128& simd() const + { + return m_data; + } + template + KFP_SIMD_INLINE float get() const { + static_assert(N >= 0, + "[Error] (Float32_128::get): Invalid value of index N. Negative"); + static_assert(N < SimdLen, + "[Error] (Float32_128::get): Invalid value of index N. Out of range."); + return _mm_extract_ps(m_data, N); + } + KFP_SIMD_INLINE float operator[](int index) const + { + assert((index >= 0) && (index < int(SimdLen))); + alignas(SimdSize) float + data[SimdLen]{}; // Helper array + store(data); + return data[index]; + } + + // ------------------------------------------------------ + // Data lanes manipulation + // ------------------------------------------------------ + KFP_SIMD_INLINE friend Float32_128 select(const Mask32_128& mask, const Float32_128& a, + const Float32_128& b) { + return _mm_blendv_ps(b.m_data, a.m_data, mask.simdf()); + } + + KFP_SIMD_INLINE Float32_128 multiplySign(const Float32_128& a) const + { + const __m128 sign( + _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0x80000000)), a.m_data) + ); + return Float32_128{ _mm_xor_ps(m_data, sign) }; + } + template + KFP_SIMD_INLINE Float32_128 rotate() const + { + if (N < 0) { + constexpr int num_shift = (-N) % SimdLen; + constexpr int left_shift_bytes = num_shift*4; + constexpr int right_shift_bytes = (SimdLen - num_shift)*4; + const __m128 left = _mm_castsi128_ps( + _mm_bsrli_si128(_mm_castps_si128(m_data), left_shift_bytes) + ); + const __m128 right = _mm_castsi128_ps( + _mm_bslli_si128(_mm_castps_si128(m_data), right_shift_bytes) + ); + return Float32_128{_mm_or_ps(left, right)}; + } else { + constexpr int num_shift = N % SimdLen; + constexpr int left_shift_bytes = (SimdLen - num_shift)*4; + constexpr int right_shift_bytes = num_shift*4; + const __m128 left = _mm_castsi128_ps( + _mm_bsrli_si128(_mm_castps_si128(m_data), left_shift_bytes) + ); + const __m128 right = _mm_castsi128_ps( + _mm_bslli_si128(_mm_castps_si128(m_data), right_shift_bytes) + ); + return Float32_128{_mm_or_ps(left, right)}; + } + } + + // ------------------------------------------------------ + // Rounding + // ------------------------------------------------------ + + KFP_SIMD_INLINE friend Float32_128 round(const Float32_128& a) + { + return _mm_round_ps(a.m_data, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); + } + + KFP_SIMD_INLINE friend Float32_128 trunc(const Float32_128& a) + { + return _mm_round_ps(a.m_data, (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)); + } + + + // ------------------------------------------------------ + // Basic Arithmetic + // ------------------------------------------------------ + friend Float32_128 operator-(const Float32_128& a) + { + return Float32_128{ _mm_sub_ps(_mm_setzero_ps(), a.m_data) }; + } + friend Float32_128 operator+(const Float32_128& a, + const Float32_128& b) + { + return Float32_128{ + _mm_add_ps(a.m_data, b.m_data) + }; + } + Float32_128& operator+=(const Float32_128& a) + { + *this = *this + a; + return *this; + } + friend Float32_128 operator-(const Float32_128& a, + const Float32_128& b) + { + return Float32_128{ + _mm_sub_ps(a.m_data, b.m_data) + }; + } + Float32_128& operator-=(const Float32_128& a) + { + *this = *this - a; + return *this; + } + friend Float32_128 operator*(const Float32_128& a, + const Float32_128& b) + { + return Float32_128{ + _mm_mul_ps(a.m_data, b.m_data) + }; + } + Float32_128& operator*=(const Float32_128& a) + { + *this = *this * a; + return *this; + } + friend Float32_128 operator/(const Float32_128& a, + const Float32_128& b) + { + return Float32_128{ + _mm_div_ps(a.m_data, b.m_data) + }; + } + Float32_128& operator/=(const Float32_128& a) + { + *this = *this / a; + return *this; + } + + // Comparison (mask returned) + friend Mask32_128 operator<(const Float32_128& a, + const Float32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_castps_si128( + _mm_cmplt_ps(a.m_data, b.m_data) + ); + return result; + } + friend Mask32_128 operator<=(const Float32_128& a, + const Float32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_castps_si128( + _mm_cmple_ps(a.m_data, b.m_data) + ); + return result; + } + friend Mask32_128 operator>(const Float32_128& a, + const Float32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_castps_si128( + _mm_cmpgt_ps(a.m_data, b.m_data) + ); + return result; + } + friend Mask32_128 operator>=(const Float32_128& a, + const Float32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_castps_si128( + _mm_cmpge_ps(a.m_data, b.m_data) + ); + return result; + } + friend Mask32_128 operator==(const Float32_128& a, + const Float32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_castps_si128( + _mm_cmpeq_ps(a.m_data, b.m_data) + ); + return result; + } + friend Mask32_128 operator!=(const Float32_128& a, + const Float32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_castps_si128( + _mm_cmpneq_ps(a.m_data, b.m_data) + ); + return result; + } + + KFP_SIMD_INLINE friend Float32_128 min(const Float32_128& a, const Float32_128& b) + { + return _mm_min_ps(a.m_data, b.m_data); + } + + KFP_SIMD_INLINE friend Float32_128 max(const Float32_128& a, const Float32_128& b) + { + return _mm_max_ps(a.m_data, b.m_data); + } + + KFP_SIMD_INLINE friend Float32_128 abs(const Float32_128& a) + { + return _mm_and_ps(a.m_data, _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF))); + } + + KFP_SIMD_INLINE friend Float32_128 sqrt(const Float32_128& a) + { + return _mm_sqrt_ps(a.m_data); + } + + // ------------------------------------------------------ + // Float checks + // ------------------------------------------------------ + + KFP_SIMD_INLINE friend Mask32_128 isNan(const Float32_128& a) + { + Mask32_128 result(UninitializeTag{}); + result.m_data = _mm_castps_si128(_mm_cmpunord_ps(a.m_data, a.m_data)); + return result; + } + + KFP_SIMD_INLINE friend Mask32_128 isFinite(const Float32_128& a) + { + Mask32_128 result(UninitializeTag{}); + result.m_data = _mm_castps_si128(_mm_cmpord_ps(a.m_data, _mm_mul_ps(_mm_setzero_ps(), a.m_data))); + return result; + } + + +private: + alignas(SimdSize) __m128 m_data; +}; + +} // namespace SIMD +} // namespace KFP + +#endif // !SIMD_SSE_FLOAT32_H diff --git a/StRoot/KFParticle/KFPSimd/SSE/int32.h b/StRoot/KFParticle/KFPSimd/SSE/int32.h new file mode 100644 index 00000000000..938f49a5029 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/SSE/int32.h @@ -0,0 +1,339 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran; +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_SSE_INT32_H +#define SIMD_SSE_INT32_H + +#include "../Utils/macros.h" +#include "../Utils/tag.h" +#include "mask32.h" +#include "constants.h" + +#include +#include +#include + +namespace KFP { +namespace SIMD { + +class Int32_128 +{ +public: + typedef std::int32_t value_type; + typedef __m128i simd_type; + static constexpr Tag tag{ Tag::SSE }; + + // ------------------------------------------------------ + // Constructors + // ------------------------------------------------------ + // Default constructor: + Int32_128() { + m_data = _mm_setzero_si128(); + } + Int32_128(UninitializeTag) {} + // Constructor to broadcast the same value into all elements: + Int32_128(std::int32_t val) + { + m_data = _mm_set1_epi32(val); + } + Int32_128(const __m128i& val_simd) + { + m_data = val_simd; + } + Int32_128(const std::int32_t* val_ptr) + { + m_data = _mm_loadu_si128(reinterpret_cast(val_ptr)); + } + Int32_128(const Int32_128& class_simd) = default; + + // Assignment constructors: + Int32_128& operator=(std::int32_t val) + { + m_data = _mm_set1_epi32(val); + return *this; + } + Int32_128& operator=(const __m128i& val_simd) + { + m_data = val_simd; + return *this; + } + Int32_128& operator=(const Int32_128& class_simd) = default; + + // ------------------------------------------------------ + // Factory methods + // ------------------------------------------------------ + KFP_SIMD_INLINE static Int32_128 indicesSequence(std::int32_t start) + { + return Int32_128{ + _mm_add_epi32(_mm_setr_epi32(0, 1, 2, 3), _mm_set1_epi32(start)) + }; + } + + KFP_SIMD_INLINE static Int32_128 indicesSequence() + { + return Int32_128{_mm_setr_epi32(0, 1, 2, 3)}; + } + + // ------------------------------------------------------ + // Load and Store + // ------------------------------------------------------ + // Member function to load from array (unaligned) + KFP_SIMD_INLINE Int32_128& loadUnaligned(const std::int32_t* val_ptr) + { + m_data = _mm_loadu_si128(reinterpret_cast(val_ptr)); + return *this; + } + // Member function to load from array (aligned) + KFP_SIMD_INLINE Int32_128& load(const std::int32_t* val_ptr) + { + m_data = _mm_load_si128(reinterpret_cast(val_ptr)); + return *this; + } + // Member function to store into array (unaligned) + KFP_SIMD_INLINE void storeUnaligned(std::int32_t* val_ptr) const + { + _mm_storeu_si128(reinterpret_cast<__m128i*>(val_ptr), m_data); + } + // Member function storing into array (aligned) + KFP_SIMD_INLINE void store(std::int32_t* val_ptr) const + { + _mm_store_si128(reinterpret_cast<__m128i*>(val_ptr), m_data); + } + + // ------------------------------------------------------ + // Gather and Scatter + // ------------------------------------------------------ + KFP_SIMD_INLINE Int32_128& gather(const std::int32_t* val_ptr, const Int32_128& index) + { + alignas(SimdSize) std::int32_t + indices[SimdLen]{}; // Helper indices array + index.store(indices); + m_data = _mm_setr_epi32( + val_ptr[indices[0]], val_ptr[indices[1]], + val_ptr[indices[2]], val_ptr[indices[3]] + ); + return *this; + } + KFP_SIMD_INLINE void scatter(std::int32_t* val_ptr, const Int32_128& index) const + { + alignas(SimdSize) std::int32_t + data[SimdLen]{}; // Helper data array + store(data); + + alignas(SimdSize) int + indices[SimdLen]{}; // Helper indices array + index.store(indices); + + val_ptr[indices[0]] = data[0]; + val_ptr[indices[1]] = data[1]; + val_ptr[indices[2]] = data[2]; + val_ptr[indices[3]] = data[3]; + } + + // ------------------------------------------------------ + // Data member accessors + // ------------------------------------------------------ + KFP_SIMD_INLINE __m128i& simd() + { + return m_data; + } + KFP_SIMD_INLINE const __m128i& simd() const + { + return m_data; + } + template + KFP_SIMD_INLINE std::int32_t get() const { + static_assert(N >= 0, + "[Error] (Int32_128::get): Invalid value of index N. Negative"); + static_assert(N < SimdLen, + "[Error] (Int32_128::get): Invalid value of index N. Out of range."); + return _mm_extract_epi32(m_data, N); + } + KFP_SIMD_INLINE std::int32_t operator[](int index) const + { + assert((index >= 0) && (index < int(SimdLen))); + alignas(SimdSize) std::int32_t + data[SimdLen]{}; // Helper array + store(data); + return data[index]; + } + + // ------------------------------------------------------ + // Data lanes manipulation + // ------------------------------------------------------ + KFP_SIMD_INLINE friend Int32_128 select(const Mask32_128& mask, const Int32_128& a, + const Int32_128& b) { + return _mm_blendv_epi8(b.m_data, a.m_data, mask.m_data); + } + + KFP_SIMD_INLINE Int32_128 sign() const + { + return Int32_128{ + _mm_and_si128(_mm_set1_epi32(0x80000000), m_data) + }; + } + template + KFP_SIMD_INLINE Int32_128 shiftPerLaneLeft() const + { + static_assert(N >= 0, + "[Error] (Int32_128::shiftPerLaneLeft): Invalid value of index N. Negative"); + return Int32_128{_mm_slli_epi32(m_data, N)}; + } + template + KFP_SIMD_INLINE Int32_128 shiftPerLaneRight() const + { + static_assert(N >= 0, + "[Error] (Int32_128::shiftPerLaneRight): Invalid value of index N. Negative"); + return Int32_128{_mm_srai_epi32(m_data, N)}; + } + template + KFP_SIMD_INLINE Int32_128 rotate() const + { + if (N < 0) { + constexpr int num_shift = (-N) % SimdLen; + constexpr int left_shift_bytes = num_shift*4; + constexpr int right_shift_bytes = (SimdLen - num_shift)*4; + const __m128i left = _mm_bsrli_si128(m_data, left_shift_bytes); + const __m128i right = _mm_bslli_si128(m_data, right_shift_bytes); + return Int32_128{_mm_or_si128(left, right)}; + } else { + constexpr int num_shift = N % SimdLen; + constexpr int left_shift_bytes = (SimdLen - num_shift)*4; + constexpr int right_shift_bytes = num_shift*4; + const __m128i left = _mm_bsrli_si128(m_data, left_shift_bytes); + const __m128i right = _mm_bslli_si128(m_data, right_shift_bytes); + return Int32_128{_mm_or_si128(left, right)}; + } + } + + // ------------------------------------------------------ + // Basic Arithmetic + // ------------------------------------------------------ + friend Int32_128 operator-(const Int32_128& a) + { + return Int32_128{ _mm_sub_epi32(_mm_setzero_si128(), a.m_data) }; + } + friend Int32_128 operator+(const Int32_128& a, + const Int32_128& b) + { + return Int32_128{ _mm_add_epi32(a.m_data, b.m_data) }; + } + Int32_128& operator+=(const Int32_128& a) + { + *this = *this + a; + return *this; + } + friend Int32_128 operator-(const Int32_128& a, + const Int32_128& b) + { + return Int32_128{ _mm_sub_epi32(a.m_data, b.m_data) }; + } + Int32_128& operator-=(const Int32_128& a) + { + *this = *this - a; + return *this; + } + friend Int32_128 operator*(const Int32_128& a, + const Int32_128& b) + { + return _mm_mullo_epi32(a.m_data, b.m_data); + } + Int32_128& operator*=(const Int32_128& a) + { + *this = *this * a; + return *this; + } + Int32_128 operator<<(int n) const + { + return _mm_slli_epi32(m_data, n); + } + Int32_128 operator>>(int n) const + { + return _mm_srai_epi32(m_data, n); + } + friend Int32_128 operator&(const Int32_128& a, + const Int32_128& b) + { + return _mm_and_si128(a.m_data, b.m_data); + } + friend Int32_128 operator|(const Int32_128& a, + const Int32_128& b) + { + return _mm_or_si128(a.m_data, b.m_data); + } + friend Int32_128 operator^(const Int32_128& a, + const Int32_128& b) + { + return _mm_xor_si128(a.m_data, b.m_data); + } + + // Comparison (mask returned) + friend Mask32_128 operator<(const Int32_128& a, + const Int32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_cmplt_epi32(a.m_data, b.m_data); + return result; + } + friend Mask32_128 operator<=(const Int32_128& a, + const Int32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_cmpeq_epi32(_mm_min_epi32(a.m_data, b.m_data), a.m_data); + return result; + } + friend Mask32_128 operator>(const Int32_128& a, + const Int32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_cmpgt_epi32(a.m_data, b.m_data); + return result; + } + friend Mask32_128 operator>=(const Int32_128& a, + const Int32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_cmpeq_epi32(_mm_min_epi32(b.m_data, a.m_data), b.m_data); + return result; + } + friend Mask32_128 operator==(const Int32_128& a, + const Int32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_cmpeq_epi32(a.m_data, b.m_data); + return result; + } + friend Mask32_128 operator!=(const Int32_128& a, + const Int32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_cmpeq_epi32(a.m_data, b.m_data); + return not result; + } + + KFP_SIMD_INLINE friend Int32_128 min(const Int32_128& a, const Int32_128& b) + { + return _mm_min_epi32(a.m_data, b.m_data); + } + KFP_SIMD_INLINE friend Int32_128 max(const Int32_128& a, const Int32_128& b) + { + return _mm_max_epi32(a.m_data, b.m_data); + } + KFP_SIMD_INLINE friend Int32_128 abs(const Int32_128& a) + { + return _mm_abs_epi32(a.m_data); + } + +private: + alignas(SimdSize) __m128i m_data; +}; + +} // namespace SIMD +} // namespace KFP + +#endif // !SIMD_SSE_INT32_H diff --git a/StRoot/KFParticle/KFPSimd/SSE/mask32.h b/StRoot/KFParticle/KFPSimd/SSE/mask32.h new file mode 100644 index 00000000000..02a8446d073 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/SSE/mask32.h @@ -0,0 +1,164 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran; +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_SSE_MASK32_H +#define SIMD_SSE_MASK32_H + +#include "../Utils/macros.h" +#include "../Utils/tag.h" +#include "constants.h" + +#include +#include + +namespace KFP { +namespace SIMD { + +class Int32_128; +class Float32_128; + +class Mask32_128 +{ +public: + typedef bool value_type; + typedef __m128i simd_type; + static constexpr Tag tag{ Tag::SSE }; + + friend class Int32_128; + friend class Float32_128; + + friend Int32_128 select(const Mask32_128& mask, const Int32_128& a, const Int32_128& b); + friend Mask32_128 operator<(const Int32_128& a, const Int32_128& b); + friend Mask32_128 operator<=(const Int32_128& a, const Int32_128& b); + friend Mask32_128 operator>(const Int32_128& a, const Int32_128& b); + friend Mask32_128 operator>=(const Int32_128& a, const Int32_128& b); + friend Mask32_128 operator==(const Int32_128& a, const Int32_128& b); + friend Mask32_128 operator!=(const Int32_128& a, const Int32_128& b); + + friend Mask32_128 operator<(const Float32_128& a, const Float32_128& b); + friend Mask32_128 operator<=(const Float32_128& a, const Float32_128& b); + friend Mask32_128 operator>(const Float32_128& a, const Float32_128& b); + friend Mask32_128 operator>=(const Float32_128& a, const Float32_128& b); + friend Mask32_128 operator==(const Float32_128& a, const Float32_128& b); + friend Mask32_128 operator!=(const Float32_128& a, const Float32_128& b); + + friend Mask32_128 isNan(const Float32_128& a); + friend Mask32_128 isFinite(const Float32_128& a); + + // ------------------------------------------------------ + // Constructors + // ------------------------------------------------------ + // Default constructor: + Mask32_128() : m_data(_mm_setzero_si128()) {} + Mask32_128(UninitializeTag) {} + // Constructor to broadcast the same value into all elements: + Mask32_128(const Mask32_128& class_simd) = default; + + Mask32_128& operator=(const Mask32_128& class_simd) = default; + + // ------------------------------------------------------ + // Setter + // ------------------------------------------------------ + + void setTrue() + { + m_data = _mm_set1_epi32(-1); + } + + // ------------------------------------------------------ + // Data member accessors + // ------------------------------------------------------ + KFP_SIMD_INLINE __m128i& simd() + { + return m_data; + } + KFP_SIMD_INLINE const __m128i& simd() const + { + return m_data; + } + KFP_SIMD_INLINE __m128 simdf() const + { + return _mm_castsi128_ps(m_data); + } + KFP_SIMD_INLINE bool operator[](int index) const + { + assert((index >= 0) && (index < int(SimdLen))); + alignas(SimdSize) int + data[SimdLen]{}; // Helper array + _mm_store_si128(reinterpret_cast<__m128i*>(data), m_data); + return data[index]; + } + + // ------------------------------------------------------ + // Print I/O + // ------------------------------------------------------ + // TODO + + // ------------------------------------------------------ + // Basic Arithmetic + // ------------------------------------------------------ + KFP_SIMD_INLINE bool isFull() const + { + return _mm_testc_si128(m_data, _mm_set1_epi32(-1)); + } + KFP_SIMD_INLINE bool isEmpty() const + { + return _mm_testz_si128(m_data, m_data); + } + + friend Mask32_128 operator!(const Mask32_128& a) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_xor_si128(_mm_set1_epi32(-1), a.m_data); + return result; + } + friend Mask32_128 operator^(const Mask32_128& a, const Mask32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_xor_si128(a.m_data, b.m_data); + return result; + } + friend Mask32_128 operator&&(const Mask32_128& a, const Mask32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_and_si128(a.m_data, b.m_data); + return result; + } + friend Mask32_128 operator||(const Mask32_128& a, const Mask32_128& b) + { + Mask32_128 result{UninitializeTag{}}; + result.m_data = _mm_or_si128(a.m_data, b.m_data); + return result; + } + + Mask32_128& operator&=(const Mask32_128& a) + { + *this = *this && a; + return *this; + } + + Mask32_128& operator|=(const Mask32_128& a) + { + *this = *this || a; + return *this; + } + + Mask32_128& operator^=(const Mask32_128& a) + { + *this = *this ^ a; + return *this; + } + +private: + alignas(SimdSize) __m128i m_data; +}; + +} // namespace SIMD +} // namespace KFP + +#endif // !SIMD_SSE_MASK32_H diff --git a/StRoot/KFParticle/KFPSimd/SSE/types.h b/StRoot/KFParticle/KFPSimd/SSE/types.h new file mode 100644 index 00000000000..09a148e4b16 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/SSE/types.h @@ -0,0 +1,40 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran; +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_SSE_TYPE_H +#define SIMD_SSE_TYPE_H + +#include "mask32.h" +#include "int32.h" +#include "float32.h" +#include +#include + +namespace KFP { +namespace SIMD { + +using simd_mask = Mask32_128; + +using simd_float = Float32_128; +static_assert(std::is_same::value, + "[Error]: Invalid value type for SSE float SimdClass."); + +using simd_int = Int32_128; +static_assert(std::is_same::value, + "[Error]: Invalid value type for SSE int SimdClass."); + +KFP_SIMD_INLINE Int32_128 toInt(const Float32_128& a) { return _mm_cvtps_epi32(a.simd()); } +KFP_SIMD_INLINE Float32_128 toFloat(const Int32_128& a) { return _mm_cvtepi32_ps(a.simd()); } + +KFP_SIMD_INLINE Int32_128 reinterpretAsInt(const Float32_128& a) { return _mm_castps_si128(a.simd()); } +KFP_SIMD_INLINE Float32_128 reinterpretAsFloat(const Int32_128& a) { return _mm_castsi128_ps(a.simd()); } + +} // namespace SIMD +} // namespace KFP + +#endif // !SIMD_SSE_TYPE_H diff --git a/StRoot/KFParticle/KFPSimd/Utils/macros.h b/StRoot/KFParticle/KFPSimd/Utils/macros.h new file mode 100644 index 00000000000..19a2c4dc528 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/Utils/macros.h @@ -0,0 +1,16 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran, P. Kisel, I. Kisel +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_MACROS_H +#define SIMD_MACROS_H + +#include "simd_detect.h" + +#define KFP_SIMD_INLINE inline __attribute__((always_inline)) + +#endif // !SIMD_MACROS_H diff --git a/StRoot/KFParticle/KFPSimd/Utils/memory.h b/StRoot/KFParticle/KFPSimd/Utils/memory.h new file mode 100644 index 00000000000..9d43f9ad896 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/Utils/memory.h @@ -0,0 +1,205 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran, P. Kisel, I. Kisel +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_ALLOCATE_H +#define SIMD_ALLOCATE_H + +#include +#include +#include +#include +#include +#include + +namespace KFP +{ +namespace SIMD +{ + +constexpr bool isAlignment(std::size_t N) +{ + return (N > 0) && ((N & (N - 1)) == 0); +} + +constexpr bool isAligned(std::size_t N, std::size_t alignment) +{ + return (N % alignment) == 0; +} + +template +inline void* alignedAllocate(std::size_t size) +{ + static_assert(alignment && isAlignment(alignment), "[Error] (KFP::SIMD::alignedAllocate): Invalid value given for aligment"); + if(!size) return nullptr; + + constexpr std::size_t voidptr_Alignment = alignof(void*); + constexpr std::size_t align_val = (alignment < voidptr_Alignment) ? voidptr_Alignment : alignment; + + constexpr std::size_t voidptr_Size = sizeof(void*); + std::size_t buffer_size = size + align_val + voidptr_Size; + void* original = ::operator new(buffer_size); + if (not original) return nullptr; + + void* aligned = static_cast(static_cast(original) + voidptr_Size); + // void* aligned = static_cast(static_cast(original) + voidptr_Size); + const std::uintptr_t tmp = reinterpret_cast(aligned) + align_val - 1; + const std::uintptr_t reminder = (tmp & (align_val - 1)); + const std::uintptr_t aligned_loc = (tmp - reminder); + aligned = reinterpret_cast(aligned_loc); + // aligned = reinterpret_cast(tmp & ~(align_val-1)); + + if (not isAligned(aligned_loc, align_val)) { + std::cerr << ("[Error] (KFP::SIMD::alignedAllocate): The allocated buffer is not aligned.\n"); + return nullptr; + } + + *(static_cast(aligned) - 1) = original; + + return aligned; +} + +inline void alignedDeallocate(void* ptr) +{ + if (ptr) { + ::operator delete(*(static_cast(ptr) - 1)); + } +} + +#define SETUP_ALIGNED_OPERATOR_NEW_DELETE(Alignment) \ + void* operator new(std::size_t size) \ + { \ + return KFP::SIMD::alignedAllocate(size); \ + } \ + void* operator new[](std::size_t size) \ + { \ + return KFP::SIMD::alignedAllocate(size); \ + } \ + void operator delete(void* ptr) \ + { \ + KFP::SIMD::alignedDeallocate(ptr); \ + } \ + void operator delete[](void* ptr) \ + { \ + KFP::SIMD::alignedDeallocate(ptr); \ + } \ + void operator delete(void* ptr, std::size_t /* sz */) \ + { \ + KFP::SIMD::alignedDeallocate(ptr); \ + } \ + void operator delete[](void* ptr, std::size_t /* sz */) \ + { \ + KFP::SIMD::alignedDeallocate(ptr); \ + } \ + void* operator new(std::size_t size, void* ptr) { return ::operator new(size, ptr); } \ + void* operator new[](std::size_t size, void* ptr) { return ::operator new[](size, ptr); } \ + void operator delete(void* memory, void* ptr) \ + { \ + return ::operator delete(memory, ptr); \ + } \ + void operator delete[](void* memory, void* ptr) \ + { \ + return ::operator delete[](memory, ptr); \ + } \ + + +template +class AlignedAllocator { + static_assert(isAlignment(Alignment), "[Error] (AlignedAllocator): Invalid value given for aligment"); + static_assert( + Alignment >= alignof(T), + "[Error] (AlignedAllocator): Types like int have minimum alignment requirements or access will result in crashes." + ); +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + template + struct rebind { + typedef AlignedAllocator other; + }; + + AlignedAllocator() noexcept + {} + template + AlignedAllocator(const AlignedAllocator&) noexcept + {} + + pointer address(reference x) const noexcept + { return std::addressof(x); } + + const_pointer address(const_reference x) const noexcept + { return std::addressof(x); } + + pointer allocate(size_type size, const_void_pointer = nullptr) + { + if (size == 0) { + return nullptr; + } + void* p = alignedAllocate(sizeof(T) * size); + if (!p) { + throw std::bad_alloc(); + } + return static_cast(p); + } + + void deallocate(pointer ptr, size_type) noexcept + { + alignedDeallocate(static_cast(ptr)); + } + + size_type max_size() const noexcept + { + return std::numeric_limits::max() / sizeof(T); + } + + template + void construct(U* ptr, const V& value) { + ::new(static_cast(ptr)) U(value); + } + + template + void construct(U* ptr) { + ::new(static_cast(ptr)) U(); + } + + template + void destroy(U* ptr) { + ptr->~U(); + } +}; + +template +inline bool +operator==(const AlignedAllocator&, + const AlignedAllocator&) noexcept +{ + return true; +} + +template +inline bool +operator!=(const AlignedAllocator&, + const AlignedAllocator&) noexcept +{ + return false; +} + +template +using Vector = std::vector>; + +} // namespace SIMD +} // namespace KFP + +#endif // !SIMD_ALLOCATE_H diff --git a/StRoot/KFParticle/KFPSimd/Utils/simd_detect.h b/StRoot/KFParticle/KFPSimd/Utils/simd_detect.h new file mode 100644 index 00000000000..3eaf0da0850 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/Utils/simd_detect.h @@ -0,0 +1,67 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran; +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_DETECT_H +#define SIMD_DETECT_H + +#include + +#ifndef KFP_SIMD_LEVEL + +#if defined(__AVX2__) +#define KFP_SIMD_AVX2 1 +#elif defined(__AVX__) +#define KFP_SIMD_AVX 1 +#else + #if defined(__SSE4_2__) + #define KFP_SIMD_SSE_4p2 1 + #elif defined(__SSE4_1__) || defined(__SSE2__) + #define KFP_SIMD_SSE_4p1 1 + #else + #define KFP_SIMD_Scalar 1 + #endif +#endif + +#else // KFP_SIMD_LEVEL + +#if KFP_SIMD_LEVEL > 3 // AVX2 supersedes SSE +#define KFP_SIMD_AVX2 1 +#elif KFP_SIMD_LEVEL > 2 // AVX supersedes SSE +#define KFP_SIMD_AVX 1 +#elif KFP_SIMD_LEVEL > 1 +#define KFP_SIMD_SSE_4p2 1 +#elif KFP_SIMD_LEVEL > 0 +#define KFP_SIMD_SSE_4p1 1 +#else +#define KFP_SIMD_Scalar 1 +#endif +#undef KFP_SIMD_LEVEL +#endif // KFP_SIMD_LEVEL + +#if defined(KFP_SIMD_AVX2) +#define KFP_SIMD_AVX 1 +#endif + +#if defined(KFP_SIMD_AVX) +#define KFP_SIMD_SSE_4p2 1 +#endif + +#if defined(KFP_SIMD_SSE_4p2) +#define KFP_SIMD_SSE_4p1 1 +#endif + +#if defined(KFP_SIMD_SSE_4p1) +#define KFP_SIMD_SSE 1 +#endif + +#if !defined(KFP_SIMD_Scalar) && !defined(KFP_SIMD_SSE) +#error \ + "[Error] (simd_detect.hpp): Invalid KFParticle SIMD implementation value was selected." +#endif + +#endif // !SIMD_DETECT_H diff --git a/StRoot/KFParticle/KFPSimd/Utils/tag.h b/StRoot/KFParticle/KFPSimd/Utils/tag.h new file mode 100644 index 00000000000..0d79f17643b --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/Utils/tag.h @@ -0,0 +1,118 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran; +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef SIMD_TAG_H +#define SIMD_TAG_H + +#include "macros.h" + +namespace KFP { +namespace SIMD { + +struct UninitializeTag {}; + +enum class Tag +{ + /// uses only fundamental types + Scalar, + // Entry to SSE versions + SSE, + /// x86 SSE + SSE2 + SSE2, + /// x86 SSE + SSE2 + SSE3 + SSE3, + /// x86 SSE + SSE2 + SSE3 + SSSE3 + SSSE3, + /// x86 SSE + SSE2 + SSE3 + SSSE3 + SSE4.1 + SSE41, + /// x86 SSE + SSE2 + SSE3 + SSSE3 + SSE4.1 + SSE4.2 + SSE42, + /// x86 AVX + AVX, + /// x86 AVX + AVX2 + AVX2, +}; + +// constexpr inline bool validateTag(Tag tag) +// { +// switch (tag) { +// case Tag::Scalar: +// return true; +// case Tag::SSE: +// return true; +// case Tag::SSE2: +// return true; +// case Tag::SSE3: +// return true; +// case Tag::SSSE3: +// return true; +// case Tag::SSE41: +// return true; +// case Tag::SSE42: +// return true; +// case Tag::AVX: +// return true; +// case Tag::AVX2: +// return true; +// default: +// return false; +// }; +// } + +constexpr inline Tag getTag() +{ +#if defined(__KFP_SIMD__AVX2) + return Tag::AVX; +#elif defined(__KFP_SIMD__AVX) + return Tag::AVX; +#elif defined(__KFP_SIMD__SSE) + #if defined(__KFP_SIMD__SSE4_2) + return Tag::SSE; + #elif defined(__KFP_SIMD__SSE4_1) + return Tag::SSE; + #elif defined(__KFP_SIMD__SSSE3) + return Tag::SSE; + #elif defined(__KFP_SIMD__SSE3) + return Tag::SSE; + #elif defined(__KFP_SIMD__SSE2) + return Tag::SSE; + #endif +#else + return Tag::Scalar; +#endif +} + +constexpr inline const char* getTagStr() +{ +#if defined(__KFP_SIMD__AVX2) + return "AVX2"; +#elif defined(__KFP_SIMD__AVX) + return "AVX"; +#elif defined(__KFP_SIMD__SSE) + #if defined(__KFP_SIMD__SSE4_2) + return "SSE4.2"; + #elif defined(__KFP_SIMD__SSE4_1) + return "SSE4.1"; + #elif defined(__KFP_SIMD__SSSE3) + return "SSSE3"; + #elif defined(__KFP_SIMD__SSE3) + return "SSE3"; + #elif defined(__KFP_SIMD__SSE2) + return "SSE2"; + #endif +#elif defined(__KFP_SIMD__Scalar) + return "Scalar"; +#else + return nullptr; +#endif +} + +} // namespace SIMD +} // namespace KFP + +#endif // !SIMD_TAG_H diff --git a/StRoot/KFParticle/KFPSimd/compile_flags.txt b/StRoot/KFParticle/KFPSimd/compile_flags.txt new file mode 100644 index 00000000000..0d2454f73a1 --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/compile_flags.txt @@ -0,0 +1,8 @@ +-xc++ +-std=c++11 +-march=native +-Wall +-Wextra +-pedantic +-Weffc++ +-Wsign-conversion diff --git a/StRoot/KFParticle/KFPSimd/simd.h b/StRoot/KFParticle/KFPSimd/simd.h new file mode 100644 index 00000000000..554fd00844d --- /dev/null +++ b/StRoot/KFParticle/KFPSimd/simd.h @@ -0,0 +1,28 @@ +// -*- C++ Header -*- +/* +================================================== +Authors: A.Mithran; +Emails: mithran@fias.uni-frankfurt.de +================================================== +*/ + +#ifndef KFP_SIMD_H +#define KFP_SIMD_H + +// Determine instruction set, and define platform-dependent functions +#include "Utils/macros.h" +// #include "Utils/memory.h" + +// Select appropriate header files depending on instruction set +#if defined(KFP_SIMD_AVX) +#error "[Error] (simd.h): KFParticle SIMD AVX not implemented." +// #include "AVX/types.h" +#elif defined(KFP_SIMD_SSE) +#include "SSE/types.h" +#else +#error "[Error] (simd.h): KFParticle SIMD Scalar not implemented." +// #include "Scalar/types.h" +#include "Scalar/types.h" +#endif + +#endif // !KFP_SIMD_H diff --git a/StRoot/KFParticle/KFPSimdAllocator.h b/StRoot/KFParticle/KFPSimdAllocator.h new file mode 100644 index 00000000000..a29d006581d --- /dev/null +++ b/StRoot/KFParticle/KFPSimdAllocator.h @@ -0,0 +1,119 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFPSimdAllocator_H +#define KFPSimdAllocator_H +#include +//#include + +/** @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 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 + struct rebind { + typedef KFPSimdAllocator 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 + KFPSimdAllocator (const KFPSimdAllocator&) throw() { } + virtual ~KFPSimdAllocator() throw() { } + + /** Return maximum number of elements that can be allocated. */ + size_type max_size () const throw() { + return std::numeric_limits::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( /*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(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(KFP::SIMD::SimdSize)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(KFP::SIMD::SimdSize)); } ///< 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/StRoot/KFParticle/KFPTrack.cxx b/StRoot/KFParticle/KFPTrack.cxx new file mode 100644 index 00000000000..f53a8a1cb83 --- /dev/null +++ b/StRoot/KFParticle/KFPTrack.cxx @@ -0,0 +1,116 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "KFPTrack.h" + +#ifdef __ROOT__ +#include "Riostream.h" +#include "TString.h" +#include "TMath.h" +#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]; + +} + +#ifdef __ROOT__ //for the STAR experiment +//________________________________________________________________________________ +void KFPTrack::Print(Option_t *opt) const { std::cout << *this << std::endl; } +std::ostream& operator<<(std::ostream& os, KFPTrack const & track) { + static const Char_t *vn[14] = {"x","y","z","px","py","pz","E","S","M","t","p","Q","Chi2","NDF"}; + os << Form("t(%4i)",track.Id()); + for (Int_t i = 0; i < 6; i++) { + if (i == 6) continue; // E + if (i == 7 && track.GetParameter(i) <= 0.0) continue; // S + if (track.GetParameter(i) == 0. && track.GetCovariance(i*((i+1)/2+1)) == 0) continue; + if (track.GetCovariance(i*((i+1)/2+1)) > 0) + os << Form(" %s:%8.3f+/-%6.3f", vn[i], track.GetParameter(i), TMath::Sqrt(track.GetCovariance(i*((i+1)/2+1)))); + else + os << Form(" %s:%8.3f", vn[i], track.GetParameter(i)); + } + os << Form(" Q:%2i chi2/NDF :%8.2f/%2i",track.Charge(),track.GetChi2(),track.GetNDF()); + return os; +} +#endif /* __ROOT__ */ diff --git a/StRoot/KFParticle/KFPTrack.h b/StRoot/KFParticle/KFPTrack.h new file mode 100644 index 00000000000..862cde25ff4 --- /dev/null +++ b/StRoot/KFParticle/KFPTrack.h @@ -0,0 +1,236 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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 +#include "TObject.h" +class KFPTrack +#ifdef __ROOT__ +: public TObject +#endif +{ + +public: + KFPTrack():fChi2(-1.f), fQ(0), fNDF(-1), fId(-1) { } + virtual ~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 +#ifdef __ROOT__ //for the STAR experiment + virtual void Print(Option_t *opt="") const; +#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 +}; +#ifdef __ROOT__ //for the STAR experiment +std::ostream& operator<<(std::ostream& os, KFPTrack const & track); +#endif + +#endif diff --git a/StRoot/KFParticle/KFPTrackVector.cxx b/StRoot/KFParticle/KFPTrackVector.cxx new file mode 100644 index 00000000000..68a8ecad1a0 --- /dev/null +++ b/StRoot/KFParticle/KFPTrackVector.cxx @@ -0,0 +1,419 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "KFPTrackVector.h" +#include "KFParticleMath.h" +#include + +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(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fP[iP][iElement]); + vec.gather(&(track.fP[iP][0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fP[iP][iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fC[iC][iElement]); + vec.gather(&(track.fC[iC][0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fC[iC][iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fField[iP][iElement]); + vec.gather(&(track.fField[iP][0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + float32_v& vec = reinterpret_cast(fField[iP][iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fId[iElement]); + vec.gather(&(track.fId[0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fId[iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fPDG[iElement]); + vec.gather(&(track.fPDG[0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fPDG[iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fQ[iElement]); + vec.gather(&(track.fQ[0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fQ[iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fPVIndex[iElement]); + vec.gather(&(track.fPVIndex[0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fPVIndex[iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fNPixelHits[iElement]); + vec.gather(&(track.fNPixelHits[0]), index); + } + const int32_v& index = reinterpret_cast(trackIndex[iElement]); + int32_v& vec = reinterpret_cast(fNPixelHits[iElement]); + const int32_v correctedIndices = select(int32_v::indicesSequence(iElement)(fP[0][firstElement]); + const float32_v yInit = reinterpret_cast(fP[1][firstElement]); + + float32_v& x = reinterpret_cast(fP[0][firstElement]); + float32_v& y = reinterpret_cast(fP[1][firstElement]); + + x = -(xInit*sA + yInit*cA); + y = xInit*cA - yInit*sA; + + const float32_v pxInit = reinterpret_cast(fP[3][firstElement]); + const float32_v pyInit = reinterpret_cast(fP[4][firstElement]); + + float32_v& px = reinterpret_cast(fP[3][firstElement]); + float32_v& py = reinterpret_cast(fP[4][firstElement]); + + px = -(pxInit*sA + pyInit*cA); + py = pxInit*cA - pyInit*sA; + + float32_v cov[21]; + for(int iC=0; iC<21; iC++) + cov[iC] = reinterpret_cast(fC[iC][firstElement]); + + reinterpret_cast(fC[0][firstElement]) = cA*cA* cov[2] + 2* cA* cov[1]* sA + cov[0]*sA* sA; + + reinterpret_cast(fC[1][firstElement]) = -(cA*cA * cov[1]) + cA* (-cov[0] + cov[2])* sA + cov[1]*sA* sA; + reinterpret_cast(fC[2][firstElement]) = cA*cA* cov[0] - 2* cA* cov[1]* sA + cov[2]*sA* sA; + + reinterpret_cast(fC[3][firstElement]) = -(cA* cov[4]) - cov[3]* sA; + reinterpret_cast(fC[4][firstElement]) = cA* cov[3] - cov[4]* sA; +// reinterpret_cast(fC[5][firstElement]) = cov[5]; + + reinterpret_cast(fC[6][firstElement]) = cA*cA* cov[11] + cA *(cov[10] + cov[7])* sA + cov[6]*sA* sA; + reinterpret_cast(fC[7][firstElement]) = -(cA*cA * cov[10]) + cA* (cov[11] - cov[6])* sA + cov[7] *sA*sA; + reinterpret_cast(fC[8][firstElement]) = -(cA *cov[12]) - cov[8] *sA; + reinterpret_cast(fC[9][firstElement]) = cA*cA* cov[14] + 2 *cA* cov[13]* sA + cov[9]* sA*sA; + + reinterpret_cast(fC[10][firstElement]) = -(cA*cA* cov[7]) + cA* (cov[11] - cov[6])* sA + cov[10]*sA* sA; + reinterpret_cast(fC[11][firstElement]) = cA*cA* cov[6] - cA* (cov[10] + cov[7]) *sA + cov[11]*sA* sA; + reinterpret_cast(fC[12][firstElement]) = cA* cov[8] - cov[12]* sA; + reinterpret_cast(fC[13][firstElement]) = -(cA*cA* cov[13]) + cA* (cov[14] - cov[9])* sA + cov[13]* sA*sA; + reinterpret_cast(fC[14][firstElement]) = cA*cA* cov[9] - 2* cA* cov[13]* sA + cov[14]* sA*sA; + + reinterpret_cast(fC[15][firstElement]) = -(cA* cov[16]) - cov[15]* sA; + reinterpret_cast(fC[16][firstElement]) = cA* cov[15] - cov[16]* sA; +// reinterpret_cast(fC[17][firstElement]) = cov[17]; + reinterpret_cast(fC[18][firstElement]) = -(cA* cov[19]) - cov[18]* sA; + reinterpret_cast(fC[19][firstElement]) = cA* cov[18] - cov[19]* sA; +// reinterpret_cast(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 + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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, He6, Li6, Li7, Be7, Sigmas. + **/ + +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), fNHe6(0), fNLi6(0), fNLi7(0), fNBe7(0), fNSigma(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_int& 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 float32_v& value, int iP, int iTr); + void SetCovariance(const float32_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 SetLastHe6 (int n) { fNHe6 = n; } ///< Sets index of the last He6. + void SetLastLi6 (int n) { fNLi6 = n; } ///< Sets index of the last Li6. + void SetLastLi7 (int n) { fNLi7 = n; } ///< Sets index of the last Li7. + void SetLastBe7 (int n) { fNBe7 = n; } ///< Sets index of the last Be7. + void SetLastSigma (int n) { fNSigma = n; } ///< Sets index of the last Sigma. + + 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; fNHe6 = 0; fNLi6 = 0; fNLi7 = 0; fNBe7 = 0; fNSigma = 0; + for(int i=0; i(fP[iP][iTr]) = value; + else + for(int i=0; i= Size()) continue; + fP[iP][iTr+i] = value[i]; + } +} + +inline void KFPTrackVector::SetCovariance(const float32_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+SimdLen) < Size()) + reinterpret_cast(fC[iC][iTr]) = value; + else + for(int i=0; i= Size()) continue; + fC[iC][iTr+i] = value[i]; + } +} + +inline 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]); + + track.SetCovariance( 0,fC[ 0][n]); + track.SetCovariance( 1,fC[ 1][n]); + track.SetCovariance( 2,fC[ 2][n]); + track.SetCovariance( 3,fC[ 3][n]); + track.SetCovariance( 4,fC[ 4][n]); + track.SetCovariance( 5,fC[ 5][n]); + track.SetCovariance( 6,fC[ 6][n]); + track.SetCovariance( 7,fC[ 7][n]); + track.SetCovariance( 8,fC[ 8][n]); + track.SetCovariance( 9,fC[ 9][n]); + track.SetCovariance(10,fC[10][n]); + track.SetCovariance(11,fC[11][n]); + track.SetCovariance(12,fC[12][n]); + track.SetCovariance(13,fC[13][n]); + track.SetCovariance(14,fC[14][n]); + track.SetCovariance(15,fC[15][n]); + track.SetCovariance(16,fC[16][n]); + track.SetCovariance(17,fC[17][n]); + track.SetCovariance(18,fC[18][n]); + track.SetCovariance(19,fC[19][n]); + track.SetCovariance(20,fC[20][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 +} +#endif diff --git a/StRoot/KFParticle/KFPVertex.cxx b/StRoot/KFParticle/KFPVertex.cxx new file mode 100644 index 00000000000..3dc788201b6 --- /dev/null +++ b/StRoot/KFParticle/KFPVertex.cxx @@ -0,0 +1,30 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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/StRoot/KFParticle/KFPVertex.h b/StRoot/KFParticle/KFPVertex.h new file mode 100644 index 00000000000..ef7c76d27a6 --- /dev/null +++ b/StRoot/KFParticle/KFPVertex.h @@ -0,0 +1,134 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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/StRoot/KFParticle/KFParticle.cxx b/StRoot/KFParticle/KFParticle.cxx new file mode 100644 index 00000000000..9cfdebb5f0a --- /dev/null +++ b/StRoot/KFParticle/KFParticle.cxx @@ -0,0 +1,4086 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * 2007-2019 Sergey Gorbunov + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#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 + +#ifdef __ROOT__ +#include "TClass.h" +#include "TRSymMatrix.h" +#include "TRVector.h" +#include + +KFParticle::KFParticle() :fChi2(0), SumDaughterMass(0), fMassHypo(-1), fNDF(-3), + fId(-1), fParentID(0), fIdTruth(0), fQuality(0), fIdParentMcVx(0), + fQ(0), fConstructMethod(0), fPDG(0), fDaughtersIds() +{ + static Bool_t first = kTRUE; + if (first) { + first = kFALSE; + KFParticle::Class()->IgnoreTObjectStreamer(); + } + //* Constructor + Clear(); +} + +void KFParticle::Clear(Option_t *option) { + Initialize(); + fIdTruth = 0; + fQuality = 0; + fIdParentMcVx = 0; + fParentID = 0; +} + +void KFParticle::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 KFParticle& 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__ +KFParticle::KFParticle() : fChi2(0), + SumDaughterMass(0), fMassHypo(-1), fNDF(-3), fId(-1), 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 + +KFParticle::KFParticle( const KFPTrack &track, const int PID ): KFParticle() +{ + /** 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); + + float energy = sqrt( mass*mass + fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]); + fP[6] = energy; + fP[7] = 0; + fNDF = track.GetNDF(); + fChi2 = track.GetChi2(); + + float energyInv = 1./energy; + float h0 = fP[3]*energyInv; + float h1 = fP[4]*energyInv; + float 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; + + SetPDG(PID); +#ifdef NonhomogeneousField + for(int iF=0; iF<10; iF++) + SetFieldCoeff( track.GetFieldCoeff()[iF], iF); +#endif +} + +KFParticle::KFParticle( const KFPVertex &vertex ): KFParticle() +{ + /** 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; +} + +void KFParticle::operator +=( const KFParticle &Daughter ) +{ + /** Operator to add daughter to the current particle. Calls AddDaughter() function. + ** \param[in] Daughter - the daughter particle + **/ + AddDaughter( Daughter ); +} + +bool KFParticle::GetMeasurement( const KFParticle& 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 F1[36]; + daughter.Transport(dS, dsdr, m, V, dsdp, nullptr, F1); + + float VFT[3][3]; + VFT[0][0] = fC[0]*F1[ 0] + fC[1]*F1[ 1] + fC[3]*F1[ 2]; + VFT[0][1] = fC[0]*F1[ 6] + fC[1]*F1[ 7] + fC[3]*F1[ 8]; + VFT[0][2] = fC[0]*F1[12] + fC[1]*F1[13] + fC[3]*F1[14]; + + VFT[1][0] = fC[1]*F1[ 0] + fC[2]*F1[ 1] + fC[4]*F1[ 2]; + VFT[1][1] = fC[1]*F1[ 6] + fC[2]*F1[ 7] + fC[4]*F1[ 8]; + VFT[1][2] = fC[1]*F1[12] + fC[2]*F1[13] + fC[4]*F1[14]; + + VFT[2][0] = fC[3]*F1[ 0] + fC[4]*F1[ 1] + fC[5]*F1[ 2]; + VFT[2][1] = fC[3]*F1[ 6] + fC[4]*F1[ 7] + fC[5]*F1[ 8]; + VFT[2][2] = fC[3]*F1[12] + fC[4]*F1[13] + fC[5]*F1[14]; + + float FVFT[6]; + FVFT[0] = F1[ 0]*VFT[0][0] + F1[ 1]*VFT[1][0] + F1[ 2]*VFT[2][0]; + FVFT[1] = F1[ 6]*VFT[0][0] + F1[ 7]*VFT[1][0] + F1[ 8]*VFT[2][0]; + FVFT[2] = F1[ 6]*VFT[0][1] + F1[ 7]*VFT[1][1] + F1[ 8]*VFT[2][1]; + FVFT[3] = F1[12]*VFT[0][0] + F1[13]*VFT[1][0] + F1[14]*VFT[2][0]; + FVFT[4] = F1[12]*VFT[0][1] + F1[13]*VFT[1][1] + F1[14]*VFT[2][1]; + FVFT[5] = F1[12]*VFT[0][2] + F1[13]*VFT[1][2] + F1[14]*VFT[2][2]; + + 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]; + V[1] += FVFT[1]; + V[2] += FVFT[2]; + V[3] += FVFT[3]; + V[4] += FVFT[4]; + V[5] += FVFT[5]; + } + + return 1; +} + +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 + **/ + + AddDaughterId( Daughter.Id() ); + + if( fNDF<-1 ){ // first daughter -> just copy +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + SetFieldCoeff(Daughter.GetFieldCoeff()[i], i); +#endif + 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]; + fMassHypo = Daughter.fMassHypo; + SumDaughterMass = Daughter.SumDaughterMass; + return; + } + + if(static_cast(fConstructMethod) == 0) + AddDaughterWithEnergyFit(Daughter); + else if(static_cast(fConstructMethod) == 2) + AddDaughterWithEnergyFitMC(Daughter); + + SumDaughterMass += Daughter.SumDaughterMass; + fMassHypo = -1; +} + +void KFParticle::AddDaughterWithEnergyFit( const KFParticle &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 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(); + fChi2 += dChi2; + + } +} + +void KFParticle::SubtractDaughter( const KFParticle &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 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(); + fChi2 += dChi2; +} + +void KFParticle::AddDaughterWithEnergyFitMC( const KFParticle &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 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(); + 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 KFParticle::SetProductionVertex( const KFParticle &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; + + { + 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; + + { + 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]; + } + } + } +} + +void KFParticle::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 KFParticle::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) * ( px*px*fC[9] + py*py*fC[14] + pz*pz*fC[20] + energy*energy*fC[27] + + float(2.f) * ( px*py*fC[13] + pz*(px*fC[18]+py*fC[19]) - energy*(px*fC[24]+py*fC[25]+pz*fC[26]) ) ); + const float dChi2 = residual*residual / dm2; + fChi2 += dChi2; + fNDF += 1; + + float mJ[7][7]; + SetMassConstraint( fP, fC, mJ, mass ); + fMassHypo = mass; + SumDaughterMass = mass; +} + +void KFParticle::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 KFParticle::Construct( const KFParticle* vDaughters[], Int_t nDaughters, const KFParticle *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=0 ) SetMassConstraint( Mass ); + if( Parent ) SetProductionVertex( *Parent ); +} + +void KFParticle::SubtractFromVertex( KFParticle &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 KFParticle::SubtractFromParticle( KFParticle &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.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 KFParticle::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; i1.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); + float 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 KFParticle::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 KFParticle::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 KFParticle::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 KFParticle::GetDStoCylinderBz( const float B, const float R, float dS[2]) const +{ + /** Calculates 2 dS = l/p parameters from a particle to a cylinder with a radius R and center at (0,0) \n + ** 1) l - signed distance to the cylinder; \n + ** 2) p - momentum of the particle; \n + ** \param[in] B - magnetic field Bz + ** \param[in] R - radius of the cylinder + ** \param[out] dS - l/p for two points of the closest approach with the cylinder + **/ + + //* Get dS to another particle for Bz field + const float kCLight = 0.000299792458f; + + //in XY plane + //first root + const float& bq1 = B*static_cast(fQ)*kCLight; + const float& bq2 = B*kCLight; + + const bool& isStraight = fabsf(bq1) < float(1.e-8f); + + const float& px1 = fP[3]; + const float& py1 = fP[4]; + + const float& px2 = R*bq2; + const float& py2 = 0; + + const float& pt12 = px1*px1 + py1*py1; + const float& pt22 = px2*px2 + py2*py2; + + const float& x01 = fP[0]; + const float& y01 = fP[1]; + + const float& x02 = 0; + const float& y02 = R; + + 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& 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& kp = (dxyp1*bq2 - dxyp2*bq1 - p1p2); + const float& kd = dr02/2.f*bq1*bq2 + kp; + const float& c1 = -(bq1*kd + pt12*bq2); + + float d1 = pt12*pt22 - kd*kd; + d1 = d1 < 0.f ? 0.f : d1; + d1 = sqrt( d1 ); + + // find two points of closest approach in XY plane + if( ! isStraight ) + { + dS[0] = std::atan2( (bq1*k11*c1 + k21*d1*bq1), (bq1*k11*d1*bq1 - k21*c1) )/bq1; + dS[1] = std::atan2( (bq1*k11*c1 - k21*d1*bq1), (-bq1*k11*d1*bq1 - k21*c1) )/bq1; + } + else if(pt12>0.f) + { + dS[0] = (k11*c1 + k21*d1)/(- k21*c1); + dS[1] = (k11*c1 - k21*d1)/(- k21*c1); + } +} + +void KFParticle::GetDStoParticleBz( float Bz, const KFParticle &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 KFParticle::GetDStoParticleBy( float B, const KFParticle &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 KFParticle::GetDStoParticleLine( const KFParticle &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 KFParticle::GetDStoParticleCBM( const KFParticle &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 KFParticle::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 ); +} + +void KFParticle::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 KFParticle::TransportBz( float Bz, float dS, const float* dsdr, float P[], float C[], float* dsdr1, float* F, float* F1, const bool fullC ) 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.000299792458f; + Bz = Bz*fQ*kCLight; + float bs= Bz*dS; + float s = sin(bs), c = cos(bs); + + float sB, cB; + if( fabs(bs)>1.e-10f){ + sB= s/Bz; + cB= (1.f-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[6][6]; + for( Int_t i=0; i<6; i++ ) + for( Int_t j=0; j<6; j++) + mJ[i][j]=0; + + for(int i=0; i<6; 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; + + const float cPx = c * px; + const float sPy = s * py; + mJ[0][0] += cPx * dsdr[0] + sPy * dsdr[0]; + mJ[0][1] += cPx * dsdr[1] + sPy * dsdr[1]; + mJ[0][2] += cPx * dsdr[2] + sPy * dsdr[2]; + mJ[0][3] += cPx * dsdr[3] + sPy * dsdr[3]; + mJ[0][4] += cPx * dsdr[4] + sPy * dsdr[4]; + mJ[0][5] += cPx * dsdr[5] + sPy * dsdr[5]; + + const float sPx = s * px; + const float cPy = c * py; + mJ[1][0] -= sPx * dsdr[0] - cPy * dsdr[0]; + mJ[1][1] -= sPx * dsdr[1] - cPy * dsdr[1]; + mJ[1][2] -= sPx * dsdr[2] - cPy * dsdr[2]; + mJ[1][3] -= sPx * dsdr[3] - cPy * dsdr[3]; + mJ[1][4] -= sPx * dsdr[4] - cPy * dsdr[4]; + mJ[1][5] -= sPx * dsdr[5] - cPy * dsdr[5]; + + mJ[2][0] += pz*dsdr[0]; + mJ[2][1] += pz*dsdr[1]; + mJ[2][2] += pz*dsdr[2]; + mJ[2][3] += pz*dsdr[3]; + mJ[2][4] += pz*dsdr[4]; + mJ[2][5] += pz*dsdr[5]; + + const float sBzPx = Bz * sPx; + const float cBzPy = Bz * cPy; + mJ[3][0] -= sBzPx * dsdr[0] - cBzPy * dsdr[0]; + mJ[3][1] -= sBzPx * dsdr[1] - cBzPy * dsdr[1]; + mJ[3][2] -= sBzPx * dsdr[2] - cBzPy * dsdr[2]; + mJ[3][3] -= sBzPx * dsdr[3] - cBzPy * dsdr[3]; + mJ[3][4] -= sBzPx * dsdr[4] - cBzPy * dsdr[4]; + mJ[3][5] -= sBzPx * dsdr[5] - cBzPy * dsdr[5]; + + const float cBzPx = Bz * cPx; + const float sBzPy = Bz * sPy; + mJ[4][0] -= cBzPx * dsdr[0] + sBzPy * dsdr[0]; + mJ[4][1] -= cBzPx * dsdr[1] + sBzPy * dsdr[1]; + mJ[4][2] -= cBzPx * dsdr[2] + sBzPy * dsdr[2]; + mJ[4][3] -= cBzPx * dsdr[3] + sBzPy * dsdr[3]; + mJ[4][4] -= cBzPx * dsdr[4] + sBzPy * dsdr[4]; + mJ[4][5] -= cBzPx * dsdr[5] + sBzPy * dsdr[5]; + + if(F) { + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + F[i*6+j] = mJ[i][j]; + } + + float CJt[6][5]; + + CJt[0][0] = fC[ 0]*mJ[0][0] + fC[ 1]*mJ[0][1] + fC[ 3]*mJ[0][2] + fC[ 6]*mJ[0][3] + fC[10]*mJ[0][4] + fC[15]*mJ[0][5]; + CJt[0][1] = fC[ 0]*mJ[1][0] + fC[ 1]*mJ[1][1] + fC[ 3]*mJ[1][2] + fC[ 6]*mJ[1][3] + fC[10]*mJ[1][4] + fC[15]*mJ[1][5]; + CJt[0][2] = fC[ 0]*mJ[2][0] + fC[ 1]*mJ[2][1] + fC[ 3]*mJ[2][2] + fC[ 6]*mJ[2][3] + fC[10]*mJ[2][4] + fC[15]*mJ[2][5]; + CJt[0][3] = fC[ 0]*mJ[3][0] + fC[ 1]*mJ[3][1] + fC[ 3]*mJ[3][2] + fC[ 6]*mJ[3][3] + fC[10]*mJ[3][4] + fC[15]*mJ[3][5]; + CJt[0][4] = fC[ 0]*mJ[4][0] + fC[ 1]*mJ[4][1] + fC[ 3]*mJ[4][2] + fC[ 6]*mJ[4][3] + fC[10]*mJ[4][4] + fC[15]*mJ[4][5]; + + CJt[1][0] = fC[ 1]*mJ[0][0] + fC[ 2]*mJ[0][1] + fC[ 4]*mJ[0][2] + fC[ 7]*mJ[0][3] + fC[11]*mJ[0][4] + fC[16]*mJ[0][5]; + CJt[1][1] = fC[ 1]*mJ[1][0] + fC[ 2]*mJ[1][1] + fC[ 4]*mJ[1][2] + fC[ 7]*mJ[1][3] + fC[11]*mJ[1][4] + fC[16]*mJ[1][5]; + CJt[1][2] = fC[ 1]*mJ[2][0] + fC[ 2]*mJ[2][1] + fC[ 4]*mJ[2][2] + fC[ 7]*mJ[2][3] + fC[11]*mJ[2][4] + fC[16]*mJ[2][5]; + CJt[1][3] = fC[ 1]*mJ[3][0] + fC[ 2]*mJ[3][1] + fC[ 4]*mJ[3][2] + fC[ 7]*mJ[3][3] + fC[11]*mJ[3][4] + fC[16]*mJ[3][5]; + CJt[1][4] = fC[ 1]*mJ[4][0] + fC[ 2]*mJ[4][1] + fC[ 4]*mJ[4][2] + fC[ 7]*mJ[4][3] + fC[11]*mJ[4][4] + fC[16]*mJ[4][5]; + + CJt[2][0] = fC[ 3]*mJ[0][0] + fC[ 4]*mJ[0][1] + fC[ 5]*mJ[0][2] + fC[ 8]*mJ[0][3] + fC[12]*mJ[0][4] + fC[17]*mJ[0][5]; + CJt[2][1] = fC[ 3]*mJ[1][0] + fC[ 4]*mJ[1][1] + fC[ 5]*mJ[1][2] + fC[ 8]*mJ[1][3] + fC[12]*mJ[1][4] + fC[17]*mJ[1][5]; + CJt[2][2] = fC[ 3]*mJ[2][0] + fC[ 4]*mJ[2][1] + fC[ 5]*mJ[2][2] + fC[ 8]*mJ[2][3] + fC[12]*mJ[2][4] + fC[17]*mJ[2][5]; + CJt[2][3] = fC[ 3]*mJ[3][0] + fC[ 4]*mJ[3][1] + fC[ 5]*mJ[3][2] + fC[ 8]*mJ[3][3] + fC[12]*mJ[3][4] + fC[17]*mJ[3][5]; + CJt[2][4] = fC[ 3]*mJ[4][0] + fC[ 4]*mJ[4][1] + fC[ 5]*mJ[4][2] + fC[ 8]*mJ[4][3] + fC[12]*mJ[4][4] + fC[17]*mJ[4][5]; + + CJt[3][0] = fC[ 6]*mJ[0][0] + fC[ 7]*mJ[0][1] + fC[ 8]*mJ[0][2] + fC[ 9]*mJ[0][3] + fC[13]*mJ[0][4] + fC[18]*mJ[0][5]; + CJt[3][1] = fC[ 6]*mJ[1][0] + fC[ 7]*mJ[1][1] + fC[ 8]*mJ[1][2] + fC[ 9]*mJ[1][3] + fC[13]*mJ[1][4] + fC[18]*mJ[1][5]; + CJt[3][2] = fC[ 6]*mJ[2][0] + fC[ 7]*mJ[2][1] + fC[ 8]*mJ[2][2] + fC[ 9]*mJ[2][3] + fC[13]*mJ[2][4] + fC[18]*mJ[2][5]; + CJt[3][3] = fC[ 6]*mJ[3][0] + fC[ 7]*mJ[3][1] + fC[ 8]*mJ[3][2] + fC[ 9]*mJ[3][3] + fC[13]*mJ[3][4] + fC[18]*mJ[3][5]; + CJt[3][4] = fC[ 6]*mJ[4][0] + fC[ 7]*mJ[4][1] + fC[ 8]*mJ[4][2] + fC[ 9]*mJ[4][3] + fC[13]*mJ[4][4] + fC[18]*mJ[4][5]; + + CJt[4][0] = fC[10]*mJ[0][0] + fC[11]*mJ[0][1] + fC[12]*mJ[0][2] + fC[13]*mJ[0][3] + fC[14]*mJ[0][4] + fC[19]*mJ[0][5]; + CJt[4][1] = fC[10]*mJ[1][0] + fC[11]*mJ[1][1] + fC[12]*mJ[1][2] + fC[13]*mJ[1][3] + fC[14]*mJ[1][4] + fC[19]*mJ[1][5]; + CJt[4][2] = fC[10]*mJ[2][0] + fC[11]*mJ[2][1] + fC[12]*mJ[2][2] + fC[13]*mJ[2][3] + fC[14]*mJ[2][4] + fC[19]*mJ[2][5]; + CJt[4][3] = fC[10]*mJ[3][0] + fC[11]*mJ[3][1] + fC[12]*mJ[3][2] + fC[13]*mJ[3][3] + fC[14]*mJ[3][4] + fC[19]*mJ[3][5]; + CJt[4][4] = fC[10]*mJ[4][0] + fC[11]*mJ[4][1] + fC[12]*mJ[4][2] + fC[13]*mJ[4][3] + fC[14]*mJ[4][4] + fC[19]*mJ[4][5]; + + CJt[5][0] = fC[15]*mJ[0][0] + fC[16]*mJ[0][1] + fC[17]*mJ[0][2] + fC[18]*mJ[0][3] + fC[19]*mJ[0][4] + fC[20]*mJ[0][5]; + CJt[5][1] = fC[15]*mJ[1][0] + fC[16]*mJ[1][1] + fC[17]*mJ[1][2] + fC[18]*mJ[1][3] + fC[19]*mJ[1][4] + fC[20]*mJ[1][5]; + CJt[5][2] = fC[15]*mJ[2][0] + fC[16]*mJ[2][1] + fC[17]*mJ[2][2] + fC[18]*mJ[2][3] + fC[19]*mJ[2][4] + fC[20]*mJ[2][5]; + CJt[5][3] = fC[15]*mJ[3][0] + fC[16]*mJ[3][1] + fC[17]*mJ[3][2] + fC[18]*mJ[3][3] + fC[19]*mJ[3][4] + fC[20]*mJ[3][5]; + CJt[5][4] = fC[15]*mJ[4][0] + fC[16]*mJ[4][1] + fC[17]*mJ[4][2] + fC[18]*mJ[4][3] + fC[19]*mJ[4][4] + fC[20]*mJ[4][5]; + + + + C[ 0] = mJ[0][0]*CJt[0][0] + mJ[0][1]*CJt[1][0] + mJ[0][2]*CJt[2][0] + mJ[0][3]*CJt[3][0] + mJ[0][4]*CJt[4][0] + mJ[0][5]*CJt[5][0]; + + C[ 1] = mJ[1][0]*CJt[0][0] + mJ[1][1]*CJt[1][0] + mJ[1][2]*CJt[2][0] + mJ[1][3]*CJt[3][0] + mJ[1][4]*CJt[4][0] + mJ[1][5]*CJt[5][0]; + C[ 2] = mJ[1][0]*CJt[0][1] + mJ[1][1]*CJt[1][1] + mJ[1][2]*CJt[2][1] + mJ[1][3]*CJt[3][1] + mJ[1][4]*CJt[4][1] + mJ[1][5]*CJt[5][1]; + + C[ 3] = mJ[2][0]*CJt[0][0] + mJ[2][1]*CJt[1][0] + mJ[2][2]*CJt[2][0] + mJ[2][3]*CJt[3][0] + mJ[2][4]*CJt[4][0] + mJ[2][5]*CJt[5][0]; + C[ 4] = mJ[2][0]*CJt[0][1] + mJ[2][1]*CJt[1][1] + mJ[2][2]*CJt[2][1] + mJ[2][3]*CJt[3][1] + mJ[2][4]*CJt[4][1] + mJ[2][5]*CJt[5][1]; + C[ 5] = mJ[2][0]*CJt[0][2] + mJ[2][1]*CJt[1][2] + mJ[2][2]*CJt[2][2] + mJ[2][3]*CJt[3][2] + mJ[2][4]*CJt[4][2] + mJ[2][5]*CJt[5][2]; + + if(fullC){ + C[ 6] = mJ[3][0]*CJt[0][0] + mJ[3][1]*CJt[1][0] + mJ[3][2]*CJt[2][0] + mJ[3][3]*CJt[3][0] + mJ[3][4]*CJt[4][0] + mJ[3][5]*CJt[5][0]; + C[ 7] = mJ[3][0]*CJt[0][1] + mJ[3][1]*CJt[1][1] + mJ[3][2]*CJt[2][1] + mJ[3][3]*CJt[3][1] + mJ[3][4]*CJt[4][1] + mJ[3][5]*CJt[5][1]; + C[ 8] = mJ[3][0]*CJt[0][2] + mJ[3][1]*CJt[1][2] + mJ[3][2]*CJt[2][2] + mJ[3][3]*CJt[3][2] + mJ[3][4]*CJt[4][2] + mJ[3][5]*CJt[5][2]; + C[ 9] = mJ[3][0]*CJt[0][3] + mJ[3][1]*CJt[1][3] + mJ[3][2]*CJt[2][3] + mJ[3][3]*CJt[3][3] + mJ[3][4]*CJt[4][3] + mJ[3][5]*CJt[5][3]; + + C[10] = mJ[4][0]*CJt[0][0] + mJ[4][1]*CJt[1][0] + mJ[4][2]*CJt[2][0] + mJ[4][3]*CJt[3][0] + mJ[4][4]*CJt[4][0] + mJ[4][5]*CJt[5][0]; + C[11] = mJ[4][0]*CJt[0][1] + mJ[4][1]*CJt[1][1] + mJ[4][2]*CJt[2][1] + mJ[4][3]*CJt[3][1] + mJ[4][4]*CJt[4][1] + mJ[4][5]*CJt[5][1]; + C[12] = mJ[4][0]*CJt[0][2] + mJ[4][1]*CJt[1][2] + mJ[4][2]*CJt[2][2] + mJ[4][3]*CJt[3][2] + mJ[4][4]*CJt[4][2] + mJ[4][5]*CJt[5][2]; + C[13] = mJ[4][0]*CJt[0][3] + mJ[4][1]*CJt[1][3] + mJ[4][2]*CJt[2][3] + mJ[4][3]*CJt[3][3] + mJ[4][4]*CJt[4][3] + mJ[4][5]*CJt[5][3]; + C[14] = mJ[4][0]*CJt[0][4] + mJ[4][1]*CJt[1][4] + mJ[4][2]*CJt[2][4] + mJ[4][3]*CJt[3][4] + mJ[4][4]*CJt[4][4] + mJ[4][5]*CJt[5][4]; + + C[15] = CJt[5][0]; + C[16] = CJt[5][1]; + C[17] = CJt[5][2]; + C[18] = CJt[5][3]; + C[19] = CJt[5][4]; + C[20] = fC[20]; + + const float C21 = fC[21]*mJ[0][0] + fC[22]*mJ[0][1] + fC[23]*mJ[0][2] + fC[24]*mJ[0][3] + fC[25]*mJ[0][4] + fC[26]*mJ[0][5]; + const float C22 = fC[21]*mJ[1][0] + fC[22]*mJ[1][1] + fC[23]*mJ[1][2] + fC[24]*mJ[1][3] + fC[25]*mJ[1][4] + fC[26]*mJ[1][5]; + const float C23 = fC[21]*mJ[2][0] + fC[22]*mJ[2][1] + fC[23]*mJ[2][2] + fC[24]*mJ[2][3] + fC[25]*mJ[2][4] + fC[26]*mJ[2][5]; + const float C24 = fC[21]*mJ[3][0] + fC[22]*mJ[3][1] + fC[23]*mJ[3][2] + fC[24]*mJ[3][3] + fC[25]*mJ[3][4] + fC[26]*mJ[3][5]; + const float C25 = fC[21]*mJ[4][0] + fC[22]*mJ[4][1] + fC[23]*mJ[4][2] + fC[24]*mJ[4][3] + fC[25]*mJ[4][4] + fC[26]*mJ[4][5]; + C[21] = C21; + C[22] = C22; + C[23] = C23; + C[24] = C24; + C[25] = C25; + C[26] = fC[26]; + C[27] = fC[27]; + + const float C28 = fC[28]*mJ[0][0] + fC[29]*mJ[0][1] + fC[30]*mJ[0][2] + fC[31]*mJ[0][3] + fC[32]*mJ[0][4] + fC[33]*mJ[0][5]; + const float C29 = fC[28]*mJ[1][0] + fC[29]*mJ[1][1] + fC[30]*mJ[1][2] + fC[31]*mJ[1][3] + fC[32]*mJ[1][4] + fC[33]*mJ[1][5]; + const float C30 = fC[28]*mJ[2][0] + fC[29]*mJ[2][1] + fC[30]*mJ[2][2] + fC[31]*mJ[2][3] + fC[32]*mJ[2][4] + fC[33]*mJ[2][5]; + const float C31 = fC[28]*mJ[3][0] + fC[29]*mJ[3][1] + fC[30]*mJ[3][2] + fC[31]*mJ[3][3] + fC[32]*mJ[3][4] + fC[33]*mJ[3][5]; + const float C32 = fC[28]*mJ[4][0] + fC[29]*mJ[4][1] + fC[30]*mJ[4][2] + fC[31]*mJ[4][3] + fC[32]*mJ[4][4] + fC[33]*mJ[4][5]; + C[28] = C28; + C[29] = C29; + C[30] = C30; + C[31] = C31; + C[32] = C32; + C[33] = fC[33]; + C[34] = fC[34]; + C[35] = fC[35]; + } + + if(F1) { + F1[ 0] = cPx * dsdr1[0] + sPy * dsdr1[0]; + F1[ 1] = cPx * dsdr1[1] + sPy * dsdr1[1]; + F1[ 2] = cPx * dsdr1[2] + sPy * dsdr1[2]; + + F1[ 6] = cPy * dsdr1[0] - sPx * dsdr1[0]; + F1[ 7] = cPy * dsdr1[1] - sPx * dsdr1[1]; + F1[ 8] = cPy * dsdr1[2] - sPx * dsdr1[2]; + + F1[12] = pz*dsdr1[0]; + F1[13] = pz*dsdr1[1]; + F1[14] = pz*dsdr1[2]; + + if(fullC){ + F1[ 3] = cPx * dsdr1[3] + sPy * dsdr1[3]; + F1[ 4] = cPx * dsdr1[4] + sPy * dsdr1[4]; + F1[ 5] = cPx * dsdr1[5] + sPy * dsdr1[5]; + + F1[ 9] = cPy * dsdr1[3] - sPx * dsdr1[3]; + F1[10] = cPy * dsdr1[4] - sPx * dsdr1[4]; + F1[11] = cPy * dsdr1[5] - sPx * dsdr1[5]; + + F1[15] = pz*dsdr1[3]; + F1[16] = pz*dsdr1[4]; + F1[17] = pz*dsdr1[5]; + + F1[18] = cBzPy * dsdr1[0] - sBzPx * dsdr1[0]; + F1[19] = cBzPy * dsdr1[1] - sBzPx * dsdr1[1]; + F1[20] = cBzPy * dsdr1[2] - sBzPx * dsdr1[2]; + F1[21] = cBzPy * dsdr1[3] - sBzPx * dsdr1[3]; + F1[22] = cBzPy * dsdr1[4] - sBzPx * dsdr1[4]; + F1[23] = cBzPy * dsdr1[5] - sBzPx * dsdr1[5]; + + F1[24] = -(cBzPx * dsdr1[0] + sBzPy * dsdr1[0]); + F1[25] = -(cBzPx * dsdr1[1] + sBzPy * dsdr1[1]); + F1[26] = -(cBzPx * dsdr1[2] + sBzPy * dsdr1[2]); + F1[27] = -(cBzPx * dsdr1[3] + sBzPy * dsdr1[3]); + F1[28] = -(cBzPx * dsdr1[4] + sBzPy * dsdr1[4]); + F1[29] = -(cBzPx * dsdr1[5] + sBzPy * dsdr1[5]); + + F1[30] = 0.f; + F1[31] = 0.f; + F1[32] = 0.f; + F1[33] = 0.f; + F1[34] = 0.f; + F1[35] = 0.f; + } + } +} + +void KFParticle::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 KFParticle::GetDistanceToVertexLine( const KFParticle &Vertex, float &l, float &dl) 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 + **/ + + float 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 dx = (Vertex.fP[0]-fP[0]); + float dy = (Vertex.fP[1]-fP[1]); + float 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 = (l < 1.e-8f) ? 1.e-8f : l; + dl = (dl > 0.f) ? sqrt(dl)/l : 1e8f; + + +// float cosV = dx*fP[3] + dy*fP[4] + dz*fP[5]; +// if((l > 3.f*dl) && (cosV>0.f)) +// dl = 1e8f; +} + +void KFParticle::GetDistanceToVertexLineWithDirection( const KFParticle &Vertex, float &l, float &dl) 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 + **/ + + float 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 dx = (Vertex.fP[0]-fP[0]); + float dy = (Vertex.fP[1]-fP[1]); + float 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 = (l < 1.e-8f) ? 1.e-8f : l; + dl = (dl > 0.f) ? sqrt(dl)/l : 1e8f; + + + float cosV = dx*fP[3] + dy*fP[4] + dz*fP[5]; + if((l > 3.f*dl) && (cosV>0.f)) + dl = 1e8f; +} + +float KFParticle::GetDistanceFromVertex( const KFParticle &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 KFParticle::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 KFParticle::GetDistanceFromParticle( const KFParticle &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 KFParticle::GetDeviationFromVertex( const KFParticle &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 KFParticle::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 F1[36]; + Transport( dS, dsdr, mP, mC, dsdp, nullptr, F1, false ); + + 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]; +// } +// } + + float VFT[3][3]; + VFT[0][0] = Cv[0]*F1[ 0] + Cv[1]*F1[ 1] + Cv[3]*F1[ 2]; + VFT[0][1] = Cv[0]*F1[ 6] + Cv[1]*F1[ 7] + Cv[3]*F1[ 8]; + VFT[0][2] = Cv[0]*F1[12] + Cv[1]*F1[13] + Cv[3]*F1[14]; + + VFT[1][0] = Cv[1]*F1[ 0] + Cv[2]*F1[ 1] + Cv[4]*F1[ 2]; + VFT[1][1] = Cv[1]*F1[ 6] + Cv[2]*F1[ 7] + Cv[4]*F1[ 8]; + VFT[1][2] = Cv[1]*F1[12] + Cv[2]*F1[13] + Cv[4]*F1[14]; + + VFT[2][0] = Cv[3]*F1[ 0] + Cv[4]*F1[ 1] + Cv[5]*F1[ 2]; + VFT[2][1] = Cv[3]*F1[ 6] + Cv[4]*F1[ 7] + Cv[5]*F1[ 8]; + VFT[2][2] = Cv[3]*F1[12] + Cv[4]*F1[13] + Cv[5]*F1[14]; + + float FVFT[6]; + FVFT[0] = F1[ 0]*VFT[0][0] + F1[ 1]*VFT[1][0] + F1[ 2]*VFT[2][0]; + FVFT[1] = F1[ 6]*VFT[0][0] + F1[ 7]*VFT[1][0] + F1[ 8]*VFT[2][0]; + FVFT[2] = F1[ 6]*VFT[0][1] + F1[ 7]*VFT[1][1] + F1[ 8]*VFT[2][1]; + FVFT[3] = F1[12]*VFT[0][0] + F1[13]*VFT[1][0] + F1[14]*VFT[2][0]; + FVFT[4] = F1[12]*VFT[0][1] + F1[13]*VFT[1][1] + F1[14]*VFT[2][1]; + FVFT[5] = F1[12]*VFT[0][2] + F1[13]*VFT[1][2] + F1[14]*VFT[2][2]; + + mC[0] += FVFT[0] + Cv[0]; + mC[1] += FVFT[1] + Cv[1]; + mC[2] += FVFT[2] + Cv[2]; + mC[3] += FVFT[3] + Cv[3]; + mC[4] += FVFT[4] + Cv[4]; + mC[5] += FVFT[5] + 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 KFParticle::GetDeviationFromParticle( const KFParticle &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 KFParticle::GetArmenterosPodolanski(const KFParticle& positive, const KFParticle& 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 KFParticle::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 KFParticle::Rotate(float angle, const KFParticle& axis) +{ + /** 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() - axis.GetX(); + Y() = Y() - axis.GetY(); + Z() = Z() - axis.GetZ(); + + // Rotate the particle + const float c = cos(angle); + const float c1 = 1.f - c; + const float s = sin(angle); + + const float axisNorm = 1.f/sqrt(axis.GetPx()*axis.GetPx() + + axis.GetPy()*axis.GetPy() + + axis.GetPz()*axis.GetPz()); + const float u[3] = {axis.GetPx()*axisNorm, + axis.GetPy()*axisNorm, + axis.GetPz()*axisNorm}; + + 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 + u[0]*u[0]*c1; mA[0][1] = u[0]*u[1]*c1 - u[2]*s; mA[0][2] = u[0]*u[2]*c1 + u[1]*s; +// mA[1][0] = u[0]*u[1]*c1 + u[2]*s; mA[1][1] = c + u[1]*u[1]*c1; mA[1][2] = u[1]*u[2]*c1 - u[0]*s; +// mA[2][0] = u[0]*u[2]*c1 - u[1]*s; mA[2][1] = u[1]*u[2]*c1 + u[0]*s; mA[2][2] = c + u[2]*u[2]*c1; + + mA[3][3] = c + u[0]*u[0]*c1; mA[3][4] = u[0]*u[1]*c1 - u[2]*s; mA[3][5] = u[0]*u[2]*c1 + u[1]*s; + mA[4][3] = u[0]*u[1]*c1 + u[2]*s; mA[4][4] = c + u[1]*u[1]*c1; mA[4][5] = u[1]*u[2]*c1 - u[0]*s; + mA[5][3] = u[0]*u[2]*c1 - u[1]*s; mA[5][4] = u[1]*u[2]*c1 + u[0]*s; mA[5][5] = c + u[2]*u[2]*c1; + + 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() + axis.GetX(); +// Y() = GetY() + axis.GetY(); +// Z() = GetZ() + axis.GetZ(); +} + +Int_t KFParticle::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 KFParticle::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 KFParticle::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 KFParticle::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 KFParticle::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 KFParticle::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 KFParticle::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 KFParticle::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 KFParticle::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; +} + +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 mP[8]; + float mC[36]; + float dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + const float dS = GetDStoPoint(vtx, dsdr); + float dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f}; + float 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 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]={ 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 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/StRoot/KFParticle/KFParticle.h b/StRoot/KFParticle/KFParticle.h new file mode 100644 index 00000000000..2b330621d43 --- /dev/null +++ b/StRoot/KFParticle/KFParticle.h @@ -0,0 +1,921 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * 2007-2019 Sergey Gorbunov + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +//#define NonhomogeneousField +// #define HomogeneousField + +#ifndef KFPARTICLE_H +#define KFPARTICLE_H + +#ifdef __ROOT__ //for the STAR experiment +#define HomogeneousField +#endif + +#ifdef HLTCA_STANDALONE +#include "RootTypesDef.h" +#else +#include "TObject.h" +#endif + +#include +#include + +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 TObject +{ + + public: + + //* + //* INITIALIZATION + //* + + //* Set magnetic field for all particles +#ifdef HomogeneousField + static void SetField( float Bz ); +#endif + //* Constructor (empty) + + KFParticle(); + + //* Destructor (empty) + + virtual ~KFParticle() {} + + //* 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(); + void Initialize( const float Param[], const float Cov[], Int_t Charge, float Mass ); + + //* + //* 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. + +#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 { return fP[i]; } ///< Returns P[i] parameter. + float GetCovariance( int i ) const { return fC[i]; } ///< Returns C[i] element of the covariance matrix in the lower triangular form. + float GetCovariance( int i, int j ) const { return fC[IJ(i,j)]; } ///< 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 () { 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 i ) { return fP[i]; }; ///< Modifier of P[i] parameter. + float & Covariance( int i ) { return fC[i]; }; ///< Modifier of C[i] element of the covariance matrix in the lower triangular form. + float & Covariance( int i, int j ) { return fC[IJ(i,j)]; }; ///< Modifier of C[i,j] element of the covariance matrix. + + const float * Parameters () const { return fP;} ///< Returns pointer to the parameters fP + const float * CovarianceMatrix() const { return fC;} ///< Returns pointer to the covariance matrix fC + + 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. + + + //* + //* CONSTRUCTION OF THE PARTICLE BY ITS DAUGHTERS AND MOTHER + //* USING THE KALMAN FILTER METHOD + //* + + + //* Add daughter to the particle + bool GetMeasurement( const KFParticle& daughter, float m[], float V[], float D[3][3] ) ; + + void AddDaughter( const KFParticle &Daughter ); + void SubtractDaughter( const KFParticle &Daughter ); + void AddDaughterWithEnergyFit( const KFParticle &Daughter ); + void AddDaughterWithEnergyFitMC( const KFParticle &Daughter ); + + void SubtractFromVertex( KFParticle &Vtx ) const; + void SubtractFromParticle( KFParticle &Vtx ) const; + + //* Add daughter via += operator: ex.{ D0; D0+=Pion; D0+= Kaon; } + + void operator +=( const KFParticle &Daughter ); + + //* Set production vertex + + void SetProductionVertex( const KFParticle &Vtx ); + + //* Set mass constraint + + void SetNonlinearMassConstraint( float Mass ); + void SetMassConstraint( float Mass, float SigmaMass = 0 ); + void SetMassConstraint( float *mP, float *mC, float mJ[7][7], float mass ); + + //* 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 ; + + 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; + + //* Get dS to other particle p (dSp for particle p also returned) + void GetDStoParticle( const KFParticle &p, float dS[2], float dsdr[4][6] ) const ; + + void GetDStoParticleLine( const KFParticle &p, float dS[2], float dsdr[4][6] ) const ; + void GetDStoParticleBz( float Bz, const KFParticle &p, float dS[2], float dsdr[4][6], const float* param1=0, const float* param2=0 ) const ; + void GetDStoParticleBy( float B, const KFParticle &p, float dS[2], float dsdr[4][6] ) const ; + void GetDStoParticleCBM( const KFParticle &p, float dS[2], float dsdr[4][6] ) const ; + + void GetDStoCylinderBz( const float B, const float R, float dS[2]) const; + +#ifdef HomogeneousField + //* Get dS to a certain space point + void GetDStoCylinder( const float R, float dS[2]) const { + GetDStoCylinderBz( GetFieldAlice(), R, dS); + } +#endif + + //* + //* OTHER UTILITIES + //* + + //* Calculate distance from another object [cm] + + void GetDistanceToVertexLine( const KFParticle &Vertex, float &l, float &dl) const; + void GetDistanceToVertexLineWithDirection( const KFParticle &Vertex, float &l, float &dl) const; + + float GetDistanceFromVertex( const float vtx[] ) const; + float GetDistanceFromVertex( const KFParticle &Vtx ) const; + float GetDistanceFromParticle( const KFParticle &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 KFParticle &Vtx ) const; + float GetDeviationFromParticle( const KFParticle &p ) const; + + //* 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 bool fullC=true ) const ; + + //Transport functions + 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 bool fullC=true ) const; + void TransportCBM( float dS, const float* dsdr, float P[], float C[], float* dsdr1=0, float* F=0, float* F1=0 ) const; + void TransportLine( float S, const float* dsdr, float P[], float C[], float* dsdr1, float* F, float* F1 ) const ; + + + static void GetArmenterosPodolanski(const KFParticle& positive, const KFParticle& negative, float QtAlfa[2] ); + void RotateXY(float angle, float Vtx[3]); + void Rotate(float angle, const KFParticle& axis); + + int Id() const { return fId; } ///< Returns Id of the particle. + int NDaughters() const { return fDaughtersIds.size(); } ///< Returns number of daughter particles. + const std::vector& 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 + 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;} + void Clear(Option_t * /*option*/ =""); +#endif + + static void InvertCholetsky3(float a[6]); + + /** 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; + } + + //* + //* INTERNAL STUFF + //* + + protected: + //* Method to access ALICE field +#ifdef HomogeneousField + static float GetFieldAlice(); +#endif + + static void MultQSQt( const float Q[], const float S[], float SOut[], const int kN ); + + /** Return an element of the covariance matrix with {i,j} indices. */ + float & Cij( Int_t i, Int_t j ){ return fC[IJ(i,j)]; } + + 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 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 + 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 fDaughtersIds; + +#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, 4 ) +#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 void KFParticle::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; + SumDaughterMass = 0; + fMassHypo = -1; +} + +inline void KFParticle::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; + + 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; +} + +inline float KFParticle::GetP () const +{ + float par, err; + if( GetMomentum( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetPt () const +{ + float par, err; + if( GetPt( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetEta () const +{ + float par, err; + if( GetEta( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetPhi () const +{ + float par, err; + if( GetPhi( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetMomentum () const +{ + float par, err; + if( GetMomentum( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetMass () const +{ + float par, err; + if( GetMass( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetDecayLength () const +{ + float par, err; + if( GetDecayLength( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetDecayLengthXY () const +{ + float par, err; + if( GetDecayLengthXY( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetLifeTime () const +{ + float par, err; + if( GetLifeTime( par, err ) ) return 0; + else return par; +} + +inline float KFParticle::GetR () const +{ + float par, err; + if( 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( GetMomentum( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrPt () const +{ + float par, err; + if( GetPt( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrEta () const +{ + float par, err; + if( GetEta( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrPhi () const +{ + float par, err; + if( GetPhi( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrMomentum () const +{ + float par, err; + if( GetMomentum( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrMass () const +{ + float par, err; + if( GetMass( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrDecayLength () const +{ + float par, err; + if( GetDecayLength( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrDecayLengthXY () const +{ + float par, err; + if( GetDecayLengthXY( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrLifeTime () const +{ + float par, err; + if( GetLifeTime( par, err ) ) return 1.e10; + else return err; +} + +inline float KFParticle::GetErrR () const +{ + float par, err; + if( 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 GetMomentum( P, SigmaP ); +} + +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 GetDStoPointBz() is called, + ** if "NonhomogeneousField" is defined - 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 GetDStoPointBz( GetFieldAlice(), xyz, dsdr ); +#endif +#ifdef NonhomogeneousField + return GetDStoPointCBM( xyz, dsdr ); +#endif +} + +#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 KFParticle &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 GetDStoParticleBz() is called, + ** if "NonhomogeneousField" is defined - 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 + GetDStoParticleBz( GetFieldAlice(), p, dS, dsdr ) ; +#endif +#ifdef NonhomogeneousField + 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 bool fullC ) 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 TransportBz() + ** is called, if "NonhomogeneousField" - 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 + TransportBz( GetFieldAlice(), dS, dsdr, P, C, dsdr1, F, F1, fullC ); +#endif +#ifdef NonhomogeneousField + TransportCBM( dS, dsdr, P, C, dsdr1, F, F1 ); +#endif +} + +#ifdef __ROOT__ //for the STAR experiment +std::ostream& operator<<(std::ostream& os, KFParticle const & particle); +#endif + +inline void KFParticle::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 + **/ + + const float d0 = 1.f/a[0]; + const float u01 = a[1]*d0; + const float u02 = a[3]*d0; + + const float d1 = 1.f/(a[2] - u01*a[1]); + const float u12_d = a[4] - u01*a[3]; + const float u12 = d1*u12_d; + const float d2 = 1.f/(a[5] - u02*a[3] - u12*u12_d); + + //find V = -U^-1 + const float v02 = u02 - u01*u12; + + //find A^-1 = U^-1 D^-1 Ut^-1 + a[5] = d2; + a[4] = -d2*u12; + a[3] = -d2*v02; + const float d1u01 = -d1*u01; + a[2] = d1 - a[4]*u12; + a[1] = d1u01 - a[3]*u12; + a[0] = d0 - d1u01*u01 - a[3]*v02; +} + + + + + + +#endif diff --git a/StRoot/KFParticle/KFParticleDatabase.cxx b/StRoot/KFParticle/KFParticleDatabase.cxx new file mode 100644 index 00000000000..a1e4dc573a9 --- /dev/null +++ b/StRoot/KFParticle/KFParticleDatabase.cxx @@ -0,0 +1,112 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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.5109989461E-03; // e + fMass[ 1] = 0.1056583745; // mu + fMass[ 2] = 0.13957039; // pi + fMass[ 3] = 0.493677; // K + fMass[ 4] = 0.9382720813; // p + fMass[ 5] = 1.87561294257; // d + fMass[ 6] = 2.80892113298; // t + fMass[ 7] = 2.80839160743; // He3 + fMass[ 8] = 3.7273794066; // He4 + fMass[ 9] = 5.6055375; // He6 + fMass[10] = 5.6015181; // Li6 + fMass[11] = 6.5338336; // Li7 + fMass[12] = 6.5341844; // Be7 + fMass[13] = 1.197449; // Sigma- + fMass[14] = 1.18937; // Sigma+ + fMass[15] = 1.32171; // Xi + fMass[16] = 1.67245; // Omega + + 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.9914; //H3L + fMassSecPDG[6] = 3.9217; //He4L + fMassSecPDG[7] = 4.8397; //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]=2.0e-3; //H3L + fMassSecPDGSigma[6]=1.5e-3; //He4L + fMassSecPDGSigma[7]=1.5e-3; //He5L + + fDatabase = this; +} + +KFParticleDatabase kfPartDatabase; //create instance diff --git a/StRoot/KFParticle/KFParticleDatabase.h b/StRoot/KFParticle/KFParticleDatabase.h new file mode 100644 index 00000000000..5bcfc618c36 --- /dev/null +++ b/StRoot/KFParticle/KFParticleDatabase.h @@ -0,0 +1,197 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef KFParticleDatabase_H +#define KFParticleDatabase_H + +#include "KFParticleDef.h" + +/** @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 1000020060: pdgIndex = 9; break; + case 1000030060: pdgIndex = 10; break; + case 1000030070: pdgIndex = 11; break; + case 1000040070: pdgIndex = 12; break; + case 3112: pdgIndex = 13; break; + case 3222: pdgIndex = 14; break; + case 3312: pdgIndex = 15; break; + case 3334: pdgIndex = 16; break; + default: pdgIndex = 2; break; + } + + return fMass[pdgIndex]; + } + + float32_v GetMass(const int32_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 + **/ + int32_v pdgIndex(2); + pdgIndex = select(abs(pdg) == 11, 0, pdgIndex); + pdgIndex = select(abs(pdg) == 13, 1, pdgIndex); + pdgIndex = select(abs(pdg) == 19, 1, pdgIndex); + pdgIndex = select(abs(pdg) == 211, 2, pdgIndex); + pdgIndex = select(abs(pdg) == 321, 3, pdgIndex); + pdgIndex = select(abs(pdg) == 2212, 4, pdgIndex); + pdgIndex = select(abs(pdg) == 1000010020, 5, pdgIndex); + pdgIndex = select(abs(pdg) == 1000010030, 6, pdgIndex); + pdgIndex = select(abs(pdg) == 1000020030, 7, pdgIndex); + pdgIndex = select(abs(pdg) == 1000020040, 8, pdgIndex); + pdgIndex = select(abs(pdg) == 1000020060, 9, pdgIndex); + pdgIndex = select(abs(pdg) == 1000030060, 10, pdgIndex); + pdgIndex = select(abs(pdg) == 1000030070, 11, pdgIndex); + pdgIndex = select(abs(pdg) == 1000040070, 12, pdgIndex); + pdgIndex = select(abs(pdg) == 3112, 13, pdgIndex); + pdgIndex = select(abs(pdg) == 3222, 14, pdgIndex); + pdgIndex = select(abs(pdg) == 3312, 15, pdgIndex); + pdgIndex = select(abs(pdg) == 3334, 16, pdgIndex); + float32_v mass; + mass.gather(fMass, pdgIndex); + return mass; + } + + void GetMotherMass(const int32_v& pdg, float32_v& massMotherPDG, float32_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 + **/ + + int32_v pdgIndex(0); + // pdgIndex = select(pdg == 310 , 0, pdgIndex); + pdgIndex = select(abs(pdg) == 3122, 1, pdgIndex); + pdgIndex = select(abs(pdg) == 3312, 2, pdgIndex); + pdgIndex = select(pdg == 22 , 3, pdgIndex); + pdgIndex = select(abs(pdg) == 3334, 4, pdgIndex); + pdgIndex = select(abs(pdg) == 3004, 5, pdgIndex); + pdgIndex = select(abs(pdg) == 3006, 6, pdgIndex); + pdgIndex = select(abs(pdg) == 3007, 7, pdgIndex); + + 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; + ** [ 9] - He6; \n [10] - Li6; \n [11] - Li7; \n [12] - Be7; \n + ** \n [13] - Sigma-; \n [14] - Sigma+; \n [15] - Xi; \n [16] - Omega. */ + float fMass[17]; + + /** 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 diff --git a/StRoot/KFParticle/KFParticleDef.h b/StRoot/KFParticle/KFParticleDef.h new file mode 100644 index 00000000000..d0aba5be9e3 --- /dev/null +++ b/StRoot/KFParticle/KFParticleDef.h @@ -0,0 +1,85 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#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 "KFPSimd/simd.h" + +using float32_v = KFP::SIMD::simd_float; +using int32_v = KFP::SIMD::simd_int; +using mask32_v = KFP::SIMD::simd_mask; +using KFP::SIMD::SimdLen; +using KFP::SIMD::SimdSize; + +// using ::Vc::float32_v; +// using ::Vc::double_v; +// using ::Vc::float32_v; +// using ::Vc::int32_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 To simd_cast(From &&x) { return static_cast(x); } +#endif +#elif defined(Vc_VERSION_NUMBER) +#if Vc_VERSION_NUMBER < Vc_VERSION_CHECK(1,0,0) +template To simd_cast(From &&x) { return static_cast(x); } +#endif +#endif + +#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 > kfvector_floatv; + +typedef std::vector > kfvector_float; +typedef std::vector > kfvector_int; + +#endif diff --git a/StRoot/KFParticle/KFParticleField.h b/StRoot/KFParticle/KFParticleField.h new file mode 100644 index 00000000000..225fcb85be3 --- /dev/null +++ b/StRoot/KFParticle/KFParticleField.h @@ -0,0 +1,201 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * 2007-2019 Sergey Gorbunov + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFParticleField_h +#define KFParticleField_h 1 + +#include + +/** @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){}; + + float32_v x; ///< Bx component of the magnetic field + float32_v y; ///< By component of the magnetic field + float32_v z; ///< Bz component of the magnetic field + + void Combine( KFParticleFieldValue &B, float32_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 float32_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. + **/ + float32_v dz = (z-fField[9]); + float32_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 float32_v B0z, + const KFParticleFieldValue &B1, const float32_v B1z, + const KFParticleFieldValue &B2, const float32_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; + float32_v dz1 = B1z-B0z, dz2 = B2z-B0z; + float32_v det = 1.f/(float32_v(dz1*dz2*(dz2-dz1))); + float32_v w21 = -dz2*det; + float32_v w22 = dz1*det; + float32_v w11 = -dz2*w21; + float32_v w12 = -dz1*w22; + + float32_v dB1 = B1.x - B0.x; + float32_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 float32_v B0z, + const KFParticleFieldValue &B1, const float32_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; + float32_v dzi = 1.f/(float32_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 + **/ + float32_v fField[10]; +}; + + +#endif diff --git a/StRoot/KFParticle/KFParticleFinder.cxx b/StRoot/KFParticle/KFParticleFinder.cxx new file mode 100644 index 00000000000..c599b0e33d1 --- /dev/null +++ b/StRoot/KFParticle/KFParticleFinder.cxx @@ -0,0 +1,4283 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "KFParticleFinder.h" + +using std::map; +using std::vector; + +#include "KFParticleMath.h" +#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), fDPi(0), fDPiBar(0), fTPi(0), fTPiBar(0), fHe3Pi(0), fHe3PiBar(0), fHe3PPi(0), fHe4Pi(0), fHe4PiBar(0), fHe4PPi(0), + fHe4L(0), fHe5L(0), fLLn(0), fH5LL(0), fPipi(0), fPpi(0), fPpiBar(0), fPPpi(0), fPPpiBar(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(); + fDPi.clear(); + fDPiBar.clear(); + fTPi.clear(); + fTPiBar.clear(); + fHe3Pi.clear(); + fHe3PiBar.clear(); + fHe3PPi.clear(); + fHe4Pi.clear(); + fHe4PiBar.clear(); + fHe4PPi.clear(); + fHe4L.clear(); + fHe5L.clear(); + fLLn.clear(); + fH5LL.clear(); + fPipi.clear(); + fPpi.clear(); + fPpiBar.clear(); + fPPpi.clear(); + fPPpiBar.clear(); + + for(int iCandidates=0; iCandidates& Particles, + std::vector >& 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 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 += SimdLen) + { + const int NClustersVec = (iEmc + SimdLen < fEmcClusters->Size()) ? SimdLen : (fEmcClusters->Size() - iEmc); + tmpGammaSIMD.Load(*fEmcClusters, iEmc, PrimVtx[0]); + for(int iV=0; iVId()[iEmc+iV]); + Particles.push_back(tmpGamma); + vGammaPrimEmc.push_back(tmpGamma); + } + } + } + } + +#if 0 + Find2DaughterDecayOneSign(vRTracks[0], Particles, PrimVtx); +#else + + // ConstructResonances2D(vRTracks, Particles, PrimVtx); + + 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 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 K0 pi+ + for(int iPV=0; iPV K0 pi- + for(int iPV=0; iPV Lambda pi+ + for(int iPV=0; iPV Lambda pi-, Xi*- -> Lambda K- + for(int iPV=0; iPV Lambda_bar pi- + for(int iPV=0; iPV Lambda_bar pi+, Xi*+ -> Lambda_bar + K+ + for(int iPV=0; iPV Xi- pi+ + for(int iPV=0; iPV Xi+ pi- + for(int iPV=0; iPV Xi- pi+ K- + for(int iPV=0; iPV Xi+ pi- K+ + for(int iPV=0; iPV pi+ pi+ pi- + FindTrackV0Decay(fPipi, 100310, vRTracks[0], 1, vRTracks[0].FirstPion(), vRTracks[0].LastPion(), Particles, PrimVtx, -1, 0, &fPrimCandidates[11]); + + // K- -> pi+ pi- pi- + FindTrackV0Decay(fPipi, 100310, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), Particles, PrimVtx, -1, 0, &fPrimCandidates[12]); + + MatchKaons(vRTracks, PrimVtx, Particles); + + //Hypernuclei + //H3L -> d p pi-, H4L -> d d pi-, H5L -> t d pi- + FindTrackV0Decay(fDPi , 3003, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastBe7(), Particles, PrimVtx, -1, 0); + //H3L_bar -> d- p- pi+, H4L_bar -> d- d- pi+, H5L_bar -> t- d- pi+ + FindTrackV0Decay(fDPiBar ,-3003, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastBe7(), Particles, PrimVtx, -1, 0); + //H4L -> t p pi-, H6L -> t t pi- + FindTrackV0Decay(fTPi , 3103, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastBe7(), Particles, PrimVtx, -1, 0); + //H4L_bar -> t- p- pi+, H6L_bar -> t- t- pi+ + FindTrackV0Decay(fTPiBar ,-3103, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastBe7(), Particles, PrimVtx, -1, 0); + //He4L -> He3 p pi- + FindTrackV0Decay(fHe3Pi , 3004, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastBe7(), Particles, PrimVtx, -1, 0); + //He5L -> He3 d pi-, He6L -> He3 t pi-, Li6L-> He3 He3 pi-, Li7L-> He4 He3 pi- +// FindTrackV0Decay(fHe3Pi , 3004, vRTracks[0], 1, vRTracks[0].FirstDeuteron(), vRTracks[0].LastBe7(), Particles, PrimVtx, -1, 0); + //He4L_bar -> He3- p- pi+, He5L_bar -> He3- d- pi+, He6L_bar -> He3- t- pi+, Li6L_bar -> He3- He3- pi+, Li7L_bar -> He4- He3- pi+ + FindTrackV0Decay(fHe3PiBar,-3004, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastBe7(), Particles, PrimVtx, -1, 0); + //He5L -> He4 p pi- + FindTrackV0Decay(fHe4Pi , 3005, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastBe7(), Particles, PrimVtx, -1, 0); + //He6L -> He4 d pi-, He7L -> He4 t pi-, Li8L-> He4 He4 pi- +// FindTrackV0Decay(fHe4Pi , 3005, vRTracks[0], 1, vRTracks[0].FirstDeuteron(), vRTracks[0].LastBe7(), Particles, PrimVtx, -1, 0, 0); + //He5L_bar -> He4- p- pi+, He6L_bar -> He4- d- pi+, He7L_bar -> He4- t- pi+, Li8L_bar -> He4- He4- pi+ + FindTrackV0Decay(fHe4PiBar,-3005, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastBe7(), Particles, PrimVtx, -1, 0); + //LLn -> H3L pi- + std::vector h3L; + float massH3L, massH3LSigma; + KFParticleDatabase::Instance()->GetMotherMass(3004, massH3L, massH3LSigma); + for(unsigned int iHe3Pi=0; iHe3Pi 3.f ) continue; + he3pi.SetNonlinearMassConstraint(massH3L); + h3L.push_back(he3pi); + } + FindTrackV0Decay(h3L , 3004, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), Particles, PrimVtx, -1, 0 ); + + //LLnn -> H4L pi- + std::vector h4L; + float massH4L = 3.9225f; + float massH4LSigma = 0.002f; + for(unsigned int iHe4Pi=0; iHe4Pi 3.f ) continue; + he4pi.SetNonlinearMassConstraint(massH4L); + h4L.push_back(he4pi); + } + FindTrackV0Decay(h4L , 3005, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), Particles, PrimVtx, -1, 0 ); + + //H4LL -> He4L pi- + FindLL(3008, -211, fHe4L, vRTracks[1], vRTracks[1].FirstPion(), vRTracks[1].LastPion(), PrimVtx[0], Particles); + FindLL(3008, -211, fHe4L, vRTracks[3], vRTracks[3].FirstPion(), vRTracks[3].LastPion(), PrimVtx[0], Particles); + // FindTrackV0Decay(fHe4L , 3006, vRTracks[1], -1, vRTracks[1].FirstPion(), vRTracks[1].LastPion(), Particles, PrimVtx, -1, 0 ); + //H5LL -> He5L pi- + FindLL(3010, -211, fHe5L, vRTracks[1], vRTracks[1].FirstPion(), vRTracks[1].LastPion(), PrimVtx[0], Particles); + FindLL(3010, -211, fHe5L, vRTracks[3], vRTracks[3].FirstPion(), vRTracks[3].LastPion(), PrimVtx[0], Particles); + // 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 ); + //H2L -> p p pi- + FindTrackV0Decay(fPpi , 8122, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), Particles, PrimVtx, -1, 0 ); + //H2L_bar -> p- p- pi+ + FindTrackV0Decay(fPpiBar ,-8122, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastProton(), Particles, PrimVtx, -1, 0 ); + //He3L -> p p p pi- + FindTrackV0Decay(fPPpi , 3028, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), Particles, PrimVtx, -1, 0 ); + //He3L_bar -> p- p- p- pi+ + FindTrackV0Decay(fPPpiBar ,-3028, vRTracks[1], -1, vRTracks[1].FirstProton(), vRTracks[1].LastProton(), Particles, PrimVtx, -1, 0 ); + //Li5L -> He3 p p pi- + FindTrackV0Decay(fHe3PPi , 3006, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), Particles, PrimVtx, -1, 0 ); + //Li6L -> He4 p p pi- + FindTrackV0Decay(fHe4PPi , 3007, vRTracks[0], 1, vRTracks[0].FirstProton(), vRTracks[0].LastProton(), Particles, PrimVtx, -1, 0 ); + + //Hyper resonances with Lambda + for(int iPV=0; iPV 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 D0_bar pi- + for(int iPV=0; iPV 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 D0_bar pi- + for(int iPV=0; iPVGetDPlusMass(), 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; iPVD- pi+ + for(int iPV=0; iPV K0 pi+ pi- + for(int iPV=0; iPV K0 K+ K- + for(int iPV=0; iPV 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 K0 pi+ pi- pi- + for(int iPV=0; iPV Lambda pi+ pi+ pi- + for(int iPV=0; iPV Lambda_bar pi+ pi- pi- + for(int iPV=0; iPV Xi- pi+ pi+ pi- + for(int iPV=0; iPV Xi+ pi+ pi- pi- + for(int iPV=0; iPV K0 K+ pi+ pi- + for(int iPV=0; iPV K0 K- pi+ pi- + for(int iPV=0; iPV p K0 pi+ pi- + for(int iPV=0; iPV p- K0 pi+ pi- + for(int iPV=0; iPV 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 K0 pi- + for(int iPV=0; iPV K0 K+ + for(int iPV=0; iPV K0 K- + for(int iPV=0; iPV Lambda pi+ + for(int iPV=0; iPV Lambda_bar pi- + for(int iPV=0; iPV p K0s + for(int iPV=0; iPV p_bar K0s + for(int iPV=0; iPV 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 Lambda_bar Gamma + for(int iPV=0; iPV 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 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 K- pi0 + for(int iPV=0; iPV K0 pi0 + for(int iPV=0; iPV Lambda pi0 + for(int iPV=0; iPV Lambda_bar pi0 + for(int iPV=0; iPV Xi- pi0 + for(int iPV=0; iPV Xi+ pi0 + for(int iPV=0; iPV Lambda Lambda_bar + for(int iPV=0; iPV Xi- Xi+ + for(int iPV=0; iPV Omega- Omega+ + for(int iPV=0; iPV gamma gamma, EMC +// vector< vector > vPi0PrimEmc(1); +// vector vPi0SecEmc; +// vector< vector > 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]); + } + #endif +} + +void KFParticleFinder::ExtrapolateToPV(vector& 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[SimdLen]; + KFParticle tmpPart[SimdLen]; + + for(int iv=0; iv& Particles, + std::vector >& PrimVtx, + const float* cuts, + const int32_v& pvIndex, + const float* secCuts, + const float32_v& massMotherPDG, + const float32_v& massMotherPDGSigma, + KFParticleSIMD& motherPrimSecCand, + int& nPrimSecCand, + vector< vector >* vMotherPrim, + vector* 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. + **/ + mask32_v isPrimary = pvIndex > -1; + int32_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 + float32_v ds[2] = {0.f,0.f}; + float32_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); + + mask32_v saveParticle = int32_v::indicesSequence() < int(NTracks); + float32_v chi2Cut = cuts[1]; + float32_v ldlCut = cuts[2]; + const mask32_v isD0 = (abs(mother.PDG()) == 421 || abs(mother.PDG()) == 426 || abs(mother.PDG()) == 420); + if( !(isD0).isEmpty() ) + { + chi2Cut = select(isD0, fCutsCharm[0], chi2Cut); + ldlCut = select(isD0, -1, ldlCut);//fCutsCharm[1]; + } + + saveParticle &= (mother.Chi2()/toFloat(mother.NDF()) < chi2Cut ); + saveParticle &= isFinite(mother.GetChi2()); + saveParticle &= (mother.GetChi2() > 0.0f); + saveParticle &= (mother.GetChi2() == mother.GetChi2()); + + if( saveParticle.isEmpty() ) return; + + float32_v lMin(1.e8f); + float32_v ldlMin(1.e8f); + mask32_v isParticleFromVertex; + + for(int iP=0; iP ldlCut) || isPrimary ); + + saveParticle &= ((!isPrimary) && isParticleFromVertex) || isPrimary; + if( saveParticle.isEmpty() ) return; + + const mask32_v isK0 = saveParticle && (mother.PDG() == int32_v(310)); + const mask32_v isLambda = saveParticle && (abs(mother.PDG()) == int32_v(3122)); + const mask32_v isGamma = saveParticle && (mother.PDG() == int32_v(22)); + const mask32_v isHyperNuclei = saveParticle && (abs(mother.PDG()) > 3000 && abs(mother.PDG()) < 3104); + + saveParticle &= ( ((isK0 || isLambda || isHyperNuclei) && lMin > float32_v(fLCut)) || !(isK0 || isLambda || isHyperNuclei) ); + + mask32_v saveMother; + + if( !(isK0.isEmpty()) || !(isLambda.isEmpty()) || !(isGamma.isEmpty())) + { + float32_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; ivfCutLVMPt*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==SimdLen) + { + SaveV0PrimSecCand(motherPrimSecCand,nPrimSecCand,mother_temp,PrimVtx,secCuts,vMotherPrim,vMotherSec); + nPrimSecCand = 0; + } + } + } +} + +inline void KFParticleFinder::SaveV0PrimSecCand(KFParticleSIMD& mother, + int& NParticles, + KFParticle& mother_temp, + std::vector >& PrimVtx, + const float* secCuts, + vector< vector >* vMotherPrim, + vector* 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; + float32_v massMotherPDG, massMotherPDGSigma; + + mask32_v isSec; + mask32_v isPrim; + vector iPrimVert[SimdLen]; + + KFParticleDatabase::Instance()->GetMotherMass(mother.PDG(),massMotherPDG,massMotherPDGSigma); + + const mask32_v isK0 = (mother.PDG() == int32_v(310)); + const mask32_v isLambda = (abs(mother.PDG()) == int32_v(3122)); + const mask32_v isGamma = (mother.PDG() == int32_v(22)); + + int32_v arrayIndex(-1); //for saving primary candidates; + + arrayIndex = select(mother.PDG() == int32_v(310), 0, arrayIndex); + arrayIndex = select(mother.PDG() == int32_v(3122), 1, arrayIndex); + arrayIndex = select(mother.PDG() == int32_v(-3122), 2, arrayIndex); + arrayIndex = select(mother.PDG() == int32_v(22), 3, arrayIndex); + + mask32_v isPrimaryPart; + + float32_v chi2TopoMin = 1.e4f; + + for(int iP=0; iP< fNPV; iP++) + { + motherTopo = mother; + motherTopo.SetProductionVertex(PrimVtx[iP]); + + const float32_v& motherTopoChi2Ndf = motherTopo.GetChi2()/toFloat(motherTopo.GetNDF()); + chi2TopoMin = select(motherTopoChi2Ndf < chi2TopoMin, motherTopoChi2Ndf, chi2TopoMin); + const mask32_v isPrimaryPartLocal = ( motherTopoChi2Ndf < secCuts[1] ); + if(isPrimaryPartLocal.isEmpty()) continue; + isPrimaryPart |= isPrimaryPartLocal; + for(int iV=0; iV& Particles, + std::vector >& PrimVtx, + const float* cuts, + const float* secCuts, + vector< vector >* vMotherPrim, + vector* 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; + alignas(SimdSize) std::int32_t idNegDaughtersArray[SimdLen]; + alignas(SimdSize) std::int32_t idPosDaughtersArray[SimdLen]; + alignas(SimdSize) std::int32_t daughterPosPDGArray[SimdLen]; + alignas(SimdSize) std::int32_t daughterNegPDGArray[SimdLen]; + alignas(SimdSize) std::int32_t pvIndexMotherArray[SimdLen]; + alignas(SimdSize) std::int32_t V0PDGArray[SimdLen]; + + int32_v idNegDaughters; + int32_v idPosDaughters; + int32_v daughterPosPDG(-1); + int32_v daughterNegPDG(-1); + + int32_v pvIndexMother(-1); + + float32_v massMotherPDG(0.f), massMotherPDGSigma(0.f); + int32_v V0PDG(0); + + 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] ]; + int32_v negTracksSize = negTracks.LastBe7(); //negTracks.Size(); + int nPositiveTracks = posTracks.LastBe7(); //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] = posTracks.LastElectron(); //nPositiveTracks; + startTCNeg[0] = 0; endTCNeg[0] = negTracks.LastElectron(); //negTracksSize[0]; + //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-, he6-, li6-, li7-, be7- + 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] = posTracks.LastElectron(); // nPositiveTracks; + startTCNeg[0] = 0; endTCNeg[0] = negTracks.LastElectron(); // negTracksSize[0]; + } + + if((iTrTypeNeg == 1) && (iTrTypePos == 1)) + { + //primary particles + nTC = 5; + // e- + startTCPos[0] = 0; endTCPos[0] = posTracks.LastElectron(); //nPositiveTracks; + startTCNeg[0] = 0; endTCNeg[0] = negTracks.LastElectron(); //negTracksSize[0]; + //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] = nPositiveTracks; + 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(negTracks.PDG()[iTrN]); + int32_v negPVIndex = reinterpret_cast(negTracks.PVIndex()[iTrN]); + int32_v negNPixelHits = reinterpret_cast(negTracks.NPixelHits()[iTrN]); + + int32_v trackPdgNeg = negPDG; + mask32_v activeNeg = (negPDG != -1); +#ifdef CBM + if( !((negPDG == -1).isEmpty()) ) + { + trackPdgNeg(negPVIndex<0 && (negPDG == -1) ) = -211; + + activeNeg |= (negPVIndex < 0) && (negPDG == -1) ; + } +#endif + activeNeg &= (int32_v::indicesSequence() < int(NTracksNeg)); + + daughterNeg.Load(negTracks, iTrN, negPDG); + + float32_v chiPrimNeg(0.f); + float32_v chiPrimPos(0.f); + + if( (iTrTypeNeg == 0) && (iTrTypePos == 0) ) + chiPrimNeg = reinterpret_cast( ChiToPrimVtx[trTypeIndexNeg[iTrTypeNeg]][iTrN]); + + for(int iTrP=startTCPos[iTC]; iTrP < endTCPos[iTC]; iTrP += SimdLen) + { + const int NTracks = (iTrP + SimdLen < nPositiveTracks) ? SimdLen : (nPositiveTracks - iTrP); + + const int32_v& posPDG = reinterpret_cast(posTracks.PDG()[iTrP]); + const int32_v& posPVIndex = reinterpret_cast(posTracks.PVIndex()[iTrP]); + const int32_v& posNPixelHits = reinterpret_cast(posTracks.NPixelHits()[iTrP]); + const mask32_v& isPosSecondary = (posPVIndex < 0); + + daughterPos.Load(posTracks, iTrP, posPDG); + + if( (iTrTypeNeg == 0) && (iTrTypePos == 0) ) + chiPrimPos = reinterpret_cast( ChiToPrimVtx[trTypeIndexPos[iTrTypePos]][iTrP]); + + for(int iRot = 0; iRot0) + { + negPDG = negPDG.rotate<1>(); + negPVIndex = negPVIndex.rotate<1>(); + negNPixelHits = negNPixelHits.rotate<1>(); + negInd = negInd.rotate<1>(); + trackPdgNeg = trackPdgNeg.rotate<1>(); + + daughterNeg.Rotate(); + chiPrimNeg = chiPrimNeg.rotate<1>(); + + activeNeg = ( (negPDG != -1) || ( (negPVIndex < 0) && (negPDG == -1) ) ) && (negInd < negTracksSize); + } + const mask32_v& isSecondary = ( negPVIndex < 0 ) && isPosSecondary; + const mask32_v& isPrimary = ( negPVIndex >= 0 ) && (!isPosSecondary); + + const mask32_v closeDaughters = (activeNeg && (int32_v::indicesSequence() < int32_v(NTracks))); + + if(closeDaughters.isEmpty() && (iTC != 0)) continue; + + + int32_v trackPdgPos[2]; + mask32_v active[2]; + + active[0] = (posPDG != -1); + active[0] &= ((isPrimary && (posPVIndex == negPVIndex)) || !(isPrimary)); + + active[1] = mask32_v{}; + + 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 && (posPDG == -1); + active[1] = isSecondary && ((posPDG == -1) || (posPDG > 1000000000) || (posPDG == 211)); + } +#else + int nPDGPos = 1; +#endif + active[0] &= closeDaughters; + active[1] &= closeDaughters; + + if(iTC==0) + { + nPDGPos = 1; + active[0] = (negInd < negTracksSize) && (int32_v::indicesSequence() < int32_v(NTracks)); + } + + for(int iPDGPos=0; iPDGPos e+ e- + //motherPDG( (abs(trackPdgPos[iPDGPos]) == 11) || (abs(trackPdgNeg) == 11) || isSecondary ) = 22; //gamma -> e+ e- + } + else if(iTC==1) + { + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 13 || abs(trackPdgPos[iPDGPos])==19) + && ((abs(trackPdgNeg) == 13) || (abs(trackPdgNeg) == 19)), 200113, motherPDG); //rho -> mu+ mu- + } + else if(iTC==2) + { + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 211), 310, motherPDG); //K0 -> pi+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 2212) && (abs(trackPdgNeg) == 211), 3122, motherPDG); //Lambda -> p+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000010020) && (abs(trackPdgNeg) == 211), 3003, motherPDG); //LambdaN -> d+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000010030) && (abs(trackPdgNeg) == 211), 3103, motherPDG); //LambdaNN -> t+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000020030) && (abs(trackPdgNeg) == 211), 3004, motherPDG); //H3Lambda -> He3+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000020040) && (abs(trackPdgNeg) == 211), 3005, motherPDG); //H4Lambda -> He4+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000020060) && (abs(trackPdgNeg) == 211), 3016, motherPDG); //H6Lambda -> He6+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000030060) && (abs(trackPdgNeg) == 211), 3019, motherPDG); //He6Lambda -> Li6+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000030070) && (abs(trackPdgNeg) == 211), 3022, motherPDG); //He7Lambda -> Li7+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 1000040070) && (abs(trackPdgNeg) == 211), 3025, motherPDG); //Li7Lambda -> Be7+ pi- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 321) && (abs(trackPdgNeg) == 211), -421, motherPDG); //D0_bar -> pi- K+ + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 321) && (abs(trackPdgNeg) == 211), 313, motherPDG); //K*0 -> K+ pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 211), 113, motherPDG); //rho -> pi+ pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 2212) && (abs(trackPdgNeg) == 211), 2114, motherPDG); //Delta0 -> p pi- + + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000010020) && (abs(trackPdgNeg) == 211), 100001, motherPDG); //d pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000010030) && (abs(trackPdgNeg) == 211), 100003, motherPDG); //t pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000020030) && (abs(trackPdgNeg) == 211), 100005, motherPDG); //He3 pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000020040) && (abs(trackPdgNeg) == 211), 100007, motherPDG); //He4 pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000020060) && (abs(trackPdgNeg) == 211), 100009, motherPDG); //He6 pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000030060) && (abs(trackPdgNeg) == 211), 100011, motherPDG); //Li6 pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000030070) && (abs(trackPdgNeg) == 211), 100013, motherPDG); //Li7 pi- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000040070) && (abs(trackPdgNeg) == 211), 100015, motherPDG); //Be7 pi- + } + else if(iTC==3) + { + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 321), 421, motherPDG); //D0 -> pi+ K- + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 321) && (abs(trackPdgNeg) == 321), 426, motherPDG); //D0 -> K+ K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 321), -313, motherPDG); //K*0_bar -> K- pi+ + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 2212) && (abs(trackPdgNeg) == 321), 3124, motherPDG); //Lambda* -> p K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 321) && (abs(trackPdgNeg) == 321), 333, motherPDG); //phi -> K+ K- + + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000010020) && (abs(trackPdgNeg) == 321), 110001, motherPDG); //d K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000010030) && (abs(trackPdgNeg) == 321), 110003, motherPDG); //t K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000020030) && (abs(trackPdgNeg) == 321), 110005, motherPDG); //He3 K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000020040) && (abs(trackPdgNeg) == 321), 110007, motherPDG); //He4 K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000020060) && (abs(trackPdgNeg) == 321), 110009, motherPDG); //He6 K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000030060) && (abs(trackPdgNeg) == 321), 110011, motherPDG); //Li6 K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000030070) && (abs(trackPdgNeg) == 321), 110013, motherPDG); //Li7 K- + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 1000040070) && (abs(trackPdgNeg) == 321), 110015, motherPDG); //Be7 K- + } + else if(iTC==4) + { + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 2212), -3122, motherPDG); //Lambda_bar -> p- pi+ + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 1000010020), -3003, motherPDG); //LambdaN_bar -> d- pi+ + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 1000010030), -3103, motherPDG); //LambdaNN_bar -> t- pi+ + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 1000020030), -3004, motherPDG); //H3Lambda_bar -> He3- pi+ + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 1000020040), -3005, motherPDG); //H4Lambda_bar -> He4- pi+ + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 1000020060), -3016, motherPDG); //H6Lambda_bar -> He6- pi+ + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 1000030060), -3019, motherPDG); //He6Lambda_bar -> Li6- pi+ + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 1000030070), -3022, motherPDG); //Li6Lambda_bar -> Li7- pi+ + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 1000040070), -3025, motherPDG); //Li7Lambda_bar -> Be7- pi+ + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 321) && (abs(trackPdgNeg) == 2212), -3124, motherPDG); //Lambda*_bar -> p- K+ + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 2212) && (abs(trackPdgNeg) == 2212), 200443, motherPDG); //JPsi -> p- p + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 2212), -2114, motherPDG); //Delta0_bar -> p- pi+ + } + } + else + { + if(iTC==0) + motherPDG = select( (abs(trackPdgPos[iPDGPos])== 11) && (abs(trackPdgNeg) == 11), 22, motherPDG); //gamma -> e+ e- + else if(iTC==1) + motherPDG = select( isPrimary && (abs(trackPdgPos[iPDGPos])== 13 || abs(trackPdgPos[iPDGPos])==19) + && ((abs(trackPdgNeg) == 13) || (abs(trackPdgNeg) == 19)), 200113, motherPDG); //rho -> mu+ mu- + else if(iTC==2) + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 321) && (abs(trackPdgNeg) == 211), -421, motherPDG); //D0_bar -> pi- K+ + else if(iTC==3) + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos])== 211) && (abs(trackPdgNeg) == 321), 421, motherPDG); //D0 -> pi+ K- + } + + if( (iTrTypeNeg == 0) && (iTrTypePos == 0) ) + { + float32_v chiprimCut = fCuts2D[0]; + chiprimCut = select( abs(motherPDG) == 421 || abs(motherPDG) == 426, fCutCharmChiPrim, chiprimCut); + active[iPDGPos] &= (chiPrimNeg > chiprimCut && chiPrimPos > chiprimCut); + } + + active[iPDGPos] &= (motherPDG != -1); + if(!(fDecayReconstructionList.empty())) + { + alignas(SimdSize) std::int32_t motherPdgArray[SimdLen]; + motherPDG.store(motherPdgArray); + for(int iV=0; iV -p12); + active[iPDGPos] &= (p1p2 > -p22); + } + + const float32_v& ptNeg2 = daughterNeg.Px()*daughterNeg.Px() + daughterNeg.Py()*daughterNeg.Py(); + const float32_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) && + (ptNeg2 >= fCutCharmPt*fCutCharmPt) && + (ptPos2 >= fCutCharmPt*fCutCharmPt) && + (chiPrimNeg > fCutCharmChiPrim) && (chiPrimPos > fCutCharmChiPrim) && + (negNPixelHits >= int32_v(3)) && (posNPixelHits >= int32_v(3)) ) + || (!(abs(motherPDG) == 421 || abs(motherPDG) == 426)); + } + + if(active[iPDGPos].isEmpty()) continue; + + for(int iV=0; iVGetMotherMass(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 ) + { + idPosDaughtersArray[nBufEntry] = iTrP+iV; + idNegDaughtersArray[nBufEntry] = negInd[iV]; + + daughterPosPDGArray[nBufEntry] = trackPdgPos[iPDGPos][iV]; + daughterNegPDGArray[nBufEntry] = trackPdgNeg[iV]; + + pvIndexMotherArray[nBufEntry] = isPrimary[iV] ? negPVIndex[iV] : -1; + + V0PDGArray[nBufEntry] = 420; + + nBufEntry++; + + if(int(nBufEntry) == SimdLen) + { + idNegDaughters.load(idNegDaughtersArray); + idPosDaughters.load(idPosDaughtersArray); + daughterNegPDG.load(daughterNegPDGArray); + daughterPosPDG.load(daughterPosPDGArray); + pvIndexMother.load(pvIndexMotherArray); + V0PDG.load(V0PDGArray); + + 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; iVGetMotherMass(V0PDG,massMotherPDG,massMotherPDGSigma); + mother.SetPDG( V0PDG ); + idNegDaughters.load(idNegDaughtersArray); + idPosDaughters.load(idPosDaughtersArray); + daughterNegPDG.load(daughterNegPDGArray); + daughterPosPDG.load(daughterPosPDGArray); + pvIndexMother.load(pvIndexMotherArray); + 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::Find2DaughterDecayOneSign(KFPTrackVector& vTracks, + std::vector& Particles, + std::vector >& PrimVtx) +{ + KFParticle mother_temp; + kfvector_floatv l(fNPV), dl(fNPV); + + KFParticleSIMD pion, fragment; + + for(int iPion = vTracks.FirstPion(); iPion < vTracks.LastPion(); iPion += SimdLen) + { + int32_v pionId = reinterpret_cast(vTracks.Id()[iPion]); + int32_v pionPDG = reinterpret_cast(vTracks.PDG()[iPion]); + pion.Load(vTracks, iPion, pionPDG); + pion.SetId(pionId); + + for(int iFragment = vTracks.FirstDeuteron(); iFragment < vTracks.LastBe7(); iFragment += SimdLen) + { + const int32_v fragmentId = reinterpret_cast(vTracks.Id()[iFragment]); + const int32_v fragmentPDG = reinterpret_cast(vTracks.PDG()[iFragment]); + + fragment.Load(vTracks, iFragment, fragmentPDG); + fragment.SetId(fragmentId); + + for(int iRot = 0; iRot(); + pion.Rotate(); + pion.SetPDG(pionPDG); + + const mask32_v isPion = (pionPDG == 211); + + int32_v motherPDG(-1); + motherPDG = select( (fragmentPDG == 1000010020) && isPion, 3030, motherPDG); //H2Sp -> d+ pi+ + motherPDG = select( (fragmentPDG == 1000010030) && isPion, 3031, motherPDG); //H3Sp -> t+ pi+ + motherPDG = select( (fragmentPDG == 1000020030) && isPion, 3032, motherPDG); //He3Sp -> He3+ pi+ + motherPDG = select( (fragmentPDG == 1000020040) && isPion, 3033, motherPDG); //He4Sp -> He4+ pi+ + motherPDG = select( (fragmentPDG == 1000020060) && isPion, 3034, motherPDG); //He6Sp -> He6+ pi+ + motherPDG = select( (fragmentPDG == 1000030060) && isPion, 3035, motherPDG); //Li6Sp -> Li6+ pi+ + motherPDG = select( (fragmentPDG == 1000030070) && isPion, 3036, motherPDG); //Li7Sp -> Li7+ pi+ + motherPDG = select( (fragmentPDG == 1000040070) && isPion, 3037, motherPDG); //Be7Sp -> Be7+ pi+ + + mask32_v saveParticle = (motherPDG != -1); + + KFParticleSIMD mother; + mother += pion; + mother += fragment; + mother.SetPDG(motherPDG); + + saveParticle &= (mother.Chi2()/toFloat(mother.NDF()) < fCuts2D[1] ); + saveParticle &= isFinite(mother.GetChi2()); + saveParticle &= (mother.GetChi2() > 0.0f); + saveParticle &= (mother.GetChi2() == mother.GetChi2()); + + if( saveParticle.isEmpty() ) continue; + + float32_v ldlMin(1.e8f); + mask32_v isParticleFromVertex; + + for(int iP=0; iP fCuts2D[2]; + saveParticle &= isParticleFromVertex; + if( saveParticle.isEmpty() ) continue; + + mask32_v isPrimaryParticle; + for(int iP=0; iP 0.0f); + isPrimary &= (mother_topo.GetChi2() == mother_topo.GetChi2()); + isPrimaryParticle |= isPrimary; + } + saveParticle &= isPrimaryParticle; + if( saveParticle.isEmpty() ) continue; + + for(int iv=0; iv& particles1, + const std::vector& particles2, + const int motherPdg, + std::vector& output) +{ + if(!(fDecayReconstructionList.empty())) + { + if(fDecayReconstructionList.find(motherPdg) == fDecayReconstructionList.end()) return; + } + + if(particles1.size() == 0U || particles2.size() == 0U) return; + + const int pdg1 = particles1[0].GetPDG(); + const int pdg2 = particles2[0].GetPDG(); + + const float M1 = KFParticleDatabase::Instance()->GetMass(pdg1); + const float M2 = KFParticleDatabase::Instance()->GetMass(pdg2); + + for(uint32_t iParticle1 = 0; iParticle1& Particles, + std::vector >& PrimVtx) +{ + std::vector piPlus; + std::vector kPlus; + std::vector pPlus; + std::vector dPlus; + std::vector tPlus; + std::vector he3Plus; + std::vector he4Plus; + std::vector he6Plus; + std::vector li6Plus; + std::vector li7Plus; + std::vector be7Plus; + + std::vector piMinus; + std::vector kMinus; + std::vector pMinus; + + const KFParticleSIMD pv = PrimVtx[0]; + KFParticleSIMD trackSIMD; + KFParticle track; + + for(int iTrack=vTracks[2].FirstPion(); iTrack < vTracks[2].LastBe7(); iTrack+=SimdLen) + { + const int32_v& pdg = reinterpret_cast(vTracks[2].PDG()[iTrack]); + const int32_v& id = reinterpret_cast(vTracks[2].Id()[iTrack]); + + trackSIMD.Load(vTracks[2], iTrack, pdg); + trackSIMD.SetPDG(pdg); + trackSIMD.SetId(id); + trackSIMD.SetProductionVertex(pv); + + for(int i=0; i= vTracks[2].LastBe7()) continue; + + trackSIMD.GetKFParticle(track, i); + + // if(track.Chi2() > 3.f * track.NDF()) continue; + + if(track.GetPDG() == 211) piPlus.push_back(track); + if(track.GetPDG() == 321) kPlus.push_back(track); + if(track.GetPDG() == 2212) pPlus.push_back(track); + if(track.GetPDG() == 1000010020) dPlus.push_back(track); + if(track.GetPDG() == 1000010030) tPlus.push_back(track); + if(track.GetPDG() == 1000020030) he3Plus.push_back(track); + if(track.GetPDG() == 1000020040) he4Plus.push_back(track); + if(track.GetPDG() == 1000020060) he6Plus.push_back(track); + if(track.GetPDG() == 1000030060) li6Plus.push_back(track); + if(track.GetPDG() == 1000030070) li7Plus.push_back(track); + if(track.GetPDG() == 1000040070) be7Plus.push_back(track); + } + } + + for(int iTrack=vTracks[3].FirstPion(); iTrack < vTracks[3].LastProton(); iTrack+=SimdLen) + { + const int32_v& pdg = reinterpret_cast(vTracks[3].PDG()[iTrack]); + const int32_v& id = reinterpret_cast(vTracks[3].Id()[iTrack]); + + trackSIMD.Load(vTracks[3], iTrack, pdg); + trackSIMD.SetPDG(pdg); + trackSIMD.SetId(id); + trackSIMD.SetProductionVertex(pv); + + for(int i=0; i= vTracks[3].LastProton()) continue; + + trackSIMD.GetKFParticle(track, i); + + // if(track.Chi2() > 3.f * track.NDF()) continue; + + if(track.GetPDG() == -211) piMinus.push_back(track); + if(track.GetPDG() == -321) kMinus.push_back(track); + if(track.GetPDG() == -2212) pMinus.push_back(track); + } + } + + + ConstructResonance(piPlus, piMinus, 113, Particles); // rho0 -> pi+ pi- + ConstructResonance(kPlus, piMinus, 313, Particles); // K*0 -> K+ pi- + ConstructResonance(kMinus, piPlus, -313, Particles); // K*0b -> K- pi+ + ConstructResonance(kPlus, kMinus, 333, Particles); // phi -> K+ K- + + ConstructResonance(pPlus, piPlus, 2224, Particles); // Delta++ + ConstructResonance(pMinus, piMinus, -2224, Particles); // Delta-- + ConstructResonance(pPlus, piMinus, 2114, Particles); // Delta0 + ConstructResonance(pMinus, piPlus, -2114, Particles); // Delta0 bar + + ConstructResonance(dPlus, piMinus, 100001, Particles); //dpi- + ConstructResonance(dPlus, piPlus, 100002, Particles); //dpi+ + ConstructResonance(tPlus, piMinus, 100003, Particles); //tpi- + ConstructResonance(tPlus, piPlus, 100004, Particles); //tpi+ + ConstructResonance(he3Plus, piMinus, 100005, Particles); //He3pi- + ConstructResonance(he3Plus, piPlus, 100006, Particles); //He3pi+ + ConstructResonance(he4Plus, piMinus, 100007, Particles); //He4pi- + ConstructResonance(he4Plus, piPlus, 100008, Particles); //He4pi+ + ConstructResonance(he6Plus, piMinus, 100009, Particles); //He6pi- + ConstructResonance(he6Plus, piPlus, 100010, Particles); //He6pi+ + ConstructResonance(li6Plus, piMinus, 100011, Particles); //Li6pi- + ConstructResonance(li6Plus, piPlus, 100012, Particles); //Li6pi+ + ConstructResonance(li7Plus, piMinus, 100013, Particles); //Li7pi- + ConstructResonance(li7Plus, piPlus, 100014, Particles); //Li7pi+ + ConstructResonance(be7Plus, piMinus, 100015, Particles); //Be7pi- + ConstructResonance(be7Plus, piPlus, 100016, Particles); //Be7pi+ + + ConstructResonance(dPlus, kMinus, 110001, Particles); //dK- + ConstructResonance(dPlus, kPlus, 110002, Particles); //dK+ + ConstructResonance(tPlus, kMinus, 110003, Particles); //tK- + ConstructResonance(tPlus, kPlus, 110004, Particles); //tK+ + ConstructResonance(he3Plus, kMinus, 110005, Particles); //He3K- + ConstructResonance(he3Plus, kPlus, 110006, Particles); //He3K+ + ConstructResonance(he4Plus, kMinus, 110007, Particles); //He4K- + ConstructResonance(he4Plus, kPlus, 110008, Particles); //He4K+ + ConstructResonance(he6Plus, kMinus, 110009, Particles); //He6K- + ConstructResonance(he6Plus, kPlus, 110010, Particles); //He6K+ + ConstructResonance(li6Plus, kMinus, 110011, Particles); //Li6K- + ConstructResonance(li6Plus, kPlus, 110012, Particles); //Li6K+ + ConstructResonance(li7Plus, kMinus, 110013, Particles); //Li7K- + ConstructResonance(li7Plus, kPlus, 110014, Particles); //Li7K+ + ConstructResonance(be7Plus, kMinus, 110015, Particles); //Be7K- + ConstructResonance(be7Plus, kPlus, 110016, Particles); //Be7K+ + + ConstructResonance(pPlus, pPlus, 200001, Particles); //pp + ConstructResonance(dPlus, pPlus, 200002, Particles); //dp + ConstructResonance(tPlus, pPlus, 200003, Particles); //tp + ConstructResonance(he3Plus, pPlus, 200004, Particles); //He3p + ConstructResonance(he4Plus, pPlus, 200005, Particles); //He4p + ConstructResonance(he6Plus, pPlus, 200006, Particles); //He6p + ConstructResonance(li6Plus, pPlus, 200007, Particles); //Li6p + ConstructResonance(li7Plus, pPlus, 200008, Particles); //Li7p + ConstructResonance(be7Plus, pPlus, 200009, Particles); //Be7p +} + +void KFParticleFinder::ConstructPrimaryBG(KFPTrackVector* vTracks, + vector& Particles, + std::vector >& PrimVtx, + const float* cuts, + const float* secCuts, + vector< vector >* vMotherPrim, + vector* 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; + float32_v dS; + + alignas(SimdSize) std::int32_t idNegDaughtersArray[SimdLen]; + alignas(SimdSize) std::int32_t idPosDaughtersArray[SimdLen]; + alignas(SimdSize) std::int32_t daughterPosPDGArray[SimdLen]; + alignas(SimdSize) std::int32_t daughterNegPDGArray[SimdLen]; + alignas(SimdSize) std::int32_t pvIndexMotherArray[SimdLen]; + alignas(SimdSize) std::int32_t V0PDGArray[SimdLen]; + + int32_v idNegDaughters; + int32_v idPosDaughters; + int32_v daughterPosPDG(-1); + int32_v daughterNegPDG(-1); + + int32_v pvIndexMother(-1); + + float32_v massMotherPDG(0.f), massMotherPDGSigma(0.f); + int32_v V0PDG(0); + + KFParticleSIMD motherPrimSecCand; + int nPrimSecCand =0; + + for(int iSet=2; iSet<4; iSet++) + { + int signPDG = 1; + if(iSet == 3) + signPDG = -1; + + KFPTrackVector& primaryTracks = vTracks[iSet]; + int nPositiveTracks = primaryTracks.LastBe7(); + + for(int iTr1 = primaryTracks.FirstPion(); iTr1 < nPositiveTracks; iTr1 ++) + { + int pdg1 = primaryTracks.PDG()[iTr1]; + int pvIndex = primaryTracks.PVIndex()[iTr1]; + + for(int iTr2 = iTr1+1; iTr2 < nPositiveTracks; iTr2 ++) + { + int pdg2 = primaryTracks.PDG()[iTr2]; + if(pvIndex != primaryTracks.PVIndex()[iTr2]) continue; + + int motherPDG = -1; + + motherPDG = (abs(pdg1) == 211) && (abs(pdg2) == 211) ? signPDG*9001 : motherPDG; //pi+pi+ + motherPDG = (abs(pdg1) == 211) && (abs(pdg2) == 321) ? signPDG*9002 : motherPDG; //pi+K+ + motherPDG = (abs(pdg1) == 211) && (abs(pdg2) == 2212) ? signPDG*2224 : motherPDG; //pi+p + motherPDG = (abs(pdg1) == 321) && (abs(pdg2) == 321) ? signPDG*9003 : motherPDG; //K+K+ + motherPDG = (abs(pdg1) == 321) && (abs(pdg2) == 2212) ? signPDG*9004 : motherPDG; //K+p + + if(signPDG) + { + motherPDG = ( pdg1 == 211) && (pdg2 == 1000010020) ? 100002 : motherPDG; //d+ pi+ + motherPDG = ( pdg1 == 211) && (pdg2 == 1000010030) ? 100004 : motherPDG; //t+ pi+ + motherPDG = ( pdg1 == 211) && (pdg2 == 1000020030) ? 100006 : motherPDG; //He3+ pi+ + motherPDG = ( pdg1 == 211) && (pdg2 == 1000020040) ? 100008 : motherPDG; //He4+ pi+ + motherPDG = ( pdg1 == 211) && (pdg2 == 1000020060) ? 100010 : motherPDG; //He6+ pi+ + motherPDG = ( pdg1 == 211) && (pdg2 == 1000030060) ? 100012 : motherPDG; //Li6+ pi+ + motherPDG = ( pdg1 == 211) && (pdg2 == 1000030070) ? 100014 : motherPDG; //Li7+ pi+ + motherPDG = ( pdg1 == 211) && (pdg2 == 1000040070) ? 100016 : motherPDG; //Be7+ pi+ + + motherPDG = ( pdg1 == 321) && (pdg2 == 1000010020) ? 110002 : motherPDG; //d+ K+ + motherPDG = ( pdg1 == 321) && (pdg2 == 1000010030) ? 110004 : motherPDG; //t+ K+ + motherPDG = ( pdg1 == 321) && (pdg2 == 1000020030) ? 110006 : motherPDG; //He3+ K+ + motherPDG = ( pdg1 == 321) && (pdg2 == 1000020040) ? 110008 : motherPDG; //He4+ K+ + motherPDG = ( pdg1 == 321) && (pdg2 == 1000020060) ? 110010 : motherPDG; //He6+ K+ + motherPDG = ( pdg1 == 321) && (pdg2 == 1000030060) ? 110012 : motherPDG; //Li6+ K+ + motherPDG = ( pdg1 == 321) && (pdg2 == 1000030070) ? 110014 : motherPDG; //Li7+ K+ + motherPDG = ( pdg1 == 321) && (pdg2 == 1000040070) ? 110016 : motherPDG; //Be7+ K+ + + motherPDG = ( pdg1 == 2212) && (pdg2 == 2212) ? 200001 : motherPDG; //p p + motherPDG = ( pdg1 == 2212) && (pdg2 == 1000010020) ? 200002 : motherPDG; //d+ p + motherPDG = ( pdg1 == 2212) && (pdg2 == 1000010030) ? 200003 : motherPDG; //t+ p + motherPDG = ( pdg1 == 2212) && (pdg2 == 1000020030) ? 200004 : motherPDG; //He3+ p + motherPDG = ( pdg1 == 2212) && (pdg2 == 1000020040) ? 200005 : motherPDG; //He4+ p + motherPDG = ( pdg1 == 2212) && (pdg2 == 1000020060) ? 200006 : motherPDG; //He6+ p + motherPDG = ( pdg1 == 2212) && (pdg2 == 1000030060) ? 200007 : motherPDG; //Li6+ p + motherPDG = ( pdg1 == 2212) && (pdg2 == 1000030070) ? 200008 : motherPDG; //Li7+ p + motherPDG = ( pdg1 == 2212) && (pdg2 == 1000040070) ? 200009 : motherPDG; //Be7+ p + } + + if(motherPDG == -1) continue; + + if(!(fDecayReconstructionList.empty())) + { + if(fDecayReconstructionList.find(motherPDG) == fDecayReconstructionList.end()) continue; + } + + { + idPosDaughtersArray[nBufEntry] = iTr2; + idNegDaughtersArray[nBufEntry] = iTr1; + + daughterPosPDGArray[nBufEntry] = pdg2; + daughterNegPDGArray[nBufEntry] = pdg1; + + pvIndexMotherArray[nBufEntry] = pvIndex; + + V0PDGArray[nBufEntry] = motherPDG; + + nBufEntry++; + + if(int(nBufEntry) == SimdLen) + { + idNegDaughters.load(idNegDaughtersArray); + idPosDaughters.load(idPosDaughtersArray); + daughterNegPDG.load(daughterNegPDGArray); + daughterPosPDG.load(daughterPosPDGArray); + pvIndexMother.load(pvIndexMotherArray); + V0PDG.load(V0PDGArray); + + 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; iVGetMotherMass(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, + int32_v& idTracks, + int32_v& trackPDG, + KFParticle* vV0[], + KFParticleSIMD& mother, + std::vector >& motherTopo, + KFParticle& mother_temp, + const unsigned short nElements, + kfvector_floatv& l, + kfvector_floatv& dl, + std::vector& Particles, + std::vector >& PrimVtx, + const float32_v* cuts, + const int32_v& pvIndex, + const float32_v& massMotherPDG, + const float32_v& massMotherPDGSigma, + std::vector< std::vector >* vMotherPrim, + std::vector* 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. + **/ + + mask32_v isPrimary = (pvIndex>-1); + + int32_v trackId(KFP::SIMD::UninitializeTag{}); + trackId.gather( &(vTracks.Id()[0]), idTracks ); + + KFParticleSIMD V0(vV0,nElements); + KFParticleSIMD track(vTracks, idTracks, trackPDG); + track.SetId(trackId); + + mask32_v isSameParticle = ((abs(mother.PDG()) == int32_v(4122)) || + (abs(mother.PDG()) == int32_v(114122)) || + (abs(mother.PDG()) == int32_v(204122)) || + (abs(mother.PDG()) == int32_v(504122)) || + (abs(mother.PDG()) == int32_v(404122)) || + (abs(mother.PDG()) == int32_v(425)) || + (abs(mother.PDG()) == int32_v(427)) || + (abs(mother.PDG()) == int32_v(200411)) || + (abs(mother.PDG()) == int32_v(300411)) || + (abs(mother.PDG()) == int32_v(300431)) || + (abs(mother.PDG()) == int32_v(400431)) || + (abs(mother.PDG()) == int32_v(411)) || + (abs(mother.PDG()) == int32_v(431)) || + (abs(mother.PDG()) == int32_v(429)) || + (abs(mother.PDG()) == int32_v(1003334)) || + (abs(mother.PDG()) == int32_v(3001)) || + (abs(mother.PDG()) == int32_v(3006)) || + (abs(mother.PDG()) == int32_v(3007)) || + (abs(mother.PDG()) == int32_v(3009)) || + (abs(mother.PDG()) == int32_v(100321)) || + (abs(mother.PDG()) >= int32_v(3011) && abs(mother.PDG()) <= int32_v(3039)) + ); + if( isSameParticle.isEmpty() ) + { +#ifdef CBM + float32_v ds[2] = {0.f,0.f}; + float32_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 + { + int32_v motherPDG = mother.PDG(); + mother = V0; + mother.SetPDG(motherPDG); + track.TransportToPoint(V0.Parameters()); + mother += track; + } + + mask32_v active = (int32_v::indicesSequence() < int(nElements)); + + mask32_v saveParticle = active; + saveParticle &= (mother.Chi2()/toFloat(mother.NDF()) < cuts[2] ); + saveParticle &= isFinite(mother.GetChi2()); + saveParticle &= (mother.GetChi2() > 0.0f); + saveParticle &= (mother.GetChi2() == mother.GetChi2()); + + if( saveParticle.isEmpty() ) { return; } + + mask32_v isSameTrack; + for(unsigned int iD=0; iD cuts[0]) || isPrimary ); + + float32_v p1p2 = track.Px()*V0.Px() + track.Py()*V0.Py() + track.Pz()*V0.Pz(); + float32_v p12 = track.Px()*track.Px() + track.Py()*track.Py() + track.Pz()*track.Pz(); + float32_v p22 = V0.Px()*V0.Px() + V0.Py()*V0.Py() + V0.Pz()*V0.Pz(); + saveParticle &= p1p2 > -p12; + saveParticle &= p1p2 > -p22; + + mask32_v setLCut = abs(mother.PDG()) == 3312 || abs(mother.PDG()) == 3334 || abs(mother.PDG()) == 3001; + saveParticle &= ( (setLCut && lMin > float32_v(fLCut)) || (!setLCut) ); + + ldlMin = 1.e8f; + for(int iP=0; iP iPrimVert[SimdLen]; + mask32_v isPrimaryPart; + + for(int iP=0; iPNDaughters(); 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); + if( mother.PDG()[iv] == 3028 ) + fPPpi.push_back(mother_temp); + if( mother.PDG()[iv] ==-3028 ) + fPPpiBar.push_back(mother_temp); + + if( mother.PDG()[iv] == 3006) + fHe3PPi.push_back(mother_temp); + if( mother.PDG()[iv] == 3007) + fHe4PPi.push_back(mother_temp); + + mother_temp.SetId(Particles.size()); + + if( !(isPrimaryPart[iv]) /*|| (mother.PDG()[iv] == 3006) || (mother.PDG()[iv] == 3007) */) + { + 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; + } + + if( (mother.PDG()[iv] == 3006) || (mother.PDG()[iv] == 3007) ) + { + float mass, errMass; + mother_temp.GetMass(mass, errMass); + if( (fabs(mass - massMotherPDG[iv])/massMotherPDGSigma[iv]) <= 6.f ) + { + KFParticle mother_sec = mother_temp; + mother_sec.SetNonlinearMassConstraint(massMotherPDG[iv]); + if(mother.PDG()[iv] == 3006) fHe4L.push_back(mother_sec); + if(mother.PDG()[iv] == 3007) fHe5L.push_back(mother_sec); + } + } + + //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 >* 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& vV0, + const int V0PDG, + KFPTrackVector& vTracks, + const int q, + const int firstTrack, + const int lastTrack, + vector& Particles, + std::vector >& PrimVtx, + int v0PVIndex, + kfvector_float* ChiToPrimVtx, + vector< vector >* vMotherPrim, + vector* 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[SimdLen]; + + KFParticleSIMD mother, track; + std::vector > motherTopo(fNPV); + + kfvector_floatv l(fNPV), dl(fNPV); + + float32_v cuts[3]; + + // for secondary V0 + unsigned int nBufEntry = 0; + float32_v dS; + int32_v idTrack; + int32_v trackPDGMother(-1); + int32_v pvIndexMother(-1); + + float32_v massMotherPDG(0.f), massMotherPDGSigma(0.f); + int32_v motherParticlePDG(0); + + alignas(SimdSize) std::int32_t idTrackArray[SimdLen]; + alignas(SimdSize) std::int32_t trackPDGMotherArray[SimdLen]; + alignas(SimdSize) std::int32_t pvIndexMotherArray[SimdLen]; + alignas(SimdSize) std::int32_t motherParticlePDGArray[SimdLen]; + alignas(SimdSize) float massMotherPDGArray[SimdLen]; + alignas(SimdSize) float massMotherPDGSigmaArray[SimdLen]; + alignas(SimdSize) float cutsArray[3][SimdLen]; + + +// 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); + + mask32_v isPvIndexNeg, isPvIndexPos; + if(v0PVIndex >= 0) isPvIndexPos.setTrue(); + else isPvIndexNeg.setTrue(); + + for(unsigned int iV0=0; iV0 < vV0.size(); iV0++) + { + if(vV0[iV0].GetPDG() != V0PDG) continue; + + int iNegDaughter = vV0[iV0].DaughterIds()[0]; + int iPosDaughter = vV0[iV0].DaughterIds()[1]; + + for(int iTr=firstTrack; iTr < lastTrack; iTr += SimdLen) + { + const int NTracks = (iTr + SimdLen < lastTrack) ? SimdLen : (lastTrack - iTr); + + const int32_v& trackPDG = reinterpret_cast(vTracks.PDG()[iTr]); + const int32_v& trackPVIndex = reinterpret_cast(vTracks.PVIndex()[iTr]); + + const mask32_v& isTrackSecondary = (trackPVIndex < 0); + const mask32_v& isSecondary = isPvIndexNeg && isTrackSecondary; + const mask32_v& isPrimary = isPvIndexPos && (!isTrackSecondary); + const mask32_v& isSamePV = (isPrimary && (v0PVIndex == trackPVIndex)) || !(isPrimary); + + mask32_v closeDaughters = isSamePV && (int32_v::indicesSequence() < int(NTracks)); + +// if(v0PVIndex < 0) +// { +// KFParticleSIMD v0(vV0[iV0]); +// track.Load(vTracks, iTr, trackPDG); + +// float32_v dsV0, dsTrack; +// float32_v dsdrV0[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; +// float32_v dsdrTrack[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; +// float32_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 float32_v& dx = par1[0] - par2[0]; +// const float32_v& dy = par1[1] - par2[1]; +// const float32_v& dz = par1[2] - par2[2]; +// const float32_v& r2 = dx*dx + dy*dy + dz*dz; +// +// const float32_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 float32_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 float32_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 < float32_v(1.f)) && (r2*r2/err2) < float32_v(3.f) && isSecondary); +// closeDaughters &= v0.GetDeviationFromParticle(track) < float32_v(10.f); +// } + + if(v0PVIndex < 0) + { + KFParticleSIMD v0(vV0[iV0]); + track.Load(vTracks, iTr, trackPDG); + closeDaughters &= v0.GetDistanceFromParticle(track) < float32_v(fDistanceCut); + if(closeDaughters.isEmpty()) continue; + } + + int32_v trackPdgPos[2]; + mask32_v active[2]; + + int nPDGPos = 2; + + active[0] = closeDaughters; + active[1] = (trackPDG == -1) && isSecondary && closeDaughters; + + trackPdgPos[0] = trackPDG; + + if( (trackPDG == -1).isEmpty() || (abs(V0PDG) == 421) || (abs(V0PDG) == 411) ) + { + nPDGPos = 1; + } + else + { + trackPdgPos[0] = select(trackPDG == -1, q*211, trackPdgPos[0]); + nPDGPos = 1;//TODO + trackPdgPos[1] = select(isSecondary, q*321, trackPdgPos[1]); + } + + for(int iPDGPos=0; iPDGPos(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211) && (id>iPosDaughter), 100321, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211) && (id>iNegDaughter), -100321, motherPDG); + } + else if( V0PDG == 3312 ) + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == 211), 3324, motherPDG); + else if( V0PDG == -3312) + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == -211), -3324, motherPDG); + else if( V0PDG == 3324 ) + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == -321), 1003334, motherPDG); + else if( V0PDG == -3324 ) + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == 321), -1003334, motherPDG); + else if(V0PDG == 421) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211), 411, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 321), 431, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212), 4122, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + mask32_v isDMeson = isSecondary && (trackPdgPos[iPDGPos] == 211); + active[iPDGPos] &= (!(isDMeson)) || (isDMeson && ( id > iPosDaughter) ); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), -521, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -321), -529, motherPDG); + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == 211), 10411, motherPDG); + } + else if(V0PDG == -421) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), -411, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -321), -431, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] ==-2212), -4122, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + mask32_v isDMeson = isSecondary && (trackPdgPos[iPDGPos] == -211); + active[iPDGPos] &= (!(isDMeson)) || (isDMeson && ( id > iNegDaughter) ); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211) , 521, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 321) , 529, motherPDG); + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == -211), -10411, motherPDG); + } + else if(V0PDG == 420 && q>0) + { + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 211), 300411, motherPDG); + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 321), 400431, motherPDG); + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 2212), 504122, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + mask32_v isDMeson = isSecondary && (abs(trackPdgPos[iPDGPos]) == 211); + active[iPDGPos] &= (!(isDMeson)) || (isDMeson && ( id > iPosDaughter) ); + } + else if(V0PDG == 420 && q<0) + { + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 211), -300411, motherPDG); + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 321), -400431, motherPDG); + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 2212), -504122, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + mask32_v isDMeson = isSecondary && (abs(trackPdgPos[iPDGPos]) == 211); + active[iPDGPos] &= (!(isDMeson)) || (isDMeson && ( id > iNegDaughter) ); + } + else if(V0PDG == 411) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), 429, motherPDG); + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == -211), 10421, motherPDG); + } + else if(V0PDG == -411) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211), -429, motherPDG); + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == 211), -10421, motherPDG); + } + else if(V0PDG == 419) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), -511, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -321), -519, motherPDG); + } + else if(V0PDG == -419) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211), 511, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 321), 519, motherPDG); + } + else if(V0PDG == 429) + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == 211), 20411, motherPDG); + else if(V0PDG == -429) + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == -211), -20411, motherPDG); + else if( V0PDG == 3002 ) + { + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + mask32_v isSameProton = (id == fLPiPIndex[iV0]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212) && (!isSameProton), 3001, motherPDG); + } + else if( V0PDG == 100411 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), 425, motherPDG); + } + else if( V0PDG == 100431 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -321), 427, motherPDG); + } + else if( V0PDG == 425) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211), 200411, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), -200411, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 321), 300431, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -321), -300431, motherPDG); + } + else if( V0PDG == 111 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212), 3222, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -2212), -3222, motherPDG); + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == 321), 100323, motherPDG); + motherPDG = select( isPrimary && (trackPdgPos[iPDGPos] == -321), -100323, motherPDG); + } + else if( V0PDG == 3003 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212), 3012, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000010020) && (id>iPosDaughter), 3014, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000010030), 3015, motherPDG); + } + else if( V0PDG == -3003 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -2212), -3012, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000010020) && (id>iNegDaughter), -3014, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000010030), -3015, motherPDG); + } + else if( V0PDG == 3103 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212), 3013, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000010030) && (id>iPosDaughter), 3017, motherPDG); + } + else if( V0PDG ==-3103 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -2212), -3013, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000010030) && (id>iNegDaughter), -3017, motherPDG); + } + else if( V0PDG == 3004 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212) , 3006, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000010020), 3018, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000010030), 3020, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000020030) && (id>iPosDaughter), 3024, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000020040), 3026, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211) && (id!=iNegDaughter), 3203, motherPDG); + } + else if( V0PDG == -3004 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -2212), -3006, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000010020), -3018, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000010030), -3020, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000020030) && (id>iNegDaughter), -3024, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000020040), -3026, motherPDG); + } + else if( V0PDG == 3005 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212) , 3007, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000010020), 3021, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000010030), 3023, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 1000020040) && (id>iPosDaughter), 3027, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211) && (id!=iNegDaughter) , 3040, motherPDG); + } + else if( V0PDG == -3005 ) + { + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -2212), -3007, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000010020), -3021, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000010030), -3023, motherPDG); + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -1000020040) && (id>iNegDaughter), -3027, motherPDG); + } + else if( V0PDG == 3006 ) + { + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212) && (id>vV0[iV0].DaughterIds()[2]), 3038, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211) && (id>iNegDaughter), 3008, motherPDG); + } + else if( V0PDG == 3007 ) + { + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212) && (id>vV0[iV0].DaughterIds()[2]), 3039, motherPDG); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211) && (id>iNegDaughter), 3010, motherPDG); + } + else if( V0PDG == 3203 ) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212), 3009, motherPDG); + else if( V0PDG == 3010 ) + { + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + mask32_v isSameProton = (id == Particles[vV0[iV0].DaughterIds()[1]].DaughterIds()[2]); + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 2212) && (!isSameProton), 3011, motherPDG); + } + else if( V0PDG == 8122) + { + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 2212) && (id>iPosDaughter), 3028, motherPDG); + } + else if( V0PDG ==-8122) + { + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 2212) && (id>iNegDaughter), -3028, motherPDG); + } + else if( V0PDG == 3028 ) + { + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 2212) && (id>vV0[iV0].DaughterIds()[2]), 3029, motherPDG); + } + else if( V0PDG ==-3028 ) + { + const int32_v& id = reinterpret_cast(vTracks.Id()[iTr]); + motherPDG = select( isSecondary && (abs(trackPdgPos[iPDGPos]) == 2212) && (id>vV0[iV0].DaughterIds()[2]), -3029, motherPDG); + } + else if(V0PDG == 304122) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211), 314122, motherPDG); + else if(V0PDG == -304122) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), -314122, motherPDG); + else if(V0PDG == 314122) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), 404122, motherPDG); + else if(V0PDG == -314122) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211), -404122, motherPDG); + else if(V0PDG == 104122) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211), 114122, motherPDG); + else if(V0PDG == -104122) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), -114122, motherPDG); + else if(V0PDG == 114122) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == -211), 204122, motherPDG); + else if(V0PDG == -114122) + motherPDG = select( isSecondary && (trackPdgPos[iPDGPos] == 211), -204122, motherPDG); + + active[iPDGPos] &= (motherPDG != -1); + if(!(fDecayReconstructionList.empty())) + { + alignas(SimdSize) std::int32_t motherPdgArray[SimdLen]; + motherPDG.store(motherPdgArray); + for(int iV=0; iV((*ChiToPrimVtx)[iTr]) > float32_v(fCuts2D[0])) ) ); + + if(active[iPDGPos].isEmpty()) continue; + + if(isCharm) + { + track.Load(vTracks, iTr, trackPDG); + const float32_v& trackPt = track.Px()*track.Px() + track.Py()*track.Py(); + const int32_v& nPixelHits = reinterpret_cast(vTracks.NPixelHits()[iTr]); + + active[iPDGPos] &= (trackPt >= fCutCharmPt*fCutCharmPt) && (reinterpret_cast((*ChiToPrimVtx)[iTr]) > fCutCharmChiPrim ) && (nPixelHits >= int32_v(3)); + } + { + mask32_v 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 float32_v& trackPt = track.Px()*track.Px() + track.Py()*track.Py(); + const int32_v& nPixelHits = reinterpret_cast(vTracks.NPixelHits()[iTr]); + + active[iPDGPos] &= ( ((trackPt >= fCutCharmPt*fCutCharmPt) && (reinterpret_cast((*ChiToPrimVtx)[iTr]) > fCutCharmChiPrim ) && (nPixelHits >= int32_v(3)) ) && isCharmParticle ) || (!isCharmParticle); + } + } + + for(int iV=0; iVGetMotherMass(motherPDG[iV],massMother,massMotherSigma); + + massMotherPDGArray[nBufEntry] = massMother; + massMotherPDGSigmaArray[nBufEntry] = massMotherSigma; + motherParticlePDGArray[nBufEntry] = motherPDG[iV]; + + int motherType = 0; + + switch (abs(motherPDG[iV])) + { + case 3312: motherType = 0; break; //Xi + case 3334: motherType = 0; break; //Omega + case 100321: motherType = 0; break; //K -> 3pi + 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 3012: motherType = 1; break; //H3L + case 3013: motherType = 1; break; //H4L + case 3014: motherType = 1; break; //H4L + case 3015: motherType = 1; break; //H5L + case 3017: motherType = 1; break; //H6L + case 3006: motherType = 1; break; //He4L + case 3007: motherType = 1; break; //He5L + case 3018: motherType = 1; break; //He5L + case 3020: motherType = 1; break; //He6L + case 3021: motherType = 1; break; //He6L + case 3023: motherType = 1; break; //He7L + case 3024: motherType = 1; break; //Li6L + case 3026: motherType = 1; break; //Li7L + case 3027: motherType = 1; break; //Li8L + case 3203: motherType = 1; break; //LLn + case 3040: motherType = 1; break; //LLnn + case 3008: motherType = 1; break; //H4LL + case 3009: motherType = 1; break; //H4LL + case 3011: motherType = 1; break; //He6LL + case 3028: motherType = 1; break; //H2L + case 3029: motherType = 1; break; //He3L + case 3038: motherType = 1; break; //Li5L + case 3039: motherType = 1; break; //Li6L + default: motherType = 2; break; //resonances + } + for(int iCut=0; iCut<3; iCut++) + cutsArray[iCut][nBufEntry] = fCutsTrackV0[motherType][iCut]; + + nBufEntry++; + + if(int(nBufEntry) == SimdLen) + { + idTrack.load(idTrackArray); + trackPDGMother.load(trackPDGMotherArray); + pvIndexMother.load(pvIndexMotherArray); + massMotherPDG.load(massMotherPDGArray); + massMotherPDGSigma.load(massMotherPDGSigmaArray); + motherParticlePDG.load(motherParticlePDGArray); + cuts[0].load(cutsArray[0]); + cuts[1].load(cutsArray[1]); + cuts[2].load(cutsArray[2]); + + 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& vParticles, + const KFPTrackVector& vTracks, + const int firstTrack, + const int lastTrack, + const KFParticleSIMD& PrimVtx, + vector& Particles) +{ + if( (vParticles.size() < 1) || ((lastTrack-firstTrack) < 1) ) return; + + if(!(fDecayReconstructionList.empty())) + { + if(fDecayReconstructionList.find(motherPDG) == fDecayReconstructionList.end()) return; + } + + // float massMother, massMotherSigma; + // KFParticleDatabase::Instance()->GetMotherMass(motherPDG, massMother, massMotherSigma); + + KFParticleSIMD track; + KFParticle candidate; + + for(unsigned int iP=0; iP < vParticles.size(); iP++) + { + const KFParticle& particle = vParticles[iP]; + const KFParticleSIMD particleSIMD(particle); + + for(int iTr=firstTrack; iTr < lastTrack; iTr += SimdLen) + { + const int NTracks = (iTr + SimdLen < lastTrack) ? SimdLen : (lastTrack - iTr); + const int32_v& trackPDG = reinterpret_cast(vTracks.PDG()[iTr]); + const int32_v& trackId = reinterpret_cast(vTracks.Id()[iTr]); + + mask32_v isOk = (trackPDG == correctTrackPDG); + + for(int iDaughter=0; iDaughter 0.0f); + isOk &= (mother.GetChi2() == mother.GetChi2()); + + if( isOk.isEmpty() ) continue; + + // float32_v l + // float32_v dl; + // mask32_v isParticleFromVertex; + // mother.GetDistanceToVertexLine(PrimVtx, l, dl, &isParticleFromVertex); + + for(int iV=0; iV& Particles, + vector& vCandidates, + std::vector >& 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[SimdLen]; + int nCand = vCandidates.size(); + + vector newCandidates; + kfvector_floatv l(fNPV), dl(fNPV); + + for(int iC=0; iC < nCand; iC += SimdLen) + { + int nEntries = (iC + SimdLen < nCand) ? SimdLen : (nCand - iC); + + for(int iv=0; iv cutLdL; + saveParticle &= (lMin < 200.f); + saveParticle &= isParticleFromVertex; + if( saveParticle.isEmpty() ) continue; + + KFParticleSIMD* candTopo = new KFParticleSIMD[fNPV]; + + for(int iP=0; iP 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& particles1, + vector& particles2, + vector& Particles, + std::vector >& PrimVtx, + const float* cuts, + int iPV, + const int MotherPDG, + bool isSameInputPart, + bool saveOnlyPrimary, + vector< vector >* vMotherPrim, + vector* 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[SimdLen]; + int nPart2 = particles2.size(); + + mask32_v isPrimary; + if(iPV >= 0) isPrimary.setTrue(); + + bool isCharm = (MotherPDG == 425) || + (MotherPDG == 427) || + (abs(MotherPDG) == 200411) || + (abs(MotherPDG) == 404122) || + (abs(MotherPDG) == 4132) || + (abs(MotherPDG) == 300431) || + (abs(MotherPDG) == 204122); + mask32_v isCharmMask; + if(isCharm) isCharmMask.setTrue(); + + 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 += SimdLen) + { + int nElements = (iP2 + SimdLen < nPart2) ? SimdLen : (nPart2 - iP2); + mask32_v active((int32_v::indicesSequence() < int(nElements))); + + for(int iv=0; ivId()[0]; +// int32_v gammaIndex1( (unsigned int)0); +// int32_v gammaIndex2( (unsigned int)0); +// for(int iv=0; ivGetPi0Mass(); +// 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); + } + + mask32_v saveParticle(active); + saveParticle &= (mother.Chi2()/toFloat(mother.NDF()) < cuts[2] ); + saveParticle &= isFinite(mother.GetChi2()); + saveParticle &= (mother.GetChi2() >= 0.0f); + saveParticle &= (mother.GetChi2() == mother.GetChi2()); + + if( saveParticle.isEmpty() ) { continue; } + + mask32_v isSameTrack; + for(unsigned int iD=0; iD -1) && (iP !=iPV) ) continue; + mask32_v isParticleFromVertexLocal; + mother.GetDistanceToVertexLine(PrimVtx[iP], l[iP], dl[iP], &isParticleFromVertexLocal); + isParticleFromVertex |= isParticleFromVertexLocal; + float32_v ldl = (l[iP]/dl[iP]); + lMin = select( (l[iP] < lMin) && active, l[iP], lMin); + ldlMin = select( (ldl < ldlMin) && active, ldl, ldlMin); + } + saveParticle &= ( ((!isPrimary) && ldlMin > cuts[0]) || isPrimary ); + saveParticle &= (lMin < 200.f); + + mask32_v setLCut = abs(mother.PDG()) == 3000; + saveParticle &= ( (setLCut && lMin > float32_v(fLCut)) || (!setLCut) ); + +// if(isPrimary && (float(ldlMin > 3) )) continue; + saveParticle &= (((!isPrimary) && isParticleFromVertex) || isPrimary ); + if( saveParticle.isEmpty() ) { continue; } + + mask32_v isSameParticle(isPrimary || isCharmMask); + if(!((isSameParticle).isFull())) + { + mask32_v isParticleFromVertexLocal; + float32_v l1, dl1; + vDaughters[0].GetDistanceToVertexLine(mother, l1, dl1, &isParticleFromVertexLocal); + + saveParticle &= ( isSameParticle || ((!isSameParticle) && isParticleFromVertexLocal)); + if( saveParticle.isEmpty() ) { continue; } + } + + for(int iP=0; iP -1) && (iP !=iPV) ) continue; + motherTopo[iP] = mother; + motherTopo[iP].SetProductionVertex(PrimVtx[iP]); + } + + vector iPrimVert[SimdLen]; + mask32_v isPrimaryPart; + + for(int iP=0; iP -1) && (iP !=iPV) ) continue; + const float32_v& motherTopoChi2Ndf = motherTopo[iP].GetChi2()/toFloat(motherTopo[iP].GetNDF()); + const mask32_v isPrimaryPartLocal = ( motherTopoChi2Ndf < float32_v(cuts[1]) ); + isPrimaryPart |= isPrimaryPartLocal; + for(int iV=0; iVId()); + } + + 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 >& PrimVtx, + std::vector& Particles) +{ + constexpr const int nKaonSets=2; + constexpr const int primCandidatesSet[nKaonSets]{11,12}; + constexpr const int trackSet[nKaonSets]{6,7}; // primary "+" and "-" tracks at last hit + constexpr const int trackPdg[nKaonSets]{321, -321}; + constexpr const int newPdg[nKaonSets]{200321, -200321}; + + KFParticleSIMD kaonTrack; + + for(int iKaonSet=0; iKaonSet >& candidateSets = fPrimCandidates[primCandidatesSet[iKaonSet]]; + KFPTrackVector& primTracks = vTracks[trackSet[iKaonSet]]; + const int firstTrack = primTracks.FirstKaon(); + const int lastTrack = primTracks.LastKaon(); + + for(unsigned int iPV=0; iPV < candidateSets.size(); iPV++) { + std::vector& candidates = candidateSets[iPV]; + + for(unsigned int iCandidate=0; iCandidate(primTracks.PDG()[iTrack]); + const int32_v& trackPVIndex = reinterpret_cast(primTracks.PVIndex()[iTrack]); + const mask32_v& isSamePV = (iPV == trackPVIndex); + + mask32_v active = (abs(trackPDG)==321) && isSamePV && (int32_v::indicesSequence() < int(NTracks)); + + if(active.isEmpty()) continue; + + kaonTrack.Load(primTracks, iTrack, trackPdg[iTrack]); + + float32_v dx = candidate.X() - kaonTrack.X(); + float32_v dy = candidate.Y() - kaonTrack.Y(); + float32_v dz = candidate.Z() - kaonTrack.Z(); + float32_v distance = sqrt(dx*dx + dy*dy + dz*dz); + active &= (distance <= float32_v(20.0f)); + if( active.isEmpty() ) continue; + + //Chi2 should be correct, momentum should be 0 within errors + KFParticleSIMD check = candidate; + check.SubtractDaughter(kaonTrack); + + active &= (check.NDF() >= 0); + active &= (check.Chi2()/toFloat(check.NDF()) <= fCuts2D[1]); + //fit should converge + active &= (check.Chi2() >= 0.f); + active &= (check.Chi2() == check.Chi2()); + //momentum shoud be 0 after subtraction + active &= (check.Px() <= 5.f*check.GetErrPx()); + active &= (check.Py() <= 5.f*check.GetErrPy()); + active &= (check.Pz() <= 5.f*check.GetErrPz()); + if( active.isEmpty() ) continue; + + for(int iV=0; iV& Particles, + std::vector >& PrimVtx) +{ + /** 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; + + int32_v idMotherTrack; + int32_v idChargedDaughter; + int32_v ChargedDaughterPDG(-1); + + int32_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] ]; + + int32_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 nMotherHypothesis(nTC,0); + vector< vector > motherPDGHypothesis(nTC); + vector< vector > neutralDaughterMassHypothesis(nTC); + + + //mu+, mu- + startTCMother[0] = 0; endTCMother[0] = MotherTracksSize; + startTCDaughter[0] = DaughterTracks.FirstMuon(); endTCDaughter[0] = DaughterTracks.LastPion(); + + 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(DaughterTracks.PDG()[iTrD]); + int32_v DaughterPVIndex = reinterpret_cast(DaughterTracks.PVIndex()[iTrD]); + int32_v daughterId = reinterpret_cast(DaughterTracks.Id()[iTrD]); + + mask32_v activeDaughter = (int32_v::indicesSequence() < int(NTracksDaughter)); + + ChargedDaughter.Load(DaughterTracks, iTrD, DaughterPDG); + ChargedDaughter.SetId(daughterId); + + for(unsigned short iTrM=startTCMother[iTC]; iTrM < endTCMother[iTC]; iTrM += SimdLen) + { + const unsigned short NTracks = (iTrM + SimdLen < MotherTracksSize) ? SimdLen : (MotherTracksSize - iTrM); + + const int32_v& MotherPDG = reinterpret_cast(MotherTracks.PDG()[iTrM]); + //const int32_v& MotherPVIndex = reinterpret_cast(MotherTracks.PVIndex()[iTrM]); + const int32_v& motherTrackId = reinterpret_cast(MotherTracks.Id()[iTrM]); + + for(int iRot = 0; iRot0) + { + DaughterPDG = DaughterPDG.rotate<1>(); + DaughterPVIndex = DaughterPVIndex.rotate<1>(); + DaughterInd = DaughterInd.rotate<1>(); + + ChargedDaughter.Rotate(); + + activeDaughter = /*( (DaughterPDG != -1) || ( (DaughterPVIndex < 0) && (DaughterPDG == -1) ) ) &&*/ (DaughterInd < DaughterTracksSize); + } + + int32_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= (lMotherTrak - float32_v(0.5f))); + active &= (distance <= float32_v(10.0f)); + if( active.isEmpty() ) continue; + + KFParticleSIMD neutralDaughter = MotherTrack; + //energy of the mother particle should be greater then of the daughter particle + active &= (neutralDaughter.E() > ChargedDaughter.E()); + if( active.isEmpty() ) continue; + + neutralDaughter.AddDaughterId(motherTrackId); + neutralDaughter.NDF() = -1; + neutralDaughter.Chi2() = 0.f; + neutralDaughter.SubtractDaughter(ChargedDaughter); + + float32_v neutralMass, neutralMassError; + neutralDaughter.GetMass(neutralMass, neutralMassError); + if(iTC > 0) + active &= (neutralMass > 0); + + //decay point shoud be between mother and daughter tracks + //TODO all PV should be checked + float32_v lNeutral, dlNeutral; + neutralDaughter.GetDistanceToVertexLine(PrimVtx[0], lNeutral, dlNeutral); + + active &= (lNeutral >= (lMotherTrak - float32_v(10.0f))); + active &= (lNeutral <= (lChargedTrak + float32_v(10.0f))); + //set cut on chi2 of the fit of the neutral daughter + active &= (neutralDaughter.NDF() >= 0); + active &= (neutralDaughter.Chi2()/toFloat(neutralDaughter.NDF()) <= fCuts2D[1]); + //fit should converge + active &= (neutralDaughter.Chi2() >= 0.f); + active &= (neutralDaughter.Chi2() == neutralDaughter.Chi2()); + if( active.isEmpty() ) continue; + + //kill particle-candidates produced by clones + active &= ( neutralDaughter.GetRapidity()<6.f /*&& neutralDaughter.GetRapidity()>0.f*/); + if ((iTC==1 && iHypothesis<4) || iTC==2) + active &= ( !( (neutralDaughter.GetPt())<0.5f && neutralDaughter.GetRapidity()<0.5f ) ); + if (iTC==3) + active &= ( !( (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 + float32_v lMother, dlMother; + mother.GetDistanceToVertexLine(PrimVtx[0], lMother, dlMother); + + active &= (lMother >= lMotherTrak); + active &= (lMother <= lChargedTrak); + //set cut on chi2 of the fit of the mother particle + active &= (mother.NDF() >= 0); + active &= (mother.Chi2()/toFloat(mother.NDF()) <= fCuts2D[1]); + //fit should converge + active &= (mother.Chi2() >= 0.f); + active &= (mother.Chi2() == mother.Chi2()); + if( active.isEmpty() ) continue; + + for(int iV=0; iV& Particles, + std::vector >& PrimVtx) +{ + /** 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, MotherFiltered, cDaughterFiltered; + + int32_v idMotherTrack; + int32_v idChargedDaughter; + int32_v ChargedDaughterPDG(-1); + + int32_v pvIndexMother(-1); + + int outNeutralDaughterPDG[6][5]; //[iTC][iHypothesis] + int outMotherPDG[6][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] ]; + + int32_v DaughterTracksSize = DaughterTracks.Size(); + int MotherTracksSize = MotherTracks.Size(); + + //track categories + int nTC = 6; + int startTCMother[6] = {0,0,0,0,0,0}; + int endTCMother[6] = {0,0,0,0,0,0}; + int startTCDaughter[6] = {0,0,0,0,0,0}; + int endTCDaughter[6] = {0,0,0,0,0,0}; + + vector nMotherHypothesis(nTC,0); + vector< vector > motherPDGHypothesis(nTC); + vector< vector > 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; + + //He3 + startTCMother[4] = 0; endTCMother[4] = MotherTracksSize; + startTCDaughter[4] = DaughterTracks.FirstHe3(); endTCDaughter[4] = DaughterTracks.LastHe3(); + + nMotherHypothesis[4] = 1; + + motherPDGHypothesis[4].push_back(7003029); + + neutralDaughterMassHypothesis[4].push_back(0.1349766); + + outNeutralDaughterPDG[4][0]= 7700111; + + outMotherPDG[4][0]= 7003029; + + //He4 + startTCMother[5] = 0; endTCMother[5] = MotherTracksSize; + startTCDaughter[5] = DaughterTracks.FirstHe4(); endTCDaughter[5] = DaughterTracks.LastHe4(); + + nMotherHypothesis[5] = 1; + + motherPDGHypothesis[5].push_back(7003006); + + neutralDaughterMassHypothesis[5].push_back(0.1349766); + + outNeutralDaughterPDG[5][0]= 7800111; + + outMotherPDG[5][0]= 7003006; + + for(int iTC=0; iTC(DaughterTracks.PDG()[iTrD]); + int32_v DaughterPVIndex = reinterpret_cast(DaughterTracks.PVIndex()[iTrD]); + int32_v daughterId = reinterpret_cast(DaughterTracks.Id()[iTrD]); + + mask32_v activeDaughter = (int32_v::indicesSequence() < int(NTracksDaughter)); + + ChargedDaughter.Load(DaughterTracks, iTrD, DaughterPDG); + ChargedDaughter.SetId(daughterId); + + for(unsigned short iTrM=startTCMother[iTC]; iTrM < endTCMother[iTC]; iTrM += SimdLen) + { + const unsigned short NTracks = (iTrM + SimdLen < MotherTracksSize) ? SimdLen : (MotherTracksSize - iTrM); + + const int32_v& MotherPDG = reinterpret_cast(MotherTracks.PDG()[iTrM]); + + //const int32_v& MotherPVIndex = reinterpret_cast(MotherTracks.PVIndex()[iTrM]); + const int32_v& motherTrackId = reinterpret_cast(MotherTracks.Id()[iTrM]); + + for(int iRot = 0; iRot0) + { + DaughterPDG = DaughterPDG.rotate<1>(); + DaughterPVIndex = DaughterPVIndex.rotate<1>(); + DaughterInd = DaughterInd.rotate<1>(); + + ChargedDaughter.Rotate(); + + activeDaughter = /*( (DaughterPDG != -1) || ( (DaughterPVIndex < 0) && (DaughterPDG == -1) ) ) &&*/ (DaughterInd < DaughterTracksSize); + } + + int32_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(iTC==4) + activeDaughter &= abs(DaughterPDG)==1000020030; + if(iTC==5) + activeDaughter &= abs(DaughterPDG)==1000020040; + if (activeDaughter.isEmpty()) continue; + + + for(int iHypothesis=0; iHypothesis=1000020030); + + MotherTrack.Load(MotherTracks, iTrM, motherPDGHypothesis[iTC][iHypothesis]); + + float32_v zMother = MotherTrack.Z(); + float32_v zCD = ChargedDaughter.Z(); + float32_v xMother = MotherTrack.X(); + float32_v xCD = ChargedDaughter.X(); + float32_v yMother = MotherTrack.Y(); + float32_v yCD = ChargedDaughter.Y(); + float32_v distance = sqrt((zMother-zCD)*(zMother-zCD)+(xMother-xCD)*(xMother-xCD)+(yMother-yCD)*(yMother-yCD)); + float32_v lMotherTrak, dlMotherTrak; + MotherTrack.GetDistanceToVertexLine(PrimVtx[0], lMotherTrak, dlMotherTrak); + float32_v lChargedTrak, dChargedTrak; + ChargedDaughter.GetDistanceToVertexLine(PrimVtx[0], lChargedTrak, dChargedTrak); + + //daughter particle should start after the last hit of a mother track +// active &= (lChargedTrak >= (lMotherTrak - float32_v(0.5f))); + active &= (distance <= float32_v(10.0f)); + if( active.isEmpty() ) continue; + + KFParticleSIMD neutralDaughter = MotherTrack; + //energy of the mother particle should be greater then of the daughter particle + active &= (neutralDaughter.E() > ChargedDaughter.E()); + if( active.isEmpty() ) continue; + + neutralDaughter.AddDaughterId(motherTrackId); + neutralDaughter.NDF() = -1; + neutralDaughter.Chi2() = 0.f; + neutralDaughter.ReconstructMissingMass(ChargedDaughter, MotherFiltered, cDaughterFiltered, neutralDaughterMassHypothesis[iTC][iHypothesis]); + + float32_v neutralMass, neutralMassError; + neutralDaughter.GetMass(neutralMass, neutralMassError); + if(iTC > 0) + active &= (neutralMass > 0.f); + + //decay point shoud be between mother and daughter tracks + //TODO all PV should be checked + float32_v lNeutral, dlNeutral; + neutralDaughter.GetDistanceToVertexLine(PrimVtx[0], lNeutral, dlNeutral); + + active &= (lNeutral >= (lMotherTrak - float32_v(10.0f))); + active &= (lNeutral <= (lChargedTrak + float32_v(10.0f))); + + //set cut on chi2 of the fit of the neutral daughter + active &= (neutralDaughter.NDF() >= 0); + active &= (neutralDaughter.Chi2()/toFloat(neutralDaughter.NDF()) <= fCuts2D[1]); + //fit should converge + active &= (neutralDaughter.Chi2() >= 0.f); + active &= (neutralDaughter.Chi2() == neutralDaughter.Chi2()); + + if(abs(motherPDGHypothesis[iTC][iHypothesis]) > 1000) + { + active &= (lNeutral < 90.f); + } + + if( active.isEmpty() ) continue; + + //kill particle-candidates produced by clones + active &= ( neutralDaughter.GetRapidity()<6.f /*&& neutralDaughter.GetRapidity()>0.f*/); + if ((iTC==1 && iHypothesis<4) || iTC==2) + active &= ( !( (neutralDaughter.GetPt())<0.5f && neutralDaughter.GetRapidity()<0.5f ) ); + if (iTC==3) + active &= ( !( (neutralDaughter.GetPt())<0.2f && neutralDaughter.GetRapidity()<1.f ) ); + if( active.isEmpty() ) continue; + + + for(int iV=0; iV -1) + { + if(iPV >= 0 && iPV + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef KFParticleFinder_h +#define KFParticleFinder_h + +#include "KFParticle.h" +#include "KFParticleSIMD.h" +#include "KFPTrackVector.h" + +#include +#include + +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& Particles, std::vector >& PrimVtx, int nPV); + + void ExtrapolateToPV(std::vector& vParticles, KFParticleSIMD& PrimVtx); + + inline void ConstructV0(KFPTrackVector* vTracks, + int iTrTypePos, + int iTrTypeNeg, + int32_v& idPosDaughters, + int32_v& idNegDaughters, + int32_v& daughterPosPDG, + int32_v& daughterNegPDG, + KFParticleSIMD& mother, + KFParticle& mother_temp, + const unsigned short NTracks, + kfvector_floatv& l, + kfvector_floatv& dl, + std::vector& Particles, + std::vector >& PrimVtx, + const float* cuts, + const int32_v& pvIndex, + const float* secCuts, + const float32_v& massMotherPDG, + const float32_v& massMotherPDGSigma, + KFParticleSIMD& motherPrimSecCand, + int& nPrimSecCand, + std::vector< std::vector >* vMotherPrim = 0, + std::vector* vMotherSec = 0 + ) __attribute__((always_inline)); + + void ConstructResonance(const std::vector& particles1, + const std::vector& particles2, + const int motherPdg, + std::vector& output); + + void ConstructResonances2D(KFPTrackVector* vTracks, + std::vector& Particles, + std::vector >& PrimVtx); + + void SaveV0PrimSecCand(KFParticleSIMD& mother, + int& NParticles, + KFParticle& mother_temp, + std::vector >& PrimVtx, + const float* secCuts, + std::vector< std::vector >* vMotherPrim, + std::vector* vMotherSec); + + void ConstructTrackV0Cand(KFPTrackVector& vTracks, + int32_v& idTracks, + int32_v& trackPDG, + KFParticle* vV0[], + KFParticleSIMD& mother, + std::vector >& motherTopo, + KFParticle& mother_temp, + const unsigned short nElements, + kfvector_floatv& l, + kfvector_floatv& dl, + std::vector& Particles, + std::vector >& PrimVtx, + const float32_v* cuts, + const int32_v& pvIndex, + const float32_v& massMotherPDG, + const float32_v& massMotherPDGSigma, + std::vector< std::vector >* vMotherPrim, + std::vector* vMotherSec); + + void Find2DaughterDecay(KFPTrackVector* vTracks, kfvector_float* ChiToPrimVtx, + std::vector& Particles, + std::vector >& PrimVtx, + const float* cuts, + const float* secCuts, + std::vector< std::vector >* vMotherPrim, + std::vector* vMotherSec ); + + void Find2DaughterDecayOneSign(KFPTrackVector& vTracks, + std::vector& Particles, + std::vector >& PrimVtx); + + void ConstructPrimaryBG(KFPTrackVector* vTracks, + std::vector& Particles, + std::vector >& PrimVtx, + const float* cuts, + const float* secCuts, + std::vector< std::vector >* vMotherPrim, + std::vector* vMotherSec ); + + void NeutralDaughterDecay(KFPTrackVector* vTracks, std::vector& Particles, + std::vector >& PrimVtx); + + void FindTrackV0Decay(std::vector& vV0, + const int V0PDG, + KFPTrackVector& vTracks, + const int q, + const int firstTrack, + const int lastTrack, + std::vector& Particles, + std::vector >& PrimVtx, + int v0PVIndex = -1, + kfvector_float* ChiToPrimVtx = 0, + std::vector< std::vector >* vMotherPrim = 0, + std::vector* vMotherSec = 0); + + void FindLL(const int motherPDG, + const int correctTrackPDG, + const std::vector& vParticles, + const KFPTrackVector& vTracks, + const int firstTrack, + const int lastTrack, + const KFParticleSIMD& PrimVtx, + std::vector& Particles); + + void SelectParticles(std::vector& Particles, + std::vector& vCandidates, + std::vector >& PrimVtx, + const float& cutChi2Topo, + const float& cutLdL, + const float& mass, + const float& massErr, + const float& massCut); + + void CombinePartPart(std::vector& particles1, + std::vector& particles2, + std::vector& Particles, + std::vector >& PrimVtx, + const float* cuts, + int iPV, + const int MotherPDG, + bool isSameInputPart = 0, + bool saveOnlyPrimary = 1, + std::vector< std::vector >* vMotherPrim = 0, + std::vector* vMotherSec = 0, + float massMotherPDG = 0.f, + float massMotherPDGSigma = 0.f); + + void MatchKaons(KFPTrackVector* vTracks, + std::vector >& PrimVtx, + std::vector& Particles); + + //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* 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& 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& 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& 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& 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& 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 >* 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >* 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >* 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 >& 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 GetReconstructionList() const { return fDecayReconstructionList; } ///< Returns list of decays to be reconstructed. + void SetReconstructionList(const std::map& 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 fD0; ///K-pi+ candidates. + std::vector fD0bar; ///K+pi- candidates. + std::vector fD04; ///K-pi+pi+pi- candidates. + std::vector fD04bar; ///K+pi+pi-pi- candidates. + std::vector fD0KK; ///K+K- candidates. + std::vector fD0pipi; ///pi+pi- candidates. + std::vector fDPlus; ///K-pi+pi+ candidates. + std::vector fDMinus; ///K+pi-pi- candidates. + std::vector fDPlus3Pi; ///pi+pi+pi- candidates. + std::vector fDMinus3Pi; ///pi+pi-pi- candidates. + std::vector fDsPlusK2Pi; ///K+pi+pi- candidates. + std::vector fDsMinusK2Pi;///K-pi+pi- candidates. + std::vector fLcPlusP2Pi; ///p pi+pi- candidates. + std::vector fLcMinusP2Pi;///p-pi+pi- candidates. + + //vectors with temporary particles for H0 and hypernuclei + std::vector fLPi; ///< Temporary Lambda pi+ combinations + std::vector fLPiPIndex; ///< Index of the proton in Labmda for Lambda pi+ combinations + std::vector fDPi; ///< Temporary d pi- combinations + std::vector fDPiBar; ///< Temporary d- pi+ combinations + std::vector fTPi; ///< Temporary t pi- combinations + std::vector fTPiBar; ///< Temporary t- pi+ combinations + std::vector fHe3Pi; ///< Temporary He3+ pi- combinations + std::vector fHe3PiBar; ///< Temporary He3- pi+ combinations + std::vector fHe3PPi; ///< Temporary He3+ p pi- combinations + std::vector fHe4Pi; ///< Temporary He4+ pi- combinations + std::vector fHe4PiBar; ///< Temporary He4- pi+ combinations + std::vector fHe4PPi; ///< Temporary He4+ p pi- combinations + std::vector fHe4L; ///< Vector with temporary He4_Lambda->He3 p pi- candidates + std::vector fHe5L; ///< Vector with temporary He4_Lambda->He4 p pi- candidates + std::vector fLLn; ///< Vector with temporary H3_Lambda pi- candidates + std::vector fH5LL; ///< Vector with temporary H5_LL->He5_Lambda pi- candidates + std::vector fPipi; ///< all pi+pi- combinations + std::vector fPpi; ///< all ppi- combinations + std::vector fPpiBar; ///< all p-pi+ combinations + std::vector fPPpi; ///< pppi- combinations + std::vector fPPpiBar; ///< p-p-pi+ combinations + + //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 fSecCandidates[fNSecCandidatesSets]; + static const int fNPrimCandidatesSets = 13; ///< 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$, + ** 11) \f$K^+\f$, 12) \f$K^-\f$. */ + std::vector< std::vector > 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 > 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 > 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 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/StRoot/KFParticle/KFParticleMath.h b/StRoot/KFParticle/KFParticleMath.h new file mode 100644 index 00000000000..80a55004066 --- /dev/null +++ b/StRoot/KFParticle/KFParticleMath.h @@ -0,0 +1,133 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef KFParticleMath_H +#define KFParticleMath_H + +#include "KFParticleDef.h" + +namespace KFPMath +{ + static inline __attribute__((always_inline)) float32_v multiplySign(const int32_v& sign, const float32_v& value) + { + const __m128 s = _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0x80000000)), _mm_castsi128_ps(sign.simd())); + return float32_v(_mm_xor_ps(value.simd(), s)); + } + + static inline __attribute__((always_inline)) float32_v sinSeries(const float32_v x) { + const float32_v x2 = x*x; + float32_v y = -1.984126984e-4f; + y = y * x2 + 8.333333333e-3f; + y = y * x2 - 1.666666667e-1f; + return y * (x2 * x) + x; + } + + static inline __attribute__((always_inline)) float32_v cosSeries(const float32_v x) { + const float32_v x2 = x*x; + float32_v y = 2.48015873e-5f; + y = y * x2 - 1.388888889e-03f; + y = y * x2 + 4.166666667e-2f; + return y * (x2 * x2) - .5f * x2 + 1.f; + } + + static inline __attribute__((always_inline)) void sincos(float32_v x, float32_v& sinX, float32_v& cosX) { +// const float32_v sin0 = sin(x); +// const float32_v cos0 = cos(x); + + const float32_v pi2i = 6.36619772e-1f; + const int32_v nPi2 = KFP::SIMD::toInt( round(x*pi2i) ); + const int32_v q = nPi2 & 3; + const int32_v sinSign = q << 30; + const int32_v cosSign = (q+1) << 30; + + const float32_v nPi2f = KFP::SIMD::toFloat(nPi2); + x -= 1.5707969666f * nPi2f; + x += 6.3975784e-7f * nPi2f; + + const float32_v sinS = sinSeries(x); + const float32_v cosS = cosSeries(x); + + const mask32_v mask = (q == 0) || (q == 2); + sinX = multiplySign(sinSign, select(mask, sinS, cosS)); + cosX = multiplySign(cosSign, select(mask, cosS, sinS)); + +// for(int i=0; i<4; i++) { +// if(fabs(sinX[i] - sin0[i]) > 1.e-7f * fabs(sin0[i]) || fabs(cosX[i] - cos0[i]) > 1.e-7f * fabs(cos0[i]) ) { +// std::cout << "x " << x << " npi2 " << nPi2 << std::endl; +// std::cout << "sin " << sinX << " " << sin0 << " " << sin(x) << std::endl; +// std::cout << "cos " << cosX << " " << cos0 << " " << cos(x) << std::endl; +// std::cin.get(); +// } +// } + } + + static inline __attribute__((always_inline)) float32_v ATan2( const float32_v &y, const float32_v &x ) + { + const float32_v pi(3.1415926535897932f); + const float32_v zero(0.f); + + const mask32_v &xZero = (x == zero); + const mask32_v &yZero = (y == zero); + const mask32_v &xNeg = (x < zero); + const mask32_v &yNeg = (y < zero); + + const float32_v &absX = abs(x); + const float32_v &absY = abs(y); + + float32_v a = absY / absX; + const mask32_v >_tan_3pi_8 = (a > float32_v(2.414213562373095f)); + const mask32_v >_tan_pi_8 = (a > float32_v(0.4142135623730950f)) && (!gt_tan_3pi_8); + float32_v b = select(gt_tan_3pi_8, pi/2.f, 0.f); + b = select(gt_tan_pi_8, pi/4.f, b); + a = select(gt_tan_3pi_8, (-1.f / a), a); + a = select(gt_tan_pi_8, ((absY - absX) / (absY + absX)), a) ; + const float32_v &a2 = a * a; + b += (((8.05374449538e-2f * a2 + - 1.38776856032E-1f) * a2 + + 1.99777106478E-1f) * a2 + - 3.33329491539E-1f) * a2 * a + + a; + b = select(xNeg ^ yNeg, -b, b); + b = select(xNeg && !yNeg, (b+pi), b); + b = select(xNeg && yNeg, (b-pi), b); + b = select(xZero && yZero, zero, b); + b = select(xZero && yNeg, (-pi/2.f), b); + return b; + } + + static inline __attribute__((always_inline)) float32_v log(const float32_v x) + { + return x; + } + + static inline __attribute__((always_inline)) float32_v acos(const float32_v x) + { + return x; + } + + // template static inline __attribute__((always_inline)) T Log ( const T &x ) { return std::log( x ); } + // template static inline __attribute__((always_inline)) T ACos( const T &x ) { return (3.1415926535897f/2.f - asin( x )); } + + +} + +#endif // KFParticleMath_H diff --git a/StRoot/KFParticle/KFParticlePVReconstructor.cxx b/StRoot/KFParticle/KFParticlePVReconstructor.cxx new file mode 100644 index 00000000000..787645bb59a --- /dev/null +++ b/StRoot/KFParticle/KFParticlePVReconstructor.cxx @@ -0,0 +1,369 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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 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 notUsedTracks(fNParticles); + vector *notUsedTracksPtr = ¬UsedTracks; + int nNotUsedTracks = fNParticles; + + vector notUsedTracksNew(fNParticles); + vector *notUsedTracksNewPtr = ¬UsedTracksNew; + int nNotUsedTracksNew = 0; + + for(int iTr=0; iTr0) + { + 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 *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 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)= 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 &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/StRoot/KFParticle/KFParticlePVReconstructor.h b/StRoot/KFParticle/KFParticlePVReconstructor.h new file mode 100644 index 00000000000..f66ea5acddf --- /dev/null +++ b/StRoot/KFParticle/KFParticlePVReconstructor.h @@ -0,0 +1,117 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef KFParticlePVReconstructor_H +#define KFParticlePVReconstructor_H + +#include "KFVertex.h" +#include "assert.h" + +#include + +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& 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 &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 fParticles; ///< Array of the input particles constructed from tracks. + int fNParticles; ///< Number of the input particles. + + std::vector 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 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 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/StRoot/KFParticle/KFParticleSIMD.cxx b/StRoot/KFParticle/KFParticleSIMD.cxx new file mode 100644 index 00000000000..ceb567be856 --- /dev/null +++ b/StRoot/KFParticle/KFParticleSIMD.cxx @@ -0,0 +1,5500 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + + +#include "KFParticleSIMD.h" +#include "KFParticle.h" +#include +#ifdef HomogeneousField +float32_v KFParticleSIMD::fgBz = -5.f; //* Bz compoment of the magnetic field +#endif + +void KFParticleSIMD::Create( const float32_v Param[], const float32_v Cov[], int32_v Charge, float32_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 + **/ + + for( Int_t i=0; i<6 ; i++ ) fP[i] = Param[i]; + for( Int_t i=0; i<21; i++ ) fC[i] = Cov[i]; + + float32_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; + + float32_v energyInv = 1.f/energy; + float32_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; +} + +KFParticleSIMD::KFParticleSIMD( const KFPTrack *track, Int_t PID ): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#ifdef NonhomogeneousField +, fField() +#endif +{ + /** Constructor of the particle from an array of tracks. + ** \param[in] track - pointer to the array of n=SimdLen tracks + ** \param[in] PID - the PID hypothesis common for all elements of the SIMD vector + **/ + + Double_t r[3]; + Double_t C[21]; + + alignas(SimdSize) float pArray[6][SimdLen]{0}; + alignas(SimdSize) float cArray[21][SimdLen]{0}; + alignas(SimdSize) int32_t qArray[SimdLen]{0}; + alignas(SimdSize) float chi2Array[SimdLen]{0}; + alignas(SimdSize) int32_t ndfArray[SimdLen]{0}; + + for(Int_t iPart = 0; iPartGetMass(PID); + Create(fP,fC,fQ,mass); +} + +KFParticleSIMD::KFParticleSIMD(KFPTrack &Track, const Int_t *pdg): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#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]; + + float32_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): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#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]; + + float32_v mass = KFParticleDatabase::Instance()->GetMass(*pdg); + Create(fP,fC,fQ,mass); +} + + +KFParticleSIMD::KFParticleSIMD(KFPTrack* Track[], int NTracks, const Int_t *pdg): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#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]; + + alignas(SimdSize) float pArray[6][SimdLen]{0}; + alignas(SimdSize) float cArray[21][SimdLen]{0}; + alignas(SimdSize) int32_t qArray[SimdLen]{0}; + alignas(SimdSize) float chi2Array[SimdLen]{0}; + alignas(SimdSize) int32_t ndfArray[SimdLen]{0}; + + for(Int_t iPart = 0; iPartXvYvZv(r); + for(Int_t i=0; i<3; i++) + pArray[i][iEntry] = r[i]; + Track[iEntry]->PxPyPz(r); + for(Int_t i=0; i<3; i++) + pArray[i+3][iEntry] = r[i]; + qArray[iEntry] = Track[iEntry]->Charge(); + Track[iEntry]->GetCovarianceXYZPxPyPz( C ); + for(Int_t i=0; i<21; i++) + cArray[i][iEntry] = C[i]; + chi2Array[iPart] = Track[iEntry]->GetChi2(); + ndfArray[iPart] = Track[iEntry]->GetNDF(); + } + + for(int i=0; i<6; i++) + fP[i].load(pArray[i]); + for(int i=0; i<21; i++) + fC[i].load(cArray[i]); + fQ.load(qArray); + fChi2.load(chi2Array); + fNDF.load(ndfArray); + + float32_v mass = KFParticleDatabase::Instance()->GetMass(*pdg); + Create(fP,fC,fQ,mass); +} + +KFParticleSIMD::KFParticleSIMD(KFPTrackVector &track, int32_v& index, const int32_v& pdg): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#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, int32_v& index, const int32_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); + + float32_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].rotate<1>(); + for(int i=0; i<27; i++) + fC[i] = fC[i].rotate<1>(); +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField.fField[i] = fField.fField[i].rotate<1>(); +#endif + fQ = fQ.rotate<1>(); + fId = fId.rotate<1>(); +} + +KFParticleSIMD::KFParticleSIMD(KFPEmcCluster &track, int32_v& index, const KFParticleSIMD& vertexGuess): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#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, int32_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 float32_v& dx = fP[0] - vertexGuess.fP[0]; + const float32_v& dy = fP[1] - vertexGuess.fP[1]; + const float32_v& dz = fP[2] - vertexGuess.fP[2]; + const float32_v& dl2 = dx*dx + dy*dy + dz*dz; + const float32_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]; + + float32_v V[10]; + for(int i=0; i<10; i++) + V[i].gather(&(track.Covariance(i)[0]), index); + + float32_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; + + float32_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 = int32_v(0); + fNDF = 0; + fChi2 = 0; + + SumDaughterMass = float32_v(0.f); + fMassHypo = float32_v(0.f); +} + +KFParticleSIMD::KFParticleSIMD(KFPEmcCluster &track, int index, const KFParticleSIMD& vertexGuess): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#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(track.Parameter(i)[index]); + fP[6] = reinterpret_cast(track.Parameter(3)[index]); + const float32_v& dx = fP[0] - vertexGuess.fP[0]; + const float32_v& dy = fP[1] - vertexGuess.fP[1]; + const float32_v& dz = fP[2] - vertexGuess.fP[2]; + const float32_v& dl2 = dx*dx + dy*dy + dz*dz; + const float32_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]; + + float32_v V[10]; + for(int i=0; i<10; i++) + V[i] = reinterpret_cast(track.Covariance(i)[index]); + + float32_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; + + float32_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 = int32_v(0); + fNDF = 0; + fChi2 = 0; + + SumDaughterMass = float32_v(0.f); + fMassHypo = float32_v(0.f); +} + +KFParticleSIMD::KFParticleSIMD( const KFPVertex &vertex ): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#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 = int32_v(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 + **/ + + alignas(SimdSize) float floatArray[SimdLen]{0}; + alignas(SimdSize) int32_t intArray[SimdLen]{0}; + + for( int i = 0; i < 7; ++i ) + { + fP[i].store(floatArray); + floatArray[iEntry] = part.Parameters()[i][iEntryPart]; + fP[i].load(floatArray); + } + for( int i = 0; i < 36; ++i ) + { + fC[i].store(floatArray); + floatArray[iEntry] = part.CovarianceMatrix()[i][iEntryPart]; + fC[i].load(floatArray); + } + + fChi2.store(floatArray); + floatArray[iEntry] = part.Chi2()[iEntryPart];; + fChi2.load(floatArray); + + fQ.store(intArray); + intArray[iEntry] = part.Q()[iEntryPart]; + fQ.load(intArray); + + fNDF.store(intArray); + intArray[iEntry] = part.NDF()[iEntryPart]; + fNDF.load(intArray); + +// SumDaughterMass[iEntry] = part.SumDaughterMass[iEntryPart]; +// fMassHypo[iEntry] = part.fMassHypo[iEntryPart]; + + fId.store(intArray); + intArray[iEntry] = part.Id()[iEntryPart]; + fId.load(intArray); + + fPDG.store(intArray); + intArray[iEntry] = part.GetPDG()[iEntryPart]; + fPDG.load(intArray); + + if(iEntry==0) + fDaughterIds.resize( part.NDaughters(), int32_v(-1) ); + + for(int iD=0; iDNDaughters(); + 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); + } + } + + alignas(SimdSize) float pArray[8][SimdLen]{0}; + alignas(SimdSize) float cArray[36][SimdLen]{0}; + alignas(SimdSize) float chi2Array[SimdLen]{0}; + alignas(SimdSize) int32_t qArray[SimdLen]{0}; + alignas(SimdSize) int32_t ndfArray[SimdLen]{0}; + alignas(SimdSize) int32_t pdgArray[SimdLen]{0}; + alignas(SimdSize) int32_t idArray[SimdLen]{0}; + + fDaughterIds.resize( (parts[0])->NDaughters(), int32_v(-1) ); + + for ( int iPart = 0; iPart < SimdLen; iPart++ ) { + Int_t iEntry = (iPart < nPart) ? iPart : 0; + KFParticle &part = *(parts[iEntry]); + + for( int i = 0; i < 8; ++i ) + pArray[i][iEntry] = part.Parameters()[i]; + for( int i = 0; i < 36; ++i ) + cArray[i][iEntry] = part.CovarianceMatrix()[i]; + + chi2Array[iEntry] = part.GetChi2(); + + qArray[iEntry] = part.GetQ(); + ndfArray[iEntry] = part.GetNDF(); + pdgArray[iEntry] = part.GetPDG(); + idArray[iEntry] = part.Id(); + +#ifdef NonhomogeneousField + fField.SetOneEntry( part.GetFieldCoeff(), iEntry); +#endif + } + + for( int i = 0; i < 8; ++i ) + fP[i].load(pArray[i]); + for( int i = 0; i < 36; ++i ) + fC[i].load(cArray[i]); + fChi2.load(chi2Array); + fQ.load(qArray); + fNDF.load(ndfArray); + fPDG.load(pdgArray); + fId.load(idArray); + + for(int iD=0; iDNDaughters(); iD++) + { + alignas(SimdSize) int32_t tmp[SimdLen]{0}; + for ( int iPart = 0; iPart < SimdLen; iPart++ ) { + Int_t iEntry = (iPart < nPart) ? iPart : 0; + + tmp[iEntry] = parts[iEntry]->DaughterIds()[iD]; + } + fDaughterIds[iD].load(tmp); + } +} + +KFParticleSIMD::KFParticleSIMD( const KFParticle &part): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#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(); + + 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 +} + +void KFParticleSIMD::operator +=( const KFParticleSIMD &Daughter ) +{ + /** Operator to add daughter to the current particle. Calls AddDaughter() function. + ** \param[in] Daughter - the daughter particle + **/ + + AddDaughter( Daughter ); +} + +void KFParticleSIMD::GetMeasurement( const KFParticleSIMD& daughter, float32_v m[], float32_v V[], float32_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) + { + float32_v ds[2] = {0.f,0.f}; + float32_v dsdr[4][6]; + float32_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 ); + + float32_v V0Tmp[36] ; + float32_v V1Tmp[36] ; + + float32_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]; + } + + float32_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]; + } + } + float32_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]; + } + } + float32_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 + { + float32_v dsdr[6]; + float32_v dS = daughter.GetDStoPoint(fP, dsdr); + + float32_v dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f}; + + float32_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); + +// float32_v V1Tmp[36] = {0.}; +// MultQSQt(F1, fC, V1Tmp, 6); + +// for(int iC=0; iC<21; iC++) +// V[iC] += V1Tmp[iC]; + + float32_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]; + } + } + + float32_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]; + } +} + +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 + **/ + + AddDaughterId( Daughter.Id() ); + + if( int(fNDF[0])<-1 ){ // first daughter -> just copy +#ifdef NonhomogeneousField + fField = Daughter.fField; +#endif + 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]; + 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 KFParticleSIMD::AddDaughterWithEnergyFit( const KFParticleSIMD &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 update the particle + + //* VHt = VH' + + float32_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 + + float32_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] ); + } + } + + float32_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] ); + } + } + + float32_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; + } + } + + float32_v mMassParticle = fP[6]*fP[6] - (fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]); + float32_v mMassDaughter = m[6]*m[6] - (m[3]*m[3] + m[4]*m[4] + m[5]*m[5]); + mMassParticle = select(mMassParticle > 0.f, sqrt(mMassParticle), mMassParticle); + mMassParticle = select(mMassParticle <= 0.f, 0.f, mMassParticle); + mMassDaughter = select(mMassDaughter > 0.f, sqrt(mMassDaughter), mMassDaughter); + mMassDaughter = select(mMassDaughter <= 0.f, 0.f, mMassDaughter); + + mask32_v mask1 = fMassHypo > -0.5f; + mask32_v mask2 = (!mask1) && ( (mMassParticle < SumDaughterMass) || (fP[6]<0.f)) ; + SetMassConstraint(fP,fC,mJ1,fMassHypo, mask1); + SetMassConstraint(fP,fC,mJ1,SumDaughterMass, mask2); + + mask32_v mask3 = Daughter.fMassHypo > -0.5f; + mask32_v mask4 = ( (!mask3) && ( (mMassDaughter update the particle + + //* VHt = VH' + + float32_v mVHt0[6], mVHt1[6], mVHt2[6]; + + 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] ; + + //* Kalman gain Km = mCH'*S + + float32_v kcdm0[6], kcdm1[6], kcdm2[6]; + + for(Int_t i=0;i<6;++i){ + kcdm0[i] = mVHt0[i]*mS[0] + mVHt1[i]*mS[1] + mVHt2[i]*mS[3]; + kcdm1[i] = mVHt0[i]*mS[1] + mVHt1[i]*mS[2] + mVHt2[i]*mS[4]; + kcdm2[i] = mVHt0[i]*mS[3] + mVHt1[i]*mS[4] + mVHt2[i]*mS[5]; + } + + //mother filtered + for(Int_t i=0;i<6;++i) + MotherFiltered.fP[i] = fP[i] + kmf0[i]*zeta[0] + kmf1[i]*zeta[1] + kmf2[i]*zeta[2]; + + for(Int_t i=0, k=0;i<6;++i){ + for(Int_t j=0;j<=i;++j,++k){ + MotherFiltered.fC[k] = fC[k] - (kmf0[i]*mCHt0[j] + kmf1[i]*mCHt1[j] + kmf2[i]*mCHt2[j] ); + } + } + + //cd filtered + for(Int_t i=0;i<6;++i) + cDaughterFiltered.fP[i] = m[i] - kcdm0[i]*zeta[0] - kcdm1[i]*zeta[1] - kcdm2[i]*zeta[2]; + + for(Int_t i=0, k=0;i<6;++i){ + for(Int_t j=0;j<=i;++j,++k){ + cDaughterFiltered.fC[k] = mV[k] - (kcdm0[i]*mVHt0[j] + kcdm1[i]*mVHt1[j] + kcdm2[i]*mVHt2[j] ); + } + } + + //////////////////// + //* CHt = CH' - D' + // float32_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 + + float32_v k0[6], k1[6], k2[6]; + + for(Int_t i=0;i<6;++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 + //neutral + for(Int_t i=0;i<6;++i) + fP[i] = fP[i] + k0[i]*zeta[0] + k1[i]*zeta[1] + k2[i]*zeta[2]; + + //* New covariance matrix C -= K*(mCH')' + //neutral + for(Int_t i=0, k=0;i<6;++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] ); + } + } + + float32_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; + } + + float32_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]; + } + } + + float32_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]; + + MotherFiltered.fC[0] += 2.f*M[0][0]; + MotherFiltered.fC[1] += M[0][1] + M[1][0]; + MotherFiltered.fC[2] += 2.f*M[1][1]; + MotherFiltered.fC[3] += M[0][2] + M[2][0]; + MotherFiltered.fC[4] += M[1][2] + M[2][1]; + MotherFiltered.fC[5] += 2.f*M[2][2]; + + cDaughterFiltered.fC[0] += 2.f*M[0][0]; + cDaughterFiltered.fC[1] += M[0][1] + M[1][0]; + cDaughterFiltered.fC[2] += 2.f*M[1][1]; + cDaughterFiltered.fC[3] += M[0][2] + M[2][0]; + cDaughterFiltered.fC[4] += M[1][2] + M[2][1]; + cDaughterFiltered.fC[5] += 2.f*M[2][2]; + + //* Calculate Chi^2 + + fNDF += 2; + fQ -= Daughter.GetQ(); + 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]; + MotherFiltered.Chi2()=fChi2; + cDaughterFiltered.Chi2()=fChi2; + MotherFiltered.NDF()=fNDF; + cDaughterFiltered.NDF()=fNDF; + + ////////energy calculations///////// + float32_v neutralenergytemp, motherenergytemp, cdaughterenergytemp; + + motherenergytemp = sqrt(mothermasshypo*mothermasshypo+MotherFiltered.fP[3]*MotherFiltered.fP[3]+MotherFiltered.fP[4]*MotherFiltered.fP[4]+MotherFiltered.fP[5]*MotherFiltered.fP[5]); + + cdaughterenergytemp = sqrt(cdaughtermasshypo*cdaughtermasshypo+cDaughterFiltered.fP[3]*cDaughterFiltered.fP[3]+cDaughterFiltered.fP[4]*cDaughterFiltered.fP[4]+cDaughterFiltered.fP[5]*cDaughterFiltered.fP[5]); + + neutralenergytemp = sqrt(neutralmasshypo*neutralmasshypo + fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]); + + fP[6] = motherenergytemp - cdaughterenergytemp; //neutral + MotherFiltered.fP[6] = cdaughterenergytemp + neutralenergytemp; + cDaughterFiltered.fP[6] = motherenergytemp - neutralenergytemp; + +} + +void KFParticleSIMD::SetProductionVertex( const KFParticleSIMD &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 float32_v *m = Vtx.fP, *mV = Vtx.fC; + + float32_v decayPoint[3] = {fP[0], fP[1], fP[2]}; + float32_v decayPointCov[6] = { fC[0], fC[1], fC[2], fC[3], fC[4], fC[5] }; + + float32_v D[6][6]; + for(int iD1=0; iD1<6; iD1++) + for(int iD2=0; iD2<6; iD2++) + D[iD1][iD2] = 0.f; + + { + float32_v dsdr[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + float32_v dS = GetDStoPoint(Vtx.fP, dsdr); + + float32_v dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f }; + + float32_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 ); + + float32_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]; + } + } + } + } + + float32_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); + + float32_v res[3] = { m[0] - X(), m[1] - Y(), m[2] - Z() }; + + float32_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)]; + } + + float32_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]; + + float32_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] ); + } + } + + float32_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; + } + + float32_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]; + } + } + + float32_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; + + { + float32_v dsdr[6] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; + fP[7] = GetDStoPoint(decayPoint, dsdr); + + float32_v dsdp[6] = {-dsdr[0], -dsdr[1], -dsdr[2], 0.f, 0.f, 0.f}; + + float32_v F[36], F1[36]; + for(int i2=0; i2<36; i2++) + { + F[i2] = 0.f; + F1[i2] = 0.f; + } + float32_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++) + { + float32_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]; + } + } + } +} + +void KFParticleSIMD::SetMassConstraint( float32_v *mP, float32_v *mC, float32_v mJ[7][7], float32_v mass, mask32_v 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 float32_v energy2 = mP[6]*mP[6], p2 = mP[3]*mP[3]+mP[4]*mP[4]+mP[5]*mP[5], mass2 = mass*mass; + + const float32_v a = energy2 - p2 + 2.f*mass2; + const float32_v b = -2.f*(energy2 + p2); + const float32_v c = energy2 - p2 - mass2; + + float32_v lambda(0.f); + lambda = select(abs(b) > float32_v(1.e-10f), -c/b, lambda) ; + + float32_v d = 4.f*energy2*p2 - mass2*(energy2-p2-2.f*mass2); + mask32_v qMask = (d >= 0.f) && (abs(a) > (1.e-10f)) ; + lambda = select(qMask, (energy2 + p2 - sqrt(d))/a, lambda); + + lambda = select(mP[6]<0.f, -1000000.f, lambda); + + Int_t iIter=0; + for(iIter=0; iIter<100; iIter++) + { + float32_v lambda2 = lambda*lambda; + float32_v lambda4 = lambda2*lambda2; + +// float32_v lambda0 = lambda; + + float32_v f = -mass2 * lambda4 + a*lambda2 + b*lambda + c; + float32_v df = -4.f*mass2 * lambda2*lambda + 2.f*a*lambda + b; + lambda = select(abs(df) > float32_v(1.e-10f), lambda - f/df, lambda); +// if(TMath::Abs(lambda0 - lambda) < 1.e-8) break; + } + + const float32_v lpi = 1.f/(1.f + lambda); + const float32_v lmi = 1.f/(1.f - lambda); + const float32_v lp2i = lpi*lpi; + const float32_v lm2i = lmi*lmi; + + float32_v lambda2 = lambda*lambda; + + float32_v dfl = -4.f*mass2 * lambda2*lambda + 2.f*a*lambda + b; + float32_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]; + float32_v dlx[4] = {1.f,1.f,1.f,1.f}; + + for(int i=0; i<4; i++) + dlx[i] = select(abs(dfl) > float32_v(1.e-10f), -dfx[i] / dfl, dlx[i]); + + float32_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; + + float32_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)] = select(mask, 0.f, mC[IJ(i,j)]); + for(Int_t l=0; l<7; l++){ + mC[IJ(i,j)] = select(mask, mC[IJ(i,j)] + mJ[i][l]*mCJ[l][j], mC[IJ(i,j)]); + } + } + } + + mP[3] = select(mask, mP[3] * lmi, mP[3]); + mP[4] = select(mask, mP[4] * lmi, mP[4]); + mP[5] = select(mask, mP[5] * lmi, mP[5]); + mP[6] = select(mask, mP[6] * lpi, mP[6]); +} + +void KFParticleSIMD::SetNonlinearMassConstraint( float32_v mass ) +{ + /** Sets the exact nonlinear mass constraint on the current particle. + ** \param[in] mass - the mass to be set on the particle + **/ + + const float32_v& px = fP[3]; + const float32_v& py = fP[4]; + const float32_v& pz = fP[5]; + const float32_v& energy = fP[6]; + + const float32_v residual = (energy*energy - px*px - py*py - pz*pz) - mass*mass; + const float32_v dm2 = float32_v(4.f) * ( fC[9]*px*px + fC[14]*py*py + fC[20]*pz*pz + fC[27]*energy*energy + + float32_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 float32_v dChi2 = residual*residual / dm2; + fChi2 += dChi2; + fNDF += 1; + + float32_v mJ[7][7]; + + mask32_v trueMask(KFP::SIMD::UninitializeTag{}); + trueMask.setTrue(); + SetMassConstraint( fP, fC, mJ, mass, trueMask ); + fMassHypo = mass; + SumDaughterMass = mass; +} + +void KFParticleSIMD::SetMassConstraint( float32_v Mass, float32_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; + + float32_v m2 = Mass*Mass; // measurement, weighted by Mass + float32_v s2 = m2*SigmaMass*SigmaMass; // sigma^2 + + float32_v p2 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + float32_v e0 = sqrt(m2+p2); + + float32_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; + + float32_v zeta = e0*e0 - e0*fP[6]; + zeta = m2 - (fP[6]*fP[6]-p2); + + float32_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 + + float32_v w2 = 1.f/( s2 + s2_est ); + fChi2 += zeta*zeta*w2; + fNDF += 1; + for( Int_t i=0, ii=0; i<8; ++i ){ + float32_v ki = mCHt[i]*w2; + fP[i]+= ki*zeta; + for(Int_t j=0;j<=i;++j) fC[ii++] -= ki*mCHt[j]; + } +} + +void KFParticleSIMD::Construct( const KFParticleSIMD* vDaughters[], Int_t nDaughters, + const KFParticleSIMD *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=0 ) SetMassConstraint( Mass ); + if( Parent ) SetProductionVertex( *Parent ); +} + +void KFParticleSIMD::SubtractFromVertex(KFParticleSIMD &Vtx) const +{ + /** Subtract the current particle from vertex Vtx using the Kalman filter mathematics. + ** \param[in] Vtx - vertex from which particle should be subtracted + **/ + + float32_v m[8]; + float32_v mCm[36]; + float32_v D[3][3]; + Vtx.GetMeasurement( *this, m, mCm, D ); + //* + + float32_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) + + float32_v zeta[3] = { m[0]-Vtx.fP[0], m[1]-Vtx.fP[1], m[2]-Vtx.fP[2] }; + + //* mCHt = mCH' - D' + + float32_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 + + float32_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 + + float32_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 KFParticleSIMD::SubtractFromParticle(KFParticleSIMD &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 + **/ + + float32_v m[8]; + float32_v mV[36]; + + float32_v D[3][3]; + Vtx.GetMeasurement( *this, m, mV, D ); + + float32_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) + + float32_v zeta[3] = { m[0]-Vtx.fP[0], m[1]-Vtx.fP[1], m[2]-Vtx.fP[2] }; + + //* CHt = CH' - D' + + float32_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 + + float32_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')' + + float32_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.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 KFParticleSIMD::GetDistanceToVertexLine( const KFParticleSIMD &Vertex, float32_v &l, float32_v &dl, mask32_v *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 + **/ + + float32_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]}; + + float32_v dx = (Vertex.fP[0]-fP[0]); + float32_v dy = (Vertex.fP[1]-fP[1]); + float32_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 = select(abs(l) < 1.e-8f, 1.e-8f, l); + mask32_v ok = float32_v(0.f)<=dl; + dl = select(ok, sqrt( dl )/l, 1.e8f); + + if(isParticleFromVertex) + { + *isParticleFromVertex = ok && ( l1.e-4f), (a + dz*pz)/p2, 0.f); + + dsdr[0] = select(mask && mask32_v(p2>1.e-4f), -px/p2, dsdr[0]); + dsdr[1] = select(mask && mask32_v(p2>1.e-4f), -py/p2, dsdr[1]); + dsdr[2] = select(mask && mask32_v(p2>1.e-4f), -pz/p2, dsdr[2]); + dsdr[3] = select(mask && mask32_v(p2>1.e-4f), (dx*p2 - 2.f* px *(a + dz *pz))/(p2*p2), dsdr[3]); + dsdr[4] = select(mask && mask32_v(p2>1.e-4f), (dy*p2 - 2.f* py *(a + dz *pz))/(p2*p2), dsdr[4]); + dsdr[5] = select(mask && mask32_v(p2>1.e-4f), (dz*p2 - 2.f* pz *(a + dz *pz))/(p2*p2), dsdr[5]); + + if(mask.isFull()) + return dS; + } + + dS = select(mask, dS, KFPMath::ATan2( abq, pt2 + bq*(dy*px -dx*py) )/bq); + + float32_v bs= bq*dS; + + float32_v s, c; + KFPMath::sincos(bs, s, c); + + bq = select(abs(bq) < LocalSmall, LocalSmall, bq); + float32_v bbq = bq*(dx*py - dy*px) - pt2; + + dsdr[0] = select(mask, dsdr[0], (px*bbq - py*abq)/(abq*abq + bbq*bbq)); + dsdr[1] = select(mask, dsdr[1], (px*abq + py*bbq)/(abq*abq + bbq*bbq)); + dsdr[2] = select(mask, dsdr[2], 0.f); + dsdr[3] = select(mask, dsdr[3], -(dx*bbq + dy*abq + 2.f*px*a)/(abq*abq + bbq*bbq)); + dsdr[4] = select(mask, dsdr[4], (dx*abq - dy*bbq - 2.f*py*a)/(abq*abq + bbq*bbq)); + dsdr[5] = select(mask, dsdr[5], 0.f); + + const float32_v cCoeff = (bbq*c - abq*s) - pz*pz ; + const float32_v sz = select(abs(cCoeff) > 1.e-8f, (dS*pz - dz)*pz / cCoeff, 0.f); + + float32_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] = select(mask, dsdr[iP], dsdr[iP] + pz*pz/cCoeff*dsdr[iP] - sz/cCoeff*dcdr[iP]); + + dsdr[2] = select(mask, dsdr[2], dsdr[2] + pz/cCoeff); + dsdr[5] = select(mask, dsdr[5], dsdr[5] + (2.f*pz*dS - dz)/cCoeff); + + dS = select(mask, dS, dS + sz); + + bs = bq*dS; + KFPMath::sincos(bs, s, c); + + float32_v sB, cB; + const float32_v kOvSqr6 = 1.f/sqrt(float32_v(6.f)); + + sB = select(LocalSmall < abs(bs), s/bq , (1.f-bs*kOvSqr6)*(1.f+bs*kOvSqr6)*dS); + cB = select(LocalSmall < abs(bs), (1.f-c)/bq, .5f*sB*bs); + + float32_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 = select(mask, dS, dS + KFPMath::ATan2( abq, p2 + bq*(dy*p[3] -dx*p[4]) )/bq); + + return dS; +} + +float32_v KFParticleSIMD::GetDStoPointBy( float32_v By, const float32_v xyz[3], float32_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 float32_v param[6] = { fP[0], -fP[2], fP[1], fP[3], -fP[5], fP[4] }; + const float32_v point[3] = { xyz[0], -xyz[2], xyz[1] }; + + float32_v dsdrBz[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + + const float32_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; +} + +float32_v KFParticleSIMD::GetDStoPointCBM( const float32_v xyz[3], float32_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 + **/ + + float32_v dS(0.f); + + float32_v fld[3]; + GetFieldValue( fP, fld ); + dS = GetDStoPointBy( fld[1],xyz, dsdr ); + + dS = select(abs(dS)>1.E3f, 0.f, dS); + + return dS; +} + +float32_v KFParticleSIMD::GetDStoPointXYBz( float32_v B, const float32_v xyz[2] ) 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 + **/ + + //* Get dS to a certain space point for Bz field + + const float32_v& px = fP[3]; + const float32_v& py = fP[4]; + + const float32_v kCLight = 0.000299792458f; + float32_v bq = B * toFloat(fQ) * kCLight; + float32_v pt2 = fP[3]*fP[3] + fP[4]*fP[4]; + + float32_v dx = xyz[0] - fP[0]; + float32_v dy = xyz[1] - fP[1]; + float32_v a = dx*fP[3]+dy*fP[4]; + float32_v dS(0.f); + + float32_v abq = bq*a; + + const float32_v LocalSmall = 1.e-8f; + mask32_v mask = ( abs(bq) 1.e-4f, dz/Pz(), dS); + return dS; +} + +void KFParticleSIMD::GetDStoCylinderBz( const float32_v B, const float32_v R, float32_v dS[2]) const +{ + /** Calculates 2 dS = l/p parameters from a particle to a cylinder with a radius R and center at (0,0) \n + ** 1) l - signed distance to the cylinder; \n + ** 2) p - momentum of the particle; \n + ** \param[in] B - magnetic field Bz + ** \param[in] R - radius of the cylinder + ** \param[out] dS - l/p for two points of the closest approach with the cylinder + **/ + + //* Get dS to another particle for Bz field + const float32_v kCLight = 0.000299792458f; + + //in XY plane + //first root + const float32_v& bq1 = B*toFloat(fQ)*kCLight; + const float32_v& bq2 = B*kCLight; + + const mask32_v& isStraight = abs(bq1) < float32_v(1.e-8f); + + const float32_v& px1 = fP[3]; + const float32_v& py1 = fP[4]; + + const float32_v& px2 = R*bq2; + const float32_v& py2 = 0.f; + + const float32_v& pt12 = px1*px1 + py1*py1; + const float32_v& pt22 = px2*px2 + py2*py2; + + const float32_v& x01 = fP[0]; + const float32_v& y01 = fP[1]; + + const float32_v& x02 = 0.f; + const float32_v& y02 = R; + + const float32_v& dx0 = (x01 - x02); + const float32_v& dy0 = (y01 - y02); + const float32_v& dr02 = dx0*dx0 + dy0*dy0; + const float32_v& drp1 = dx0*px1 + dy0*py1; + const float32_v& dxyp1 = dx0*py1 - dy0*px1; + const float32_v& dxyp2 = dx0*py2 - dy0*px2; + const float32_v& p1p2 = px1*px2 + py1*py2; + const float32_v& dp1p2 = px1*py2 - px2*py1; + + const float32_v& k11 = (bq2*drp1 - dp1p2); + const float32_v& k21 = (bq1*(bq2*dxyp1 - p1p2) + bq2*pt12); + + const float32_v& kp = (dxyp1*bq2 - dxyp2*bq1 - p1p2); + const float32_v& kd = dr02/2.f*bq1*bq2 + kp; + const float32_v& c1 = -(bq1*kd + pt12*bq2); + + float32_v d1 = pt12*pt22 - kd*kd; + d1 = select(d1 < 0.f, 0.f, d1); + d1 = sqrt( d1 ); + + // find two points of closest approach in XY plane + if( ! ( (!isStraight).isEmpty() ) ) + { + dS[0] = select(!isStraight, KFPMath::ATan2( (bq1*k11*c1 + k21*d1*bq1), (bq1*k11*d1*bq1 - k21*c1) )/bq1, dS[0]); + dS[1] = select(!isStraight, KFPMath::ATan2( (bq1*k11*c1 - k21*d1*bq1), (-bq1*k11*d1*bq1 - k21*c1) )/bq1, dS[1]); + } + if( ! ( isStraight.isEmpty() ) ) + { + dS[0] = select(isStraight && (pt12>0.f), (k11*c1 + k21*d1)/(- k21*c1), dS[0]); + dS[1] = select(isStraight && (pt12>0.f), (k11*c1 - k21*d1)/(- k21*c1), dS[1]); + } +} + +void KFParticleSIMD::GetDStoParticleBz( float32_v B, const KFParticleSIMD &p, + float32_v dS[2], float32_v dsdr[4][6], const float32_v* param1, const float32_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 float32_v kOvSqr6 = 1.f/sqrt(float32_v(6.f)); + const float32_v kCLight = 0.000299792458f; + + //in XY plane + //first root + const float32_v& bq1 = B*toFloat(fQ)*kCLight; + const float32_v& bq2 = B*toFloat(p.fQ)*kCLight; + + const mask32_v& isStraight1 = abs(bq1) < float32_v(1.e-8f); + const mask32_v& isStraight2 = abs(bq2) < float32_v(1.e-8f); + + if( isStraight1.isFull() && isStraight2.isFull() ) + { + GetDStoParticleLine(p, dS, dsdr); + return; + } + + const float32_v& px1 = param1[3]; + const float32_v& py1 = param1[4]; + const float32_v& pz1 = param1[5]; + + const float32_v& px2 = param2[3]; + const float32_v& py2 = param2[4]; + const float32_v& pz2 = param2[5]; + + const float32_v& pt12 = px1*px1 + py1*py1; + const float32_v& pt22 = px2*px2 + py2*py2; + + const float32_v& x01 = param1[0]; + const float32_v& y01 = param1[1]; + const float32_v& z01 = param1[2]; + + const float32_v& x02 = param2[0]; + const float32_v& y02 = param2[1]; + const float32_v& z02 = param2[2]; + + float32_v dS1[2] = {0.f, 0.f}, dS2[2]={0.f, 0.f}; + + const float32_v& dx0 = (x01 - x02); + const float32_v& dy0 = (y01 - y02); + const float32_v& dr02 = dx0*dx0 + dy0*dy0; + const float32_v& drp1 = dx0*px1 + dy0*py1; + const float32_v& dxyp1 = dx0*py1 - dy0*px1; + const float32_v& drp2 = dx0*px2 + dy0*py2; + const float32_v& dxyp2 = dx0*py2 - dy0*px2; + const float32_v& p1p2 = px1*px2 + py1*py2; + const float32_v& dp1p2 = px1*py2 - px2*py1; + + const float32_v& k11 = (bq2*drp1 - dp1p2); + const float32_v& k21 = (bq1*(bq2*dxyp1 - p1p2) + bq2*pt12); + const float32_v& k12 = ((bq1*drp2 - dp1p2)); + const float32_v& k22 = (bq2*(bq1*dxyp2 + p1p2) - bq1*pt22); + + const float32_v& kp = (dxyp1*bq2 - dxyp2*bq1 - p1p2); + const float32_v& kd = dr02/2.f*bq1*bq2 + kp; + const float32_v& c1 = -(bq1*kd + pt12*bq2); + const float32_v& c2 = bq2*kd + pt22*bq1; + + float32_v d1 = pt12*pt22 - kd*kd; + d1 = select(d1 < 0.f, 0.f, d1); + d1 = sqrt( d1 ); + float32_v d2 = pt12*pt22 - kd*kd; + d2 = select(d2 < 0.f, 0.f, d2); + d2 = sqrt( d2 ); + + float32_v dS1dR1[2][6]; + float32_v dS2dR2[2][6]; + + float32_v dS1dR2[2][6]; + float32_v dS2dR1[2][6]; + + float32_v dk11dr1[6] = {bq2*px1, bq2*py1, 0.f, bq2*dx0 - py2, bq2*dy0 + px2, 0.f}; + float32_v dk11dr2[6] = {-bq2*px1, -bq2*py1, 0.f, py1, -px1, 0.f}; + float32_v dk12dr1[6] = {bq1*px2, bq1*py2, 0.f, -py2, px2, 0.f}; + float32_v dk12dr2[6] = {-bq1*px2, -bq1*py2, 0.f, bq1*dx0 + py1, bq1*dy0 - px1, 0.f}; + float32_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}; + float32_v dk21dr2[6] = {-(bq1*bq2*py1), bq1*bq2*px1, 0.f, -(bq1*px1), -(bq1*py1), 0.f}; + float32_v dk22dr1[6] = {bq1*bq2*py2, -(bq1*bq2*px2), 0.f, bq2*px2, bq2*py2, 0.f}; + float32_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}; + + float32_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}; + float32_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}; + + float32_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}; + float32_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}; + + float32_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}; + float32_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}; + + float32_v dd1dr1[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + float32_v dd1dr2[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + { + for(int i=0; i<6; i++) + { + dd1dr1[i] = select(d1>0.f, dd1dr1[i] - kd/d1*dkddr1[i], dd1dr1[i]); + dd1dr2[i] = select(d1>0.f, dd1dr2[i] - kd/d1*dkddr2[i], dd1dr2[i]); + } + dd1dr1[3] = select(d1>0.f, dd1dr1[3] + px1/d1*pt22, dd1dr1[3]); dd1dr1[4] = select(d1>0.f, dd1dr1[4] + py1/d1*pt22, dd1dr1[4]); + dd1dr2[3] = select(d1>0.f, dd1dr2[3] + px2/d1*pt12, dd1dr2[3]); dd1dr2[4] = select(d1>0.f, dd1dr2[4] + py2/d1*pt12, dd1dr2[4]); + } + + // find two points of closest approach in XY plane + if( ! ( (!isStraight1).isEmpty() ) ) + { + dS1[0] = select(!isStraight1, KFPMath::ATan2( (bq1*k11*c1 + k21*d1*bq1), (bq1*k11*d1*bq1 - k21*c1) )/bq1, dS1[0]); + dS1[1] = select(!isStraight1, KFPMath::ATan2( (bq1*k11*c1 - k21*d1*bq1), (-bq1*k11*d1*bq1 - k21*c1) )/bq1, dS1[1]); + + float32_v a = bq1*(k11*c1 + k21*d1); + float32_v b = bq1*k11*d1*bq1 - k21*c1; + for(int iP=0; iP<6; iP++) + { + const float32_v dadr1 = bq1*( dk11dr1[iP]*c1 + k11*dc1dr1[iP] + dk21dr1[iP]*d1 + k21*dd1dr1[iP] ); + const float32_v dadr2 = bq1*( dk11dr2[iP]*c1 + k11*dc1dr2[iP] + dk21dr2[iP]*d1 + k21*dd1dr2[iP] ); + const float32_v dbdr1 = bq1*bq1*( dk11dr1[iP]*d1 + k11*dd1dr1[iP] ) - ( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float32_v dbdr2 = bq1*bq1*( dk11dr2[iP]*d1 + k11*dd1dr2[iP] ) - ( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[0][iP] = select(!isStraight1, 1/bq1 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ), dS1dR1[0][iP]); + dS1dR2[0][iP] = select(!isStraight1, 1/bq1 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ), dS1dR2[0][iP]); + } + + a = bq1*(k11*c1 - k21*d1); + b = -bq1*k11*d1*bq1 - k21*c1; + for(int iP=0; iP<6; iP++) + { + const float32_v dadr1 = bq1*( dk11dr1[iP]*c1 + k11*dc1dr1[iP] - (dk21dr1[iP]*d1 + k21*dd1dr1[iP]) ); + const float32_v dadr2 = bq1*( dk11dr2[iP]*c1 + k11*dc1dr2[iP] - (dk21dr2[iP]*d1 + k21*dd1dr2[iP]) ); + const float32_v dbdr1 = -bq1*bq1*( dk11dr1[iP]*d1 + k11*dd1dr1[iP] ) - ( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float32_v dbdr2 = -bq1*bq1*( dk11dr2[iP]*d1 + k11*dd1dr2[iP] ) - ( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[1][iP] = select(!isStraight1, 1/bq1 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ), dS1dR1[1][iP]); + dS1dR2[1][iP] = select(!isStraight1, 1/bq1 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ), dS1dR2[1][iP]); + } + } + if( ! ( (!isStraight2).isEmpty() ) ) + { + dS2[0] = select(!isStraight2, KFPMath::ATan2( (bq2*k12*c2 + k22*d2*bq2), (bq2*k12*d2*bq2 - k22*c2) )/bq2, dS2[0]); + dS2[1] = select(!isStraight2, KFPMath::ATan2( (bq2*k12*c2 - k22*d2*bq2), (-bq2*k12*d2*bq2 - k22*c2) )/bq2, dS2[1]); + + float32_v a = bq2*(k12*c2 + k22*d2); + float32_v b = bq2*k12*d2*bq2 - k22*c2; + for(int iP=0; iP<6; iP++) + { + const float32_v dadr1 = bq2*( dk12dr1[iP]*c2 + k12*dc2dr1[iP] + dk22dr1[iP]*d1 + k22*dd1dr1[iP] ); + const float32_v dadr2 = bq2*( dk12dr2[iP]*c2 + k12*dc2dr2[iP] + dk22dr2[iP]*d1 + k22*dd1dr2[iP] ); + const float32_v dbdr1 = bq2*bq2*( dk12dr1[iP]*d1 + k12*dd1dr1[iP] ) - (dk22dr1[iP]*c2 + k22*dc2dr1[iP]); + const float32_v dbdr2 = bq2*bq2*( dk12dr2[iP]*d1 + k12*dd1dr2[iP] ) - (dk22dr2[iP]*c2 + k22*dc2dr2[iP]); + + dS2dR1[0][iP] = select(!isStraight2, 1/bq2 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ), dS2dR1[0][iP]); + dS2dR2[0][iP] = select(!isStraight2, 1/bq2 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ), dS2dR2[0][iP]); + } + + a = bq2*(k12*c2 - k22*d2); + b = -bq2*k12*d2*bq2 - k22*c2; + for(int iP=0; iP<6; iP++) + { + const float32_v dadr1 = bq2*( dk12dr1[iP]*c2 + k12*dc2dr1[iP] - (dk22dr1[iP]*d1 + k22*dd1dr1[iP]) ); + const float32_v dadr2 = bq2*( dk12dr2[iP]*c2 + k12*dc2dr2[iP] - (dk22dr2[iP]*d1 + k22*dd1dr2[iP]) ); + const float32_v dbdr1 = -bq2*bq2*( dk12dr1[iP]*d1 + k12*dd1dr1[iP] ) - (dk22dr1[iP]*c2 + k22*dc2dr1[iP]); + const float32_v dbdr2 = -bq2*bq2*( dk12dr2[iP]*d1 + k12*dd1dr2[iP] ) - (dk22dr2[iP]*c2 + k22*dc2dr2[iP]); + + dS2dR1[1][iP] = select(!isStraight2, 1/bq2 * 1/( b*b + a*a ) * ( dadr1*b - dbdr1*a ), dS2dR1[1][iP]); + dS2dR2[1][iP] = select(!isStraight2, 1/bq2 * 1/( b*b + a*a ) * ( dadr2*b - dbdr2*a ), dS2dR2[1][iP]); + } + } + if( ! ( isStraight1.isEmpty() ) ) + { + dS1[0] = select(isStraight1 && (pt12>0.f), (k11*c1 + k21*d1)/(- k21*c1), dS1[0]); + dS1[1] = select(isStraight1 && (pt12>0.f), (k11*c1 - k21*d1)/(- k21*c1), dS1[1]); + + float32_v a = k11*c1 + k21*d1; + float32_v b = -k21*c1; + + for(int iP=0; iP<6; iP++) + { + const float32_v dadr1 = ( dk11dr1[iP]*c1 + k11*dc1dr1[iP] + dk21dr1[iP]*d1 + k21*dd1dr1[iP] ); + const float32_v dadr2 = ( dk11dr2[iP]*c1 + k11*dc1dr2[iP] + dk21dr2[iP]*d1 + k21*dd1dr2[iP] ); + const float32_v dbdr1 = -( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float32_v dbdr2 = -( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[0][iP] = select(isStraight1 && (pt12>0.f), dadr1/b - dbdr1*a/(b*b), dS1dR1[0][iP]); + dS1dR2[0][iP] = select(isStraight1 && (pt12>0.f), dadr2/b - dbdr2*a/(b*b), dS1dR2[0][iP]); + } + + a = k11*c1 - k21*d1; + for(int iP=0; iP<6; iP++) + { + const float32_v dadr1 = ( dk11dr1[iP]*c1 + k11*dc1dr1[iP] - dk21dr1[iP]*d1 - k21*dd1dr1[iP] ); + const float32_v dadr2 = ( dk11dr2[iP]*c1 + k11*dc1dr2[iP] - dk21dr2[iP]*d1 - k21*dd1dr2[iP] ); + const float32_v dbdr1 = -( dk21dr1[iP]*c1 + k21*dc1dr1[iP] ); + const float32_v dbdr2 = -( dk21dr2[iP]*c1 + k21*dc1dr2[iP] ); + + dS1dR1[1][iP] = select(isStraight1 && (pt12>0.f), dadr1/b - dbdr1*a/(b*b), dS1dR1[1][iP]); + dS1dR2[1][iP] = select(isStraight1 && (pt12>0.f), dadr2/b - dbdr2*a/(b*b), dS1dR2[1][iP]); + } + } + if( ! ( isStraight2.isEmpty() ) ) + { + dS2[0] = select(isStraight2 && (pt22>0.f), (k12*c2 + k22*d2)/(- k22*c2), dS2[0]); + dS2[1] = select(isStraight2 && (pt22>0.f), (k12*c2 - k22*d2)/(- k22*c2), dS2[1]); + + float32_v a = k12*c2 + k22*d1; + float32_v b = -k22*c2; + + for(int iP=0; iP<6; iP++) + { + const float32_v dadr1 = ( dk12dr1[iP]*c2 + k12*dc2dr1[iP] + dk22dr1[iP]*d1 + k22*dd1dr1[iP] ); + const float32_v dadr2 = ( dk12dr2[iP]*c2 + k12*dc2dr2[iP] + dk22dr2[iP]*d1 + k22*dd1dr2[iP] ); + const float32_v dbdr1 = -( dk22dr1[iP]*c2 + k22*dc2dr1[iP] ); + const float32_v dbdr2 = -( dk22dr2[iP]*c2 + k22*dc2dr2[iP] ); + + dS2dR1[0][iP] = select(isStraight2 && (pt22>0.f), dadr1/b - dbdr1*a/(b*b), dS2dR1[0][iP]); + dS2dR2[0][iP] = select(isStraight2 && (pt22>0.f), dadr2/b - dbdr2*a/(b*b), dS2dR2[0][iP]); + } + + a = k12*c2 - k22*d1; + for(int iP=0; iP<6; iP++) + { + const float32_v dadr1 = ( dk12dr1[iP]*c2 + k12*dc2dr1[iP] - dk22dr1[iP]*d1 - k22*dd1dr1[iP] ); + const float32_v dadr2 = ( dk12dr2[iP]*c2 + k12*dc2dr2[iP] - dk22dr2[iP]*d1 - k22*dd1dr2[iP] ); + const float32_v dbdr1 = -( dk22dr1[iP]*c2 + k22*dc2dr1[iP] ); + const float32_v dbdr2 = -( dk22dr2[iP]*c2 + k22*dc2dr2[iP] ); + + dS2dR1[1][iP] = select(isStraight2 && (pt22>0.f), dadr1/b - dbdr1*a/(b*b), dS2dR1[1][iP]); + dS2dR2[1][iP] = select(isStraight2 && (pt22>0.f), dadr2/b - dbdr2*a/(b*b), dS2dR2[1][iP]); + } + } + + //select a point which is close to the primary vertex (with the smallest r) + + float32_v dr2[2]; + for(int iP = 0; iP<2; iP++) + { + const float32_v& bs1 = bq1*dS1[iP]; + const float32_v& bs2 = bq2*dS2[iP]; + float32_v sss, ccc; + KFPMath::sincos(bs1, sss, ccc); + + const mask32_v& bs1Big = abs(bs1) > 1.e-8f; + const mask32_v& bs2Big = abs(bs2) > 1.e-8f; + + float32_v sB(0.f), cB(0.f); + sB = select(bs1Big, sss/bq1, sB); + sB = select(!bs1Big, (1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS1[iP], sB); + cB = select(bs1Big, (1.f-ccc)/bq1, cB); + cB = select(!bs1Big, 0.5f*sB*bs1, cB); + + const float32_v& x1 = param1[0] + sB*px1 + cB*py1; + const float32_v& y1 = param1[1] - cB*px1 + sB*py1; + const float32_v& z1 = param1[2] + dS1[iP]*param1[5]; + + KFPMath::sincos(bs2, sss, ccc); + + sB = select(bs2Big, sss/bq2, sB); + sB = select(!bs2Big, ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS2[iP]), sB); + cB = select(bs2Big, (1.f-ccc)/bq2, cB); + cB = select(!bs2Big, 0.5f*sB*bs2, cB); + + const float32_v& x2 = param2[0] + sB*px2 + cB*py2; + const float32_v& y2 = param2[1] - cB*px2 + sB*py2; + const float32_v& z2 = param2[2] + dS2[iP]*param2[5]; + + float32_v dx = (x1-x2); + float32_v dy = (y1-y2); + float32_v dz = (z1-z2); + + dr2[iP] = dx*dx + dy*dy + dz*dz; + } + + float32_v pointParam[2][8]; + float32_v pointCov[2][36]; + + float32_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]); + float32_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 float32_v drPoint[3] = { pointParam[0][0] - pointParam[1][0], pointParam[0][1] - pointParam[1][1], pointParam[0][2] - pointParam[1][2] } ; + const float32_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] }; + float32_v dr2Points = drPoint[0]*drPoint[0] + drPoint[1]*drPoint[1] + drPoint[2]*drPoint[2]; + float32_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 mask32_v isMiddlePoint = (dr2Points*dr2Points < 25.f*dr2PointCov);// && (abs(fPDG)==int32_v(11)) && (abs(p.fPDG)==int32_v(11)); + const mask32_v isFirstRoot = (dr2[0] < dr2[1]) && (!isMiddlePoint); + + // if(!(isFirstRoot.isEmpty())) + { + dS[0] = select(isFirstRoot, dS1[0], dS[0]); + dS[1] = select(isFirstRoot, dS2[0], dS[1]); + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP] = select(isFirstRoot, dS1dR1[0][iP], dsdr[0][iP]); + dsdr[1][iP] = select(isFirstRoot, dS1dR2[0][iP], dsdr[1][iP]); + dsdr[2][iP] = select(isFirstRoot, dS2dR1[0][iP], dsdr[2][iP]); + dsdr[3][iP] = select(isFirstRoot, dS2dR2[0][iP], dsdr[3][iP]); + } + } + // if( !( (!isFirstRoot).isEmpty() ) ) + { + dS[0] = select(!isFirstRoot, dS1[1], dS[0]); + dS[1] = select(!isFirstRoot, dS2[1], dS[1]); + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP] = select(!isFirstRoot, dS1dR1[1][iP], dsdr[0][iP]); + dsdr[1][iP] = select(!isFirstRoot, dS1dR2[1][iP], dsdr[1][iP]); + dsdr[2][iP] = select(!isFirstRoot, dS2dR1[1][iP], dsdr[2][iP]); + dsdr[3][iP] = select(!isFirstRoot, dS2dR2[1][iP], dsdr[3][iP]); + } + } + // if(!(isMiddlePoint.isEmpty())) + { + dS[0] = select(isMiddlePoint, (dS1[0] + dS1[1]) / 2.f, dS[0]); + dS[1] = select(isMiddlePoint, (dS2[0] + dS2[1]) / 2.f, dS[1]); + + for(int iP=0; iP<6; iP++) + { + dsdr[0][iP] = select(isMiddlePoint, (dS1dR1[1][iP] + dS1dR1[0][iP])/2.f, dsdr[0][iP]); + dsdr[1][iP] = select(isMiddlePoint, (dS1dR2[1][iP] + dS1dR2[0][iP])/2.f, dsdr[1][iP]); + dsdr[2][iP] = select(isMiddlePoint, (dS2dR1[1][iP] + dS2dR1[0][iP])/2.f, dsdr[2][iP]); + dsdr[3][iP] = select(isMiddlePoint, (dS2dR2[1][iP] + dS2dR2[0][iP])/2.f, dsdr[3][iP]); + } + } + + //find correct parts of helices + int32_v n1(0); + int32_v n2(0); +// float32_v dzMin = abs( (z01-z02) + dS[0]*pz1 - dS[1]*pz2 ); + const float32_v pi2(6.283185307f); + +// //TODO optimise for loops for neutral particles +// const float32_v& i1Float = -bq1/pi2*(z01/pz1+dS[0]); +// for(int di1=-1; di1<=1; di1++) +// { +// int32_v i1(0); +// i1(int_m(!isStraight1)) = int32_v(i1Float) + di1; +// +// const float32_v& i2Float = ( ((z01-z02) + (dS[0]+pi2*i1/bq1)*pz1)/pz2 - dS[1]) * bq2/pi2; +// for(int di2 = -1; di2<=1; di2++) +// { +// int32_v i2(0); +// i2(int_m(!isStraight2)) = int32_v(i2Float) + di2; +// +// const float32_v& z1 = z01 + (dS[0]+pi2*i1/bq1)*pz1; +// const float32_v& z2 = z02 + (dS[1]+pi2*i2/bq2)*pz2; +// const float32_v& dz = abs( z1-z2 ); +// +// n1(int_m(dz < dzMin)) = i1; +// n2(int_m(dz < dzMin)) = i2; +// dzMin(dz < dzMin) = dz; +// } +// } +// +// dS[0](!isStraight1) += float32_v(n1)*pi2/bq1; +// dS[1](!isStraight2) += float32_v(n2)*pi2/bq2; + + //add a correction on z-coordinate +#if 0 + { + const float32_v& bs1 = bq1*dS[0]; + const float32_v& bs2 = bq2*dS[1]; + + float32_v sss = KFPMath::Sin(bs1), ccc = KFPMath::Cos(bs1); + const float32_v& xr1 = sss*px1 - ccc*py1; + const float32_v& yr1 = ccc*px1 + sss*py1; + + float32_v sss1 = KFPMath::Sin(bs2), ccc1 = KFPMath::Cos(bs2); + const float32_v& xr2 = sss1*px2 - ccc1*py2; + const float32_v& yr2 = ccc1*px2 + sss1*py2; + + const float32_v& br = xr1*xr2 + yr1*yr2; + const float32_v& dx0mod = dx0*bq1*bq2 + py1*bq2 - py2*bq1; + const float32_v& dy0mod = dy0*bq1*bq2 - px1*bq2 + px2*bq1; + const float32_v& ar1 = dx0mod*xr1 + dy0mod*yr1; + const float32_v& ar2 = dx0mod*xr2 + dy0mod*yr2; + const float32_v& cz = (z01 - z02) + dS[0]*pz1 - dS[1]*pz2; + + float32_v kz11 = - ar1 + bq1*br + bq2*pz1*pz1; + float32_v kz12 = -bq2*(br+pz1*pz2); + float32_v kz21 = bq1*(br+pz1*pz2); + float32_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 float32_v& delta = kz11*kz22 - kz12*kz21; + float32_v sz1(0.f); + float32_v sz2(0.f); + + { + float32_v aaa1 = -cz*(pz1*bq2*kz22 - pz2*bq1*kz12); + float32_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; + + float32_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; + float32_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; + + float32_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; + float32_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; + float32_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; + float32_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; + float32_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); + float32_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; + + float32_v dczdr1[6] = {0.f, 0.f, 1.f, 0.f, 0.f, dS[0]}; + float32_v dczdr2[6] = {0.f, 0.f, -1.f, 0.f, 0.f, -dS[1]}; + + float32_v daaa1dr1[6]; + float32_v daaa1dr2[6]; + float32_v daaa2dr2[6]; + float32_v daaa2dr1[6]; + float32_v dDeltadr1[6]; + float32_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 + float32_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)); + float32_v dkz11ds1 = bq1*bq2*( xr1*yr2 - xr2*yr1 ); + dkz11ds1(isStraight2) = bq1*(px2*xr1 + py2*yr1); + float32_v dkz12ds0 = bq2*bq1*( xr1*yr2 - xr2*yr1 ); + dkz12ds0(isStraight2) = bq1*( xr1*yr2 - xr2*yr1 ); + float32_v dkz12ds1 = bq2*bq2*( xr2*yr1 - xr1*yr2 ); + dkz12ds1(isStraight2) = 0; + float32_v dkz21ds0 = bq1*bq1*( xr2*yr1 - xr1*yr2 ); + dkz21ds0(isStraight1) = 0.f; + float32_v dkz21ds1 = bq1*bq2*( xr1*yr2 - xr2*yr1 ); + dkz21ds1(isStraight1) = px1*(bq2*ccc1*py2 - bq2*px2*sss1) - py1*(bq2*ccc1*px2 + bq2*py2*sss1); + float32_v dkz22ds0 = bq1*bq2*( xr1*yr2 - xr2*yr1 ); + dkz22ds0(isStraight1) = -bq2*(px1*xr2 + py1*yr2); + float32_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 float32_v dczds0 = pz1; + const float32_v dczds1 = -pz2; + const float32_v da1ds0 = -( dczds0*(pz1*bq2*kz22 - pz2*bq1*kz12) + cz*(pz1*bq2*dkz22ds0 - pz2*bq1*dkz12ds0)); + const float32_v da1ds1 = -( dczds1*(pz1*bq2*kz22 - pz2*bq1*kz12) + cz*(pz1*bq2*dkz22ds1 - pz2*bq1*dkz12ds1)); + const float32_v da2ds0 = -( dczds0*(pz2*bq1*kz11 - pz1*bq2*kz21) + cz*(pz2*bq1*dkz11ds0 - pz1*bq2*dkz21ds0)); + const float32_v da2ds1 = -( dczds1*(pz2*bq1*kz11 - pz1*bq2*kz21) + cz*(pz2*bq1*dkz11ds1 - pz1*bq2*dkz21ds1)); + const float32_v dDeltads0 = kz11*dkz22ds0 + dkz11ds0*kz11 - kz12*dkz21ds0 - dkz12ds0*kz21; + const float32_v dDeltads1 = kz11*dkz22ds1 + dkz11ds1*kz11 - kz12*dkz21ds1 - dkz12ds1*kz21; + + const float32_v dsz1ds0 = da1ds0/delta - aaa1*dDeltads0/(delta*delta); + const float32_v dsz1ds1 = da1ds1/delta - aaa1*dDeltads1/(delta*delta); + const float32_v dsz2ds0 = da2ds0/delta - aaa2*dDeltads0/(delta*delta); + const float32_v dsz2ds1 = da2ds1/delta - aaa2*dDeltads1/(delta*delta); + + float32_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 float32_v& bs1 = bq1*dS[0]; + const float32_v& bs2 = bq2*dS[1]; + float32_v sss, ccc; + KFPMath::sincos(bs1, sss, ccc); + + const mask32_v& bs1Big = abs(bs1) > 1.e-8f; + const mask32_v& bs2Big = abs(bs2) > 1.e-8f; + + float32_v sB(0.f), cB(0.f); + sB = select(bs1Big, sss/bq1, sB); + cB = select(bs1Big, (1.f-ccc)/bq1, cB); + sB = select(!bs1Big, ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS[0]), sB); + cB = select(!bs1Big, .5f*sB*bs1, cB); + + const float32_v& x1 = x01 + sB*px1 + cB*py1; + const float32_v& y1 = y01 - cB*px1 + sB*py1; + const float32_v& z1 = z01 + dS[0]*pz1; + const float32_v& ppx1 = ccc*px1 + sss*py1; + const float32_v& ppy1 = -sss*px1 + ccc*py1; + const float32_v& ppz1 = pz1; + + float32_v sss1, ccc1; + KFPMath::sincos(bs2, sss1, ccc1); + + float32_v sB1(0.f), cB1(0.f); + sB1 = select(bs2Big, sss1/bq2, sB1); + cB1 = select(bs2Big, (1.f-ccc1)/bq2, cB1); + sB1 = select(!bs2Big, ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS[1]), sB1); + cB1 = select(!bs2Big, .5f*sB1*bs2, cB1); + + const float32_v& x2 = x02 + sB1*px2 + cB1*py2; + const float32_v& y2 = y02 - cB1*px2 + sB1*py2; + const float32_v& z2 = z02 + dS[1]*pz2; + const float32_v& ppx2 = ccc1*px2 + sss1*py2; + const float32_v& ppy2 = -sss1*px2 + ccc1*py2; + const float32_v& ppz2 = pz2; + + const float32_v& p12 = ppx1*ppx1 + ppy1*ppy1 + ppz1*ppz1; + const float32_v& p22 = ppx2*ppx2 + ppy2*ppy2 + ppz2*ppz2; + const float32_v& lp1p2 = ppx1*ppx2 + ppy1*ppy2 + ppz1*ppz2; + + const float32_v& dx = (x2 - x1); + const float32_v& dy = (y2 - y1); + const float32_v& dz = (z2 - z1); + + const float32_v& ldrp1 = ppx1*dx + ppy1*dy + ppz1*dz; + const float32_v& ldrp2 = ppx2*dx + ppy2*dy + ppz2*dz; + + float32_v detp = lp1p2*lp1p2 - p12*p22; + detp = select(abs(detp)<1.e-4f, 1.f, detp); //TODO correct!!! + + //dsdr calculation + const float32_v a1 = ldrp2*lp1p2 - ldrp1*p22; + const float32_v a2 = ldrp2*p12 - ldrp1*lp1p2; + const float32_v lp1p2_ds0 = bq1*( ppx2*ppy1 - ppy2*ppx1); + const float32_v lp1p2_ds1 = bq2*( ppx1*ppy2 - ppy1*ppx2); + const float32_v ldrp1_ds0 = -p12 + bq1*(ppy1*dx - ppx1*dy); + const float32_v ldrp1_ds1 = lp1p2; + const float32_v ldrp2_ds0 = -lp1p2; + const float32_v ldrp2_ds1 = p22 + bq2*(ppy2*dx - ppx2*dy); + const float32_v detp_ds0 = 2.f*lp1p2*lp1p2_ds0; + const float32_v detp_ds1 = 2.f*lp1p2*lp1p2_ds1; + const float32_v a1_ds0 = ldrp2_ds0*lp1p2 + ldrp2*lp1p2_ds0 - ldrp1_ds0*p22; + const float32_v a1_ds1 = ldrp2_ds1*lp1p2 + ldrp2*lp1p2_ds1 - ldrp1_ds1*p22; + const float32_v a2_ds0 = ldrp2_ds0*p12 - ldrp1_ds0*lp1p2 - ldrp1*lp1p2_ds0; + const float32_v a2_ds1 = ldrp2_ds1*p12 - ldrp1_ds1*lp1p2 - ldrp1*lp1p2_ds1; + + const float32_v dsl1ds0 = a1_ds0/detp - a1*detp_ds0/(detp*detp); + const float32_v dsl1ds1 = a1_ds1/detp - a1*detp_ds1/(detp*detp); + const float32_v dsl2ds0 = a2_ds0/detp - a2*detp_ds0/(detp*detp); + const float32_v dsl2ds1 = a2_ds1/detp - a2*detp_ds1/(detp*detp); + + float32_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 float32_v lp1p2_dr0[6] = {0.f, 0.f, 0.f, ccc*ppx2 - ppy2*sss, ccc*ppy2 + ppx2*sss, pz2}; + const float32_v lp1p2_dr1[6] = {0.f, 0.f, 0.f, ccc1*ppx1 - ppy1*sss1, ccc1*ppy1 + ppx1*sss1, pz1}; + const float32_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 float32_v ldrp1_dr1[6] = { ppx1, ppy1, pz1, -cB1*ppy1 + ppx1*sB1, cB1*ppx1 + ppy1*sB1, dS[1]*pz1}; + const float32_v ldrp2_dr0[6] = {-ppx2, -ppy2, -pz2, cB*ppy2 - ppx2*sB, -cB*ppx2-ppy2*sB, -dS[0]*pz2}; + const float32_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 float32_v p12_dr0[6] = {0.f, 0.f, 0.f, 2.f*px1, 2.f*py1, 2.f*pz1}; + const float32_v p22_dr1[6] = {0.f, 0.f, 0.f, 2.f*px2, 2.f*py2, 2.f*pz2}; + float32_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 KFParticleSIMD::GetDStoParticleBz( float32_v B, const KFParticleSIMD &p, + float32_v dS[2], const float32_v* param1, const float32_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 float32_v kOvSqr6 = 1.f/sqrt(float32_v(6.f)); + const float32_v kCLight = 0.000299792458f; + + //in XY plane + //first root + const float32_v& bq1 = B*toFloat(fQ)*kCLight; + const float32_v& bq2 = B*toFloat(p.fQ)*kCLight; + + const mask32_v& isStraight1 = abs(bq1) < float32_v(1.e-8f); + const mask32_v& isStraight2 = abs(bq2) < float32_v(1.e-8f); + + if( isStraight1.isFull() && isStraight2.isFull() ) + { + GetDStoParticleLine(p, dS); + return; + } + + const float32_v& px1 = param1[3]; + const float32_v& py1 = param1[4]; + const float32_v& pz1 = param1[5]; + + const float32_v& px2 = param2[3]; + const float32_v& py2 = param2[4]; + const float32_v& pz2 = param2[5]; + + const float32_v& pt12 = px1*px1 + py1*py1; + const float32_v& pt22 = px2*px2 + py2*py2; + + const float32_v& x01 = param1[0]; + const float32_v& y01 = param1[1]; + const float32_v& z01 = param1[2]; + + const float32_v& x02 = param2[0]; + const float32_v& y02 = param2[1]; + const float32_v& z02 = param2[2]; + + float32_v dS1[2] = {0.f, 0.f}, dS2[2]={0.f, 0.f}; + + const float32_v& dx0 = (x01 - x02); + const float32_v& dy0 = (y01 - y02); + const float32_v& dr02 = dx0*dx0 + dy0*dy0; + const float32_v& drp1 = dx0*px1 + dy0*py1; + const float32_v& dxyp1 = dx0*py1 - dy0*px1; + const float32_v& drp2 = dx0*px2 + dy0*py2; + const float32_v& dxyp2 = dx0*py2 - dy0*px2; + const float32_v& p1p2 = px1*px2 + py1*py2; + const float32_v& dp1p2 = px1*py2 - px2*py1; + + const float32_v& k11 = (bq2*drp1 - dp1p2); + const float32_v& k21 = (bq1*(bq2*dxyp1 - p1p2) + bq2*pt12); + const float32_v& k12 = ((bq1*drp2 - dp1p2)); + const float32_v& k22 = (bq2*(bq1*dxyp2 + p1p2) - bq1*pt22); + + const float32_v& kp = (dxyp1*bq2 - dxyp2*bq1 - p1p2); + const float32_v& kd = dr02/2.f*bq1*bq2 + kp; + const float32_v& c1 = -(bq1*kd + pt12*bq2); + const float32_v& c2 = bq2*kd + pt22*bq1; + + float32_v d1 = pt12*pt22 - kd*kd; + d1 = select(d1 < 0.f, 0.f, d1); + d1 = sqrt( d1 ); + float32_v d2 = pt12*pt22 - kd*kd; + d2 = select(d2 < 0.f, 0.f, d2); + d2 = sqrt( d2 ); + + // find two points of closest approach in XY plane + if( ! ( (!isStraight1).isEmpty() ) ) + { + dS1[0] = select(!isStraight1, KFPMath::ATan2( (bq1*k11*c1 + k21*d1*bq1), (bq1*k11*d1*bq1 - k21*c1) )/bq1, dS1[0]); + dS1[1] = select(!isStraight1, KFPMath::ATan2( (bq1*k11*c1 - k21*d1*bq1), (-bq1*k11*d1*bq1 - k21*c1) )/bq1, dS1[1]); + } + if( ! ( (!isStraight2).isEmpty() ) ) + { + dS2[0] = select(!isStraight2, KFPMath::ATan2( (bq2*k12*c2 + k22*d2*bq2), (bq2*k12*d2*bq2 - k22*c2) )/bq2, dS2[0]); + dS2[1] = select(!isStraight2, KFPMath::ATan2( (bq2*k12*c2 - k22*d2*bq2), (-bq2*k12*d2*bq2 - k22*c2) )/bq2, dS2[1]); + } + if( ! ( isStraight1.isEmpty() ) ) + { + dS1[0] = select(isStraight1 && (pt12>0.f), (k11*c1 + k21*d1)/(- k21*c1), dS1[0]); + dS1[1] = select(isStraight1 && (pt12>0.f), (k11*c1 - k21*d1)/(- k21*c1), dS1[1]); + } + if( ! ( isStraight2.isEmpty() ) ) + { + dS2[0] = select(isStraight2 && (pt22>0.f), (k12*c2 + k22*d2)/(- k22*c2), dS2[0]); + dS2[1] = select(isStraight2 && (pt22>0.f), (k12*c2 - k22*d2)/(- k22*c2), dS2[1]); + } + + //select a point which is close to the primary vertex (with the smallest r) + + float32_v dr2[2]; + for(int iP = 0; iP<2; iP++) + { + const float32_v& bs1 = bq1*dS1[iP]; + const float32_v& bs2 = bq2*dS2[iP]; + float32_v sss, ccc; + KFPMath::sincos(bs1, sss, ccc); + + const mask32_v& bs1Big = abs(bs1) > 1.e-8f; + const mask32_v& bs2Big = abs(bs2) > 1.e-8f; + + float32_v sB(0.f), cB(0.f); + sB = select(bs1Big, sss/bq1, sB); + sB = select(!bs1Big, ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS1[iP]), sB); + cB = select(bs1Big, (1.f-ccc)/bq1, cB); + cB = select(!bs1Big, .5f*sB*bs1, cB); + + const float32_v& x1 = param1[0] + sB*px1 + cB*py1; + const float32_v& y1 = param1[1] - cB*px1 + sB*py1; + const float32_v& z1 = param1[2] + dS1[iP]*param1[5]; + + KFPMath::sincos(bs2, sss, ccc); + + sB = select(bs2Big, sss/bq2, sB); + sB = select(!bs2Big, ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS2[iP]), sB); + cB = select(bs2Big, (1.f-ccc)/bq2, cB); + cB = select(!bs2Big, .5f*sB*bs2, cB); + + const float32_v& x2 = param2[0] + sB*px2 + cB*py2; + const float32_v& y2 = param2[1] - cB*px2 + sB*py2; + const float32_v& z2 = param2[2] + dS2[iP]*param2[5]; + + float32_v dx = (x1-x2); + float32_v dy = (y1-y2); + float32_v dz = (z1-z2); + + dr2[iP] = dx*dx + dy*dy + dz*dz; + } + + + const mask32_v isFirstRoot = (dr2[0] < dr2[1]); + + // if(!(isFirstRoot.isEmpty())) + { + dS[0] = select(isFirstRoot, dS1[0], dS[0]); + dS[1] = select(isFirstRoot, dS2[0], dS[1]); + } + // if( !( (!isFirstRoot).isEmpty() ) ) + { + dS[0] = select(!isFirstRoot, dS1[1], dS[0]); + dS[1] = select(!isFirstRoot, dS2[1], dS[1]); + } + + //find correct parts of helices + int32_v n1(0); + int32_v n2(0); +// float32_v dzMin = abs( (z01-z02) + dS[0]*pz1 - dS[1]*pz2 ); + const float32_v pi2(6.283185307f); + +// //TODO optimise for loops for neutral particles +// const float32_v& i1Float = -bq1/pi2*(z01/pz1+dS[0]); +// for(int di1=-1; di1<=1; di1++) +// { +// int32_v i1(0); +// i1(int_m(!isStraight1)) = int32_v(i1Float) + di1; +// +// const float32_v& i2Float = ( ((z01-z02) + (dS[0]+pi2*i1/bq1)*pz1)/pz2 - dS[1]) * bq2/pi2; +// for(int di2 = -1; di2<=1; di2++) +// { +// int32_v i2(0); +// i2(int_m(!isStraight2)) = int32_v(i2Float) + di2; +// +// const float32_v& z1 = z01 + (dS[0]+pi2*i1/bq1)*pz1; +// const float32_v& z2 = z02 + (dS[1]+pi2*i2/bq2)*pz2; +// const float32_v& dz = abs( z1-z2 ); +// +// n1(int_m(dz < dzMin)) = i1; +// n2(int_m(dz < dzMin)) = i2; +// dzMin(dz < dzMin) = dz; +// } +// } +// +// dS[0](!isStraight1) += float32_v(n1)*pi2/bq1; +// dS[1](!isStraight2) += float32_v(n2)*pi2/bq2; + + //Line correction + { + const float32_v& bs1 = bq1*dS[0]; + const float32_v& bs2 = bq2*dS[1]; + float32_v sss, ccc; + KFPMath::sincos(bs1, sss, ccc); + + const mask32_v& bs1Big = abs(bs1) > 1.e-8f; + const mask32_v& bs2Big = abs(bs2) > 1.e-8f; + + float32_v sB(0.f), cB(0.f); + sB = select(bs1Big, sss/bq1, sB); + cB = select(bs1Big, (1.f-ccc)/bq1, cB); + sB = select(!bs1Big, ((1.f-bs1*kOvSqr6)*(1.f+bs1*kOvSqr6)*dS[0]), sB); + cB = select(!bs1Big, .5f*sB*bs1, cB); + + const float32_v& x1 = x01 + sB*px1 + cB*py1; + const float32_v& y1 = y01 - cB*px1 + sB*py1; + const float32_v& z1 = z01 + dS[0]*pz1; + const float32_v& ppx1 = ccc*px1 + sss*py1; + const float32_v& ppy1 = -sss*px1 + ccc*py1; + const float32_v& ppz1 = pz1; + + float32_v sss1, ccc1; + KFPMath::sincos(bs2, sss1, ccc1); + + float32_v sB1(0.f), cB1(0.f); + sB1 = select(bs2Big, sss1/bq2, sB1); + cB1 = select(bs2Big, (1.f-ccc1)/bq2, cB1); + sB1 = select(!bs2Big, ((1.f-bs2*kOvSqr6)*(1.f+bs2*kOvSqr6)*dS[1]), sB1); + cB1 = select(!bs2Big, .5f*sB1*bs2, cB1); + + const float32_v& x2 = x02 + sB1*px2 + cB1*py2; + const float32_v& y2 = y02 - cB1*px2 + sB1*py2; + const float32_v& z2 = z02 + dS[1]*pz2; + const float32_v& ppx2 = ccc1*px2 + sss1*py2; + const float32_v& ppy2 = -sss1*px2 + ccc1*py2; + const float32_v& ppz2 = pz2; + + const float32_v& p12 = ppx1*ppx1 + ppy1*ppy1 + ppz1*ppz1; + const float32_v& p22 = ppx2*ppx2 + ppy2*ppy2 + ppz2*ppz2; + const float32_v& lp1p2 = ppx1*ppx2 + ppy1*ppy2 + ppz1*ppz2; + + const float32_v& dx = (x2 - x1); + const float32_v& dy = (y2 - y1); + const float32_v& dz = (z2 - z1); + + const float32_v& ldrp1 = ppx1*dx + ppy1*dy + ppz1*dz; + const float32_v& ldrp2 = ppx2*dx + ppy2*dy + ppz2*dz; + + float32_v detp = lp1p2*lp1p2 - p12*p22; + detp = select(abs(detp)<1.e-4f, 1.f, detp); //TODO correct!!! + + dS[0] += (ldrp2*lp1p2 - ldrp1*p22) /detp; + dS[1] += (ldrp2*p12 - ldrp1*lp1p2)/detp; + } +} + +void KFParticleSIMD::GetDStoParticleBy( float32_v B, const KFParticleSIMD &p, float32_v dS[2], float32_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 float32_v param1[6] = { fP[0], -fP[2], fP[1], fP[3], -fP[5], fP[4] }; + const float32_v param2[6] = { p.fP[0], -p.fP[2], p.fP[1], p.fP[3], -p.fP[5], p.fP[4] }; + + float32_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 KFParticleSIMD::GetDStoParticleBy( float32_v B, const KFParticleSIMD &p, float32_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 float32_v param1[6] = { fP[0], -fP[2], fP[1], fP[3], -fP[5], fP[4] }; + const float32_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 KFParticleSIMD::GetDStoParticleB( float32_v B[3], const KFParticleSIMD &p, float32_v dS[2], float32_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 float32_v& Bx = B[0]; + const float32_v& By = B[1]; + const float32_v& Bz = B[2]; + + const float32_v& Bxz = sqrt(Bx*Bx + Bz*Bz); + const float32_v& Br = sqrt(Bx*Bx + By*By + Bz*Bz); + + float32_v cosA = 1.f; + float32_v sinA = 0.f; + + cosA = select( abs(Bxz) > 1.e-8f, Bz/Bxz, cosA); + sinA = select( abs(Bxz) > 1.e-8f, Bx/Bxz, sinA); + + const float32_v& sinP = By/Br; + const float32_v& cosP = Bxz/Br; + + + const float32_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 float32_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]}; + + float32_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 KFParticleSIMD::GetDStoParticleB( float32_v B[3], const KFParticleSIMD &p, float32_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 float32_v& Bx = B[0]; + const float32_v& By = B[1]; + const float32_v& Bz = B[2]; + + const float32_v& Bxz = sqrt(Bx*Bx + Bz*Bz); + const float32_v& Br = sqrt(Bx*Bx + By*By + Bz*Bz); + + float32_v cosA = 1.f; + float32_v sinA = 0.f; + + cosA = select( abs(Bxz) > 1.e-8f, Bz/Bxz, cosA); + sinA = select( abs(Bxz) > 1.e-8f, Bx/Bxz, sinA); + + const float32_v& sinP = By/Br; + const float32_v& cosP = Bxz/Br; + + + const float32_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 float32_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 KFParticleSIMD::GetDStoParticleLine( const KFParticleSIMD &p, float32_v dS[2], float32_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 + **/ + + float32_v p12 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; + float32_v p22 = p.fP[3]*p.fP[3] + p.fP[4]*p.fP[4] + p.fP[5]*p.fP[5]; + float32_v p1p2 = fP[3]*p.fP[3] + fP[4]*p.fP[4] + fP[5]*p.fP[5]; + + float32_v drp1 = fP[3]*(p.fP[0]-fP[0]) + fP[4]*(p.fP[1]-fP[1]) + fP[5]*(p.fP[2]-fP[2]); + float32_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]); + + float32_v detp = p1p2*p1p2 - p12*p22; + detp = select( abs(detp) 100.f, 0.f, fld[iF1][iF2]); + + 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; + + float32_v c2[3][3] = { { 5.f, -4.f, -1.f},{ 44.f, 80.f, -4.f},{ 11.f, 44.f, 5.f} }; // /=360. + float32_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; + + } + +// float32_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); + + float32_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]; + + float32_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] = select(abs(dS)>0.f, 1.f - 3.f*ssyy/dS, mJds[0][3]); + mJds[1][3] = select(abs(dS)>0.f, -2.f*ssz/dS, mJds[1][3]); + mJds[2][3] = select(abs(dS)>0.f, (2.f*ssy-4.f*ssyyy)/dS, mJds[2][3]); + + mJds[0][4] = select(abs(dS)>0.f, 2.f*ssx/dS, mJds[0][4]); + mJds[1][4] = select(abs(dS)>0.f, 1.f, mJds[1][4]); + mJds[2][4] = select(abs(dS)>0.f,-2.f*ssx/dS, mJds[2][4]); + + mJds[0][5] = select(abs(dS)>0.f, (4.f*ssyyy-2.f*ssy)/dS, mJds[0][5]); + mJds[1][5] = select(abs(dS)>0.f, (2.f*ssx + 3.f*ssyz)/dS, mJds[1][5]); + mJds[2][5] = select(abs(dS)>0.f, 1.f - 3.f*ssyy/dS, mJds[2][5]); + + mJds[3][3] = select(abs(dS)>0.f, -2.f*syy/dS, mJds[3][3]); + mJds[4][3] = select(abs(dS)>0.f, -sz/dS, mJds[4][3]); + mJds[5][3] = select(abs(dS)>0.f, sy/dS - 3.f*syyy/dS, mJds[5][3]); + + mJds[3][4] = select(abs(dS)>0.f, sx/dS, mJds[3][4]); + mJds[4][4] = select(abs(dS)>0.f,0.f, mJds[4][4]); + mJds[5][4] = select(abs(dS)>0.f,-sx/dS, mJds[5][4]); + + mJds[3][5] = select(abs(dS)>0.f,3.f*syyy/dS - sy/dS, mJds[3][5]); + mJds[4][5] = select(abs(dS)>0.f, sx/dS + 2.f*syz/dS, mJds[4][5]); + mJds[5][5] = select(abs(dS)>0.f,-2.f*syy/dS, mJds[5][5]); + + 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 KFParticleSIMD::TransportCBM( float32_v dS, float32_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 == int32_v(0)).isFull() ){ + TransportLine( dS, P ); + return; + } + + const float32_v kCLight = 0.000299792458f; + + float32_v c = toFloat(fQ)*kCLight; + + // construct coefficients + + float32_v + px = fP[3], + py = fP[4], + pz = fP[5]; + + float32_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 + + float32_v fld[3][3]; + float32_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] ); + + float32_v ssy1 = ( 7.f*fld[0][1] + 6.f*fld[1][1]-fld[2][1] )*c*dS*dS/96.f; + float32_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] = select(abs(fld[iF1][iF2]) > 100.f, 0.f, fld[iF1][iF2]); + + 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; + + float32_v c2[3][3] = { { 5.f, -4.f, -1.f},{ 44.f, 80.f, -4.f},{ 11.f, 44.f, 5.f} }; // /=360. + float32_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; + + } + + float32_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 KFParticleSIMD::TransportBz( float32_v Bz, float32_v dS, const float32_v* dsdr, float32_v P[], float32_v C[], float32_v* dsdr1, float32_v* F, float32_v* F1, const bool fullC ) 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 float32_v kCLight = 0.000299792458f; + Bz = Bz*toFloat(fQ)*kCLight; + float32_v bs= Bz*dS; + float32_v s, c; + KFPMath::sincos(bs, s, c); + + float32_v sB(0.f), cB(0.f); + + const float32_v kOvSqr6 = 1.f/sqrt(float32_v(6.f)); + const float32_v LocalSmall = 1.e-10f; + + Bz = select(abs(bs) <= LocalSmall, LocalSmall, Bz); + sB = select(LocalSmall < abs(bs), s/Bz, sB); + sB = select(LocalSmall >= abs(bs), (1.f-bs*kOvSqr6)*(1.f+bs*kOvSqr6)*dS, sB); + cB = select(LocalSmall < abs(bs), (1.f-c)/Bz, cB); + cB = select(LocalSmall >= abs(bs), .5f*sB*bs, cB); + + float32_v px = fP[3]; + float32_v py = fP[4]; + float32_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]; + + float32_v mJ[6][6]; + + const float32_v cPx = c * px; + const float32_v sPy = s * py; + mJ[0][0] = (cPx * dsdr[0] + sPy * dsdr[0]) + 1.f; + mJ[0][1] = cPx * dsdr[1] + sPy * dsdr[1]; + mJ[0][2] = cPx * dsdr[2] + sPy * dsdr[2]; + mJ[0][3] = (cPx * dsdr[3] + sPy * dsdr[3]) + sB; + mJ[0][4] = (cPx * dsdr[4] + sPy * dsdr[4]) + cB; + mJ[0][5] = cPx * dsdr[5] + sPy * dsdr[5]; + + const float32_v sPx = s * px; + const float32_v cPy = c * py; + mJ[1][0] = (cPy * dsdr[0] - sPx * dsdr[0]); + mJ[1][1] = (cPy * dsdr[1] - sPx * dsdr[1]) + 1.f; + mJ[1][2] = (cPy * dsdr[2] - sPx * dsdr[2]); + mJ[1][3] = (cPy * dsdr[3] - sPx * dsdr[3]) - cB; + mJ[1][4] = (cPy * dsdr[4] - sPx * dsdr[4]) + sB; + mJ[1][5] = (cPy * dsdr[5] - sPx * dsdr[5]); + + mJ[2][0] = pz*dsdr[0]; + mJ[2][1] = pz*dsdr[1]; + mJ[2][2] = pz*dsdr[2] + 1.f; + mJ[2][3] = pz*dsdr[3]; + mJ[2][4] = pz*dsdr[4]; + mJ[2][5] = pz*dsdr[5] + dS; + + float32_v CJt[6][5]; + + CJt[0][0] = fC[ 0]*mJ[0][0] + fC[ 1]*mJ[0][1] + fC[ 3]*mJ[0][2] + fC[ 6]*mJ[0][3] + fC[10]*mJ[0][4] + fC[15]*mJ[0][5]; + CJt[0][1] = fC[ 0]*mJ[1][0] + fC[ 1]*mJ[1][1] + fC[ 3]*mJ[1][2] + fC[ 6]*mJ[1][3] + fC[10]*mJ[1][4] + fC[15]*mJ[1][5]; + CJt[0][2] = fC[ 0]*mJ[2][0] + fC[ 1]*mJ[2][1] + fC[ 3]*mJ[2][2] + fC[ 6]*mJ[2][3] + fC[10]*mJ[2][4] + fC[15]*mJ[2][5]; + + CJt[1][0] = fC[ 1]*mJ[0][0] + fC[ 2]*mJ[0][1] + fC[ 4]*mJ[0][2] + fC[ 7]*mJ[0][3] + fC[11]*mJ[0][4] + fC[16]*mJ[0][5]; + CJt[1][1] = fC[ 1]*mJ[1][0] + fC[ 2]*mJ[1][1] + fC[ 4]*mJ[1][2] + fC[ 7]*mJ[1][3] + fC[11]*mJ[1][4] + fC[16]*mJ[1][5]; + CJt[1][2] = fC[ 1]*mJ[2][0] + fC[ 2]*mJ[2][1] + fC[ 4]*mJ[2][2] + fC[ 7]*mJ[2][3] + fC[11]*mJ[2][4] + fC[16]*mJ[2][5]; + + CJt[2][0] = fC[ 3]*mJ[0][0] + fC[ 4]*mJ[0][1] + fC[ 5]*mJ[0][2] + fC[ 8]*mJ[0][3] + fC[12]*mJ[0][4] + fC[17]*mJ[0][5]; + CJt[2][1] = fC[ 3]*mJ[1][0] + fC[ 4]*mJ[1][1] + fC[ 5]*mJ[1][2] + fC[ 8]*mJ[1][3] + fC[12]*mJ[1][4] + fC[17]*mJ[1][5]; + CJt[2][2] = fC[ 3]*mJ[2][0] + fC[ 4]*mJ[2][1] + fC[ 5]*mJ[2][2] + fC[ 8]*mJ[2][3] + fC[12]*mJ[2][4] + fC[17]*mJ[2][5]; + + CJt[3][0] = fC[ 6]*mJ[0][0] + fC[ 7]*mJ[0][1] + fC[ 8]*mJ[0][2] + fC[ 9]*mJ[0][3] + fC[13]*mJ[0][4] + fC[18]*mJ[0][5]; + CJt[3][1] = fC[ 6]*mJ[1][0] + fC[ 7]*mJ[1][1] + fC[ 8]*mJ[1][2] + fC[ 9]*mJ[1][3] + fC[13]*mJ[1][4] + fC[18]*mJ[1][5]; + CJt[3][2] = fC[ 6]*mJ[2][0] + fC[ 7]*mJ[2][1] + fC[ 8]*mJ[2][2] + fC[ 9]*mJ[2][3] + fC[13]*mJ[2][4] + fC[18]*mJ[2][5]; + + CJt[4][0] = fC[10]*mJ[0][0] + fC[11]*mJ[0][1] + fC[12]*mJ[0][2] + fC[13]*mJ[0][3] + fC[14]*mJ[0][4] + fC[19]*mJ[0][5]; + CJt[4][1] = fC[10]*mJ[1][0] + fC[11]*mJ[1][1] + fC[12]*mJ[1][2] + fC[13]*mJ[1][3] + fC[14]*mJ[1][4] + fC[19]*mJ[1][5]; + CJt[4][2] = fC[10]*mJ[2][0] + fC[11]*mJ[2][1] + fC[12]*mJ[2][2] + fC[13]*mJ[2][3] + fC[14]*mJ[2][4] + fC[19]*mJ[2][5]; + + CJt[5][0] = fC[15]*mJ[0][0] + fC[16]*mJ[0][1] + fC[17]*mJ[0][2] + fC[18]*mJ[0][3] + fC[19]*mJ[0][4] + fC[20]*mJ[0][5]; + CJt[5][1] = fC[15]*mJ[1][0] + fC[16]*mJ[1][1] + fC[17]*mJ[1][2] + fC[18]*mJ[1][3] + fC[19]*mJ[1][4] + fC[20]*mJ[1][5]; + CJt[5][2] = fC[15]*mJ[2][0] + fC[16]*mJ[2][1] + fC[17]*mJ[2][2] + fC[18]*mJ[2][3] + fC[19]*mJ[2][4] + fC[20]*mJ[2][5]; + + + C[ 0] = mJ[0][0]*CJt[0][0] + mJ[0][1]*CJt[1][0] + mJ[0][2]*CJt[2][0] + mJ[0][3]*CJt[3][0] + mJ[0][4]*CJt[4][0] + mJ[0][5]*CJt[5][0]; + + C[ 1] = mJ[1][0]*CJt[0][0] + mJ[1][1]*CJt[1][0] + mJ[1][2]*CJt[2][0] + mJ[1][3]*CJt[3][0] + mJ[1][4]*CJt[4][0] + mJ[1][5]*CJt[5][0]; + C[ 2] = mJ[1][0]*CJt[0][1] + mJ[1][1]*CJt[1][1] + mJ[1][2]*CJt[2][1] + mJ[1][3]*CJt[3][1] + mJ[1][4]*CJt[4][1] + mJ[1][5]*CJt[5][1]; + + C[ 3] = mJ[2][0]*CJt[0][0] + mJ[2][1]*CJt[1][0] + mJ[2][2]*CJt[2][0] + mJ[2][3]*CJt[3][0] + mJ[2][4]*CJt[4][0] + mJ[2][5]*CJt[5][0]; + C[ 4] = mJ[2][0]*CJt[0][1] + mJ[2][1]*CJt[1][1] + mJ[2][2]*CJt[2][1] + mJ[2][3]*CJt[3][1] + mJ[2][4]*CJt[4][1] + mJ[2][5]*CJt[5][1]; + C[ 5] = mJ[2][0]*CJt[0][2] + mJ[2][1]*CJt[1][2] + mJ[2][2]*CJt[2][2] + mJ[2][3]*CJt[3][2] + mJ[2][4]*CJt[4][2] + mJ[2][5]*CJt[5][2]; + + const float32_v sBzPx = Bz * sPx; + const float32_v cBzPy = Bz * cPy; + const float32_v cBzPx = Bz * cPx; + const float32_v sBzPy = Bz * sPy; + + if(fullC){ + mJ[3][0] = (cBzPy * dsdr[0] - sBzPx * dsdr[0]); + mJ[3][1] = (cBzPy * dsdr[1] - sBzPx * dsdr[1]); + mJ[3][2] = (cBzPy * dsdr[2] - sBzPx * dsdr[2]); + mJ[3][3] = (cBzPy * dsdr[3] - sBzPx * dsdr[3]) + c; + mJ[3][4] = (cBzPy * dsdr[4] - sBzPx * dsdr[4]) + s; + mJ[3][5] = (cBzPy * dsdr[5] - sBzPx * dsdr[5]); + + mJ[4][0] = -(cBzPx * dsdr[0] + sBzPy * dsdr[0]); + mJ[4][1] = -(cBzPx * dsdr[1] + sBzPy * dsdr[1]); + mJ[4][2] = -(cBzPx * dsdr[2] + sBzPy * dsdr[2]); + mJ[4][3] = -s - (cBzPx * dsdr[3] + sBzPy * dsdr[3]); + mJ[4][4] = c - (cBzPx * dsdr[4] + sBzPy * dsdr[4]); + mJ[4][5] = -(cBzPx * dsdr[5] + sBzPy * dsdr[5]); + + mJ[5][0] = 0.f; + mJ[5][1] = 0.f; + mJ[5][2] = 0.f; + mJ[5][3] = 0.f; + mJ[5][4] = 0.f; + mJ[5][5] = 1.f; + + CJt[0][3] = fC[ 0]*mJ[3][0] + fC[ 1]*mJ[3][1] + fC[ 3]*mJ[3][2] + fC[ 6]*mJ[3][3] + fC[10]*mJ[3][4] + fC[15]*mJ[3][5]; + CJt[0][4] = fC[ 0]*mJ[4][0] + fC[ 1]*mJ[4][1] + fC[ 3]*mJ[4][2] + fC[ 6]*mJ[4][3] + fC[10]*mJ[4][4] + fC[15]*mJ[4][5]; + + CJt[1][3] = fC[ 1]*mJ[3][0] + fC[ 2]*mJ[3][1] + fC[ 4]*mJ[3][2] + fC[ 7]*mJ[3][3] + fC[11]*mJ[3][4] + fC[16]*mJ[3][5]; + CJt[1][4] = fC[ 1]*mJ[4][0] + fC[ 2]*mJ[4][1] + fC[ 4]*mJ[4][2] + fC[ 7]*mJ[4][3] + fC[11]*mJ[4][4] + fC[16]*mJ[4][5]; + + CJt[2][3] = fC[ 3]*mJ[3][0] + fC[ 4]*mJ[3][1] + fC[ 5]*mJ[3][2] + fC[ 8]*mJ[3][3] + fC[12]*mJ[3][4] + fC[17]*mJ[3][5]; + CJt[2][4] = fC[ 3]*mJ[4][0] + fC[ 4]*mJ[4][1] + fC[ 5]*mJ[4][2] + fC[ 8]*mJ[4][3] + fC[12]*mJ[4][4] + fC[17]*mJ[4][5]; + + CJt[3][3] = fC[ 6]*mJ[3][0] + fC[ 7]*mJ[3][1] + fC[ 8]*mJ[3][2] + fC[ 9]*mJ[3][3] + fC[13]*mJ[3][4] + fC[18]*mJ[3][5]; + CJt[3][4] = fC[ 6]*mJ[4][0] + fC[ 7]*mJ[4][1] + fC[ 8]*mJ[4][2] + fC[ 9]*mJ[4][3] + fC[13]*mJ[4][4] + fC[18]*mJ[4][5]; + + CJt[4][3] = fC[10]*mJ[3][0] + fC[11]*mJ[3][1] + fC[12]*mJ[3][2] + fC[13]*mJ[3][3] + fC[14]*mJ[3][4] + fC[19]*mJ[3][5]; + CJt[4][4] = fC[10]*mJ[4][0] + fC[11]*mJ[4][1] + fC[12]*mJ[4][2] + fC[13]*mJ[4][3] + fC[14]*mJ[4][4] + fC[19]*mJ[4][5]; + + CJt[5][3] = fC[15]*mJ[3][0] + fC[16]*mJ[3][1] + fC[17]*mJ[3][2] + fC[18]*mJ[3][3] + fC[19]*mJ[3][4] + fC[20]*mJ[3][5]; + CJt[5][4] = fC[15]*mJ[4][0] + fC[16]*mJ[4][1] + fC[17]*mJ[4][2] + fC[18]*mJ[4][3] + fC[19]*mJ[4][4] + fC[20]*mJ[4][5]; + + C[ 6] = mJ[3][0]*CJt[0][0] + mJ[3][1]*CJt[1][0] + mJ[3][2]*CJt[2][0] + mJ[3][3]*CJt[3][0] + mJ[3][4]*CJt[4][0] + mJ[3][5]*CJt[5][0]; + C[ 7] = mJ[3][0]*CJt[0][1] + mJ[3][1]*CJt[1][1] + mJ[3][2]*CJt[2][1] + mJ[3][3]*CJt[3][1] + mJ[3][4]*CJt[4][1] + mJ[3][5]*CJt[5][1]; + C[ 8] = mJ[3][0]*CJt[0][2] + mJ[3][1]*CJt[1][2] + mJ[3][2]*CJt[2][2] + mJ[3][3]*CJt[3][2] + mJ[3][4]*CJt[4][2] + mJ[3][5]*CJt[5][2]; + C[ 9] = mJ[3][0]*CJt[0][3] + mJ[3][1]*CJt[1][3] + mJ[3][2]*CJt[2][3] + mJ[3][3]*CJt[3][3] + mJ[3][4]*CJt[4][3] + mJ[3][5]*CJt[5][3]; + + C[10] = mJ[4][0]*CJt[0][0] + mJ[4][1]*CJt[1][0] + mJ[4][2]*CJt[2][0] + mJ[4][3]*CJt[3][0] + mJ[4][4]*CJt[4][0] + mJ[4][5]*CJt[5][0]; + C[11] = mJ[4][0]*CJt[0][1] + mJ[4][1]*CJt[1][1] + mJ[4][2]*CJt[2][1] + mJ[4][3]*CJt[3][1] + mJ[4][4]*CJt[4][1] + mJ[4][5]*CJt[5][1]; + C[12] = mJ[4][0]*CJt[0][2] + mJ[4][1]*CJt[1][2] + mJ[4][2]*CJt[2][2] + mJ[4][3]*CJt[3][2] + mJ[4][4]*CJt[4][2] + mJ[4][5]*CJt[5][2]; + C[13] = mJ[4][0]*CJt[0][3] + mJ[4][1]*CJt[1][3] + mJ[4][2]*CJt[2][3] + mJ[4][3]*CJt[3][3] + mJ[4][4]*CJt[4][3] + mJ[4][5]*CJt[5][3]; + C[14] = mJ[4][0]*CJt[0][4] + mJ[4][1]*CJt[1][4] + mJ[4][2]*CJt[2][4] + mJ[4][3]*CJt[3][4] + mJ[4][4]*CJt[4][4] + mJ[4][5]*CJt[5][4]; + + C[15] = CJt[5][0]; + C[16] = CJt[5][1]; + C[17] = CJt[5][2]; + C[18] = CJt[5][3]; + C[19] = CJt[5][4]; + C[20] = fC[20]; + + const float32_v C21 = fC[21]*mJ[0][0] + fC[22]*mJ[0][1] + fC[23]*mJ[0][2] + fC[24]*mJ[0][3] + fC[25]*mJ[0][4] + fC[26]*mJ[0][5]; + const float32_v C22 = fC[21]*mJ[1][0] + fC[22]*mJ[1][1] + fC[23]*mJ[1][2] + fC[24]*mJ[1][3] + fC[25]*mJ[1][4] + fC[26]*mJ[1][5]; + const float32_v C23 = fC[21]*mJ[2][0] + fC[22]*mJ[2][1] + fC[23]*mJ[2][2] + fC[24]*mJ[2][3] + fC[25]*mJ[2][4] + fC[26]*mJ[2][5]; + const float32_v C24 = fC[21]*mJ[3][0] + fC[22]*mJ[3][1] + fC[23]*mJ[3][2] + fC[24]*mJ[3][3] + fC[25]*mJ[3][4] + fC[26]*mJ[3][5]; + const float32_v C25 = fC[21]*mJ[4][0] + fC[22]*mJ[4][1] + fC[23]*mJ[4][2] + fC[24]*mJ[4][3] + fC[25]*mJ[4][4] + fC[26]*mJ[4][5]; + C[21] = C21; + C[22] = C22; + C[23] = C23; + C[24] = C24; + C[25] = C25; + C[26] = fC[26]; + C[27] = fC[27]; + + const float32_v C28 = fC[28]*mJ[0][0] + fC[29]*mJ[0][1] + fC[30]*mJ[0][2] + fC[31]*mJ[0][3] + fC[32]*mJ[0][4] + fC[33]*mJ[0][5]; + const float32_v C29 = fC[28]*mJ[1][0] + fC[29]*mJ[1][1] + fC[30]*mJ[1][2] + fC[31]*mJ[1][3] + fC[32]*mJ[1][4] + fC[33]*mJ[1][5]; + const float32_v C30 = fC[28]*mJ[2][0] + fC[29]*mJ[2][1] + fC[30]*mJ[2][2] + fC[31]*mJ[2][3] + fC[32]*mJ[2][4] + fC[33]*mJ[2][5]; + const float32_v C31 = fC[28]*mJ[3][0] + fC[29]*mJ[3][1] + fC[30]*mJ[3][2] + fC[31]*mJ[3][3] + fC[32]*mJ[3][4] + fC[33]*mJ[3][5]; + const float32_v C32 = fC[28]*mJ[4][0] + fC[29]*mJ[4][1] + fC[30]*mJ[4][2] + fC[31]*mJ[4][3] + fC[32]*mJ[4][4] + fC[33]*mJ[4][5]; + C[28] = C28; + C[29] = C29; + C[30] = C30; + C[31] = C31; + C[32] = C32; + C[33] = fC[33]; + C[34] = fC[34]; + C[35] = fC[35]; + } + + if(F) { + for(int i=0; i<6; i++) + for(int j=0; j<6; j++) + F[i*6+j] = mJ[i][j]; + } + + if(F1) { + F1[ 0] = cPx * dsdr1[0] + sPy * dsdr1[0]; + F1[ 1] = cPx * dsdr1[1] + sPy * dsdr1[1]; + F1[ 2] = cPx * dsdr1[2] + sPy * dsdr1[2]; + + F1[ 6] = cPy * dsdr1[0] - sPx * dsdr1[0]; + F1[ 7] = cPy * dsdr1[1] - sPx * dsdr1[1]; + F1[ 8] = cPy * dsdr1[2] - sPx * dsdr1[2]; + + F1[12] = pz*dsdr1[0]; + F1[13] = pz*dsdr1[1]; + F1[14] = pz*dsdr1[2]; + + if(fullC){ + F1[ 3] = cPx * dsdr1[3] + sPy * dsdr1[3]; + F1[ 4] = cPx * dsdr1[4] + sPy * dsdr1[4]; + F1[ 5] = cPx * dsdr1[5] + sPy * dsdr1[5]; + + F1[ 9] = cPy * dsdr1[3] - sPx * dsdr1[3]; + F1[10] = cPy * dsdr1[4] - sPx * dsdr1[4]; + F1[11] = cPy * dsdr1[5] - sPx * dsdr1[5]; + + F1[15] = pz*dsdr1[3]; + F1[16] = pz*dsdr1[4]; + F1[17] = pz*dsdr1[5]; + + F1[18] = cBzPy * dsdr1[0] - sBzPx * dsdr1[0]; + F1[19] = cBzPy * dsdr1[1] - sBzPx * dsdr1[1]; + F1[20] = cBzPy * dsdr1[2] - sBzPx * dsdr1[2]; + F1[21] = cBzPy * dsdr1[3] - sBzPx * dsdr1[3]; + F1[22] = cBzPy * dsdr1[4] - sBzPx * dsdr1[4]; + F1[23] = cBzPy * dsdr1[5] - sBzPx * dsdr1[5]; + + F1[24] = -(cBzPx * dsdr1[0] + sBzPy * dsdr1[0]); + F1[25] = -(cBzPx * dsdr1[1] + sBzPy * dsdr1[1]); + F1[26] = -(cBzPx * dsdr1[2] + sBzPy * dsdr1[2]); + F1[27] = -(cBzPx * dsdr1[3] + sBzPy * dsdr1[3]); + F1[28] = -(cBzPx * dsdr1[4] + sBzPy * dsdr1[4]); + F1[29] = -(cBzPx * dsdr1[5] + sBzPy * dsdr1[5]); + + F1[30] = 0.f; + F1[31] = 0.f; + F1[32] = 0.f; + F1[33] = 0.f; + F1[34] = 0.f; + F1[35] = 0.f; + } + } +} + +void KFParticleSIMD::TransportBz( float32_v Bz, float32_v dS, float32_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 float32_v kCLight = 0.000299792458f; + Bz = Bz*toFloat(fQ)*kCLight; + float32_v bs= Bz*dS; + float32_v s, c; + KFPMath::sincos(bs, s, c); + + float32_v sB(0.f), cB(0.f); + + const float32_v kOvSqr6 = 1.f/sqrt(float32_v(6.f)); + const float32_v LocalSmall = 1.e-10f; + + Bz = select(abs(bs) <= LocalSmall, LocalSmall, Bz); + sB = select(LocalSmall < abs(bs), s/Bz, sB); + sB = select(LocalSmall >= abs(bs), (1.f-bs*kOvSqr6)*(1.f+bs*kOvSqr6)*dS, sB); + cB = select(LocalSmall < abs(bs), (1.f-c)/Bz, cB); + cB = select(LocalSmall >= abs(bs), .5f*sB*bs, cB); + + float32_v px = fP[3]; + float32_v py = fP[4]; + float32_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]; +} + +void KFParticleSIMD::TransportLine( float32_v dS, const float32_v* dsdr, float32_v P[], float32_v C[], float32_v* dsdr1, float32_v* F, float32_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) + **/ + + float32_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; + + float32_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]; + + float32_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 KFParticleSIMD::TransportLine( float32_v dS, float32_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]; +} + +mask32_v KFParticleSIMD::GetMomentum( float32_v &p, float32_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 + **/ + + float32_v x = fP[3]; + float32_v y = fP[4]; + float32_v z = fP[5]; + float32_v x2 = x*x; + float32_v y2 = y*y; + float32_v z2 = z*z; + float32_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 float32_v LocalSmall = 1.e-4f; + mask32_v mask = (0.f < error) && (LocalSmall < abs(p)); + error = select(!mask, 1.e20f, error); + error = sqrt(error); + return (!mask); +} + +mask32_v KFParticleSIMD::GetPt( float32_v &pt, float32_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 + **/ + + float32_v px = fP[3]; + float32_v py = fP[4]; + float32_v px2 = px*px; + float32_v py2 = py*py; + float32_v pt2 = px2+py2; + pt = sqrt(pt2); + error = (px2*fC[9] + py2*fC[14] + 2*px*py*fC[13] ); + const float32_v LocalSmall = 1.e-4f; + mask32_v mask = ( (0.f < error) && (LocalSmall < abs(pt))); + error = select(!mask, 1.e20f, error); + error = sqrt(error); + return (!mask); +} + +mask32_v KFParticleSIMD::GetEta( float32_v &eta, float32_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 float32_v BIG = 1.e8f; + const float32_v LocalSmall = 1.e-8f; + + float32_v px = fP[3]; + float32_v py = fP[4]; + float32_v pz = fP[5]; + float32_v pt2 = px*px + py*py; + float32_v p2 = pt2 + pz*pz; + float32_v p = sqrt(p2); + float32_v a = p + pz; + float32_v b = p - pz; + eta = BIG; + float32_v c = 0.f; + c = select(b > LocalSmall, a/b, c); + float32_v logc = 0.5f*KFPMath::log(c); + eta = select(LocalSmall(1.e-8f)); + a = select(mask, ( mP[3]*mP1[3] + mP[4]*mP1[4] + mP[5]*mP1[5] )/n, a); + mask = ( abs(a) < float32_v(1.f)); + mask32_v aPos = (a>=float32_v(0.f)); + a = select(mask, KFPMath::acos(a), a); + a = select((!mask) && aPos, 0.f, a); + a = select((!mask) && (!aPos), 3.1415926535f, a); + return a; +} + +float32_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 + **/ + + float32_v ds[2] = {0.f,0.f}; + float32_v dsdr[4][6]; + GetDStoParticle( p, ds, dsdr ); + float32_v mP[8], mC[36], mP1[8], mC1[36]; + Transport( ds[0], dsdr[0], mP, mC ); + p.Transport( ds[1], dsdr[3], mP1, mC1 ); + float32_v n = sqrt( mP[3]*mP[3] + mP[4]*mP[4] ); + float32_v n1= sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] ); + n*=n1; + float32_v a(0.f); + mask32_v mask = (n>(1.e-8f)); + a = ( mP[3]*mP1[3] + mP[4]*mP1[4] )/n; + a = select(!mask, 0.f, a); + mask = ( abs(a) < float32_v(1.f)); + mask32_v aPos = (a>=float32_v(0.f)); + a = select(mask, KFPMath::acos(a), a); + a = select((!mask) && aPos, 0.f, a); + a = select((!mask) && (!aPos), 3.1415926535f, a); + return a; +} + +float32_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 + **/ + + float32_v ds[2] = {0.f,0.f}; + float32_v dsdr[4][6]; + GetDStoParticle( p, ds, dsdr ); + float32_v mP[8], mC[36], mP1[8], mC1[36]; + Transport( ds[0], dsdr[0], mP, mC ); + p.Transport( ds[1], dsdr[3], mP1, mC1 ); + float32_v nr = sqrt( mP[3]*mP[3] + mP[4]*mP[4] ); + float32_v n1r= sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] ); + float32_v n = sqrt( nr*nr + mP[5]*mP[5] ); + float32_v n1= sqrt( n1r*n1r + mP1[5]*mP1[5] ); + n*=n1; + float32_v a(0.f); + mask32_v mask = (n>(1.e-8f)); + a = select(mask, ( nr*n1r +mP[5]*mP1[5])/n, a); + mask = ( abs(a) < float32_v(0.f)); + mask32_v aPos = (a>=float32_v(0.f)); + a = select(mask, KFPMath::acos(a), a); + a = select((!mask) && aPos, 0.f, a); + a = select((!mask) && (!aPos), 3.1415926535f, a); + return a; +} + +float32_v KFParticleSIMD::GetPseudoProperDecayTime( const KFParticleSIMD &pV, const float32_v& mass, float32_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 float32_v ipt2 = 1/( Px()*Px() + Py()*Py() ); + const float32_v mipt2 = mass*ipt2; + const float32_v dx = X() - pV.X(); + const float32_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 float32_v f0 = Px()*mipt2; + const float32_v f1 = Py()*mipt2; + const float32_v mipt2derivative = mipt2*(1-2*Px()*Px()*ipt2); + const float32_v f2 = dx*mipt2derivative; + const float32_v f3 = -dy*mipt2derivative; + const float32_v f4 = -f0; + const float32_v f5 = -f1; + + const float32_v& mC00 = GetCovariance(0,0); + const float32_v& mC10 = GetCovariance(0,1); + const float32_v& mC11 = GetCovariance(1,1); + const float32_v& mC20 = GetCovariance(3,0); + const float32_v& mC21 = GetCovariance(3,1); + const float32_v& mC22 = GetCovariance(3,3); + const float32_v& mC30 = GetCovariance(4,0); + const float32_v& mC31 = GetCovariance(4,1); + const float32_v& mC32 = GetCovariance(4,3); + const float32_v& mC33 = GetCovariance(4,4); + const float32_v& mC44 = pV.GetCovariance(0,0); + const float32_v& mC54 = pV.GetCovariance(1,0); + const float32_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(Id()[iPart])); + + Part.CleanDaughtersId(); + for( unsigned int i = 0; i < DaughterIds().size(); i++ ) + Part.AddDaughterId(static_cast(DaughterIds()[i][iPart])); + + Part.SetPDG( static_cast(GetPDG()[iPart]) ); + + for(int iP=0; iP<8; iP++) + Part.Parameter(iP) = fP[iP][iPart]; + for(int iC=0; iC<36; iC++) + Part.Covariance(iC) = fC[iC][iPart]; + + Part.NDF() = static_cast(GetNDF()[iPart]); + Part.Chi2() = fChi2[iPart]; + Part.Q() = fQ[iPart]; +#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= 0.f, pn*sqrt(ptm), qt); + alpha = (plp-pln)/(plp+pln); + + QtAlfa[0] = select(mask, qt, QtAlfa[0]); + QtAlfa[1] = select(mask, alpha, QtAlfa[1]); +} + +void KFParticleSIMD::RotateXY(float32_v angle, float32_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 + float32_v s, c; + KFPMath::sincos(angle, s, c); + + float32_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; + + float32_v mAC[8][8]; + float32_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++ ){ + float32_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 KFParticleSIMD::MultQSQt( const float32_v Q[], const float32_v S[], float32_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 + **/ + + float32_v* mA = new float32_v[kN*kN]; + + for( Int_t i=0, ij=0; i + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +//#define NonhomogeneousField +// #define HomogeneousField + +#ifndef KFPARTICLESIMD_H +#define KFPARTICLESIMD_H + +#include "KFPTrack.h" +#include "KFPTrackVector.h" +#include "KFPEmcCluster.h" +#include "KFPVertex.h" +#include "KFParticleDatabase.h" +#include "KFParticleMath.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: + + void *operator new(size_t size) { return _mm_malloc(size, sizeof(float32_v)); } ///< new operator for allocation of the SIMD-alligned dynamic memory allocation + void *operator new[](size_t size) { return _mm_malloc(size, sizeof(float32_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( float32_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(): fQ(0), fNDF(-3), fChi2(0.f), SumDaughterMass(0.f), fMassHypo(-1.f), fId(-1), fPDG(0), fConstructMethod(0), fDaughterIds() +#ifdef NonhomogeneousField + , fField() +#endif + { + for( int i=0; i<8; i++) fP[i] = 0.f; + for(int i=0;i<36;++i) fC[i]=0.f; + fC[0] = fC[2] = fC[5] = 100.f; + fC[35] = 1.f; + } + + //* Initialisation from "cartesian" coordinates ( X Y Z Px Py Pz ) + //* Parameters, covariance matrix, charge and PID hypothesis should be provided + + void Create( const float32_v Param[], const float32_v Cov[], int32_v Charge, float32_v mass /*int PID*/ ); + + void SetOneEntry(int iEntry, KFParticleSIMD& part, int iEntryPart); + + KFParticleSIMD( const KFPTrack *track, int PID ); + KFParticleSIMD( KFPTrack* Track[], int NTracks, const int *pdg=0 ); + KFParticleSIMD( KFPTrackVector &track, int32_v& index, const int32_v& pdg ); + + void Create(KFPTrack* Track[], int NTracks, const int *pdg=0); + void Create(KFPTrackVector &track, int32_v& index, const int32_v& pdg); + void Load(const KFPTrackVector &track, int index, const int32_v& pdg); + void Load(const KFPTrackVector &track, int index); + void Rotate(); + + KFParticleSIMD(KFPTrack &Track, const int *pdg=0); + KFParticleSIMD(KFPTrackVector &track, int n, const int *pdg=0); + + KFParticleSIMD( KFPEmcCluster &track, int32_v& index, const KFParticleSIMD& vertexGuess ); + KFParticleSIMD( KFPEmcCluster &track, int index, const KFParticleSIMD& vertexGuess ); + void Create( KFPEmcCluster &track, int32_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( const KFParticle &part ); + + //* + //* ACCESSORS + //* + + //* Simple accessors + + float32_v GetX () const { return fP[0]; } ///< Returns the sum of masses of the daughters + float32_v GetY () const { return fP[1]; } ///< Returns the sum of masses of the daughters + float32_v GetZ () const { return fP[2]; } ///< Returns the sum of masses of the daughters + float32_v GetPx () const { return fP[3]; } ///< Returns the sum of masses of the daughters + float32_v GetPy () const { return fP[4]; } ///< Returns the sum of masses of the daughters + float32_v GetPz () const { return fP[5]; } ///< Returns the sum of masses of the daughters + float32_v GetE () const { return fP[6]; } ///< Returns the sum of masses of the daughters + float32_v GetS () const { return fP[7]; } ///< Returns the sum of masses of the daughters + int32_v GetQ () const { return fQ; } ///< Returns the sum of masses of the daughters + float32_v GetChi2 () const { return fChi2; } ///< Returns the sum of masses of the daughters + int32_v GetNDF () const { return fNDF; } ///< Returns the sum of masses of the daughters + + const float32_v& X () const { return fP[0]; } ///< Retruns X coordinate of the particle, fP[0]. + const float32_v& Y () const { return fP[1]; } ///< Retruns Y coordinate of the particle, fP[1]. + const float32_v& Z () const { return fP[2]; } ///< Retruns Z coordinate of the particle, fP[2]. + const float32_v& Px () const { return fP[3]; } ///< Retruns X component of the momentum, fP[3]. + const float32_v& Py () const { return fP[4]; } ///< Retruns Y component of the momentum, fP[4]. + const float32_v& Pz () const { return fP[5]; } ///< Retruns Z component of the momentum, fP[5]. + const float32_v& E () const { return fP[6]; } ///< Returns energy of the particle, fP[6]. + const float32_v& S () const { return fP[7]; } ///< Returns dS=l/p, l - decay length, fP[7], defined if production vertex is set. + const int32_v& Q () const { return fQ; } ///< Returns charge of the particle. + const float32_v& Chi2 () const { return fChi2; } ///< Returns Chi2 of the fit. + const int32_v& NDF () const { return fNDF; } ///< Returns number of decrease of freedom. + + float32_v GetParameter ( int i ) const { return fP[i]; } ///< Returns P[i] parameter. + float32_v GetCovariance( int i ) const { return fC[i]; } ///< Returns C[i] element of the covariance matrix in the lower triangular form. + float32_v GetCovariance( int i, int j ) const { return Cij(i, j); } ///< Returns C[i,j] element of the covariance matrix. + + //* Accessors with calculations, value returned w/o error flag + + float32_v GetP () const; ///< Returns momentum + float32_v GetPt () const; ///< Returns transverse momentum + float32_v GetEta () const; ///< Returns pseudorapidity + float32_v GetPhi () const; ///< Returns the azimuthal angle phi + float32_v GetMomentum () const; ///< Returns momentum + float32_v GetMass () const; ///< Returns mass + float32_v GetDecayLength () const; ///< Returns decay length + float32_v GetDecayLengthXY () const; ///< Returns decay length in XY + float32_v GetLifeTime () const; ///< Returns life time ctau [cm] + float32_v GetR () const; ///< Returns distance to the origin of the coordinate system {0,0,0} + float32_v GetRapidity() const { return float32_v(0.5f)*KFPMath::log((fP[6] + fP[5])/(fP[6] - fP[5])); } ///< Returns rapidity of the particle + + //* Accessors to estimated errors + + float32_v GetErrX () const ; ///< Returns the error of X of current position + float32_v GetErrY () const ; ///< Returns the error of Y of current position + float32_v GetErrZ () const ; ///< Returns the error of Z of current position + float32_v GetErrPx () const ; ///< Returns the error of X-compoment of the particle momentum + float32_v GetErrPy () const ; ///< Returns the error of Y-compoment of the particle momentum + float32_v GetErrPz () const ; ///< Returns the error of Z-compoment of the particle momentum + float32_v GetErrE () const ; ///< Returns the error of energy + float32_v GetErrS () const ; ///< Returns the error of decay length / momentum + float32_v GetErrP () const ; ///< Returns the error of momentum + float32_v GetErrPt () const ; ///< Returns the error of transverse momentum + float32_v GetErrEta () const ; ///< Returns the error of pseudorapidity + float32_v GetErrPhi () const ; ///< Returns the error of the azimuthal angle phi + float32_v GetErrMomentum () const ; ///< Returns the error of momentum + float32_v GetErrMass () const ; ///< Returns the error of mass + float32_v GetErrDecayLength () const ; ///< Returns the error of decay length + float32_v GetErrDecayLengthXY () const ; ///< Returns the error of decay length in XY + float32_v GetErrLifeTime () const ; ///< Returns the error of life time + float32_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) + + mask32_v GetP ( float32_v &P, float32_v &SigmaP ) const ; //* momentum + mask32_v GetPt ( float32_v &Pt, float32_v &SigmaPt ) const ; //* transverse momentum + mask32_v GetEta ( float32_v &Eta, float32_v &SigmaEta ) const ; //* pseudorapidity + mask32_v GetPhi ( float32_v &Phi, float32_v &SigmaPhi ) const ; //* phi + mask32_v GetMomentum ( float32_v &P, float32_v &SigmaP ) const ; //* momentum + mask32_v GetMass ( float32_v &M, float32_v &SigmaM ) const ; //* mass + mask32_v GetDecayLength ( float32_v &L, float32_v &SigmaL ) const ; //* decay length + mask32_v GetDecayLengthXY ( float32_v &L, float32_v &SigmaL ) const ; //* decay length in XY + mask32_v GetLifeTime ( float32_v &T, float32_v &SigmaT ) const ; //* life time + mask32_v GetR ( float32_v &R, float32_v &SigmaR ) const ; //* R + + //* + //* MODIFIERS + //* + + float32_v & X () { return fP[0]; } ///< Modifier of X coordinate of the particle, fP[0]. + float32_v & Y () { return fP[1]; } ///< Modifier of Y coordinate of the particle, fP[1]. + float32_v & Z () { return fP[2]; } ///< Modifier of Z coordinate of the particle, fP[2]. + float32_v & Px () { return fP[3]; } ///< Modifier of X component of the momentum, fP[3]. + float32_v & Py () { return fP[4]; } ///< Modifier of Y component of the momentum, fP[4]. + float32_v & Pz () { return fP[5]; } ///< Modifier of Z component of the momentum, fP[5]. + float32_v & E () { return fP[6]; } ///< Modifier of energy of the particle, fP[6]. + float32_v & S () { return fP[7]; } ///< Modifier of dS=l/p, l - decay length, fP[7], defined if production vertex is set. + int32_v & Q () { return fQ; } ///< Modifier of charge of the particle. + float32_v & Chi2 () { return fChi2; } ///< Modifier of Chi2 of the fit. + int32_v & NDF () { return fNDF; } ///< Modifier of number of decrease of freedom. + + float32_v & Parameter ( int i ) { return fP[i]; } ///< Modifier of P[i] parameter. + float32_v & Covariance( int i ) { return fC[i]; } ///< Modifier of C[i] element of the covariance matrix in the lower triangular form. + float32_v & Covariance( int i, int j ) { return fC[IJ(i,j)]; } ///< Modifier of C[i,j] element of the covariance matrix. + + const float32_v * Parameters() const { return fP; } ///< Returns pointer to the parameters fP + const float32_v * CovarianceMatrix() const { return fC; } ///< Returns pointer to the covariance matrix fC + + void SetConstructMethod(int m) {fConstructMethod = m;} ///< Defines the construction method for the current particle (see description of fConstructMethod). + void SetMassHypo(float32_v m) { fMassHypo = m;} ///< Sets the mass hypothesis to the particle, is used when fConstructMethod = 2. + const float32_v& GetMassHypo() const { return fMassHypo; } ///< Returns the mass hypothesis. + const float32_v& GetSumDaughterMass() const {return SumDaughterMass;} ///< Returns the sum of masses of the daughters. + + int32_v Id() const { return fId; } ///< Returns Id of the particle. + int NDaughters() const { return fDaughterIds.size(); } ///< Returns number of daughter particles. + std::vector & DaughterIds() { return fDaughterIds; } ///< Returns the vector with the indices of daughter particles. + int32_v GetDaughterId(int iD) const { return fDaughterIds[iD]; } ///< Returns the daughter Id with the index iD. + + void SetId( int32_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( int32_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 ( const int pdg ) { fPDG = pdg; } ///< Sets the PDG hypothesis common for all elements of the SIMD vector. + void SetPDG ( const int32_v pdg ) { fPDG = pdg; } ///< Sets the PDG hypothesis individual for each entry of the SIMD vector. + const int32_v& GetPDG () const { return fPDG; } ///< Returns the PDG hypothesis. + const int32_v& PDG () const { return fPDG; } ///< Returns the PDG hypothesis. + + 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 + //* + + //* Simple way to add daughter ex. D0+= Pion; + + void operator +=( const KFParticleSIMD &Daughter ); + + //* Add daughter track to the particle + void AddDaughter( const KFParticleSIMD &Daughter ); + void SubtractDaughter( const KFParticleSIMD &Daughter ); + void ReconstructMissingMass(const KFParticleSIMD &Daughter, KFParticleSIMD &MotherFiltered, KFParticleSIMD &cDaughterFiltered, float32_v neutralmasshypo ); + + void AddDaughterWithEnergyFit( const KFParticleSIMD &Daughter ); + void AddDaughterWithEnergyFitMC( const KFParticleSIMD &Daughter ); + + //* Subtract a particle from a vertex + void SubtractFromVertex( KFParticleSIMD &Vtx ) const; + void SubtractFromParticle( KFParticleSIMD &Vtx ) const; + + //* Set production vertex + + void SetProductionVertex( const KFParticleSIMD &Vtx ); + + //* Set mass constraint + + void SetNonlinearMassConstraint( float32_v Mass ); + void SetMassConstraint( float32_v Mass, float32_v SigmaMass = float32_v(0.f) ); + + //* 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 float32_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 ); + + //* Transport the particle on dS parameter (SignedPath/Momentum) + + void TransportToDS( float32_v dS, const float32_v* dsdr ); + void TransportToDSLine( float32_v dS, const float32_v* dsdr ); + //* Particular extrapolators one can use + void TransportBz( float32_v Bz, float32_v dS, const float32_v* dsdr, float32_v P[], float32_v C[], float32_v* dsdr1=0, float32_v* F=0, float32_v* F1=0, const bool fullC=true ) const; + void TransportBz( float32_v Bz, float32_v dS, float32_v P[] ) const; + void TransportCBM( float32_v dS, const float32_v* dsdr, float32_v P[], float32_v C[], float32_v* dsdr1=0, float32_v* F=0, float32_v* F1=0 ) const; + void TransportCBM( float32_v dS, float32_v P[] ) const; + + void TransportLine( float32_v S, const float32_v* dsdr, float32_v P[], float32_v C[], float32_v* dsdr1=0, float32_v* F=0, float32_v* F1=0 ) const ; + void TransportLine( float32_v S, float32_v P[] ) const ; + + //* Get dS to a certain space point + + float32_v GetDStoPoint( const float32_v xyz[3], float32_v dsdr[6] ) const ; + float32_v GetDStoPointLine( const float32_v xyz[3], float32_v dsdr[6] ) const; + float32_v GetDStoPointBz( float32_v Bz, const float32_v xyz[3], float32_v dsdr[6], const float32_v* param = 0 ) const; + float32_v GetDStoPointBy( float32_v By, const float32_v xyz[3], float32_v dsdr[6] ) const; + float32_v GetDStoPointCBM( const float32_v xyz[3], float32_v dsdr[6] ) const; + + float32_v GetDStoPointXYBz( float32_v B, const float32_v xy[2] ) const; + float32_v GetDStoPointZBz( const float32_v z0 ) const; + void GetDStoCylinderBz( const float32_v B, const float32_v R, float32_v dS[2] ) const; + +#ifdef HomogeneousField + float32_v GetDStoPointXY( const float32_v xyz[2] ) const { + return GetDStoPointXYBz( GetFieldAlice(), xyz ); + } + //* Get dS to a certain space point + void GetDStoCylinder( const float32_v R, float32_v dS[2] ) const { + GetDStoCylinderBz( GetFieldAlice(), R, dS ); + } +#endif + + //* Get dS to other particle p (dSp for particle p also returned) + + void GetDStoParticle( const KFParticleSIMD &p, float32_v dS[2], float32_v dsdr[4][6] ) const ; + void GetDStoParticleFast( const KFParticleSIMD &p, float32_v dS[2] ) const ; + void GetDStoParticleLine( const KFParticleSIMD &p, float32_v dS[2], float32_v dsdr[4][6] ) const ; + void GetDStoParticleLine( const KFParticleSIMD &p, float32_v dS[2] ) const ; + void GetDStoParticleBz( float32_v Bz, const KFParticleSIMD &p, float32_v dS[2], float32_v dsdr[4][6], const float32_v* param1 =0, const float32_v* param2 =0 ) const ; + void GetDStoParticleBz( float32_v Bz, const KFParticleSIMD &p, float32_v dS[2], const float32_v* param1 =0, const float32_v* param2 =0 ) const ; + void GetDStoParticleBy( float32_v B, const KFParticleSIMD &p, float32_v dS[2], float32_v dsdr[4][6] ) const ; + void GetDStoParticleBy( float32_v B, const KFParticleSIMD &p, float32_v dS[2] ) const ; + void GetDStoParticleB( float32_v B[3], const KFParticleSIMD &p, float32_v dS[2], float32_v dsdr[4][6] ) const; + void GetDStoParticleB( float32_v B[3], const KFParticleSIMD &p, float32_v dS[2] ) const; + void GetDStoParticleCBM( const KFParticleSIMD &p, float32_v dS[2], float32_v dsdr[4][6] ) const ; + void GetDStoParticleCBM( const KFParticleSIMD &p, float32_v dS[2] ) const ; + + void GetDistanceToVertexLine( const KFParticleSIMD &Vertex, float32_v &l, float32_v &dl, mask32_v *isParticleFromVertex = 0 ) const; + + //* + //* OTHER UTILITIES + //* + + //* Calculate distance from another object [cm] + + float32_v GetDistanceFromVertex( const float32_v vtx[] ) const; + float32_v GetDistanceFromVertex( const KFParticleSIMD &Vtx ) const; + float32_v GetDistanceFromParticle( const KFParticleSIMD &p ) const; + + //* Calculate CAMath::Sqrt(Chi2/ndf) deviation from vertex + //* v = [xyz], Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix + + float32_v GetDeviationFromVertex( const float32_v v[], + const float32_v Cv[]=0 ) const; + float32_v GetDeviationFromVertex( const KFParticleSIMD &Vtx ) const; + float32_v GetDeviationFromParticle( const KFParticleSIMD &p ) const; + + //* Calculate distance from another object [cm] in XY-plane + + mask32_v GetDistanceFromVertexXY( const float32_v vtx[], float32_v &val, float32_v &err ) const ; + mask32_v GetDistanceFromVertexXY( const float32_v vtx[], const float32_v Cv[], float32_v &val, float32_v &err ) const ; + mask32_v GetDistanceFromVertexXY( const KFParticleSIMD &Vtx, float32_v &val, float32_v &err ) const ; +#ifdef HomogeneousField + mask32_v GetDistanceFromVertexXY( const KFPVertex &Vtx, float32_v &val, float32_v &err ) const ; +#endif + + float32_v GetDistanceFromVertexXY( const float32_v vtx[] ) const ; + float32_v GetDistanceFromVertexXY( const KFParticleSIMD &Vtx ) const ; +#ifdef HomogeneousField + float32_v GetDistanceFromVertexXY( const KFPVertex &Vtx ) const ; +#endif + float32_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 ) + + float32_v GetDeviationFromVertexXY( const float32_v v[], const float32_v Cv[]=0 ) const ; + float32_v GetDeviationFromVertexXY( const KFParticleSIMD &Vtx ) const ; +#ifdef HomogeneousField + float32_v GetDeviationFromVertexXY( const KFPVertex &Vtx ) const ; +#endif + float32_v GetDeviationFromParticleXY( const KFParticleSIMD &p ) const ; + + //* Calculate opennig angle between two particles + + float32_v GetAngle ( const KFParticleSIMD &p ) const ; + float32_v GetAngleXY( const KFParticleSIMD &p ) const ; + float32_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 + float32_v GetPseudoProperDecayTime( const KFParticleSIMD &primVertex, const float32_v& mass, float32_v* timeErr2 = 0 ) const; + + void GetFieldValue( const float32_v xyz[], float32_v B[] ) const ; + + void Transport( float32_v dS, const float32_v* dsdr, float32_v P[], float32_v C[], float32_v* dsdr1=0, float32_v* F=0, float32_v* F1=0, const bool fullC=true ) const ; + void TransportFast( float32_v dS, float32_v P[] ) const ; + + static void GetArmenterosPodolanski(KFParticleSIMD& positive, KFParticleSIMD& negative, float32_v QtAlfa[2] ); + void RotateXY(float32_v angle, float32_v Vtx[3]); + static void MultQSQt( const float32_v Q[], const float32_v S[], float32_v SOut[], const int kN ); + + private: + void GetMeasurement( const KFParticleSIMD& daughter, float32_v m[], float32_v V[], float32_v D[3][3] ) ; + //* Mass constraint function. is needed for the nonlinear mass constraint and a fit with mass constraint + void SetMassConstraint( float32_v *mP, float32_v *mC, float32_v mJ[7][7], float32_v mass, mask32_v mask ); + + static void InvertCholetsky3(float32_v a[6]); + + //* + //* INTERNAL STUFF + //* + + /** Converts a pair of indices {i,j} of the covariance matrix to one index corresponding to the triangular form. */ + static int IJ( int i, int 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. */ + float32_v Cij( int i, int j ) const { return fC[IJ(i,j)]; } + + float32_v fP[8]; ///< Particle parameters { X, Y, Z, Px, Py, Pz, E, S[=DecayLength/P]}. + float32_v fC[36]; ///< Low-triangle covariance matrix of fP. + int32_v fQ; ///< The charge of the particle in the units of the elementary charge. + int32_v fNDF; ///< Number of degrees of freedom. + float32_v fChi2; ///< Chi^2. + float32_v SumDaughterMass; ///< Sum of the daughter particles masses. Needed to set the constraint on the minimum mass during particle construction. + float32_v fMassHypo; ///< The mass hypothesis, used for the constraints during particle construction. + int32_v fId; ///< Id of the particle. + int32_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 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 fDaughterIds; // id of particles it created from. if size == 1 then this is id of track. + + //* Method to access ALICE field +#ifdef HomogeneousField + static float32_v GetFieldAlice(); +#endif + + private: +#ifdef HomogeneousField + static float32_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 +} __attribute__((aligned(sizeof(float32_v)))); + +inline void KFParticleSIMD::InvertCholetsky3(float32_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 + **/ + + const float32_v d0 = 1.f/a[0]; + const float32_v u01 = a[1]*d0; + const float32_v u02 = a[3]*d0; + + const float32_v d1 = 1.f/(a[2] - u01*a[1]); + const float32_v u12_d = a[4] - u01*a[3]; + const float32_v u12 = d1*u12_d; + const float32_v d2 = 1.f/(a[5] - u02*a[3] - u12*u12_d); + + //find V = -U^-1 + const float32_v v02 = u02 - u01*u12; + + //find A^-1 = U^-1 D^-1 Ut^-1 + a[5] = d2; + a[4] = -d2*u12; + a[3] = -d2*v02; + const float32_v d1u01 = -d1*u01; + a[2] = d1 - a[4]*u12; + a[1] = d1u01 - a[3]*u12; + a[0] = d0 - d1u01*u01 - a[3]*v02; +} + +//--------------------------------------------------------------------- +// +// Inline implementation of the KFParticleSIMD methods +// +//--------------------------------------------------------------------- + +#ifdef HomogeneousField +inline void KFParticleSIMD::SetField( float32_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 float32_v KFParticleSIMD::GetP () const +{ + float32_v par, err; + GetMomentum( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetPt () const +{ + float32_v par, err; + GetPt( par, err ) ; + return par; +} + +inline float32_v KFParticleSIMD::GetEta () const +{ + float32_v par, err; + GetEta( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetPhi () const +{ + float32_v par, err; + KFParticleSIMD::GetPhi( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetMomentum () const +{ + float32_v par, err; + GetMomentum( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetMass () const +{ + float32_v par, err; + GetMass( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetDecayLength () const +{ + float32_v par, err; + GetDecayLength( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetDecayLengthXY () const +{ + float32_v par, err; + KFParticleSIMD::GetDecayLengthXY( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetLifeTime () const +{ + float32_v par, err; + KFParticleSIMD::GetLifeTime( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetR () const +{ + float32_v par, err; + KFParticleSIMD::GetR( par, err ); + return par; +} + +inline float32_v KFParticleSIMD::GetErrX () const +{ + return sqrt(abs( GetCovariance(0,0) )); +} + +inline float32_v KFParticleSIMD::GetErrY () const +{ + return sqrt(abs( GetCovariance(1,1) )); +} + +inline float32_v KFParticleSIMD::GetErrZ () const +{ + return sqrt(abs( GetCovariance(2,2) )); +} + +inline float32_v KFParticleSIMD::GetErrPx () const +{ + return sqrt(abs( GetCovariance(3,3) )); +} + +inline float32_v KFParticleSIMD::GetErrPy () const +{ + return sqrt(abs( GetCovariance(4,4) )); +} + +inline float32_v KFParticleSIMD::GetErrPz () const +{ + return sqrt(abs( GetCovariance(5,5) )); +} + +inline float32_v KFParticleSIMD::GetErrE () const +{ + return sqrt(abs( GetCovariance(6,6) )); +} + +inline float32_v KFParticleSIMD::GetErrS () const +{ + return sqrt(abs( GetCovariance(7,7) )); +} + +inline float32_v KFParticleSIMD::GetErrP () const +{ + float32_v par, err; + mask32_v mask = GetMomentum( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrPt () const +{ + float32_v par, err; + mask32_v mask = GetPt( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrEta () const +{ + float32_v par, err; + mask32_v mask = GetEta( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrPhi () const +{ + float32_v par, err; + mask32_v mask = GetPhi( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrMomentum () const +{ + float32_v par, err; + mask32_v mask = GetMomentum( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrMass () const +{ + float32_v par, err; + mask32_v mask = KFParticleSIMD::GetMass( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrDecayLength () const +{ + float32_v par, err; + mask32_v mask = KFParticleSIMD::GetDecayLength( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrDecayLengthXY () const +{ + float32_v par, err; + mask32_v mask = KFParticleSIMD::GetDecayLengthXY( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrLifeTime () const +{ + float32_v par, err; + mask32_v mask = KFParticleSIMD::GetLifeTime( par, err ); + return select(mask, 1.e10f, err); +} + +inline float32_v KFParticleSIMD::GetErrR () const +{ + float32_v par, err; + mask32_v mask = KFParticleSIMD::GetR( par, err ); + return select(mask, 1.e10f, err); +} + +inline mask32_v KFParticleSIMD::GetP( float32_v &P, float32_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 GetMomentum( P, SigmaP ); +} + +inline void KFParticleSIMD::TransportToPoint( const float32_v xyz[] ) +{ + /** Transports particle to the distance of closest approach to the point xyz. + ** \param[in] xyz[3] - point, where particle should be transported + **/ + + float32_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + const float32_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. + **/ + float32_v dsdr[4][6]; + float32_v dS[2]; + GetDStoParticle( p, dS, dsdr ); + TransportToDS( dS[0], dsdr[0] ); +} + +inline float32_v KFParticleSIMD::GetDStoPoint( const float32_v xyz[3], float32_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 GetDStoPointBz() is called, + ** if "NonhomogeneousField" is defined - 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 GetDStoPointBz( GetFieldAlice(), xyz, dsdr ); +#endif +#ifdef NonhomogeneousField + return GetDStoPointCBM( xyz, dsdr ); +#endif +} + +#ifdef HomogeneousField +inline float32_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 float32_v * /*xyz*/, float32_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 float32_v xyz[], float32_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(fField).Get(xyz[2]); + B[0] = mB.x; + B[1] = mB.y; + B[2] = mB.z; +} +#endif + +inline void KFParticleSIMD::GetDStoParticle( const KFParticleSIMD &p, float32_v dS[2], float32_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 GetDStoParticleBz() is called, + ** if "NonhomogeneousField" is defined - 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 + GetDStoParticleBz( GetFieldAlice(), p, dS, dsdr ) ; +#endif +#ifdef NonhomogeneousField + GetDStoParticleCBM( p, dS, dsdr ) ; +#endif +} + +inline void KFParticleSIMD::GetDStoParticleFast( const KFParticleSIMD &p, float32_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 GetDStoParticleBz() is called, + ** if "NonhomogeneousField" is defined - 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 + GetDStoParticleBz( GetFieldAlice(), p, dS ) ; +#endif +#ifdef NonhomogeneousField + GetDStoParticleCBM( p, dS ) ; +#endif +} + +inline void KFParticleSIMD::Transport( float32_v dS, const float32_v* dsdr, float32_v P[], float32_v C[], float32_v* dsdr1, float32_v* F, float32_v* F1, const bool fullC ) 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 TransportBz() + ** is called, if "NonhomogeneousField" - 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 + TransportBz( GetFieldAlice(), dS, dsdr, P, C, dsdr1, F, F1, fullC ); +#endif +#ifdef NonhomogeneousField + TransportCBM( dS, dsdr, P, C, dsdr1, F, F1 ); +#endif +} + +inline void KFParticleSIMD::TransportFast( float32_v dS, float32_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 TransportBz() + ** is called, if "NonhomogeneousField" - 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 + TransportBz( GetFieldAlice(), dS, P ); +#endif +#ifdef NonhomogeneousField + TransportCBM( dS, P ); +#endif +} + +inline void KFParticleSIMD::Load(const KFPTrackVector &track, int index, const int32_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 + **/ + + fP[0] = reinterpret_cast(track.Parameter(0)[index]); + fP[1] = reinterpret_cast(track.Parameter(1)[index]); + fP[2] = reinterpret_cast(track.Parameter(2)[index]); + fP[3] = reinterpret_cast(track.Parameter(3)[index]); + fP[4] = reinterpret_cast(track.Parameter(4)[index]); + fP[5] = reinterpret_cast(track.Parameter(5)[index]); + + fC[ 0] = reinterpret_cast(track.Covariance( 0)[index]); + fC[ 1] = reinterpret_cast(track.Covariance( 1)[index]); + fC[ 2] = reinterpret_cast(track.Covariance( 2)[index]); + fC[ 3] = reinterpret_cast(track.Covariance( 3)[index]); + fC[ 4] = reinterpret_cast(track.Covariance( 4)[index]); + fC[ 5] = reinterpret_cast(track.Covariance( 5)[index]); + fC[ 6] = reinterpret_cast(track.Covariance( 6)[index]); + fC[ 7] = reinterpret_cast(track.Covariance( 7)[index]); + fC[ 8] = reinterpret_cast(track.Covariance( 8)[index]); + fC[ 9] = reinterpret_cast(track.Covariance( 9)[index]); + fC[10] = reinterpret_cast(track.Covariance(10)[index]); + fC[11] = reinterpret_cast(track.Covariance(11)[index]); + fC[12] = reinterpret_cast(track.Covariance(12)[index]); + fC[13] = reinterpret_cast(track.Covariance(13)[index]); + fC[14] = reinterpret_cast(track.Covariance(14)[index]); + fC[15] = reinterpret_cast(track.Covariance(15)[index]); + fC[16] = reinterpret_cast(track.Covariance(16)[index]); + fC[17] = reinterpret_cast(track.Covariance(17)[index]); + fC[18] = reinterpret_cast(track.Covariance(18)[index]); + fC[19] = reinterpret_cast(track.Covariance(19)[index]); + fC[20] = reinterpret_cast(track.Covariance(20)[index]); + +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField.fField[i] = reinterpret_cast(track.FieldCoefficient(i)[index]); +#endif + + // fPDG.gather(&(track.PDG()[0]), index); + fQ = reinterpret_cast(track.Q()[index]); + + float32_v mass = KFParticleDatabase::Instance()->GetMass(pdg); + + float32_v energy = sqrt( mass*mass + fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]); + fP[6] = energy; + fP[7] = 0; + fNDF = 0; + fChi2 = 0; + + float32_v energyInv = 1.f/energy; + float32_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 i=28; i<36; i++ ) fC[i] = 0.f; + fC[35] = 1.f; + + SumDaughterMass = mass; + fMassHypo = mass; +} + +inline void KFParticleSIMD::Load(const KFPTrackVector &track, int index) +{ + /** 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 + **/ + + fP[0] = reinterpret_cast(track.Parameter(0)[index]); + fP[1] = reinterpret_cast(track.Parameter(1)[index]); + fP[2] = reinterpret_cast(track.Parameter(2)[index]); + fP[3] = reinterpret_cast(track.Parameter(3)[index]); + fP[4] = reinterpret_cast(track.Parameter(4)[index]); + fP[5] = reinterpret_cast(track.Parameter(5)[index]); + + fC[ 0] = reinterpret_cast(track.Covariance( 0)[index]); + fC[ 1] = reinterpret_cast(track.Covariance( 1)[index]); + fC[ 2] = reinterpret_cast(track.Covariance( 2)[index]); + fC[ 3] = reinterpret_cast(track.Covariance( 3)[index]); + fC[ 4] = reinterpret_cast(track.Covariance( 4)[index]); + fC[ 5] = reinterpret_cast(track.Covariance( 5)[index]); + fC[ 6] = reinterpret_cast(track.Covariance( 6)[index]); + fC[ 7] = reinterpret_cast(track.Covariance( 7)[index]); + fC[ 8] = reinterpret_cast(track.Covariance( 8)[index]); + fC[ 9] = reinterpret_cast(track.Covariance( 9)[index]); + fC[10] = reinterpret_cast(track.Covariance(10)[index]); + fC[11] = reinterpret_cast(track.Covariance(11)[index]); + fC[12] = reinterpret_cast(track.Covariance(12)[index]); + fC[13] = reinterpret_cast(track.Covariance(13)[index]); + fC[14] = reinterpret_cast(track.Covariance(14)[index]); + fC[15] = reinterpret_cast(track.Covariance(15)[index]); + fC[16] = reinterpret_cast(track.Covariance(16)[index]); + fC[17] = reinterpret_cast(track.Covariance(17)[index]); + fC[18] = reinterpret_cast(track.Covariance(18)[index]); + fC[19] = reinterpret_cast(track.Covariance(19)[index]); + fC[20] = reinterpret_cast(track.Covariance(20)[index]); + +#ifdef NonhomogeneousField + for(int i=0; i<10; i++) + fField.fField[i] = reinterpret_cast(track.FieldCoefficient(i)[index]); +#endif + + fQ = reinterpret_cast(track.Q()[index]); +} + +#endif diff --git a/StRoot/KFParticle/KFParticleTopoReconstructor.cxx b/StRoot/KFParticle/KFParticleTopoReconstructor.cxx new file mode 100644 index 00000000000..db604dba47b --- /dev/null +++ b/StRoot/KFParticle/KFParticleTopoReconstructor.cxx @@ -0,0 +1,1208 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "KFParticleTopoReconstructor.h" + +#ifdef KFPWITHTRACKER +#include "AliHLTTPCCAGBTracker.h" +#endif + +#include "KFParticleSIMD.h" +#include "KFParticleDatabase.h" + +#include +#include +#include +#include +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* 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/SimdLen+1)*SimdLen ); + fTracks[5].Resize( int(nTracks/SimdLen+1)*SimdLen ); + fParticles.clear(); + int iOTr = 0; // index in out array + + float32_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( !isFinite(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 &= isFinite( 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 == SimdLen) + { + 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 &particles, vector* pdg, vector* nPixelHits, bool initPVTracks) +{ +#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; iTrat(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); + } + + if(initPVTracks) + 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& 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(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 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& tracks = GetPVTrackIndexArray(iPV); + for(unsigned int iTr=0; iTr 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, + ** He6, Li6, Li7, Be7. + **/ +#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 sortedTracks(Size); + kfvector_int 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 newIndex(Size); + int iCurrentTrack=0; + for(int iTC=0; iTC<4; iTC++) + { + for(int iTrackIndex=0; iTrackIndexGetPVTrackIndexArray(iPV)[iTrack] = newIndex[GetPVTrackIndexArray(iPV)[iTrack]]; + } + } + + if(fTracks[6].Size() > 0) + { + for(int iTrack=0; iTrack 0) + { + for(int iTrack=0; iTrack(fTracks[iTV].PDG()[iTr]); + const int32_v& pvIndex = reinterpret_cast(fTracks[iTV].PVIndex()[iTr]); + + tmpPart.Load(fTracks[iTV], iTr, pdg); + + for(unsigned int iV=0; iV < (unsigned int)SimdLen; iV++) + { + if(iV+iTr >= NTr) continue; + + int iPV = pvIndex[iV]; + pointArray[0][iV] = fPV[iPV].X()[0]; + pointArray[1][iV] = fPV[iPV].Y()[0]; + pointArray[2][iV] = fPV[iPV].Z()[0]; + } + point[0].load(pointArray[0]); + point[1].load(pointArray[1]); + point[2].load(pointArray[2]); + + 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 += SimdLen) + { + int32_v trackIndex = int32_v::indicesSequence(iTr); + const int32_v& pdg = reinterpret_cast(fTracks[iTV].PDG()[iTr]); + tmpPart.Create(fTracks[iTV],trackIndex, pdg); + + float32_v& chi2 = reinterpret_cast(fChiToPrimVtx[iTV][iTr]); + chi2 = select(trackIndexchiVec) && (trackIndex= 3003 && abs(PDG) <= 3040); //hypernuclei + use &= PDG != 3008; + 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; + std::vector isUsed(fParticles.size()); + std::vector deleteCandidate(fParticles.size()); + std::vector bestMother(fParticles.size()); + + for(unsigned int iParticle=0; iParticle daughterIds(fParticles[iParticle].NDaughters()); +// for(int iDaughter=0; iDaughter daughterIdsDPlus(fParticles[jParticle].NDaughters()); +// for(int iDaughter=0; iDaughterGetDPlusMass()) < 3*KFParticleDatabase::Instance()->GetDPlusMassSigma()) +// { +// deleteCandidate[iParticle] = true; +// break; +// } +// } +// } +// } +// } + + + //clean K0 and Lambda + for(unsigned int iParticle=0; iParticleGetMotherMass(fParticles[iParticle].GetPDG(), massPDG, massPDGSigma); + + float dm1 = fabs(mass - massPDG)/massPDGSigma; +// if(dm1 > 3.f) continue; + + for(unsigned int jParticle=iParticle+1; jParticleGetMotherMass(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; iParticleGetMotherMass(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; iPIGetMotherMass(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; iDaughterGetMotherMass(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 -1) + { + deleteCandidate[iParticle] = true; + break; + } + } +#endif + for(unsigned int iParticle=0; iParticle 7e6) && (abs(particle.GetPDG()) < 1e7)) return 0; // missing mass + + vector daughters; + GetListOfDaughterTracks(particle, daughters); + std::sort(daughters.begin(), daughters.end()); + bool sameDaughter=0; + for(unsigned int iDaughter=1; iDaughter& 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; iDaughterFindParticles(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(buffer); + int dataSize = NInputSets + 1 + 1; //sizes of the track vectors and pv vector, and field + for(int iSet=0; iSet(data[NInputSets+1]); + field = Bz; + + int offset = NInputSets+2; + + for(int iSet=0; iSet(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(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 + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFParticleTopoReconstructor_H +#define KFParticleTopoReconstructor_H + +#include "KFParticlePVReconstructor.h" +#include "KFParticleFinder.h" + +#include +#include + +#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 +#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* 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 &particles, std::vector* pdg=0, std::vector* nPixelHits=0, bool initPVTracks = false); + /** 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& 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& GetPVTrackIndexArray(int iPV=0) const { return fKFParticlePVReconstructor->GetPVTrackIndexArray(iPV); } + + std::vector 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 && iParticleCleanPV(); + } + void AddPV(const KFVertex &pv, const std::vector &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; iPVAddCandidate(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& 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 fParticles; ///< Vector of the reconstructed candidates of short-lived particles. + std::vector > 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(float32_v)))); // class KFParticleTopoReconstructor + + + +#endif // KFParticleTopoReconstructor_H + diff --git a/StRoot/KFParticle/KFVertex.cxx b/StRoot/KFParticle/KFVertex.cxx new file mode 100644 index 00000000000..93ed54f1273 --- /dev/null +++ b/StRoot/KFParticle/KFVertex.cxx @@ -0,0 +1,147 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#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; +} + +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; i2 ) +// { +// float worstChi = 0.; +// Int_t worstDaughter = 0; +// for( Int_t it=0; it= 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 ChiCut*ChiCut*GetNDF() ) { + for( int i=0; i + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#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/StRoot/KFParticlePerformance/.includes_for_export.flg b/StRoot/KFParticlePerformance/.includes_for_export.flg new file mode 100644 index 00000000000..e69de29bb2d diff --git a/StRoot/KFParticlePerformance/KFMCCounter.h b/StRoot/KFParticlePerformance/KFMCCounter.h new file mode 100644 index 00000000000..b72332a5094 --- /dev/null +++ b/StRoot/KFParticlePerformance/KFMCCounter.h @@ -0,0 +1,129 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFMCCounter_H +#define KFMCCounter_H + +#include +#include +#include + +/** @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 +struct KFMCCounter +{ + int NCounters; ///< Number of counters in the current object. + + std::vector 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 + KFMCCounter operator/(KFMCCounter& a){ + KFMCCounter 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 + KFMCCounter operator/(double a){ + KFMCCounter 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 &a ){ + strm << a.NCounters << " " << a.counters.size() << " "; + for(unsigned int iV=0; iV &a ){ + strm << a.NCounters << " " << a.counters.size() << " "; + for(unsigned int iV=0; iV>(std::fstream &strm, KFMCCounter &a ){ + int tmp; + strm >> tmp; + a.NCounters = tmp; + strm >> tmp; + a.counters.resize(tmp,T(0)); + for(int iV=0; iV> 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/StRoot/KFParticlePerformance/KFMCParticle.cxx b/StRoot/KFParticlePerformance/KFMCParticle.cxx new file mode 100644 index 00000000000..eec5d1c6126 --- /dev/null +++ b/StRoot/KFParticlePerformance/KFMCParticle.cxx @@ -0,0 +1,46 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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/StRoot/KFParticlePerformance/KFMCParticle.h b/StRoot/KFParticlePerformance/KFMCParticle.h new file mode 100644 index 00000000000..18b14feb06c --- /dev/null +++ b/StRoot/KFParticlePerformance/KFMCParticle.h @@ -0,0 +1,112 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _KFMCParticle_h_ +#define _KFMCParticle_h_ + +#include + +#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(); + virtual ~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& 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 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/StRoot/KFParticlePerformance/KFMCTrack.h b/StRoot/KFParticlePerformance/KFMCTrack.h new file mode 100644 index 00000000000..293fe68db8f --- /dev/null +++ b/StRoot/KFParticlePerformance/KFMCTrack.h @@ -0,0 +1,92 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFMCTRACK_H +#define KFMCTRACK_H + +#include + +/** @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/StRoot/KFParticlePerformance/KFMCVertex.cxx b/StRoot/KFParticlePerformance/KFMCVertex.cxx new file mode 100644 index 00000000000..b74d607e27d --- /dev/null +++ b/StRoot/KFParticlePerformance/KFMCVertex.cxx @@ -0,0 +1,48 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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/StRoot/KFParticlePerformance/KFMCVertex.h b/StRoot/KFParticlePerformance/KFMCVertex.h new file mode 100644 index 00000000000..e17d920fe8e --- /dev/null +++ b/StRoot/KFParticlePerformance/KFMCVertex.h @@ -0,0 +1,105 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFMCVERTEX_H +#define KFMCVERTEX_H + +#include +#include + +/** @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 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/StRoot/KFParticlePerformance/KFPHistogram/KFPHistogram.h b/StRoot/KFParticlePerformance/KFPHistogram/KFPHistogram.h new file mode 100644 index 00000000000..d36ea25d3ba --- /dev/null +++ b/StRoot/KFParticlePerformance/KFPHistogram/KFPHistogram.h @@ -0,0 +1,174 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef KFPHISTOGRAM +#define KFPHISTOGRAM + +#include "KFPHistogramSet.h" +#include "KFPartEfficiencies.h" +#include "KFParticleTopoReconstructor.h" +#include +#include +#include +#include +/** @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::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> iSet; + const int& nHistograms = fKFPHistogramSet[iParticle].GetNHisto1D(); + for(int iHistogram = 0; iHistogram> 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> 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 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/StRoot/KFParticlePerformance/KFPHistogram/KFPHistogram1D.h b/StRoot/KFParticlePerformance/KFPHistogram/KFPHistogram1D.h new file mode 100644 index 00000000000..37f204ea685 --- /dev/null +++ b/StRoot/KFParticlePerformance/KFPHistogram/KFPHistogram1D.h @@ -0,0 +1,119 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFPHISTOGRAM1D +#define KFPHISTOGRAM1D + +#include +#include +#include +#include +#include + +/** @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 + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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 + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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 + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFPVEfficiencies_H +#define KFPVEfficiencies_H + +#ifndef HLTCA_STANDALONE +#include "TNamed.h" +#endif + +#include +#include +#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 ")); + } + + ~KFPVEfficiencies(){} + + 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 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 names; ///< Names of the counters. The same for all counters objects. + std::map indices; ///< Map between the counter index and its short name. + + KFMCCounter ratio_reco; ///< Efficiency. + + KFMCCounter mc; ///< Counters of the Monte Carlo vertices. + KFMCCounter reco; ///< Counters of the reconstructed vertices. + + KFMCCounter ratio_ghost; ///< Ratio of the ghost candidates to the total number of candidates. + KFMCCounter ratio_bg; ///< Ratio of the physics background candidates to the total number of candidates. + KFMCCounter ratio_clone; ///< Ratio of double reconstructed vertices to the total number of signal candidates. + + KFMCCounter ghost; ///< Counters of the ghost candidates. + KFMCCounter bg; ///< Counters of the physics background candidates. + KFMCCounter clone; ///< Counters of the double reconstructed vertices. +}; + +#endif diff --git a/StRoot/KFParticlePerformance/KFPartEfficiencies.cxx b/StRoot/KFParticlePerformance/KFPartEfficiencies.cxx new file mode 100644 index 00000000000..6546cad7866 --- /dev/null +++ b/StRoot/KFParticlePerformance/KFPartEfficiencies.cxx @@ -0,0 +1,26 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "KFPartEfficiencies.h" + +#ifndef KFParticleStandalone +ClassImp(KFPartEfficiencies) +#endif diff --git a/StRoot/KFParticlePerformance/KFPartEfficiencies.h b/StRoot/KFParticlePerformance/KFPartEfficiencies.h new file mode 100644 index 00000000000..f6643d4b442 --- /dev/null +++ b/StRoot/KFParticlePerformance/KFPartEfficiencies.h @@ -0,0 +1,1956 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFPartEfficiencies_H +#define KFPartEfficiencies_H + +#include +#include +#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 + KFEfficiencyParticleInfo("K+_{3pi}", "K+3pi ", 100321, 0.0f, 1.0f, 0.493677 , 1.238e-8, 1, 0.0030), //44 + KFEfficiencyParticleInfo("K-_{3pi}", "K+3pi ", -100321, 0.0f, 1.0f, 0.493677 , 1.238e-8, -1, 0.0030), //45 + KFEfficiencyParticleInfo("K+_{3piK}", "K+3piK ", 200321, 0.0f, 1.0f, 0.493677 , 1.238e-8, 1, 0.0030), //46 + KFEfficiencyParticleInfo("K-_{3piK}", "K+3piK ", -200321, 0.0f, 1.0f, 0.493677 , 1.238e-8, -1, 0.0030), //47 +//Delta and N resonances + KFEfficiencyParticleInfo("Delta0", "Delta0 ", 2114, 1.0f, 3.0f, 1.232 , 5.63e-24, 0, 0.0030), //48 + KFEfficiencyParticleInfo("Delta0 b", "Delta0 b ", -2114, 1.0f, 3.0f, 1.232 , 5.63e-24, 0, 0.0030), //49 + KFEfficiencyParticleInfo("Delta++", "Delta++ ", 2224, 1.0f, 3.0f, 1.232 , 5.63e-24, 2, 0.0030), //50 + KFEfficiencyParticleInfo("Delta-- b", "Delta-- b ", -2224, 1.0f, 3.0f, 1.232 , 5.63e-24, -2, 0.0030), //51 +//Nuclear resonances + KFEfficiencyParticleInfo("dpi-", "dpi- ", 100001, 2.0f, 4.0f, 2.170 , 5.63e-24, 0, 0.0030), //52 + KFEfficiencyParticleInfo("dpi+", "dpi+ ", 100002, 2.0f, 4.0f, 2.170 , 5.63e-24, 0, 0.0030), //53 + KFEfficiencyParticleInfo("tpi-", "tpi- ", 100003, 2.8f, 4.8f, 3.108 , 5.63e-24, 0, 0.0030), //54 + KFEfficiencyParticleInfo("tpi+", "tpi+ ", 100004, 2.8f, 4.8f, 3.108 , 5.63e-24, 0, 0.0030), //55 + KFEfficiencyParticleInfo("He3pi-", "He3pi- ", 100005, 2.8f, 4.8f, 3.108 , 5.63e-24, 0, 0.0030), //56 + KFEfficiencyParticleInfo("He3pi+", "He3pi+ ", 100006, 2.8f, 4.8f, 3.108 , 5.63e-24, 0, 0.0030), //57 + KFEfficiencyParticleInfo("He4pi-", "He4pi- ", 100007, 3.7f, 5.7f, 4.046 , 5.63e-24, 0, 0.0030), //58 + KFEfficiencyParticleInfo("He4pi+", "He4pi+ ", 100008, 3.7f, 5.7f, 4.046 , 5.63e-24, 0, 0.0030), //59 + KFEfficiencyParticleInfo("He6pi-", "He6pi- ", 100009, 5.6f, 7.6f, 5.922 , 5.63e-24, 0, 0.0030), //60 + KFEfficiencyParticleInfo("He6pi+", "He6pi+ ", 100010, 5.6f, 7.6f, 5.922 , 5.63e-24, 0, 0.0030), //61 + KFEfficiencyParticleInfo("Li6pi-", "Li6pi- ", 100011, 5.6f, 7.6f, 5.922 , 5.63e-24, 0, 0.0030), //62 + KFEfficiencyParticleInfo("Li6pi+", "Li6pi+ ", 100012, 5.6f, 7.6f, 5.922 , 5.63e-24, 0, 0.0030), //63 + KFEfficiencyParticleInfo("Li7pi-", "Li7pi- ", 100013, 6.5f, 8.5f, 6.860 , 5.63e-24, 0, 0.0030), //64 + KFEfficiencyParticleInfo("Li7pi+", "Li7pi+ ", 100014, 6.5f, 8.5f, 6.860 , 5.63e-24, 0, 0.0030), //65 + KFEfficiencyParticleInfo("Be7pi-", "Be7pi- ", 100015, 6.5f, 8.5f, 6.860 , 5.63e-24, 0, 0.0030), //66 + KFEfficiencyParticleInfo("Be7pi+", "Be7pi+ ", 100016, 6.5f, 8.5f, 6.860 , 5.63e-24, 0, 0.0030), //67 + KFEfficiencyParticleInfo("dK-", "dK- ", 110001, 2.2f, 4.2f, 2.170 , 5.63e-24, 0, 0.0030), //68 + KFEfficiencyParticleInfo("dK+", "dK+ ", 110002, 2.2f, 4.2f, 2.170 , 5.63e-24, 0, 0.0030), //69 + KFEfficiencyParticleInfo("tK-", "tK- ", 110003, 2.8f, 4.8f, 3.108 , 5.63e-24, 0, 0.0030), //70 + KFEfficiencyParticleInfo("tK+", "tK+ ", 110004, 2.8f, 4.8f, 3.108 , 5.63e-24, 0, 0.0030), //71 + KFEfficiencyParticleInfo("He3K-", "He3K- ", 110005, 2.8f, 4.8f, 3.108 , 5.63e-24, 0, 0.0030), //72 + KFEfficiencyParticleInfo("He3K+", "He3K+ ", 110006, 2.8f, 4.8f, 3.108 , 5.63e-24, 0, 0.0030), //73 + KFEfficiencyParticleInfo("He4K-", "He4K- ", 110007, 3.7f, 5.7f, 4.046 , 5.63e-24, 0, 0.0030), //74 + KFEfficiencyParticleInfo("He4K+", "He4K+ ", 110008, 3.7f, 5.7f, 4.046 , 5.63e-24, 0, 0.0030), //75 + KFEfficiencyParticleInfo("He6K-", "He6K- ", 110009, 5.6f, 7.6f, 5.922 , 5.63e-24, 0, 0.0030), //76 + KFEfficiencyParticleInfo("He6K+", "He6K+ ", 110010, 5.6f, 7.6f, 5.922 , 5.63e-24, 0, 0.0030), //77 + KFEfficiencyParticleInfo("Li6K-", "Li6K- ", 110011, 5.6f, 7.6f, 5.922 , 5.63e-24, 0, 0.0030), //78 + KFEfficiencyParticleInfo("Li6K+", "Li6K+ ", 110012, 5.6f, 7.6f, 5.922 , 5.63e-24, 0, 0.0030), //79 + KFEfficiencyParticleInfo("Li7K-", "Li7K- ", 110013, 6.5f, 8.5f, 6.860 , 5.63e-24, 0, 0.0030), //80 + KFEfficiencyParticleInfo("Li7K+", "Li7K+ ", 110014, 6.5f, 8.5f, 6.860 , 5.63e-24, 0, 0.0030), //81 + KFEfficiencyParticleInfo("Be7K-", "Be7K- ", 110015, 6.5f, 8.5f, 6.860 , 5.63e-24, 0, 0.0030), //82 + KFEfficiencyParticleInfo("Be7K+", "Be7K+ ", 110016, 6.5f, 8.5f, 6.860 , 5.63e-24, 0, 0.0030), //83 + KFEfficiencyParticleInfo("pp", "pp ", 200001, 1.7f, 3.7f, 1.876 , 5.63e-24, 0, 0.0030), //84 + KFEfficiencyParticleInfo("dp", "dp ", 200002, 2.7f, 4.7f, 2.813 , 5.63e-24, 0, 0.0030), //85 + KFEfficiencyParticleInfo("tp", "tp ", 200003, 3.6f, 4.6f, 3.747 , 5.63e-24, 0, 0.0030), //86 + KFEfficiencyParticleInfo("He3p", "He3p ", 200004, 3.6f, 4.6f, 3.747 , 5.63e-24, 0, 0.0030), //87 + KFEfficiencyParticleInfo("He4p", "He4p ", 200005, 4.5f, 6.5f, 4.665 , 5.63e-24, 0, 0.0030), //88 + KFEfficiencyParticleInfo("He6p", "He6p ", 200006, 6.4f, 8.4f, 6.539 , 5.63e-24, 0, 0.0030), //89 + KFEfficiencyParticleInfo("Li6p", "Li6p ", 200007, 6.4f, 8.4f, 6.539 , 5.63e-24, 0, 0.0030), //90 + KFEfficiencyParticleInfo("Li7p", "Li7p ", 200008, 7.3f, 9.3f, 7.472 , 5.63e-24, 0, 0.0030), //91 + KFEfficiencyParticleInfo("Be7p", "Be7p ", 200009, 7.3f, 9.3f, 7.472 , 5.63e-24, 0, 0.0030), //92 +//charmonium + KFEfficiencyParticleInfo("JPsi_ee", "JPsi_ee ", 443, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //93 + KFEfficiencyParticleInfo("JPsi_mumu", "JPsi_mm ", 100443, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //94 + KFEfficiencyParticleInfo("JPsi_pp", "JPsi_pp ", 200443, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //95 + KFEfficiencyParticleInfo("JPsi_LL", "JPsi_LL ", 300443, 2.0f, 5.0f, 3.096916 , 7.1e-21, 0, 0.0030), //96 + KFEfficiencyParticleInfo("JPsi_XiXi", "JPsi_XiXi ", 400443, 2.0f, 5.0f, 3.096916 , 7.1e-21, 0, 0.0030), //97 + KFEfficiencyParticleInfo("Psi_OO", "Psi_OO ", 500443, 3.0f, 6.0f, 3.686109 , 2.1e-22, 0, 0.0030), //98 +//open charm + KFEfficiencyParticleInfo("D0", "D0 ", 421, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //99 + KFEfficiencyParticleInfo("D0b", "D0b ", -421, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //100 + KFEfficiencyParticleInfo("D0_4", "D0_4 ", 429, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0100), //101 + KFEfficiencyParticleInfo("D0b_4", "D0b_4 ", -429, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0100), //102 + KFEfficiencyParticleInfo("D0_pipi", "D0_pipi ", 420, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //103 + KFEfficiencyParticleInfo("D0_2pi2pi", "D0_2pi2pi ", 470, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //104 + KFEfficiencyParticleInfo("D0_K0pipi", "D0_K0pipi ", 425, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0150), //105 + KFEfficiencyParticleInfo("D0_KK", "D0_KK ", 426, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0130), //106 + KFEfficiencyParticleInfo("D0_KKK0", "D0_KKK0 ", 427, 0.6f, 3.6f, 1.86486 , 4.1e-13, 0, 0.0154), //107 + KFEfficiencyParticleInfo("D0_pi0", "D0_#pi0 ", 428, 1.0f, 3.0f, 1.86486 , 4.1e-13, 0, 0.0030), //108 + KFEfficiencyParticleInfo("D+", "D+ ", 411, 1.0f, 3.0f, 1.86962 , 1.04e-13, 1, 0.0114), //109 + KFEfficiencyParticleInfo("D-", "D- ", -411, 1.0f, 3.0f, 1.86962 , 1.04e-13, -1, 0.0114), //110 + KFEfficiencyParticleInfo("D+_K0pi+", "D+_K0pi+ ", 100411, 0.6f, 4.6f, 1.86962 , 1.04e-13, 1, 0.0030), //111 + KFEfficiencyParticleInfo("D-_K0pi-", "D-_K0pi- ", -100411, 0.6f, 4.6f, 1.86962 , 1.04e-13, -1, 0.0030), //112 + KFEfficiencyParticleInfo("D+_K03pi", "D+_K03pi ", 200411, 0.6f, 4.6f, 1.86962 , 1.04e-13, 1, 0.0030), //113 + KFEfficiencyParticleInfo("D-_K03pi", "D-_K03pi ", -200411, 0.6f, 4.6f, 1.86962 , 1.04e-13, -1, 0.0030), //114 + KFEfficiencyParticleInfo("D+_3pi", "D+_3pi ", 300411, 0.6f, 4.6f, 1.86962 , 1.04e-13, 1, 0.0030), //115 + KFEfficiencyParticleInfo("D-_3pi", "D-_3pi ", -300411, 0.6f, 4.6f, 1.86962 , 1.04e-13, -1, 0.0030), //116 + KFEfficiencyParticleInfo("Ds+", "Ds+ ", 431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0110), //117 + KFEfficiencyParticleInfo("Ds-", "Ds- ", -431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0110), //118 + KFEfficiencyParticleInfo("Ds+_K0K+", "Ds+_K0K+ ", 100431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0030), //119 + KFEfficiencyParticleInfo("Ds-_K0K-", "Ds-_K0K- ", -100431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0030), //120 + KFEfficiencyParticleInfo("Ds+_K0K0pi+", "Ds+_K0K0pi+ ", 200431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0030), //121 + KFEfficiencyParticleInfo("Ds-_K0K0pi-", "Ds-_K0K0pi- ", -200431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0030), //122 + KFEfficiencyParticleInfo("Ds+_K0K+pipi", "Ds+_K0K+pipi ", 300431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0030), //123 + KFEfficiencyParticleInfo("Ds-_K0K-pipi", "Ds-_K0K-pipi ", -300431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0030), //124 + KFEfficiencyParticleInfo("Ds+_K+pipi", "Ds+_K+pipi ", 400431, 1.0f, 3.0f, 1.96850 , 5.0e-13, 1, 0.0030), //125 + KFEfficiencyParticleInfo("Ds-_K-pipi", "Ds-_K-pipi ", -400431, 1.0f, 3.0f, 1.96850 , 5.0e-13, -1, 0.0030), //126 + KFEfficiencyParticleInfo("Lc", "Lambdac ", 4122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0110), //127 + KFEfficiencyParticleInfo("Lcb", "Lambdac b ", -4122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0110), //128 + KFEfficiencyParticleInfo("Lc_{pK0}", "Lc {pK0} ", 104122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //129 + KFEfficiencyParticleInfo("Lcb_{pK0}", "Lc b {pK0} ", -104122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //130 + KFEfficiencyParticleInfo("Lc_{pK02pi}", "Lc {pK02pi} ", 204122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //131 + KFEfficiencyParticleInfo("Lcb_{pK02pi}", "Lc b {pK02pi} ", -204122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //132 + KFEfficiencyParticleInfo("Lc_{Lpi}", "Lc {Lpi} ", 304122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //133 + KFEfficiencyParticleInfo("Lcb_{Lpi}", "Lc b {Lpi} ", -304122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //134 + KFEfficiencyParticleInfo("Lc_{L3pi}", "Lc {L3pi} ", 404122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //135 + KFEfficiencyParticleInfo("Lcb_{L3pi}", "Lc b {L3pi} ", -404122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //136 + KFEfficiencyParticleInfo("Lc_{p2pi}", "Lc {p2pi} ", 504122, 1.8f, 3.8f, 2.28646 , 2.0e-13, 1, 0.0030), //137 + KFEfficiencyParticleInfo("Lcb_{p2pi}", "Lc b {p2pi} ", -504122, 1.8f, 3.8f, 2.28646 , 2.0e-13, -1, 0.0030), //138 + KFEfficiencyParticleInfo("Xic0", "Xic0 ", 4132, 2.1f, 4.1f, 2.47087 , 1.0e-13, 0, 0.0030), //139 + KFEfficiencyParticleInfo("Xic0b", "Xic0b ", -4132, 2.1f, 4.1f, 2.47087 , 1.0e-13, 0, 0.0030), //140 + KFEfficiencyParticleInfo("D*0", "D*0 ", 10421, 1.8f, 3.8f, 2.00699 , 3.0e-22, 0, 0.0030), //141 + KFEfficiencyParticleInfo("D*0b", "D*0 b ", -10421, 1.8f, 3.8f, 2.00699 , 3.0e-22, 0, 0.0030), //142 + KFEfficiencyParticleInfo("D*+", "D*+ ", 10411, 1.8f, 3.8f, 2.01029 , 6.86e-21, 1, 0.0030), //143 + KFEfficiencyParticleInfo("D*-", "D*- ", -10411, 1.8f, 3.8f, 2.01029 , 6.86e-21, -1, 0.0030), //144 + KFEfficiencyParticleInfo("D*+_4", "D*+_4 ", 20411, 1.8f, 3.8f, 2.01029 , 6.86e-21, 1, 0.0030), //145 + KFEfficiencyParticleInfo("D*-_4", "D*-_4 ", -20411, 1.8f, 3.8f, 2.01029 , 6.86e-21, -1, 0.0030), //146 + KFEfficiencyParticleInfo("D0*_pi0", "D0*_#pi0 ", 10428, 1.8f, 3.8f, 2.00699 , 6.86e-21, 0, 0.0030), //147 +//B mesons + KFEfficiencyParticleInfo("B_Jpsi_ee", "B_Jpsi_ee ", 500, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //148 + KFEfficiencyParticleInfo("B_Jpsi_mm", "B_Jpsi_mm ", 501, 1.0f, 4.0f, 3.096916 , 7.1e-21, 0, 0.0030), //149 + KFEfficiencyParticleInfo("B+_D0bPi+", "B+ {D0bPi+} ", 521, 3.0f, 7.0f, 5.27931 , 1.638e-12, 0, 0.0030), //150 + KFEfficiencyParticleInfo("B-_D0Pi-", "B- {D0Pi-} ", -521, 3.0f, 7.0f, 5.27931 , 1.638e-12, 0, 0.0030), //151 + KFEfficiencyParticleInfo("B+_D0bK+", "B+ {D0bK+} ", 529, 3.0f, 7.0f, 5.27931 , 1.638e-12, 0, 0.0030), //152 + KFEfficiencyParticleInfo("B-_D0K-", "B- {D0K+} ", -529, 3.0f, 7.0f, 5.27931 , 1.638e-12, 0, 0.0030), //153 + KFEfficiencyParticleInfo("B0_D-Pi+", "B0 {D-Pi+} ", 511, 3.0f, 7.0f, 5.27962 , 1.520e-12, 0, 0.0030), //154 + KFEfficiencyParticleInfo("B0b_D+Pi-", "B0b {D+Pi-} ", -511, 3.0f, 7.0f, 5.27962 , 1.520e-12, 0, 0.0030), //155 + KFEfficiencyParticleInfo("B0_D-K+", "B0 {D-K+} ", 519, 3.0f, 7.0f, 5.27962 , 1.520e-12, 0, 0.0030), //156 + KFEfficiencyParticleInfo("B0b_D+K-", "B0b {D+K-} ", -519, 3.0f, 7.0f, 5.27962 , 1.520e-12, 0, 0.0030), //157 + KFEfficiencyParticleInfo("H0_{Lppi}", "H0 ", 3001, 2.0f, 4.0f, 2.21 , 1.32e-10, 0, 0.0030), //158 +//hypernuclei + KFEfficiencyParticleInfo("LambdaN", "LambdaN ", 3003, 1.0f, 3.0f, 2.046 , 2.632e-10, 0, 0.0025), //159 + KFEfficiencyParticleInfo("LambdaNb", "LambdaN b ", -3003, 1.0f, 3.0f, 2.046 , 2.632e-10, 0, 0.0025), //160 + KFEfficiencyParticleInfo("LambdaNN", "LambdaNN ", 3103, 2.0f, 4.0f, 2.99352 , 2.632e-10, 0, 0.0020), //161 + KFEfficiencyParticleInfo("LambdaNNb", "LambdaNN b ", -3103, 2.0f, 4.0f, 2.99352 , 2.632e-10, 0, 0.0020), //162 + KFEfficiencyParticleInfo("H3L", "H3L ", 3004, 2.0f, 4.0f, 2.9908 , 2.632e-10, 1, 0.0020), //163 + KFEfficiencyParticleInfo("H3Lb", "H3L b ", -3004, 2.0f, 4.0f, 2.9908 , 2.632e-10, -1, 0.0020), //164 + KFEfficiencyParticleInfo("H3L_{dppi}", "H3L_{dppi} ", 3012, 2.0f, 4.0f, 2.9908 , 2.632e-10, 1, 0.0025), //165 + KFEfficiencyParticleInfo("H3L_{dppi}b", "H3L_{dppi} b ", -3012, 2.0f, 4.0f, 2.9908 , 2.632e-10, -1, 0.0025), //166 + KFEfficiencyParticleInfo("H4L", "H4L ", 3005, 3.0f, 5.0f, 3.9224 , 2.632e-10, 1, 0.0020), //167 + KFEfficiencyParticleInfo("H4Lb", "H4L b ", -3005, 3.0f, 5.0f, 3.9224 , 2.632e-10, -1, 0.0020), //168 + KFEfficiencyParticleInfo("H4L_{tppi}", "H4L_{tppi} ", 3013, 3.0f, 5.0f, 3.9224 , 2.632e-10, 1, 0.0025), //169 + KFEfficiencyParticleInfo("H4L_{tppi}b", "H4L_{tppi} b ", -3013, 3.0f, 5.0f, 3.9224 , 2.632e-10, -1, 0.0025), //170 + KFEfficiencyParticleInfo("H4L_{ddpi}", "H4L_{ddpi} ", 3014, 3.0f, 5.0f, 3.9224 , 2.632e-10, 1, 0.0025), //171 + KFEfficiencyParticleInfo("H4L_{ddpi}b", "H4L_{ddpi} b ", -3014, 3.0f, 5.0f, 3.9224 , 2.632e-10, -1, 0.0025), //172 + KFEfficiencyParticleInfo("H5L_{tdpi}", "H5L_{tdpi} ", 3015, 4.0f, 6.0f, 4.845 , 2.632e-10, 1, 0.0030), //173 + KFEfficiencyParticleInfo("H5L_{tdpi}b", "H5L_{tdpi} b ", -3015, 4.0f, 6.0f, 4.845 , 2.632e-10, -1, 0.0030), //174 + KFEfficiencyParticleInfo("H6L_{He6pi}", "H6L_{He6pi} ", 3016, 5.0f, 7.0f, 5.775 , 2.632e-10, 1, 0.0030), //175 + KFEfficiencyParticleInfo("H6L_{He6pi}b", "H6L_{He6pi} b ", -3016, 5.0f, 7.0f, 5.775 , 2.632e-10, -1, 0.0030), //176 + KFEfficiencyParticleInfo("H6L_{ttpi}", "H6L_{ttpi} ", 3017, 5.0f, 7.0f, 5.775 , 2.632e-10, 1, 0.0030), //177 + KFEfficiencyParticleInfo("H6L_{ttpi}b", "H6L_{ttpi} b ", -3017, 5.0f, 7.0f, 5.775 , 2.632e-10, -1, 0.0030), //178 + KFEfficiencyParticleInfo("He4L", "He4L ", 3006, 3.0f, 5.0f, 3.9210 , 2.632e-10, 2, 0.0025), //179 + KFEfficiencyParticleInfo("He4Lb", "He4L b ", -3006, 3.0f, 5.0f, 3.9210 , 2.632e-10, -2, 0.0025), //180 + KFEfficiencyParticleInfo("He5L", "He5L ", 3007, 4.0f, 6.0f, 4.8393 , 2.632e-10, 2, 0.0025), //181 + KFEfficiencyParticleInfo("He5Lb", "He5L b ", -3007, 4.0f, 6.0f, 4.8393 , 2.632e-10, -2, 0.0025), //182 + KFEfficiencyParticleInfo("He5L_{He3dpi}", "He5L_{He3dpi} ", 3018, 4.0f, 6.0f, 4.8393 , 2.632e-10, 2, 0.0025), //183 + KFEfficiencyParticleInfo("He5L_{He3dpi}b", "He5L_{He3dpi}b", -3018, 4.0f, 6.0f, 4.8393 , 2.632e-10, -2, 0.0025), //184 + KFEfficiencyParticleInfo("He6L_{Li6pi}", "He6L_{Li6pi} ", 3019, 5.0f, 7.0f, 5.775 , 2.632e-10, 2, 0.0030), //185 + KFEfficiencyParticleInfo("He6L_{Li6pi}b", "He6L_{Li6pi}b", -3019, 5.0f, 7.0f, 5.775 , 2.632e-10, -2, 0.0030), //186 + KFEfficiencyParticleInfo("He6L_{He3tpi}", "He6L_{He3tpi} ", 3020, 5.0f, 7.0f, 5.775 , 2.632e-10, 2, 0.0030), //187 + KFEfficiencyParticleInfo("He6L_{He3tpi}b", "He6L_{He3tpi}b", -3020, 5.0f, 7.0f, 5.775 , 2.632e-10, -2, 0.0030), //188 + KFEfficiencyParticleInfo("He6L_{He4dpi}", "He6L_{He4dpi} ", 3021, 5.0f, 7.0f, 5.775 , 2.632e-10, 2, 0.0030), //189 + KFEfficiencyParticleInfo("He6L_{He4dpi}b", "He6L_{He4dpi}b", -3021, 5.0f, 7.0f, 5.775 , 2.632e-10, -2, 0.0030), //190 + KFEfficiencyParticleInfo("He7L_{Li7pi}", "He7L_{Li7pi} ", 3022, 6.0f, 8.0f, 6.717 , 2.632e-10, 2, 0.0030), //191 + KFEfficiencyParticleInfo("He7L_{Li7pi}b", "He7L_{Li7pi}b", -3022, 6.0f, 8.0f, 6.717 , 2.632e-10, -2, 0.0030), //192 + KFEfficiencyParticleInfo("He7L_{He4tpi}", "He7L_{He4tpi} ", 3023, 6.0f, 8.0f, 6.717 , 2.632e-10, 2, 0.0030), //193 + KFEfficiencyParticleInfo("He7L_{He4tpi}b", "He7L_{He4tpi}b", -3023, 6.0f, 8.0f, 6.717 , 2.632e-10, -2, 0.0030), //194 + KFEfficiencyParticleInfo("Li6L_{2He3pi}", "Li6L_{2He3pi} ", 3024, 5.0f, 7.0f, 5.77 , 2.632e-10, 3, 0.0030), //195 + KFEfficiencyParticleInfo("Li6L_{2He3pi}b", "Li6L_{2He3pi}b", -3024, 5.0f, 7.0f, 5.77 , 2.632e-10, -3, 0.0030), //196 + KFEfficiencyParticleInfo("Li7L_{Be7pi}", "Li7L_{Be7pi} ", 3025, 6.0f, 8.0f, 6.711 , 2.632e-10, 3, 0.0030), //197 + KFEfficiencyParticleInfo("Li7L_{Be7pi}b", "Li7L_{Be7pi} b", -3025, 6.0f, 8.0f, 6.711 , 2.632e-10, -3, 0.0030), //198 + KFEfficiencyParticleInfo("Li7L_{He3He4pi}", "Li7L ", 3026, 6.0f, 8.0f, 6.711 , 2.632e-10, 3, 0.0025), //199 + KFEfficiencyParticleInfo("Li7L_{He3He4pi}b", "Li7L b ", -3026, 6.0f, 8.0f, 6.711 , 2.632e-10, -3, 0.0025), //200 + KFEfficiencyParticleInfo("Li8L_{2He4pi}", "Li8L_{2He4pi} ", 3027, 7.0f, 9.0f, 7.642 , 2.632e-10, 3, 0.0025), //201 + KFEfficiencyParticleInfo("Li8L_{2He4pi}b", "Li8L_{2He4pi}b", -3027, 7.0f, 9.0f, 7.642 , 2.632e-10, -3, 0.0025), //202 + KFEfficiencyParticleInfo("LLn", "LLn ", 3203, 3.0f, 5.0f, 3.16964 , 2.632e-10, 0, 0.0030), //203 + KFEfficiencyParticleInfo("LLnn", "LLnn ", 3040, 4.0f, 6.0f, 4.16964 , 2.632e-10, 0, 0.0030), //204 + KFEfficiencyParticleInfo("H4LL_{He4Lpi-}", "H4LL_{He4Lpi-}", 3008, 3.0f, 5.0f, 4.10791 , 2.632e-10, 1, 0.0030), //205 + KFEfficiencyParticleInfo("H4LL_{H3Lppi-}", "H4LL_{H3Lppi-}", 3009, 3.0f, 5.0f, 4.10791 , 2.632e-10, 1, 0.0030), //206 + KFEfficiencyParticleInfo("H5LL_{He5Lpi-}", "H5LL_{He5Lpi-}", 3010, 4.0f, 6.0f, 5.04748 , 2.632e-10, 1, 0.0030), //207 + KFEfficiencyParticleInfo("He6LL", "He6LL ", 3011, 5.0f, 7.0f, 5.98575 , 2.632e-10, 2, 0.0030), //208 + KFEfficiencyParticleInfo("H2L", "H2L ", 3028, 1.5f, 3.5f, 2.05 , 2.632e-10, 1, 0.0020), //209 + KFEfficiencyParticleInfo("H2Lb", "H2L b ", -3028, 1.5f, 3.5f, 2.05 , 2.632e-10, -1, 0.0020), //210 + KFEfficiencyParticleInfo("He3L", "He3L ", 3029, 2.0f, 4.0f, 2.992 , 2.632e-10, 2, 0.0020), //211 + KFEfficiencyParticleInfo("He3Lb", "He3L b ", -3029, 2.0f, 4.0f, 2.992 , 2.632e-10, -2, 0.0020), //212 + KFEfficiencyParticleInfo("H2L*", "H2L* ", 1003003, 1.5f, 2.5f, 2.053 , 1.55e-22, 1, 0.0030), //213 + KFEfficiencyParticleInfo("H2L*b", "H2L* b ", -1003003, 1.5f, 2.5f, 2.053 , 1.55e-22, 1, 0.0030), //214 + KFEfficiencyParticleInfo("H3L*", "H3L* ", 1003004, 2.5f, 3.5f, 2.992 , 1.55e-22, 1, 0.0030), //215 + KFEfficiencyParticleInfo("H3L*b", "H3L* b ", -1003004, 2.5f, 3.5f, 2.992 , 1.55e-22, 1, 0.0030), //216 + KFEfficiencyParticleInfo("H4L*", "H4L* ", 1003005, 3.5f, 4.5f, 3.923 , 1.55e-22, 1, 0.0030), //217 + KFEfficiencyParticleInfo("H4L*b", "H4L* b ", -1003005, 3.5f, 4.5f, 3.923 , 1.55e-22, 1, 0.0030), //218 + KFEfficiencyParticleInfo("He4L*_{HeL}", "He4L*_{HeL} ", 1003006, 3.5f, 4.5f, 3.923 , 1.55e-22, 2, 0.0030), //219 + KFEfficiencyParticleInfo("He4L*_{HeL}b", "He4L*_{HeL} b ", -1003006, 3.5f, 4.5f, 3.923 , 1.55e-22, 2, 0.0030), //220 + KFEfficiencyParticleInfo("He4L*_{H3Lp}", "He4L*_{H3Lp} ", 2003006, 3.5f, 4.5f, 3.923 , 1.55e-22, 2, 0.0030), //221 + KFEfficiencyParticleInfo("He4L*_{H3Lp}b", "He4L*_{H3Lp} b", -2003006, 3.5f, 4.5f, 3.923 , 1.55e-22, 2, 0.0030), //222 + KFEfficiencyParticleInfo("He5L*_{HeL}", "He5L*_{HeL} ", 1003007, 4.5f, 5.5f, 4.842 , 1.55e-22, 2, 0.0030), //223 + KFEfficiencyParticleInfo("He5L*_{HeL}b", "He5L*_{HeL} b ", -1003007, 4.5f, 5.5f, 4.842 , 1.55e-22, 2, 0.0030), //224 + KFEfficiencyParticleInfo("He5L*_{H4Lp}", "He5L*_{H4Lp} ", 2003007, 4.5f, 5.5f, 4.842 , 1.55e-22, 2, 0.0030), //225 + KFEfficiencyParticleInfo("He5L*_{H4Lp}b", "He5L*_{H4Lp} b", -2003007, 4.5f, 5.5f, 4.842 , 1.55e-22, 2, 0.0030), //226 + KFEfficiencyParticleInfo("H2Sp", "H2Sp ", 3030, 1.0f, 3.0f, 2.135 , 8.018e-11, 0, 0.0025), //227 + KFEfficiencyParticleInfo("H3Sp", "H3Sp ", 3031, 2.0f, 4.0f, 3.075 , 8.018e-11, 0, 0.0025), //228 + KFEfficiencyParticleInfo("He3Sp", "He3Sp ", 3032, 2.0f, 4.0f, 3.073 , 8.018e-11, 0, 0.0025), //229 + KFEfficiencyParticleInfo("He4Sp", "He4Sp ", 3033, 3.0f, 5.0f, 4.013 , 8.018e-11, 0, 0.0025), //230 + KFEfficiencyParticleInfo("He6Sp", "He6Sp ", 3034, 5.0f, 7.0f, 5.892 , 8.018e-11, 0, 0.0025), //231 + KFEfficiencyParticleInfo("Li6Sp", "Li6Sp ", 3035, 5.0f, 7.0f, 5.891 , 8.018e-11, 0, 0.0025), //232 + KFEfficiencyParticleInfo("Li7Sp", "Li7Sp ", 3036, 6.0f, 8.0f, 6.830 , 8.018e-11, 0, 0.0025), //233 + KFEfficiencyParticleInfo("Be7Sp", "Be7Sp ", 3037, 6.0f, 8.0f, 6.829 , 8.018e-11, 0, 0.0025), //234 + KFEfficiencyParticleInfo("Li5L", "Li5L ", 3038, 4.0f, 6.0f, 4.840 , 2.632e-10, 0, 0.0025), //235 + KFEfficiencyParticleInfo("Li6L", "Li6L ", 3039, 5.0f, 7.0f, 5.775 , 2.632e-10, 0, 0.0025), //236 +//missing mass method + KFEfficiencyParticleInfo("pi-_{mu,nu}", "pi-_{mnu} ", -7000211, 0.f, 1.0f, 0.139570 , 2.6e-8, -1, 0.0030), //237 + KFEfficiencyParticleInfo("nu_{pi-}", "nu_{mupi-} b ", -7000014,-1.0f, 1.0f, 0. , 1.0e20, 0, 0.0030), //238 + KFEfficiencyParticleInfo("pi+_{mu,nu}", "pi+_{mnu} ", 7000211, 0.f, 1.0f, 0.139570 , 2.6e-8, 1, 0.0030), //239 + KFEfficiencyParticleInfo("nu_{pi+}", "nu_{mupi+} ", 7000014,-1.0f, 1.0f, 0. , 1.0e20, 0, 0.0030), //240 + KFEfficiencyParticleInfo("K-_{mu,nu}", "K-_{mnu} ", -7000321, 0.f, 1.0f, 0.493677 , 1.238e-8, -1, 0.0030), //241 + KFEfficiencyParticleInfo("nu_{K-}", "nu_{K-} b ", -8000014,-1.0f, 1.0f, 0. , 1.0e20, 0, 0.0030), //242 + KFEfficiencyParticleInfo("K+_{mu,nu}", "K+_{mnu} ", 7000321, 0.f, 1.0f, 0.493677 , 1.238e-8, 1, 0.0030), //243 + KFEfficiencyParticleInfo("nu_{K+}", "nu_{K+} ", 8000014,-1.0f, 1.0f, 0. , 1.0e20, 0, 0.0030), //244 + KFEfficiencyParticleInfo("Sigma-_{pi-,n}", "Sigma-_{pi-n} ", 7003112, 0.0f, 2.0f, 1.197449 , 1.479e-10, -1, 0.0100), //245 + KFEfficiencyParticleInfo("n_{Sigma-}", "n_{Sigma-} ", 7002112, 0.0f, 1.5f, 0.9395654 , 880, 0, 0.0030), //246 + KFEfficiencyParticleInfo("Sigma+_{pi+n}b", "Sigma+{pi+n} b", -7003112, 0.0f, 2.0f, 1.197449 , 1.479e-10, -1, 0.0030), //247 + KFEfficiencyParticleInfo("n_{Sigma+} b", "n_{Sigma+b} b ", -7002112, 0.0f, 1.5f, 0.9395654 , 880, 0, 0.0030), //248 + KFEfficiencyParticleInfo("Sigma-_{pi-n}b", "Sigma+{pi-n} b", -7003222, 0.0f, 2.0f, 1.18937 , 0.8018e-10, 1, 0.0030), //249 + KFEfficiencyParticleInfo("n_{Sigma-} b", "n_{Sigma-_b} b", -8002112, 0.0f, 1.5f, 0.9395654 , 0.93956541, 0, 0.0030), //250 + KFEfficiencyParticleInfo("Sigma+_{pi+n}", "Sigma+_{pi+n} ", 7003222, 0.0f, 2.0f, 1.18937 , 0.8018e-10, 1, 0.0100), //251 + KFEfficiencyParticleInfo("n_{Sigma+}", "n_{Sigma+} ", 8002112, 0.0f, 1.5f, 0.9395654 , 880, 0, 0.0030), //252 + KFEfficiencyParticleInfo("Xi-_{pi-L}", "Xi-_{pi-L} ", 7003312, 0.0f, 2.0f, 1.32171 , 1.639e-10, -1, 0.0030), //253 + KFEfficiencyParticleInfo("Lambda_{Xi-}", "Lambda_{Xi-} ", 7003122, 0.0f, 2.0f, 1.115683 , 2.632e-10, 0, 0.0030), //254 + KFEfficiencyParticleInfo("Xi+_{pi+L_b}", "Xi+_{pi+L_b} ", -7003312, 0.0f, 2.0f, 1.32171 , 1.639e-10, 1, 0.0030), //255 + KFEfficiencyParticleInfo("Lambda_{Xi+} b", "Lambda_{Xi+} b", -7003122, 0.0f, 2.0f, 1.115683 , 2.632e-10, 0, 0.0030), //256 + KFEfficiencyParticleInfo("Omega-_{Xi-pi0}", "Omega-{pi-Xi0}", 7003334, 0.0f, 2.0f, 1.67245 , 0.821e-10, -1, 0.0030), //257 + KFEfficiencyParticleInfo("Xi0_{Omega-}", "Xi0_{Omega-} ", 7003322, 0.0f, 2.0f, 1.31486 , 2.9e-10, 0, 0.0030), //258 + KFEfficiencyParticleInfo("Omega+_{Xi+pi0}", "Omega+_{Xipi0}", -7003334, 0.0f, 2.0f, 1.67245 , 0.821e-10, 1, 0.0030), //259 + KFEfficiencyParticleInfo("Xi0_{Omega+} b", "Xi0_{Omega+} b", -7003322, 0.0f, 2.0f, 1.31486 , 2.9e-10, 0, 0.0030), //260 + KFEfficiencyParticleInfo("K-_{pi-pi0}", "K-_{pi-pi0} ", -9000321, 0.0f, 1.0f, 0.493677 , 1.24e-8, -1, 0.0030), //261 + KFEfficiencyParticleInfo("pi0_{K-}", "pi0_{K-} ", -9000111, 0.0f, 1.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //262 + KFEfficiencyParticleInfo("K+_{pi+pi0}", "K+_{pi+pi0} ", 9000321, 0.0f, 1.0f, 0.493677 , 1.24e-8, 1, 0.0030), //263 + KFEfficiencyParticleInfo("pi0_{K+}", "pi0_{K+} ", 9000111, 0.0f, 1.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //264 + KFEfficiencyParticleInfo("Omega-{K-L}", "Omega-_{K-L} ", 8003334, 0.0f, 2.0f, 1.67245 , 0.821e-10, -1, 0.0030), //265 + KFEfficiencyParticleInfo("Lambda_{Omega-}", "Lambda_{O-} ", 8003122, 0.0f, 2.0f, 1.115683 , 2.632e-10, 0, 0.0030), //266 + KFEfficiencyParticleInfo("Omega+_{K+L_b}", "Omega+_{K+Lb} ", -8003334, 0.0f, 2.0f, 1.67245 , 0.821e-10, 1, 0.0030), //267 + KFEfficiencyParticleInfo("Lamda_{Omega+} b", "Lambda_{O+} b ", -8003122, 0.0f, 2.0f, 1.115683 , 2.632e-10, 0, 0.0030), //268 + KFEfficiencyParticleInfo("Sigma-{p_b pi0} b","Sigma-{ppi0} b", -8003222, 0.0f, 2.0f, 1.18937 , 0.8018e-10, 1, 0.0030), //269 + KFEfficiencyParticleInfo("pi0_{Sigma-b}", "pi0_{Sigma-_b}", -8000111, 0.0f, 1.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //270 + KFEfficiencyParticleInfo("Sigma+_{p pi0}", "Sigma+_{ppi0} ", 8003222, 0.0f, 2.0f, 1.18937 , 0.8018e-10, 1, 0.0250), //271 + KFEfficiencyParticleInfo("pi0_{Sigma+}", "pi0_{Sigma+} ", 8000111, 0.0f, 1.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //272 + KFEfficiencyParticleInfo("He3L_{He3pi0}", "He3L_{He3pi0} ", 7003029, 2.9f, 3.9f, 2.991 , 2.632e-10, 2, 0.0020), //273 + KFEfficiencyParticleInfo("pi0_{He3L+}", "pi0_{He3L+} ", 7700111, 0.0f, 1.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //274 + KFEfficiencyParticleInfo("He3L_{He3pi0} b", "He3L_{He3pi0}b", -7003029, 2.9f, 3.9f, 2.991 , 2.632e-10, 2, 0.0020), //275 + KFEfficiencyParticleInfo("pi0_{He3L-}", "pi0_{He3L-} ", -7700111, 0.0f, 1.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //276 + KFEfficiencyParticleInfo("He4L_{He4pi0}", "He4L_{He4pi0} ", 7003006, 3.8f, 4.8f, 3.921 , 2.632e-10, 2, 0.0020), //277 + KFEfficiencyParticleInfo("pi0_{He4L+}", "pi0_{He4L+} ", 7800111, 0.0f, 1.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //278 + KFEfficiencyParticleInfo("He4L_{He4pi0} b", "He4L_{He4pi0}b", -7003006, 3.8f, 4.8f, 3.921 , 2.632e-10, 2, 0.0020), //279 + KFEfficiencyParticleInfo("pi0_{He4L-}", "pi0_{He4L-} ", -7800111, 0.0f, 1.0f, 0.1349766 , 8.52e-17, 0, 0.0030), //280 +//tracks + KFEfficiencyParticleInfo("e-", "e- ", 11, 0.0f,0.01f, 5.109989461E-04, 1.0e20,-1, 0.0030), //281 + KFEfficiencyParticleInfo("e+", "e+ ", -11, 0.0f,0.01f, 5.109989461E-04, 1.0e20, 1, 0.0030), //282 + KFEfficiencyParticleInfo("mu-", "mu- ", 13, 0.0f, 1.0f, 0.1056583745, 2.2e-6, -1, 0.0030), //283 + KFEfficiencyParticleInfo("mu+", "mu+ ", -13, 0.0f, 1.0f, 0.1056583745, 2.2e-6, 1, 0.0030), //284 + KFEfficiencyParticleInfo("pi+", "pi+ ", 211, 0.0f, 1.0f, 0.13957039 , 2.6e-8, 1, 0.0030), //285 + KFEfficiencyParticleInfo("pi-", "pi- ", -211, 0.0f, 1.0f, 0.13957039 , 2.6e-8, -1, 0.0030), //286 + KFEfficiencyParticleInfo("K+", "K+ ", 321, 0.0f, 1.0f, 0.493677 , 1.238e-8, 1, 0.0030), //287 + KFEfficiencyParticleInfo("K-", "K- ", -321, 0.0f, 1.0f, 0.493677 , 1.238e-8, -1, 0.0030), //288 + KFEfficiencyParticleInfo("p+", "p+ ", 2212, 0.0f, 1.5f, 0.9382720813, 1.0e20, 1, 0.0030), //289 + KFEfficiencyParticleInfo("p-", "p- ", -2212, 0.0f, 1.5f, 0.9382720813, 1.0e20, -1, 0.0030), //290 + KFEfficiencyParticleInfo("d+", "d+ ", 1000010020, 0.0f, 2.5f, 1.87561294257, 1.0e20, 1, 0.0030), //291 + KFEfficiencyParticleInfo("d-", "d- ",-1000010020, 0.0f, 2.5f, 1.87561294257, 1.0e20, -1, 0.0030), //292 + KFEfficiencyParticleInfo("t+", "t+ ", 1000010030, 0.0f, 3.5f, 2.80892113298, 1.0e20, 1, 0.0030), //293 + KFEfficiencyParticleInfo("t-", "t- ",-1000010030, 0.0f, 3.5f, 2.80892113298, 1.0e20, -1, 0.0030), //294 + KFEfficiencyParticleInfo("He3+", "He3+ ", 1000020030, 0.0f, 3.5f, 2.80839160743, 1.0e20, 2, 0.0030), //295 + KFEfficiencyParticleInfo("He3-", "He3- ",-1000020030, 0.0f, 3.5f, 2.80839160743, 1.0e20, -2, 0.0030), //296 + KFEfficiencyParticleInfo("He4+", "He4+ ", 1000020040, 0.0f, 4.5f, 3.7273794066, 1.0e20, 2, 0.0030), //297 + KFEfficiencyParticleInfo("He4-", "He4- ",-1000020040, 0.0f, 4.5f, 3.7273794066, 1.0e20, -2, 0.0030), //298 + KFEfficiencyParticleInfo("He6+", "He6+ ", 1000020060, 0.0f, 6.5f, 5.6055375 , 1.0e20, 2, 0.0030), //299 + KFEfficiencyParticleInfo("He6-", "He6- ",-1000020060, 0.0f, 6.5f, 5.6055375 , 1.0e20, -2, 0.0030), //300 + KFEfficiencyParticleInfo("Li6+", "Li6+ ", 1000030060, 0.0f, 6.5f, 5.6015181 , 1.0e20, 3, 0.0030), //301 + KFEfficiencyParticleInfo("Li6-", "Li6- ",-1000030060, 0.0f, 6.5f, 5.6015181 , 1.0e20, -3, 0.0030), //302 + KFEfficiencyParticleInfo("Li7+", "Li7+ ", 1000030070, 0.0f, 7.5f, 6.5338336 , 1.0e20, 3, 0.0030), //303 + KFEfficiencyParticleInfo("Li7-", "Li7- ",-1000030070, 0.0f, 7.5f, 6.5338336 , 1.0e20, -3, 0.0030), //304 + KFEfficiencyParticleInfo("Be7+", "Be7+ ", 1000040070, 0.0f, 7.5f, 6.5341844 , 1.0e20, 4, 0.0030), //305 + KFEfficiencyParticleInfo("Be7-", "Be7- ",-1000040070, 0.0f, 7.5f, 6.5341844 , 1.0e20, -4, 0.0030), //306 +//background for subtraction + KFEfficiencyParticleInfo("pi+pi+", "pi+pi+ ", 9001, 0.0f, 2.0f, 0 , 1.0e20, 0, 0.0030), //307 + KFEfficiencyParticleInfo("pi+K+", "pi+K+ ", 9002, 0.6f, 5.6f, 0 , 1.0e20, 0, 0.0030), //308 + KFEfficiencyParticleInfo("K+K+", "K+K+ ", 9003, 0.8f, 3.8f, 0 , 1.0e20, 0, 0.0030), //309 + KFEfficiencyParticleInfo("K+p+", "K+p+ ", 9004, 1.4f, 5.4f, 0 , 1.0e20, 0, 0.0030), //310 + KFEfficiencyParticleInfo("pi-pi-", "pi-pi- ", -9001, 0.0f, 2.0f, 0 , 1.0e20, 0, 0.0030), //311 + KFEfficiencyParticleInfo("pi-K-", "pi-K- ", -9002, 0.6f, 5.6f, 0 , 1.0e20, 0, 0.0030), //312 + KFEfficiencyParticleInfo("K-K-", "K-K- ", -9003, 0.8f, 3.8f, 0 , 1.0e20, 0, 0.0030), //313 + KFEfficiencyParticleInfo("K-p-", "K-p- ", -9004, 1.4f, 5.4f, 0 , 1.0e20, 0, 0.0030), //314 +//V0 + KFEfficiencyParticleInfo("V0", "V0 ", 123456789, 0.3f, 1.3f, 0 , 0, 0, 0.0030) //315 + }; + + int mPartMaxMult[nParticles]; + for(int i=0; i 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( 211); //K+ -> pi+ pi- pi+ + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //K+ -> pi+ pi- pi- + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //K+ -> pi+ pi- pi+ and mother K+ + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( 211); + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 211); //K+ -> pi+ pi- pi- and mother K- + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -211); + partDaughterPdg[curPart].push_back( -321); + 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( 1000010020); //d pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010020); //d pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //t pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //t pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //He3 pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //He3 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He4 pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He4 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020060); //He6 pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020060); //He6 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030060); //Li6 pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030060); //Li6 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030070); //Li7 pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030070); //Li7 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000040070); //Be7 pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000040070); //Be7 pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010020); //d K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010020); //d K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //t K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //t K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //He3 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //He3 K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He4 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He4 K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020060); //He6 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020060); //He6 K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030060); //Li6 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030060); //Li6 K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030070); //Li7 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030070); //Li7 K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000040070); //Be7 K- + partDaughterPdg[curPart].push_back( -321); + curPart++; + + partDaughterPdg[curPart].push_back( 1000040070); //Be7 K+ + partDaughterPdg[curPart].push_back( 321); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //p p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010020); //d p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //t p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //He3 p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He4 p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020060); //He6 p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030060); //Li6 p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030070); //Li7 p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000040070); //Be7 p + partDaughterPdg[curPart].push_back( 2212); + 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( 1000010020); //H3Lambda -> d p pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010020); //H3Lambda_bar -> d- p- pi+ + partDaughterPdg[curPart].push_back(-2212); + 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( 1000010030); //H4Lambda -> t p pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010030); //H4Lambda_bar -> t- p- pi+ + partDaughterPdg[curPart].push_back(-2212); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010020); //H4Lambda -> d d pi- + partDaughterPdg[curPart].push_back( 1000010020); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010020); //H4Lambda_bar -> d- d- pi+ + partDaughterPdg[curPart].push_back(-1000010020); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //H5Lambda -> t d pi- + partDaughterPdg[curPart].push_back( 1000010020); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010030); //H5Lambda_bar -> -t -d pi+ + partDaughterPdg[curPart].push_back(-1000010020); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020060); //H6Lambda -> He6+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020060); //H6Lambda_bar -> He6- pi- + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //H6Lambda -> t t pi- + partDaughterPdg[curPart].push_back( 1000010030); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010030); //H6Lambda -> t- t- pi+ + partDaughterPdg[curPart].push_back(-1000010030); + 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( 1000020030); //He5Lambda -> He3+ d pi- + partDaughterPdg[curPart].push_back( 1000010020); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020030); //He5Lambda_bar -> He3- d- pi+ + partDaughterPdg[curPart].push_back(-1000010020); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030060); //He6Lambda -> Li6+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000030060); //He6Lambda_bar -> Li6- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //He6Lambda -> He3+ t pi- + partDaughterPdg[curPart].push_back( 1000010030); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020030); //He6Lambda_bar -> He3- t- pi+ + partDaughterPdg[curPart].push_back(-1000010030); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He6Lambda -> He4+ d pi- + partDaughterPdg[curPart].push_back( 1000010020); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020040); //He6Lambda_bar -> He4- d- pi+ + partDaughterPdg[curPart].push_back(-1000010020); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000030070); //He7Lambda -> Li7+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000030070); //He7Lambda_bar -> Li7- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He7Lambda -> He4+ t pi- + partDaughterPdg[curPart].push_back( 1000010030); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020040); //He7Lambda_bar -> He4- t- pi+ + partDaughterPdg[curPart].push_back(-1000010030); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //Li6Lambda -> He3+ He3+ pi- + partDaughterPdg[curPart].push_back( 1000020030); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020030); //Li6Lambda_bar -> He3- He3- pi+ + partDaughterPdg[curPart].push_back(-1000020030); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000040070); //Li7Lambda -> Be7+ pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000040070); //Li7Lambda_bar -> Be7- pi+ + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //Li7Lambda -> He3+ He4+ pi- + partDaughterPdg[curPart].push_back( 1000020040); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020030); //Li7Lambda_bar -> He3- He4- pi+ + partDaughterPdg[curPart].push_back(-1000020040); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //Li8Lambda -> He4+ He4+ pi- + partDaughterPdg[curPart].push_back( 1000020040); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020040); //Li8Lambda_bar -> He4- He4- pi+ + partDaughterPdg[curPart].push_back(-1000020040); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 3004); //LLn -> H3Lambda pi- + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 3005); //LLnn -> H4Lambda 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( 2212); //H2L -> p p pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //H2L_bar -> p- p- pi+ + partDaughterPdg[curPart].push_back(-2212); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //He3L -> p p p pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //He3L_bar -> p- p- p- pi+ + partDaughterPdg[curPart].push_back(-2212); + partDaughterPdg[curPart].push_back(-2212); + partDaughterPdg[curPart].push_back( 211); + curPart++; + + partDaughterPdg[curPart].push_back( 2212); //H2L* -> p Lambda + partDaughterPdg[curPart].push_back( 3122); + curPart++; + + partDaughterPdg[curPart].push_back(-2212); //H2L* -> p- Lambda_bar + partDaughterPdg[curPart].push_back(-3122); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010020); //H3L* -> d+ Lambda + partDaughterPdg[curPart].push_back( 3122); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010020); //H3L*b -> d- Lambda b + partDaughterPdg[curPart].push_back(-3122); + curPart++; + + partDaughterPdg[curPart].push_back( 1000010030); //H4L* -> t+ Lambda + partDaughterPdg[curPart].push_back( 3122); + curPart++; + + partDaughterPdg[curPart].push_back(-1000010030); //H4L*b -> t- Lambda b + partDaughterPdg[curPart].push_back(-3122); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //He4L* -> He3+ Lambda + partDaughterPdg[curPart].push_back( 3122); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020030); //He4L*b -> He3- Lambda b + partDaughterPdg[curPart].push_back(-3122); + curPart++; + + partDaughterPdg[curPart].push_back( 3004); //He4L* -> H3L p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back(-3004); //He4L*b -> H3Lb p- + partDaughterPdg[curPart].push_back(-2212); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //He5L* -> He4+ Lambda + partDaughterPdg[curPart].push_back( 3122); + curPart++; + + partDaughterPdg[curPart].push_back(-1000020040); //He5L*b -> He4- Lambda b + partDaughterPdg[curPart].push_back(-3122); + curPart++; + + partDaughterPdg[curPart].push_back( 3005); //He5L* -> H4L p + partDaughterPdg[curPart].push_back( 2212); + curPart++; + + partDaughterPdg[curPart].push_back(-3005); //He5L*b -> H4Lb p- + partDaughterPdg[curPart].push_back(-2212); + curPart++; + + partDaughterPdg[curPart].push_back(1000010020); //H2Sp -> d pi+ + partDaughterPdg[curPart].push_back(211); + curPart++; + + partDaughterPdg[curPart].push_back(1000010030); //H3Sp -> t pi+ + partDaughterPdg[curPart].push_back(211); + curPart++; + + partDaughterPdg[curPart].push_back(1000020030); //He3Sp -> He3 pi+ + partDaughterPdg[curPart].push_back(211); + curPart++; + + partDaughterPdg[curPart].push_back(1000020040); //He4Sp -> He4 pi+ + partDaughterPdg[curPart].push_back(211); + curPart++; + + partDaughterPdg[curPart].push_back(1000020060); //He6Sp -> He6 pi+ + partDaughterPdg[curPart].push_back(211); + curPart++; + + partDaughterPdg[curPart].push_back(1000030060); //Li6Sp -> Li6 pi+ + partDaughterPdg[curPart].push_back(211); + curPart++; + + partDaughterPdg[curPart].push_back(1000030070); //Li7Sp -> Li7 pi+ + partDaughterPdg[curPart].push_back(211); + curPart++; + + partDaughterPdg[curPart].push_back(1000040070); //Be7Sp -> Be7 pi+ + partDaughterPdg[curPart].push_back(211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020030); //Li5Lambda -> He3+ p+ p+ pi- + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( 2212); + partDaughterPdg[curPart].push_back( -211); + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); //Li6Lambda -> He4+ p+ p+ pi- + partDaughterPdg[curPart].push_back( 2212); + 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++; + + partDaughterPdg[curPart].push_back( 1000020030); // He3L+ -> He3 + Pi0 + partDaughterPdg[curPart].push_back( 7700111); // + curPart++; + + partDaughterPdg[curPart].push_back( 7003029); // Pi0 <- He3L+ - He3 + partDaughterPdg[curPart].push_back( 1000020030); // + curPart++; + + partDaughterPdg[curPart].push_back(-1000020030); // He3L- -> He3- + Pi0 + partDaughterPdg[curPart].push_back( -7700111); // + curPart++; + + partDaughterPdg[curPart].push_back( -7003029); // Pi0 <- He3L- - He3- + partDaughterPdg[curPart].push_back(-1000020030); // + curPart++; + + partDaughterPdg[curPart].push_back( 1000020040); // He4L+ -> He4 + Pi0 + partDaughterPdg[curPart].push_back( 7800111); // + curPart++; + + partDaughterPdg[curPart].push_back( 7003006); // Pi0 <- He4L+ - He4 + partDaughterPdg[curPart].push_back( 1000020040); // + curPart++; + + partDaughterPdg[curPart].push_back(-1000020040); // He4L- -> He4- + Pi0 + partDaughterPdg[curPart].push_back( -7800111); // + curPart++; + + partDaughterPdg[curPart].push_back( -7003006); // Pi0 <- He4L- - He4- + partDaughterPdg[curPart].push_back(-1000020040); // + curPart++; + + for(int iP=0; iP::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 GetPdgToIndexMap() const { return fPdgToIndex; } + + 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 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 = 316; ///< Number of particles. + static const int fFirstHypernucleusIndex = 159; ///< Index of the first hypernuclei in the list. + static const int fLastHypernucleusIndex = 236; ///< Index of the last hypernuclei in the list. + static const int fFirstMissingMassParticleIndex = 237; ///< Index of the first decay reconstructed by the missing mass method. + static const int fLastMissingMassParticleIndex = 280; ///< Index of the last decay reconstructed by the missing mass method. + static const int fFirstStableParticleIndex = 281; ///< Index of the first stable particle in the list. + static const int fLastStableParticleIndex = 306; ///< 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 > 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 names; ///< Names of the counters. The same for all counters objects. + std::map indices; ///< Map between the counter index and its short name. + + std::map fPdgToIndex; ///< The map between PDG code assigned to the decay and index in the decay list. + + KFMCCounter ratio_reco1; ///< Efficiency in 4 pi for all decays. + KFMCCounter ratio_reco2; ///< Efficiency normalised on the particles with all daughters reconstructable for all decays. + KFMCCounter ratio_reco3; ///< Efficiency normalised on the particles with all daughters reconstructed for all decays. + + KFMCCounter mc1; ///< Counters of the Monte Carlo particles of all species. + KFMCCounter mc2; ///< Counters of the Monte Carlo particles with all daughters reconstructable for all species. + KFMCCounter mc3; ///< Counters of the Monte Carlo particles with all daughters found for all species. + + KFMCCounter reco; ///< Counters of the reconstructed particles for all species. + + KFMCCounter ratio_ghost; ///< Ratio of the ghost candidates to the total number of candidates for all species. + KFMCCounter ratio_bg; ///< Ratio of the physics background candidates to the total number of candidates for all species. + KFMCCounter ratio_clone; ///< Ratio of double reconstructed particles to the total number of signal candidates for all species. + + KFMCCounter ghost; ///< Counters of the ghost candidates for all species. + KFMCCounter bg; ///< Counters of the physics background candidates for all species. + KFMCCounter clone; ///< Counters of the double reconstructed particles for all species. + +#ifndef KFParticleStandalone + ClassDef( KFPartEfficiencies, 1 ) +#endif +}; + +#endif diff --git a/StRoot/KFParticlePerformance/KFPartMatch.h b/StRoot/KFParticlePerformance/KFPartMatch.h new file mode 100644 index 00000000000..554661240e5 --- /dev/null +++ b/StRoot/KFParticlePerformance/KFPartMatch.h @@ -0,0 +1,58 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFPartMatch_H +#define KFPartMatch_H + +#include + + +/** @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 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 idsMI; ///< Vector of links, PDG hypothesis of the reconstructed particle differs from the Monte Carlo particle. +}; + +#endif diff --git a/StRoot/KFParticlePerformance/KFParticlePerformanceBase.cxx b/StRoot/KFParticlePerformance/KFParticlePerformanceBase.cxx new file mode 100644 index 00000000000..006802a53d5 --- /dev/null +++ b/StRoot/KFParticlePerformance/KFParticlePerformanceBase.cxx @@ -0,0 +1,1540 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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), fStore3DEfficiency(0), fHistoDir(0) +{ + /** The default constructor. Initialises all pointers to nullptr. **/ + for(int iParticle=0; iParticle 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.fLastStableParticleIndex)) + if(decays.find(fParteff.partPDG[iPart]) == decays.end()) continue; + + gDirectory->mkdir(fParteff.partName[iPart].data()); + gDirectory->cd(fParteff.partName[iPart].data()); + { + if((iPart >= 48 && iPart <= 92) || (iPart == 13 || iPart == 14 || iPart == 37 || iPart == 38) ) + { + gDirectory->mkdir("Daughters"); + gDirectory->cd("Daughters"); + { + for(uint32_t iDaughter=0; iDaughtermkdir(fParteff.partName[iPartDaughter].data()); + gDirectory->cd(fParteff.partName[iPartDaughter].data()); + { + hPartDaughterPTheta[iPart][iDaughter] = new TH2F("P vs #theta", GetDirectoryPath()+TString("P vs #theta"), 1000., 0., 10., 1000., 0, M_PI); + hPartDaughterPhi[iPart][iDaughter] = new TH1F("#phi", GetDirectoryPath()+TString("#phi"),1000., -M_PI, M_PI); + } + gDirectory->cd(".."); //Daughters + } + } + gDirectory->cd(".."); //particle directory + } + + 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] = {4.,4.,10.,0.3,0.3,0.3,0.3,0.01}; + + for( int iH=0; iHcd(".."); //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.}; + float xMax[3] = {4.f, 4.f, 10.f}; + + 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], hPartEfficiencyMulti[iPart], 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] = {-10., -10., -160., 0, -0.5, 0., -0.5, 0., 0., -0.01, -0.01, -0.01, -0.01, -0.01, 0.}; + // float xMax[nHistosPVParam] = { 10., 10., 230., 10, 1000.5, 1000., 1000.5, 1000., 1., 1.01, 1.01, 1.01, 1.01, 1.01, 100.}; + float xMin[nHistosPVParam] = {-10., -10., 195., 0, -0.5, 0., -0.5, 0., 0., -0.01, -0.01, -0.01, -0.01, -0.01, 0.}; + float xMax[nHistosPVParam] = { 10., 10., 205., 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] = {-10.}; + float xMax2D[nHistosPVParam2D] = { 10.}; + int nBinsY2D[nHistosPVParam2D] = {1000}; + float yMin2D[nHistosPVParam2D] = {-10.}; + float yMax2D[nHistosPVParam2D] = { 10.}; + + for(int iH=0; iHGetXaxis()->SetTitle(parAxisName[iH].Data()); + } + + for(int iH=0; iHGetXaxis()->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; iHcd(".."); //L1 + + gDirectory->mkdir("Pileup"); + gDirectory->cd("Pileup"); + { + for( int iH=0; iHcd(".."); //L1 + + gDirectory->mkdir("Signal_MCReconstructable"); + gDirectory->cd("Signal_MCReconstructable"); + { + for( int iH=0; iHcd(".."); //L1 + + gDirectory->mkdir("Pileup_MCReconstructable"); + gDirectory->cd("Pileup_MCReconstructable"); + { + for( int iH=0; iHcd(".."); //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; iHcd(".."); //L1 + + gDirectory->mkdir("Signal"); + gDirectory->cd("Signal"); + { + gDirectory->mkdir("FitQA"); + gDirectory->cd("FitQA"); + { + gDirectory->mkdir("FitQAvcNMCPVTracks"); + gDirectory->cd("FitQAvcNMCPVTracks"); + { + for(int iHPV=0; iHPVcd(".."); //FitQA + + gDirectory->mkdir("FitQAvcNPVTracks"); + gDirectory->cd("FitQAvcNPVTracks"); + { + for(int iHPV=0; iHPVcd(".."); //FitQA + + for(int iHPV=0; iHPVcd(".."); //Signal + + for(int iH=0; iHGetXaxis()->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; iHPVcd(".."); //FitQA + + gDirectory->mkdir("FitQAvcNPVTracks"); + gDirectory->cd("FitQAvcNPVTracks"); + { + for(int iHPV=0; iHPVcd(".."); //FitQA + + for(int iHPV=0; iHPVcd(".."); //Signal + + for(int iH=0; iHGetXaxis()->SetTitle(parAxisName[iH].Data()); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Background"); + gDirectory->cd("Background"); + { + for(int iH=0; iHGetXaxis()->SetTitle(parAxisName[iH].Data()); + } + } + gDirectory->cd(".."); //L1 + + gDirectory->mkdir("Ghost"); + gDirectory->cd("Ghost"); + { + for(int iH=0; iHGetXaxis()->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 xMax[nFitQA/2] = {5.f,5.f,10.f,0.1,0.1,0.5,0.5,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; iMult45 && iPart<64) + { +#ifdef CBM + for(int iMult=0; iMult<3; iMult++) + mult[iMult] = 0.03; + for(int iMult=3; iMultGetXaxis()->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], THnSparseF* histoN[4], int iPart) +{ + /** Creates efficiency plots in the current ROOT folder. + ** \param[in,out] histo - 1D efficiency plots + ** \param[in,out] histo2 - 2D efficiency plots + ** \param[in,out] histoN - ND 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 , 40 , 360 , 60 , 60 , 140 , 60 , 100 }; + float xMinEff[nPartEfficiency] = { 0., 0., 0., -10., -10., -10., 0., 0. , 0.}; + float xMaxEff[nPartEfficiency] = { 20., 5., 4., 80., 50., 50., 70., 30. , 4.}; +#else + int nBinsEff[nPartEfficiency] = { 100 , 100 , 60 , 100 , 60 , 60 , 100 , 100 , 100 }; + float xMinEff[nPartEfficiency] = { 0., 0., -3., -230., -10., -10., 0., 0., 0. }; + float xMaxEff[nPartEfficiency] = { 10., 10., 3., 230., 50., 50., 50., 50., 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; iHGetYaxis()->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); + + if(IsCollectDalitz(iPart)) + { + int nBinsM12 = 100; + int nBinsM23 = 100; + int nBinsM13 = 100; + + const int pdg1 = fParteff.partDaughterPdg[iPart][0]; + const int pdg2 = fParteff.partDaughterPdg[iPart][1]; + const int pdg3 = fParteff.partDaughterPdg[iPart][2]; + + int index1 = fParteff.GetParticleIndex(pdg1); + int index2 = fParteff.GetParticleIndex(pdg2); + int index3 = fParteff.GetParticleIndex(pdg3); + + float m1 = fParteff.partMass[index1]; + float m2 = fParteff.partMass[index2]; + float m3 = fParteff.partMass[index3]; + + const float MMax = fParteff.partMass[iPart] + 0.05; + + const float m12Min = (m1+m2)*0.998; + const float m12Max = (MMax-m3); + + const float m23Min = (m2+m3)*0.998; + const float m23Max = (MMax-m1); + + const float m13Min = (m1+m3)*0.998; + const float m13Max = (MMax-m2); + + TString axis12 = "m_{"; + axis12 += fParteff.partName[index1]; + axis12 += fParteff.partName[index2]; + axis12 += "}"; + + TString axis23 = "m_{"; + axis23 += fParteff.partName[index2]; + axis23 += fParteff.partName[index3]; + axis23 += "}"; + + TString axis13 = "m_{"; + axis13 += fParteff.partName[index1]; + axis13 += fParteff.partName[index3]; + axis13 += "}"; + + histo2[iEff][2] = new TProfile2D( "EffDalitz1", (GetDirectoryPath()+fParteff.partName[index1]+fParteff.partName[index2]).Data(), + nBinsM12, m12Min, m12Max, + nBinsM23, m23Min, m23Max); + histo2[iEff][2]->GetXaxis()->SetTitle(axis12 + " [GeV/c]"); + histo2[iEff][2]->GetYaxis()->SetTitle(axis23 + " [GeV/c]"); + histo2[iEff][2]->GetZaxis()->SetTitle("Efficiency"); + + histo2[iEff][3] = new TProfile2D( "EffDalitz2", (GetDirectoryPath()+fParteff.partName[index2]+fParteff.partName[index3]).Data(), + nBinsM13, m13Min, m13Max, + nBinsM23, m23Min, m23Max); + histo2[iEff][3]->GetXaxis()->SetTitle(axis13 + " [GeV/c]"); + histo2[iEff][3]->GetYaxis()->SetTitle(axis23 + " [GeV/c]"); + histo2[iEff][3]->GetZaxis()->SetTitle("Efficiency"); + + histo2[iEff][4] = new TProfile2D( "EffDalitz3", (GetDirectoryPath()+fParteff.partName[index1]+fParteff.partName[index3]).Data(), + nBinsM12, m12Min, m12Max, + nBinsM13, m13Min, m13Max); + histo2[iEff][4]->GetXaxis()->SetTitle(axis12 + " [GeV/c]"); + histo2[iEff][4]->GetYaxis()->SetTitle(axis13 + " [GeV/c]"); + histo2[iEff][4]->GetZaxis()->SetTitle("Efficiency"); + } + else + { + histo2[iEff][2] = nullptr; + histo2[iEff][3] = nullptr; + histo2[iEff][4] = nullptr; + } + } + gDirectory->cd("..");// particle directory / Efficiency + } + + if(fStore3DEfficiency) + { + gDirectory->mkdir("Multidimensional"); + gDirectory->cd("Multidimensional"); + { +#if 1 + constexpr int nDimensions = 3; + // phi theta p + int nBins[nDimensions] { 100, 25, 25 }; + double xMin[nDimensions]{-TMath::Pi(), TMath::Pi()/2, 0.}; + double xMax[nDimensions]{ TMath::Pi(), TMath::Pi(), 10.}; + + histoN[0] = new THnSparseF( "Acceptance_reco", GetDirectoryPath()+"Acceptance reco", + nDimensions, nBins, xMin, xMax); + histoN[0] -> GetAxis(0) -> SetTitle("#phi"); + histoN[0] -> GetAxis(1) -> SetTitle("#theta"); + histoN[0] -> GetAxis(2) -> SetTitle("p [GeV/c]"); + + gDirectory->Append(histoN[0]); + + histoN[1] = new THnSparseF( "Acceptance_mc", GetDirectoryPath()+"Acceptance mc", + nDimensions, nBins, xMin, xMax); + histoN[1] -> GetAxis(0) -> SetTitle("#phi"); + histoN[1] -> GetAxis(1) -> SetTitle("#theta"); + histoN[1] -> GetAxis(2) -> SetTitle("p [GeV/c]"); + + gDirectory->Append(histoN[1]); + + constexpr int nDimensions2 = 4; + // phi theta p l/dl + int nBins2[nDimensions2] { 100, 25, 25 , 20 }; + double xMin2[nDimensions2]{ -TMath::Pi(), TMath::Pi()/2, 0., 0.}; + double xMax2[nDimensions2]{ TMath::Pi(), TMath::Pi(), 10., 100.}; + + histoN[2] = new THnSparseF( "Cuts_reco", GetDirectoryPath()+"Cuts reco", + nDimensions2, nBins2, xMin2, xMax2); + histoN[2] -> GetAxis(0) -> SetTitle("p_{t} [GeV/c]"); + histoN[2] -> GetAxis(1) -> SetTitle("p [GeV/c]"); + histoN[2] -> GetAxis(2) -> SetTitle("Decay length [cm]"); + + gDirectory->Append(histoN[2]); + + histoN[3] = new THnSparseF( "Cuts_mc", GetDirectoryPath()+"Cuts mc", + nDimensions2, nBins2, xMin2, xMax2); + histoN[3] -> GetAxis(0) -> SetTitle("p_{t} [GeV/c]"); + histoN[3] -> GetAxis(1) -> SetTitle("p [GeV/c]"); + histoN[3] -> GetAxis(2) -> SetTitle("Decay length [cm]"); + + gDirectory->Append(histoN[3]); +#else + constexpr int nDimensions = 5; + // phi theta p pt eta + int nBins[nDimensions] { 100, 100 , 100 , 100 , 30 }; + double xMin[nDimensions]{-TMath::Pi(), 0., 0., 0., -3.}; + double xMax[nDimensions]{ TMath::Pi(), TMath::Pi(), 10., 10., 0.}; + + histoN[0] = new THnSparseF( "Acceptance_reco", GetDirectoryPath()+"phi-theta-p-pt-eta reco", + nDimensions, nBins, xMin, xMax); + histoN[0] -> GetAxis(0) -> SetTitle("#phi"); + histoN[0] -> GetAxis(1) -> SetTitle("#theta"); + histoN[0] -> GetAxis(2) -> SetTitle("p [GeV/c]"); + histoN[0] -> GetAxis(3) -> SetTitle("p_{t} [GeV/c]"); + histoN[0] -> GetAxis(4) -> SetTitle("eta"); + + gDirectory->Append(histoN[0]); + + histoN[1] = new THnSparseF( "Acceptance_mc", GetDirectoryPath()+"phi-theta-p-pt-eta mc", + nDimensions, nBins, xMin, xMax); + histoN[1] -> GetAxis(0) -> SetTitle("#phi"); + histoN[1] -> GetAxis(1) -> SetTitle("#theta"); + histoN[1] -> GetAxis(2) -> SetTitle("p [GeV/c]"); + histoN[1] -> GetAxis(3) -> SetTitle("p_{t} [GeV/c]"); + histoN[1] -> GetAxis(4) -> SetTitle("eta"); + + gDirectory->Append(histoN[1]); + + + + constexpr int nDimensions2 = 5; + // pt y p DL, ldl + int nBins2[nDimensions2] { 50, 30, 100, 100 , 100 }; + double xMin2[nDimensions2]{ 0, -3, 0., 0., 0.}; + double xMax2[nDimensions2]{ 5, 0, 10., 100., 100.}; + + histoN[2] = new THnSparseF( "Cuts_reco", GetDirectoryPath()+"pt-y-p-DL-ldl reco", + nDimensions2, nBins2, xMin2, xMax2); + histoN[2] -> GetAxis(0) -> SetTitle("p_t [GeV/c]"); + histoN[2] -> GetAxis(1) -> SetTitle("y"); + histoN[2] -> GetAxis(2) -> SetTitle("p [GeV/c]"); + histoN[2] -> GetAxis(3) -> SetTitle("decay length [cm]"); + histoN[2] -> GetAxis(4) -> SetTitle("l/dl"); + + gDirectory->Append(histoN[2]); + + histoN[3] = new THnSparseF( "Cuts_mc", GetDirectoryPath()+"pt-y-p-DL-ldl mc", + nDimensions2, nBins2, xMin2, xMax2); + histoN[3] -> GetAxis(0) -> SetTitle("p_t [GeV/c]"); + histoN[3] -> GetAxis(1) -> SetTitle("y"); + histoN[3] -> GetAxis(2) -> SetTitle("p [GeV/c]"); + histoN[3] -> GetAxis(3) -> SetTitle("decay length [cm]"); + histoN[3] -> GetAxis(4) -> SetTitle("l/dl"); + + gDirectory->Append(histoN[3]); +#endif + } + gDirectory->cd(".."); + } + } + 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", + "dX", "dY", "dZ", "dPx", "dPy", "dPz", "dE", "dM"}; + TString parTitle[nHistoPartParam]; + TString parName2D[nHistoPartParam2D] = {"y-p_{t}", "Z-R", "Armenteros", "y-m_{t}", "dalitz1", "dalitz2", "dalitz3"}; + 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", "dalitz", "dalitz2","dalitz3","dalitzM2", "dalitz2M2", "dalitz3M2"}; + TString parTitle3D[nHistoPartParam3D]; + for(int iParam=0; iParam(TMath::Pi()), // phi + -10.f, // X + -10.f, // Y + -230.f, // Z + 0.f, // R + 0.f, // L + -1.f, // L/dL + 0.f, // Mt + -0.5f, + 0.f, // dX + 0.f, // dY + 0.f, // dZ + 0.f, // dPx + 0.f, // dPy + 0.f, // dPz + 0.f, // dE + 0.f // dM + }; + float xMax[nHistoPartParam] = { fParteff.partMHistoMax[iPart], // M + 10.f, // p + 10.f, // pt + 3.f, // y + 50.f, // DecayL + 50.f, // ctau + 20.f, // chi2/ndf + 1.f, // prob + -static_cast(TMath::Pi()), // theta + -static_cast(TMath::Pi()), // phi + 10.f, // X + 10.f, // Y + 230.f, // Z + 200.f, // R + 200.f, // L + 200.f, // L/dL + 10.f, // Mt + float(fParteff.partMaxMult[iPart])+0.5f, + 10.f, // dX + 10.f, // dY + 10.f, // dZ + 0.2f, // dPx + 0.2f, // dPy + 0.2f, // dPz + 0.2f, // dE + 0.02f // dM + }; + 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; iHGetXaxis()->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(IsCollectDalitz(iPart)) + { + int nBinsM12 = 100; + int nBinsM23 = 100; + int nBinsM13 = 100; + + const int pdg1 = fParteff.partDaughterPdg[iPart][0]; + const int pdg2 = fParteff.partDaughterPdg[iPart][1]; + const int pdg3 = fParteff.partDaughterPdg[iPart][2]; + + int index1 = fParteff.GetParticleIndex(pdg1); + int index2 = fParteff.GetParticleIndex(pdg2); + int index3 = fParteff.GetParticleIndex(pdg3); + + float m1 = fParteff.partMass[index1]; + float m2 = fParteff.partMass[index2]; + float m3 = fParteff.partMass[index3]; + + const float MMax = fParteff.partMass[iPart] + 0.05; + + const float m12Min = (m1+m2)*0.998; + const float m12Max = (MMax-m3); + + const float m23Min = (m2+m3)*0.998; + const float m23Max = (MMax-m1); + + const float m13Min = (m1+m3)*0.998; + const float m13Max = (MMax-m2); + + TString axis12 = "m_{"; + axis12 += fParteff.partName[index1]; + axis12 += fParteff.partName[index2]; + axis12 += "}"; + + TString axis23 = "m_{"; + axis23 += fParteff.partName[index2]; + axis23 += fParteff.partName[index3]; + axis23 += "}"; + + TString axis13 = "m_{"; + axis13 += fParteff.partName[index1]; + axis13 += fParteff.partName[index3]; + axis13 += "}"; + + histoParameters2D[iPart][4] = new TH2F(parName2D[4].Data(),parTitle2D[4].Data(), + nBinsM12, m12Min, m12Max, + nBinsM23, m23Min, m23Max); + histoParameters2D[iPart][4]->GetXaxis()->SetTitle(axis12 + " [GeV/c]"); + histoParameters2D[iPart][4]->GetYaxis()->SetTitle(axis23 + " [GeV/c]"); + histoParameters2D[iPart][4]->GetZaxis()->SetTitle("Efficiency"); + + histoParameters2D[iPart][5] = new TH2F(parName2D[5].Data(),parTitle2D[5].Data(), + nBinsM13, m13Min, m13Max, + nBinsM23, m23Min, m23Max); + histoParameters2D[iPart][5]->GetXaxis()->SetTitle(axis13 + " [GeV/c]"); + histoParameters2D[iPart][5]->GetYaxis()->SetTitle(axis23 + " [GeV/c]"); + histoParameters2D[iPart][5]->GetZaxis()->SetTitle("Efficiency"); + + histoParameters2D[iPart][6] = new TH2F(parName2D[6].Data(),parTitle2D[6].Data(), + nBinsM12, m12Min, m12Max, + nBinsM13, m13Min, m13Max); + histoParameters2D[iPart][6]->GetXaxis()->SetTitle(axis12 + " [GeV/c]"); + histoParameters2D[iPart][6]->GetYaxis()->SetTitle(axis13 + " [GeV/c]"); + histoParameters2D[iPart][6]->GetZaxis()->SetTitle("Efficiency"); + } + else + { + histoParameters2D[iPart][4] = nullptr; + histoParameters2D[iPart][5] = nullptr; + histoParameters2D[iPart][6] = nullptr; + } + + 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"); + + if(IsCollectDalitz(iPart)) + { + int nBinsM12 = 100; + int nBinsM23 = 100; + int nBinsM13 = 100; + int nBinsMass = 100; + + const int pdg1 = fParteff.partDaughterPdg[iPart][0]; + const int pdg2 = fParteff.partDaughterPdg[iPart][1]; + const int pdg3 = fParteff.partDaughterPdg[iPart][2]; + + int index1 = fParteff.GetParticleIndex(pdg1); + int index2 = fParteff.GetParticleIndex(pdg2); + int index3 = fParteff.GetParticleIndex(pdg3); + + float m1 = fParteff.partMass[index1]; + float m2 = fParteff.partMass[index2]; + float m3 = fParteff.partMass[index3]; + + const float MMin = m1+m2+m3; + const float MMax = fParteff.partMass[iPart] + 0.05; + + const float m12Min = (m1+m2)*0.998; + const float m12Max = (MMax-m3); + + const float m23Min = (m2+m3)*0.998; + const float m23Max = (MMax-m1); + + const float m13Min = (m1+m3)*0.998; + const float m13Max = (MMax-m2); + + TString axis12 = "m_{"; + axis12 += fParteff.partName[index1]; + axis12 += fParteff.partName[index2]; + axis12 += "}"; + + TString axis23 = "m_{"; + axis23 += fParteff.partName[index2]; + axis23 += fParteff.partName[index3]; + axis23 += "}"; + + TString axis13 = "m_{"; + axis13 += fParteff.partName[index1]; + axis13 += fParteff.partName[index3]; + axis13 += "}"; + + histoParameters3D[iPart][6] = new TH3F(parName3D[6].Data(),parTitle3D[6].Data(), + nBinsM12, m12Min, m12Max, + nBinsM23, m23Min, m23Max, + nBinsMass,MMin, MMax); + histoParameters3D[iPart][6]->GetYaxis()->SetTitle(axis23 + " [GeV/c]"); + histoParameters3D[iPart][6]->GetXaxis()->SetTitle(axis12 + " [GeV/c]"); + histoParameters3D[iPart][6]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][6]->GetZaxis()->SetTitle("M"); + + histoParameters3D[iPart][7] = new TH3F(parName3D[7].Data(),parTitle3D[7].Data(), + nBinsM13, m13Min, m13Max, + nBinsM23, m23Min, m23Max, + nBinsMass,MMin, MMax); + histoParameters3D[iPart][7]->GetXaxis()->SetTitle(axis13 + " [GeV/c]"); + histoParameters3D[iPart][7]->GetYaxis()->SetTitle(axis23 + " [GeV/c]"); + histoParameters3D[iPart][7]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][7]->GetZaxis()->SetTitle("M"); + + histoParameters3D[iPart][8] = new TH3F(parName3D[8].Data(),parTitle3D[8].Data(), + nBinsM12, m12Min, m12Max, + nBinsM13, m13Min, m13Max, + nBinsMass,MMin, MMax); + histoParameters3D[iPart][8]->GetXaxis()->SetTitle(axis12 + " [GeV/c]"); + histoParameters3D[iPart][8]->GetYaxis()->SetTitle(axis13 + " [GeV/c]"); + histoParameters3D[iPart][8]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][8]->GetZaxis()->SetTitle("M"); + + histoParameters3D[iPart][9] = new TH3F(parName3D[9].Data(),parTitle3D[9].Data(), + nBinsM12, m12Min*m12Min, m12Max*m12Max, + nBinsM23, m23Min*m23Min, m23Max*m23Max, + nBinsMass,MMin, MMax); + histoParameters3D[iPart][9]->GetXaxis()->SetTitle(axis12 + "^{2} [GeV^{2}/c^{2}]"); + histoParameters3D[iPart][9]->GetYaxis()->SetTitle(axis23 + "^{2} [GeV^{2}/c^{2}]"); + histoParameters3D[iPart][9]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][9]->GetZaxis()->SetTitle("M"); + + histoParameters3D[iPart][10] = new TH3F(parName3D[10].Data(),parTitle3D[10].Data(), + nBinsM13, m13Min*m13Min, m13Max*m13Max, + nBinsM23, m23Min*m23Min, m23Max*m23Max, + nBinsMass,MMin, MMax); + histoParameters3D[iPart][10]->GetXaxis()->SetTitle(axis13 + "^{2} [GeV^{2}/c^{2}]"); + histoParameters3D[iPart][10]->GetYaxis()->SetTitle(axis23 + "^{2} [GeV^{2}/c^{2}]"); + histoParameters3D[iPart][10]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][10]->GetZaxis()->SetTitle("M"); + + histoParameters3D[iPart][11] = new TH3F(parName3D[11].Data(),parTitle3D[11].Data(), + nBinsM12, m12Min*m12Min, m12Max*m12Max, + nBinsM13, m13Min*m13Min, m13Max*m13Max, + nBinsMass,MMin, MMax); + histoParameters3D[iPart][11]->GetXaxis()->SetTitle(axis12 + "^{2} [GeV^{2}/c^{2}]"); + histoParameters3D[iPart][11]->GetYaxis()->SetTitle(axis13 + "^{2} [GeV^{2}/c^{2}]"); + histoParameters3D[iPart][11]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][11]->GetZaxis()->SetTitle("M"); +#if 0 + TString nameXAxis = "#sqrt{3}*(T_{"; + nameXAxis += fParteff.partName[index1]; + nameXAxis += "} - T_{"; + nameXAxis += fParteff.partName[index2]; + nameXAxis += "})/Q"; + TString nameYAxis = "(2T_{"; + nameYAxis += fParteff.partName[index3]; + nameYAxis += "} - T_{"; + nameYAxis += fParteff.partName[index1]; + nameYAxis += "} - T_{"; + nameYAxis += fParteff.partName[index2]; + nameYAxis += "})/Q"; + histoParameters3D[iPart][10] = new TH3F(parName3D[10].Data(),parTitle3D[10].Data(), + 100, -1.2, 1.2, + 100, -1.2, 1.2, + nBinsMass,MMin, MMax); + histoParameters3D[iPart][10]->GetXaxis()->SetTitle(nameXAxis); + histoParameters3D[iPart][10]->GetYaxis()->SetTitle(nameYAxis); + histoParameters3D[iPart][10]->GetYaxis()->SetTitleOffset(1.0); + histoParameters3D[iPart][10]->GetZaxis()->SetTitle("M"); +#endif + } + } + 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 && (!fStore3DEfficiency); +} + +bool KFParticlePerformanceBase::IsCollect3DHistogram(int iParticle) const +{ + /** Checks if 3D histograms for decay "iParticle" should be created. */ + return 0; //TODO +// return (!fStore3DEfficiency) && (abs(fParteff.partPDG[iParticle]) == 310 || +// abs(fParteff.partPDG[iParticle]) == 3122 || +// abs(fParteff.partPDG[iParticle]) == 3312 || +// abs(fParteff.partPDG[iParticle]) == 3334 || +// (abs(fParteff.partPDG[iParticle]) >= 3000 && +// abs(fParteff.partPDG[iParticle]) <= 3029) || +// abs(fParteff.partPDG[iParticle]) == 3103 || +// abs(fParteff.partPDG[iParticle]) == 3203 || +// #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 0; //TODO +// return (!fStore3DEfficiency) && (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 +} + +bool KFParticlePerformanceBase::IsCollectDalitz(int iParticle) const +{ + /** Checks if Armenteros-Podoliansky plot for decay "iParticle" should be created. */ + return 0; // TODO +// return fParteff.partPDG[iParticle] == 3006 || +// fParteff.partPDG[iParticle] == 3007 || +// fParteff.partPDG[iParticle] == 3012 || +// fParteff.partPDG[iParticle] == 3013 || +// +// fParteff.partPDG[iParticle] == 3014 || +// fParteff.partPDG[iParticle] == 3015 || +// fParteff.partPDG[iParticle] == 3017 || +// fParteff.partPDG[iParticle] == 3018 || +// fParteff.partPDG[iParticle] == 3020 || +// fParteff.partPDG[iParticle] == 3021 || +// fParteff.partPDG[iParticle] == 3023 || +// fParteff.partPDG[iParticle] == 3024 || +// fParteff.partPDG[iParticle] == 3026 || +// fParteff.partPDG[iParticle] == 3027 || +// +// fParteff.partPDG[iParticle] == 3028 || +// fParteff.partPDG[iParticle] == 3029 ; +} + +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; +} + diff --git a/StRoot/KFParticlePerformance/KFParticlePerformanceBase.h b/StRoot/KFParticlePerformance/KFParticlePerformanceBase.h new file mode 100644 index 00000000000..a958294f2f3 --- /dev/null +++ b/StRoot/KFParticlePerformance/KFParticlePerformanceBase.h @@ -0,0 +1,215 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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 "THnSparse.h" + +#include "KFPartEfficiencies.h" +#include "KFPVEfficiencies.h" + +#include +#include + +class TDirectory; +class TH1F; +class TH2F; +class TH3F; + +class TProfile; +class TProfile2D; + +class KFParticle; + +/** @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(); + ~KFParticlePerformanceBase(){} + + /// Histograms + void CreateHistos(std::string histoDir = "", TDirectory* outFile = 0, std::map decays = std::map()); + 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; } + /** Switch on collection of 3D efficiency plots. Should be called + ** before KFParticlePerformanceBase::CreateHistos(). **/ + void Store3DEfficiency() { fStore3DEfficiency = true; } + + /** 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. + bool fStore3DEfficiency; ///< Flag showing if 3D efficiency histograms should be created and collected. "False" 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, + ** dX, dY, dZ, dPx, dPy, dPz, dE, dM **/ + static const int nHistoPartParam = 26; + /** 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. + + TH2F* hPartDaughterPTheta[KFPartEfficiencies::nParticles][2]; + TH1F* hPartDaughterPhi[KFPartEfficiencies::nParticles][2]; + + static const int nHistoPartParam2D = 7; ///< Number of 2D histograms: 0 - y-pt, 1 - z-r, 2 - armenteros, 3- y-mt, 4-6 dalitz + 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 = 12; ///< Number of 3D histograms: y-pt-M, y-mt-M, b-pt-M, b-y-M, b-mt-M, ct-pt-M, dalitz1-4 + 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 = 5; ///< Number of 2D efficiency plots for each decay: y-pt, y-mt, 3 dalitz + TProfile2D* hPartEfficiency2D[KFPartEfficiencies::nParticles][3][nPartEfficiency2D]; ///< 2D efficiency plots. + THnSparseF* hPartEfficiencyMulti[KFPartEfficiencies::nParticles][4]; ///< Multidimensional efficiency: phi-theta-p-ctau-z, 0 - N reco, 1 - N mc + ///< pt-y-p-ctau, 2 - N reco, 3 - N mc + + 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; + bool IsCollectDalitz(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], THnSparseF* histoN[4], int iPart); + 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 diff --git a/StRoot/KFParticlePerformance/KFTopoPerformance.cxx b/StRoot/KFParticlePerformance/KFTopoPerformance.cxx new file mode 100644 index 00000000000..5d9e2f2b8fa --- /dev/null +++ b/StRoot/KFParticlePerformance/KFTopoPerformance.cxx @@ -0,0 +1,2687 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#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 "TFile.h" +#include "TMath.h" +#include "TH1.h" +#include "TH2.h" +#include "TH3.h" + +#include "TProfile.h" +#include "TProfile2D.h" + +#include +#include +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), + fEfficiencyMapFile(nullptr), fAcceptanceMapReco(KFPartEfficiencies::nParticles, nullptr), + fAcceptanceMapMC(KFPartEfficiencies::nParticles, nullptr),fCutsEfficiencyMapReco(KFPartEfficiencies::nParticles, nullptr), + fCutsEfficiencyMapMC(KFPartEfficiencies::nParticles, nullptr) +{ +} + +KFTopoPerformance::~KFTopoPerformance() +{ + if(fEfficiencyMapFile) fEfficiencyMapFile->Close(); +} + +void KFTopoPerformance::Set3DEfficiency(TString fileName = "") +{ + /** */ + if(fileName.IsNull()) + { + std::cout << "An empty string is provided for KFTopoPerformance::Set3DEfficiency. Stop the program." << std::endl; + exit(0); + } + + TFile* curfile = gFile; + TDirectory* curdir = gDirectory; + + fEfficiencyMapFile = new TFile(fileName.Data(), "READ"); + if(!fEfficiencyMapFile) + { + std::cout << "File defined by the KFTopoPerformance::Set3DEfficiency does not exist. Stop the program." << std::endl; + exit(0); + } + + TString path = "Particles/KFParticlesFinder/Particles/"; + for(int iDecay=0; iDecayGet(acceptanceHistoName + "_reco"); + fAcceptanceMapMC[iDecay] = (THnSparseF*) fEfficiencyMapFile->Get(acceptanceHistoName + "_mc"); + + TString cutsHistoName = path + fParteff.partName[iDecay].data() + "/Efficiency/Multidimensional/Cuts"; + fCutsEfficiencyMapReco[iDecay] = (THnSparseF*) fEfficiencyMapFile->Get(cutsHistoName + "_reco"); + fCutsEfficiencyMapMC[iDecay] = (THnSparseF*) fEfficiencyMapFile->Get(cutsHistoName + "_mc"); + } + + gFile = curfile; + gDirectory = curdir; +} + +#ifdef KFPWITHTRACKER +void KFTopoPerformance::SetNewEvent( + const AliHLTTPCCAGBTracker * const tracker, + AliHLTResizableArray *hitLabels, + AliHLTResizableArray *mcTracks, + AliHLTResizableArray *localMCPoints) +{ + vMCTracks.resize(mcTracks->Size()); + for(int iTr=0; iTr pvIndex; + for(unsigned int iTr=0; iTr= 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 mmMotherPDG(NmmPDG); //PDG for particles found by the missing mass method + vector mmChargedDaughterPDG(NmmPDG); + vector mmNeutralDaughterPDG(NmmPDG); + vector newMotherPDG(NmmPDG); + vector 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 -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 xDaughter; + vector yDaughter; + vector zDaughter; + vector< vector > nDaughtersAtPoint; + + for(int iMCDaughter=0; iMCDaughter newPointIndex; + newPointIndex.push_back(iMCDaughter); + nDaughtersAtPoint.push_back(newPointIndex); + } + } + + for(unsigned int iPoint = 0; iPoint newDaughters; + for(unsigned int iD=0; iD isDaughterFound(nDaughters); + vector isDaughterUsed(nDaughters); + for(int iDMC=0; iDMC= 15) + part.SetAsReconstructable(1); + + 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 pdg(nDaughters); + + for(unsigned int iD=0; iD isDaughterFound(nDaughters); + for(unsigned int iDMC=0; iDMC& 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= 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 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 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; iMCPVNPrimaryVertices(); iPV++ ) { + + vector &tracks = fTopoReconstructor->GetPVTrackIndexArray(iPV); + + int nPVTracks = tracks.size()>0 ? tracks.size() : -1;//tracks.size(); + + vector nTracksFromMCPV(fPrimVertices.size() + vMCParticles.size(), 0); + vector< vector > 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 nTracksBestMCPV ) + { + nTracksBestMCPV = nTracksFromMCPV[iMCPV]; + iBestMCPV = iMCPV; + } + } + + if( (iBestMCPV > -1) && (iBestMCPVGetMCData())[iTr].IsReconstructed() ) + vMCTracks[iTr].SetReconstructed(); + } + fTrackMatch.resize(AliHLTTPCCAPerformance::Instance().GetSubPerformance("Global Performance")->GetRecoData().size()); + for(int iTr=0; iTrGetRecoData())[iTr]; + if( matchInfo.IsGhost(PParameters::MinTrackPurity) || matchInfo.GetMCTrackId()<0 ) + fTrackMatch[iTr] = -1; + else + fTrackMatch[iTr] = matchInfo.GetMCTrackId(); + } +#endif + + for(unsigned int iTrack=0; iTrackGetParticles().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 isReco; + vector nClones; + + vector iParticle; + iParticle.push_back(fParteff.GetParticleIndex(pdg)); + vector< vector > isReconstructable; + vector isRecPart; + + const std::map& 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 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=0) continue; + if(!isReconstructable[iPType][iEff]) continue; + + int iMCTrack = part.GetMCTrackID(); + KFMCTrack &mcTrack = vMCTracks[iMCTrack]; + + double massMC = fParteff.partMass[iPart]; + double E = sqrt(mcTrack.P()*mcTrack.P() + massMC*massMC); + double Y = 0.5*log((E + mcTrack.Pz())/(E - mcTrack.Pz())); + double Z = mcTrack.Z(); + double R = sqrt(mcTrack.X()*mcTrack.X() + mcTrack.Y()*mcTrack.Y()); + double L = 0.f; + double Mt_mc = sqrt(mcTrack.Pt()*mcTrack.Pt()+massMC*massMC)-massMC; + double cT = -1.e10; + double decayLength = -1.e10; + + if(part.NDaughters() > 0 && !(iPart>=fParteff.fFirstStableParticleIndex && iPart<=fParteff.fLastStableParticleIndex)) + { + int mcDaughterId = part.GetDaughterIds()[0]; + KFMCTrack &mcDaughter = vMCTracks[mcDaughterId]; + + R = sqrt(mcDaughter.X()*mcDaughter.X() + mcDaughter.Y()*mcDaughter.Y()); + double dxL = mcDaughter.X() - mcTrack.X(); + double dyL = mcDaughter.Y() - mcTrack.Y(); + double dzL = mcDaughter.Z() - mcTrack.Z(); + L = sqrt(dxL*dxL + dyL*dyL + dzL*dzL); + Z = mcDaughter.Z(); + + if(mcTrack.MotherId() < 0) + { + KFParticle motherKFParticle; + float decayPoint[3] = { mcDaughter.X(), mcDaughter.Y(), mcDaughter.Z() }; + for(int iParam=0; iParam<6; iParam++) + motherKFParticle.Parameter(iParam) = mcTrack.Par()[iParam]; + motherKFParticle.Q() = round(mcTrack.Par()[6]*mcTrack.P()); + + 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][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] ); + + if(IsCollectDalitz(iPart)) + { + const KFMCTrack daughter1 = vMCTracks[part.GetDaughterIds()[2]]; + const KFMCTrack daughter2 = vMCTracks[part.GetDaughterIds()[1]]; + const KFMCTrack daughter3 = vMCTracks[part.GetDaughterIds()[0]]; + + const int pdg1 = fParteff.partDaughterPdg[iPart][0]; + const int pdg2 = fParteff.partDaughterPdg[iPart][1]; + const int pdg3 = fParteff.partDaughterPdg[iPart][2]; + + const float m1 = fParteff.GetMass(fParteff.GetParticleIndex(pdg1)); + const float m2 = fParteff.GetMass(fParteff.GetParticleIndex(pdg2)); + const float m3 = fParteff.GetMass(fParteff.GetParticleIndex(pdg3)); + + const float p1x = daughter1.Px(); + const float p1y = daughter1.Py(); + const float p1z = daughter1.Pz(); + const float E1 = sqrt(m1*m1 + p1x*p1x + p1y*p1y + p1z*p1z); + + const float p2x = daughter2.Px(); + const float p2y = daughter2.Py(); + const float p2z = daughter2.Pz(); + const float E2 = sqrt(m2*m2 + p2x*p2x + p2y*p2y + p2z*p2z); + + const float p3x = daughter3.Px(); + const float p3y = daughter3.Py(); + const float p3z = daughter3.Pz(); + const float E3 = sqrt(m3*m3 + p3x*p3x + p3y*p3y + p3z*p3z); + + const float p12x = p1x + p2x; + const float p12y = p1y + p2y; + const float p12z = p1z + p2z; + const float E12 = E1 + E2; + const float m12 = sqrt(E12*E12 - (p12x*p12x + p12y*p12y + p12z*p12z)); + + const float p13x = p1x + p3x; + const float p13y = p1y + p3y; + const float p13z = p1z + p3z; + const float E13 = E1 + E3; + const float m13 = sqrt(E13*E13 - (p13x*p13x + p13y*p13y + p13z*p13z)); + + const float p23x = p2x + p3x; + const float p23y = p2y + p3y; + const float p23z = p2z + p3z; + const float E23 = E2 + E3; + const float m23 = sqrt(E23*E23 - (p23x*p23x + p23y*p23y + p23z*p23z)); + + hPartEfficiency2D[iPart][iEff][2]->Fill( m12, m23, isReco[iPType] ); + hPartEfficiency2D[iPart][iEff][3]->Fill( m13, m23, isReco[iPType] ); + hPartEfficiency2D[iPart][iEff][4]->Fill( m12, m13, isReco[iPType] ); + } +#if 0 + if(fStore3DEfficiency) + { + const float phi = atan2(mcTrack.Py(),mcTrack.Px()); + const float theta = atan2(mcTrack.Pt(),mcTrack.Pz()); + const float eta = -log(tan(theta/2.)); + const double point[5]{phi, theta, mcTrack.P(), mcTrack.Pt(), eta}; + + if(iEff == 0) + hPartEfficiencyMulti[iPart][1]->Fill( point, 1 ); + + if(iEff == 2) + { + hPartEfficiencyMulti[iPart][0]->Fill( point, 1 ); + + const KFParticle& pv = fTopoReconstructor->GetPrimVertex(0); + const float pvPosition[3] = {pv.X(), pv.Y(), pv.Z()}; + + KFParticle mother; + if(!(iPart>=fParteff.fFirstStableParticleIndex && iPart<=fParteff.fLastStableParticleIndex)) { + const int nDaughters = part.GetDaughterIds().size(); + for(int iDaughter=0; iDaughterGetParticles()[daughterRecoId]; + mother += daughter; + } + } + else { + const int recoId = MCtoRParticleId[iP].GetBestMatch(); + mother = fTopoReconstructor->GetParticles()[recoId]; + mother.TransportToPoint(pvPosition); + } + + float l, dl; + mother.GetDistanceToVertexLine(pv, l, dl); + mother.SetProductionVertex(pv); + const double point2[5]{mcTrack.Pt(), Y, mcTrack.P(), mother.GetDecayLength(), l/dl}; + + hPartEfficiencyMulti[iPart][2]->Fill( point2, isReco[iPType] ); + hPartEfficiencyMulti[iPart][3]->Fill( point2, 1 ); + } + } +#else + if(fStore3DEfficiency) + { + const float phi = atan2(mcTrack.Py(),mcTrack.Px()); + const float theta = atan2(mcTrack.Pt(),mcTrack.Pz()); +// const float eta = -log(tan(theta/2.)); + const double point[3]{phi, theta, mcTrack.P()}; + + if(iEff == 0) + hPartEfficiencyMulti[iPart][1]->Fill( point, 1 ); + + if(iEff == 2) + { + hPartEfficiencyMulti[iPart][0]->Fill( point, 1 ); + + const KFParticle& pv = fTopoReconstructor->GetPrimVertex(0); + const float pvPosition[3] = {pv.X(), pv.Y(), pv.Z()}; + + KFParticle mother; + if(!(iPart>=fParteff.fFirstStableParticleIndex && iPart<=fParteff.fLastStableParticleIndex)) { + const int nDaughters = part.GetDaughterIds().size(); + for(int iDaughter=0; iDaughterGetParticles()[daughterRecoId]; + mother += daughter; + } + } + else { + const int recoId = MCtoRParticleId[iP].GetBestMatch(); + mother = fTopoReconstructor->GetParticles()[recoId]; + mother.TransportToPoint(pvPosition); + } + +// float l, dl; +// mother.GetDistanceToVertexLine(pv, l, dl); + mother.SetProductionVertex(pv); + const double point2[4]{mother.GetPhi(), mother.GetTheta(), mother.GetP(), mother.GetDecayLength()}; + + hPartEfficiencyMulti[iPart][2]->Fill( point2, isReco[iPType] ); + hPartEfficiencyMulti[iPart][3]->Fill( point2, 1 ); + } + } +#endif + } + } + } + } + } + + 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<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<GetBin(point); + const float nReco = fAcceptanceMapReco[iParticle]->GetBinContent(binReco); + const Long64_t binMC = fAcceptanceMapMC[iParticle]->GetBin(point); + const float nMC = fAcceptanceMapMC[iParticle]->GetBinContent(binMC); + const float eff = nReco/nMC; + + return ((nMC > 0.f) && (eff > 0.0001f)) ? eff : 0.f; +} + +float KFTopoPerformance::GetCutsEffWeight(const double* point, const int iParticle) +{ + const Long64_t binReco = fCutsEfficiencyMapReco[iParticle]->GetBin(point); + const float nReco = fCutsEfficiencyMapReco[iParticle]->GetBinContent(binReco); + const Long64_t binMC = fCutsEfficiencyMapMC[iParticle]->GetBin(point); + const float nMC = fCutsEfficiencyMapMC[iParticle]->GetBinContent(binMC); + const float eff = nReco/nMC; + + return ((nMC > 0.f) && (eff > 0.01)) ? eff : 0.f; +} + +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* multiplicities) +{ + /** Fills provided histograms with the parameters of the given particle. */ + const std::map& decays = fTopoReconstructor->GetKFParticleFinder()->GetReconstructionList(); + if(!(decays.empty()) && (iParticle < fParteff.fFirstStableParticleIndex || iParticle > fParteff.fLastStableParticleIndex)) + if(decays.find(TempPart.GetPDG()) == decays.end()) return; + + if(TempPart.NDaughters() == 1 && TempPart.GetDeviationFromVertex(fTopoReconstructor->GetPrimVertex(0)) > 18.) return; + + float M, M_t, ErrM; + float dL = 0.f, ErrdL = 0.f; // decay length + float cT = 0.f, ErrcT = 0.f; // 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); + + KFParticle TempPartTopo = TempPart; + TempPartTopo.SetProductionVertex(fTopoReconstructor->GetPrimVertex(0)); + if(TempPart.NDaughters() > 1) + { + TempPartTopo.GetDecayLength(dL,ErrdL); + TempPartTopo.GetLifeTime(cT,ErrcT); + } + Pt = TempPartTopo.GetPt(); + Rapidity = TempPartTopo.GetRapidity(); + Theta = TempPartTopo.GetTheta(); + Phi = TempPartTopo.GetPhi(); + + float chi2 = TempPart.GetChi2(); + Int_t ndf = TempPart.GetNDF(); + float prob = TMath::Prob(chi2, ndf);//(TDHelper::Chi2IProbability( ndf, chi2 )); + X = TempPart.GetX(); + Y = TempPart.GetY(); + Z = TempPart.GetZ(); + R = sqrt(X*X+Y*Y); + M_t = sqrt(Pt*Pt+fParteff.GetMass(iParticle)*fParteff.GetMass(iParticle))-fParteff.GetMass(iParticle); + + KFParticleSIMD tempSIMDPart(TempPart); + float32_v l,dl; + KFParticleSIMD pv(fTopoReconstructor->GetPrimVertex(iPV)); + tempSIMDPart.GetDistanceToVertexLine(pv, l, dl); + + float weight = 1.f; + if(fAcceptanceMapReco[iParticle] && fAcceptanceMapMC[iParticle] && + fCutsEfficiencyMapReco[iParticle] && fCutsEfficiencyMapMC[iParticle]) + { + const double pointAcceptance[3]{Phi, Theta, P}; + const double pointCuts[4]{Phi, Theta, P, dL}; + weight = GetAcceptanceWeight(pointAcceptance, iParticle) * GetCutsEffWeight(pointCuts, iParticle); + if(weight > 0.f) + weight = 1.f/weight; + } + +#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; + + // float r = sqrt(X*X + Y*Y); +// if(r < 5 ) return; //TODO collider +#endif + +// float M0 = M; +// for(int iDM=0; iDMGetParticles()[TempPart.DaughterIds()[iDM]].GetPDG(); +// const int daughterIndexPDG = fParteff.GetParticleIndex(daughterPDG); +// Double_t daughterMass = (daughterIndexPDG>=0) ? fParteff.partMass[daughterIndexPDG] :0.13957; +// M0 -= daughterMass; +// } + + 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 }; + float errors[8] = {TempPart.GetErrX(), TempPart.GetErrY(), TempPart.GetErrZ(), + TempPart.GetErrPx()/fabsf(TempPart.GetPx()), TempPart.GetErrPy()/fabsf(TempPart.GetPy()), TempPart.GetErrPz()/fabsf(TempPart.GetPz()), + TempPart.GetErrE()/TempPart.GetE(), ErrM}; + + //for all particle-candidates + for(int iParam=0; iParam<17; iParam++) + histoParameters[0][iParticle][iParam]->Fill(parameters[iParam], 1); + for(int iParam=0; iParam<8; iParam++) + histoParameters[0][iParticle][18+iParam]->Fill(errors[iParam], 1); + + 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, weight); + histoParameters3D[0][iParticle][1]->Fill(Rapidity, M_t, M, weight); + 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, weight); + + if(IsCollectDalitz(iParticle)) + { + KFParticle pion = fTopoReconstructor->GetParticles()[TempPart.DaughterIds()[0]]; + KFParticle fragment = fTopoReconstructor->GetParticles()[TempPart.DaughterIds()[1]]; + KFParticle proton = fTopoReconstructor->GetParticles()[TempPart.DaughterIds()[2]]; + + const float vtx[3] = {X, Y, Z}; + pion.TransportToPoint(vtx); + fragment.TransportToPoint(vtx); + proton.TransportToPoint(vtx); + + KFParticle p12; + p12 += fragment; + p12 += proton; + float m12, dm12; + p12.GetMass(m12, dm12); + + KFParticle p23; + p23 += pion; + p23 += proton; + float m23, dm23; + p23.GetMass(m23, dm23); + + KFParticle p13; + p13 += pion; + p13 += fragment; + float m13, dm13; + p13.GetMass(m13, dm13); + + histoParameters3D[0][iParticle][6]->Fill(m12, m23, M, 1); + histoParameters3D[0][iParticle][7]->Fill(m13, m23, M, 1); + histoParameters3D[0][iParticle][8]->Fill(m12, m13, M, 1); + + histoParameters3D[0][iParticle][ 9]->Fill(m12*m12, m23*m23, M, 1); + histoParameters3D[0][iParticle][10]->Fill(m13*m13, m23*m23, M, 1); + histoParameters3D[0][iParticle][11]->Fill(m12*m12, m13*m13, M, 1); + + histoParameters2D[0][iParticle][4]->Fill( m12, m23, 1 ); + histoParameters2D[0][iParticle][5]->Fill( m13, m23, 1 ); + histoParameters2D[0][iParticle][6]->Fill( m12, m13, 1 ); +#if 0 + float fMass = fParteff.partMass[fParteff.GetParticleIndex(fragment.GetPDG())]; + float pMass = fParteff.partMass[fParteff.GetParticleIndex(proton.GetPDG())]; + float piMass= fParteff.partMass[fParteff.GetParticleIndex(pion.GetPDG())]; + + const float gamma = TempPart.GetE()/M; + const float bgamma = P/M; + const float pLF = (fragment.Px()*TempPart.Px() + + fragment.Py()*TempPart.Py() + + fragment.Pz()*TempPart.Pz())/P; + const float EcF = fragment.GetE()*gamma - pLF*bgamma; + const float pLP = (proton.Px()*TempPart.Px() + + proton.Py()*TempPart.Py() + + proton.Pz()*TempPart.Pz())/P; + const float EcP = proton.GetE()*gamma - pLP*bgamma; + const float pLPi= (pion.Px()*TempPart.Px() + + pion.Py()*TempPart.Py() + + pion.Pz()*TempPart.Pz())/P; + const float EcPi= pion.GetE()*gamma - pLPi*bgamma; + + const float T3 = EcF - fMass; + const float T1 = EcP - pMass; + const float T2 = EcPi- piMass; + + const float Q = M - fMass - pMass - piMass; + std::cout << "Q " << Q << " T1 " << T1 << " T2 " << T2 << " T3 " << T3 << " Ts " << (T1+T2+T3) << std::endl; + const float xTQ = sqrt(3.)*(T1 - T2)/Q; + const float yTQ = (2.f*T3 - T1 - T2)/Q; + std::cout << "x " << xTQ << " y " << yTQ << std::endl; + std::cin.get(); + histoParameters3D[0][iParticle][10]->Fill(xTQ, yTQ, M, 1); +#endif + } + } + + //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], weight); + for(int iParam=0; iParam<8; iParam++) + histoParameters[4][iParticle][18+iParam]->Fill(errors[iParam], weight); + + if(multiplicities) + multiplicities[4][iParticle]++; + + histoParameters2D[4][iParticle][0]->Fill(Rapidity, Pt, weight); + histoParameters2D[4][iParticle][3]->Fill(Rapidity, M_t, weight); + + if(drawZR) + if(histoParameters2D[4][iParticle][1]) + histoParameters2D[4][iParticle][1]->Fill(Z,R,1); + if(TempPart.NDaughters() == 2 && IsCollectArmenteros(iParticle)) + 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], weight); + for(int iParam=0; iParam<8; iParam++) + histoParameters[5][iParticle][18+iParam]->Fill(errors[iParam], weight); + + if(multiplicities) + multiplicities[5][iParticle]++; + + histoParameters2D[5][iParticle][0]->Fill(Rapidity, Pt, weight); + histoParameters2D[5][iParticle][3]->Fill(Rapidity, M_t, weight); + + if(drawZR) + if(histoParameters2D[5][iParticle][1]) + histoParameters2D[5][iParticle][1]->Fill(Z,R,1); + if(TempPart.NDaughters() == 2 && IsCollectArmenteros(iParticle)) + 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]); + for(int iParam=0; iParam<8; iParam++) + histoParameters[iSet][iParticle][18+iParam]->Fill(errors[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(TempPart.NDaughters() == 2 && IsCollectArmenteros(iParticle)) + 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 }; + + if(TempPart.NDaughters() == 1) + TempPart.TransportToPoint(decayVtx); + + 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 && (TempPart.NDaughters() > 1)) + { + for(int iD=0; iDGetParticles()[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(); + + float32_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}; + + float32_v dS[2] = {0.f, 0.f}; + float32_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); + float32_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; + } + } + + float32_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 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; iPGetParticles().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 && fStorePrimSecHistograms) + { + for(int iSet=0; iSet& SecondaryCandidates = fTopoReconstructor->GetKFParticleFinder()->GetSecondaryCandidates()[iSet]; + for(unsigned int iP=0; iPGetParticles()[id]; + FillParticleParameters(TempPart, iParticle, id, 0, hPartParamSecondary, hPartParam2DSecondary, 0); + } + } + + for(int iSet=0; iSetNPrimaryVertices(); iPV++) + { + const std::vector& PrimaryCandidates = fTopoReconstructor->GetKFParticleFinder()->GetPrimaryCandidates()[iSet][iPV]; + for(unsigned int iP=0; iPGetParticles()[id]; + FillParticleParameters(TempPart,iParticle, id, iPV, hPartParamPrimary, hPartParam2DPrimary, 0, hFitQANoConstraint); + } + + const std::vector& PrimaryCandidatesTopo = fTopoReconstructor->GetKFParticleFinder()->GetPrimaryTopoCandidates()[iSet][iPV]; + for(unsigned int iP=0; iP& PrimaryCandidatesTopoMass = fTopoReconstructor->GetKFParticleFinder()->GetPrimaryTopoMassCandidates()[iSet][iPV]; + for(unsigned int iP=0; iPGetParticles().size(); iP++) + { + KFParticle TempPart = fTopoReconstructor->GetParticles()[iP]; + KFParticle vtx = fTopoReconstructor->GetPrimVertex(0); + + if(fStoreMCHistograms) { + 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 1 //wo MC + int iParticle = fParteff.GetParticleIndex(fTopoReconstructor->GetParticles()[iP].GetPDG()); + if(iParticle > -1 && iParticleFill(chi2 ); +#else + 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 && iParticleFill(chi2 ); +#endif + } + + + + // ============================================================================================================================== + for(int iParticle=0; iParticle<=92; iParticle++) + { + if( !(iParticle>=48 || iParticle == 13 || iParticle == 14 || iParticle == 37 || iParticle == 38) ) continue; + + const std::map& decays = fTopoReconstructor->GetKFParticleFinder()->GetReconstructionList(); + if(!(decays.empty()) && (iParticle < fParteff.fFirstStableParticleIndex || iParticle > fParteff.fLastStableParticleIndex)) + if(decays.find(fParteff.partPDG[iParticle]) == decays.end()) continue; + + std::vector used; + + KFParticleSIMD pv(fTopoReconstructor->GetPrimVertex(0)); + + for(unsigned int iP=0; iPGetParticles().size(); iP++) + { + int jParticle = fParteff.GetParticleIndex(fTopoReconstructor->GetParticles()[iP].GetPDG()); + if(iParticle != jParticle) continue; + + KFParticle particle = fTopoReconstructor->GetParticles()[iP]; + KFParticle d0 = fTopoReconstructor->GetParticles()[particle.DaughterIds()[0]]; + KFParticle d1 = fTopoReconstructor->GetParticles()[particle.DaughterIds()[1]]; + + const bool needSwap = fParteff.partDaughterPdg[iParticle][0] == d1.GetPDG(); + + KFParticle daughter0 = needSwap ? d1 : d0; + KFParticle daughter1 = needSwap ? d0 : d1; + + daughter0.SetProductionVertex(fTopoReconstructor->GetPrimVertex(0)); + daughter1.SetProductionVertex(fTopoReconstructor->GetPrimVertex(0)); + + const float px0 = daughter0.Px(); + const float py0 = daughter0.Py(); + const float pz0 = daughter0.Pz(); + const float pt0 = sqrt(px0 * px0 + py0 * py0); + const float p0 = sqrt(px0 * px0 + py0 * py0 + pz0 * pz0); + const float theta0 = atan2(pt0, pz0); + const float phi0 = atan2(py0, px0); + + hPartDaughterPTheta[iParticle][0]->Fill(p0 / fabsf(daughter0.Q()), theta0); + hPartDaughterPhi[iParticle][0]->Fill(phi0); + + const float px1 = daughter1.Px(); + const float py1 = daughter1.Py(); + const float pz1 = daughter1.Pz(); + const float pt1 = sqrt(px1 * px1 + py1 * py1); + const float p1 = sqrt(px1 * px1 + py1 * py1 + pz1 * pz1); + const float theta1 = atan2(pt1, pz1); + const float phi1 = atan2(py1, px1); + + hPartDaughterPTheta[iParticle][1]->Fill(p1 / fabsf(daughter1.Q()), theta1); + hPartDaughterPhi[iParticle][1]->Fill(phi1); + } + } + // ============================================================================================================================== + + + + //fill histograms of the primary vertex quality + for(int iPV = 0; iPVNPrimaryVertices(); iPV++) + { + KFParticle & vtx = fTopoReconstructor->GetPrimVertex(iPV); + vector &tracks = fTopoReconstructor->GetPVTrackIndexArray(iPV); + + Double_t probPV = TMath::Prob(vtx.Chi2(), vtx.NDF());//(TDHelper::Chi2IProbability( ndf, chi2 )); + + 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); + + hPVParam2D[0]->Fill(vtx.X(),vtx.Y()); + + if(!fStoreMCHistograms) continue; + + vector 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[ 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; iZFill(dzPV[iZ]); + + + 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; iZFill(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; iZFill(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; iZFill(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; iZFill(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(dRPVr[0]/sqrt(errPV[0])), + static_cast(dRPVr[1]/sqrt(errPV[1])), + static_cast(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 + if(fStoreMCHistograms) { + for(unsigned int iP=0; iPGetParticles().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; iMCTrack0 && !(iPDG>=fParteff.fFirstStableParticleIndex && iPDG<=fParteff.fLastStableParticleIndex)) + { + X = vMCTracks[part.GetDaughterIds()[0]].X(); + Y = vMCTracks[part.GetDaughterIds()[0]].Y(); + Z = vMCTracks[part.GetDaughterIds()[0]].Z(); + dx = X - vMCTracks[iMCTrack].X(); + dy = Y - vMCTracks[iMCTrack].Y(); + dz = Z - vMCTracks[iMCTrack].Z(); + + KFParticle motherKFParticle; + float decayPoint[3] = { X, Y, Z }; + for(int iP=0; iP<6; iP++) + motherKFParticle.Parameter(iP) = vMCTracks[iMCTrack].Par()[iP]; + motherKFParticle.Q() = round(vMCTracks[iMCTrack].Par()[6]*vMCTracks[iMCTrack].P()); + + float dsdr[6]; + float s = motherKFParticle.GetDStoPoint(decayPoint, dsdr); + int iParticlePDG = fParteff.GetParticleIndex(vMCTracks[iMCTrack].PDG()); + float massMC = (iParticlePDG>=0) ? fParteff.partMass[iParticlePDG] :0.13957; + + cT = s*massMC; + decayLength = s*vMCTracks[iMCTrack].P(); + } + else + { + X = vMCTracks[iMCTrack].X(); + Y = vMCTracks[iMCTrack].Y(); + Z = vMCTracks[iMCTrack].Z(); + } + R = sqrt(X*X+Y*Y); + float L = sqrt(dx*dx + dy*dy + dz*dz); + + float Theta = atan2(vMCTracks[iMCTrack].Pt(),vMCTracks[iMCTrack].Pz()); + float Phi = atan2(vMCTracks[iMCTrack].Py(),vMCTracks[iMCTrack].Px()); + + if(fAcceptanceMapReco[iPDG] && fAcceptanceMapMC[iPDG] && + fCutsEfficiencyMapReco[iPDG] && fCutsEfficiencyMapMC[iPDG]) + { + const double pointAcceptance[3]{Phi, Theta, P}; + const double point2[4]{Phi, Theta, P, decayLength}; + float weight = GetAcceptanceWeight(pointAcceptance, iPDG)*GetCutsEffWeight(point2, iPDG); + if(weight <= 0.f) continue; + } + + float parameters[17] = {M, P, Pt, Rapidity, decayLength, cT, 0, 0, Theta, Phi, X, Y, Z, R, L, 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) && part.NDaughters() == 2) + { + 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); + } + + if(IsCollectDalitz(iPDG) && part.NDaughters() == 3) + { + const KFMCTrack daughter1 = vMCTracks[part.GetDaughterIds()[2]]; + const KFMCTrack daughter2 = vMCTracks[part.GetDaughterIds()[1]]; + const KFMCTrack daughter3 = vMCTracks[part.GetDaughterIds()[0]]; + + const int pdg1 = fParteff.partDaughterPdg[iPDG][0]; + const int pdg2 = fParteff.partDaughterPdg[iPDG][1]; + const int pdg3 = fParteff.partDaughterPdg[iPDG][2]; + + const float m1 = fParteff.GetMass(fParteff.GetParticleIndex(pdg1)); + const float m2 = fParteff.GetMass(fParteff.GetParticleIndex(pdg2)); + const float m3 = fParteff.GetMass(fParteff.GetParticleIndex(pdg3)); + + const float p1x = daughter1.Px(); + const float p1y = daughter1.Py(); + const float p1z = daughter1.Pz(); + const float E1 = sqrt(m1*m1 + p1x*p1x + p1y*p1y + p1z*p1z); + + const float p2x = daughter2.Px(); + const float p2y = daughter2.Py(); + const float p2z = daughter2.Pz(); + const float E2 = sqrt(m2*m2 + p2x*p2x + p2y*p2y + p2z*p2z); + + const float p3x = daughter3.Px(); + const float p3y = daughter3.Py(); + const float p3z = daughter3.Pz(); + const float E3 = sqrt(m3*m3 + p3x*p3x + p3y*p3y + p3z*p3z); + + const float p12x = p1x + p2x; + const float p12y = p1y + p2y; + const float p12z = p1z + p2z; + const float E12 = E1 + E2; + const float m12 = sqrt(E12*E12 - (p12x*p12x + p12y*p12y + p12z*p12z)); + + const float p13x = p1x + p3x; + const float p13y = p1y + p3y; + const float p13z = p1z + p3z; + const float E13 = E1 + E3; + const float m13 = sqrt(E13*E13 - (p13x*p13x + p13y*p13y + p13z*p13z)); + + const float p23x = p2x + p3x; + const float p23y = p2y + p3y; + const float p23z = p2z + p3z; + const float E23 = E2 + E3; + const float m23 = sqrt(E23*E23 - (p23x*p23x + p23y*p23y + p23z*p23z)); + + hPartParam2D[6][iPDG][4]->Fill( m12, m23, 1 ); + hPartParam2D[6][iPDG][5]->Fill( m13, m23, 1 ); + hPartParam2D[6][iPDG][6]->Fill( m12, m13, 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; iHAdd(hFitDaughtersQA[iK0][iH]); + hFitQA[iV0][iH]->Add(hFitQA[iK0][iH]); + } + + for(int iV=0; iV<4; iV++) + for(int iH=0; iHAdd(hPartParam[iV][iK0][iH]); +} + +void KFTopoPerformance::FillHistos(const KFPHistogram* histograms) +{ + /** Fill histograms with the histograms from the provided KFPHistogram object. */ + for(int iParticle=0; iParticleGetHistogramSet(0).GetNHisto1D(); + for(int iHistogram=0; iHistogramGetHistogram(iParticle,iHistogram); + for(int iBin=0; iBinSetBinContent( iBin, histogram.GetHistogram()[iBin] ); + } + } +} diff --git a/StRoot/KFParticlePerformance/KFTopoPerformance.h b/StRoot/KFParticlePerformance/KFTopoPerformance.h new file mode 100644 index 00000000000..c1cadb77f1b --- /dev/null +++ b/StRoot/KFParticlePerformance/KFTopoPerformance.h @@ -0,0 +1,178 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFTOPOPERFORMANCE_H +#define KFTOPOPERFORMANCE_H + + +#include "KFParticlePerformanceBase.h" + +#include "KFMCVertex.h" +#include "KFMCTrack.h" +#include +#include + +#include "KFPartMatch.h" +#include "KFMCParticle.h" + +class AliHLTTPCCAGBTracker; + +class KFParticleTopoReconstructor; +class KFPHistogram; + +class TFile; + +/** @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(); + ~KFTopoPerformance(); +#ifdef KFPWITHTRACKER + void SetNewEvent( + const AliHLTTPCCAGBTracker * const Tracker, + AliHLTResizableArray *hitLabels, + AliHLTResizableArray *mcTracks, + AliHLTResizableArray *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. + void CheckMCTracks(); // fill mcData. + // Find reco-MCTracks correspondence + void MatchTracks(); // fill recoData. + // Calculate efficiencies + + /// Histograms + void FillHistos(); + void FillHistos(const KFPHistogram* histograms); + void FillMCHistos(); + + void AddV0Histos(); + + void SetTrackMatch(const std::vector& trackMatch) { fTrackMatch = trackMatch;} ///< Fill matching between Monte Carlo and reconstructed tracks. + void SetMCTracks(const std::vector& 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 GetPrimVertices() { return fPrimVertices; } ///< Returns Monte Carlo primary vertices in the current event. + const std::vector& MCParticles() { return vMCParticles; } ///< Returns Monte Carlo particles in the current event. + const std::vector& ParticlesMatch() { return RtoMCParticleId; } ///< Returns matching between reconstructed and Monte Carlo particles. + const std::vector& GetMCtoRPVId() { return MCtoRPVId; } ///< Returns matching between Monte Carlo and reconstructed primary vertices. + const std::vector& 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. + + void Set3DEfficiency(TString fileName); + + 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* multiplicities = 0); + float GetAcceptanceWeight(const double* point, const int iParticle); + float GetCutsEffWeight(const double* point, const int iParticle); + + const KFParticleTopoReconstructor *fTopoReconstructor; ///< Pointer to the KFParticleTopoReconstructor object with particles and vertices to be analysed. + + std::vector fPrimVertices; ///< Monte Carlo primary vertices. + std::vector fMCTrackToMCPVMatch; ///< Matching of Monte Carlo tracks and corresponding primary vertex + std::vector fPVPurity; ///< Purity of the primary vertices. + std::vector fPVTracksRate[4]; ///< Ratio in the primary vertices of: 0 - ghost tracks, 1 - from trigger PV, 2 - from pileup, 3 - from physics background. + std::vector fNCorrectPVTracks; ///< Number of correctly attached tracks in the corresponding reconstructed primary vertex. + + std::vector fTrackMatch; ///< Matching between reconstructed tracks and + std::vector vMCTracks; ///< Monte Carlo tracks (parameters of the particle trajectories at the production point). + std::vector vMCParticles; ///< Monte Carlo particles. + std::vector 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 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 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 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 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. + + TFile* fEfficiencyMapFile; + std::vector fAcceptanceMapReco; + std::vector fAcceptanceMapMC; + std::vector fCutsEfficiencyMapReco; + std::vector fCutsEfficiencyMapMC; +}; + +#endif diff --git a/StRoot/KFParticlePerformance/PACKAGE b/StRoot/KFParticlePerformance/PACKAGE new file mode 100644 index 00000000000..7757b526483 --- /dev/null +++ b/StRoot/KFParticlePerformance/PACKAGE @@ -0,0 +1,6 @@ +# $Id $ +# package KFParticlePerformance +# author: +#Library:libKFParticlePerformance.so:LIBS += -lStChain -lStDbBroker +Library:libKFParticlePerformance.so:LIBS += -lKFParticle +#Library:libKFParticlePerformance.so:LIBS += -lStChain -lStDbBroker diff --git a/StRoot/KFParticleTest/KFParticleK0.ref b/StRoot/KFParticleTest/KFParticleK0.ref new file mode 100644 index 00000000000..7cf20111b52 --- /dev/null +++ b/StRoot/KFParticleTest/KFParticleK0.ref @@ -0,0 +1,85 @@ + ******************************************* + * * + * W E L C O M E to R O O T * + * * + * Version 5.34/39 12 March 2018 * + * * + * You are welcome to visit our Web site * + * http://root.cern.ch * + * * + ******************************************* + +ROOT 5.34/39 (heads/v5-34-00-patches@v5-34-38-1-g507abd2, Jun 13 2024, 09:51:00 on linuxx8664gcc) + +CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010 +Type ? for help. Commands must be C++ statements. +Enclose multiple statements between { }. +*** Float Point Exception is OFF *** + *** Start at Date : Sun Oct 27 09:29:01 2024 +QAInfo:You are using STAR_LEVEL : TFG24e, git = heads/TFG,tag:a73d8f19a4, ROOT_LEVEL : 5.99.99 and node : l409.l4.bnl.local with 40 Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz + +Processing StRoot/KFParticleTest/KFParticleTest.C... +Try different constructors + +1. Construction from Vertex + +Vertex Particle p1 + p( -1, 0, 0) x: 0.000+/- 0.100 y: 0.000+/- 0.100 z: 10.000+/- 0.100 M: 0.000 p: 0.000 pdg: 0 Q: 0 chi2/NDF : 1.01/ 1 +Set Field 4.980 + +2. Construction from Track + +Track Particle p2 + p( -1, 0, 0) x: -0.062+/- 0.006 y: -1.358+/- 0.218 z: 27.147+/- 0.179 px: 0.625+/- 0.008 py: -0.029+/- 0.003 pz: -0.185+/- 0.003 M: 0.140+/- 0.000 p: 0.653+/- 0.008 pdg: -211 Q:-1 chi2/NDF : 1.50/ 1 + +3. Now we will create one more particle from track and call the construction from these 2 particles + +Track Particle p3 + p( -1, 0, 0) x: -0.204+/- 0.015 y: 3.068+/- 0.299 z: -19.940+/- 0.335 px: 0.375+/- 0.004 py: 0.025+/- 0.003 pz: 0.190+/- 0.003 M: 0.140+/- 0.000 p: 0.422+/- 0.004 pdg: 211 Q: 1 chi2/NDF : 2.50/ 2 +Particle p4(p2,p3) + p( -1, 0, 0) x: 58.499+/- 0.463 y: 0.071+/- 0.137 z: 9.856+/- 0.167 px: 0.994+/- 0.008 py: -0.004+/- 0.004 pz: 0.006+/- 0.004 M: 0.497+/- 0.004 p: 0.994+/- 0.008 pdg: 0 Q: 0 chi2/NDF : 0.01/ 1 ND: 2:-1,-1 + +4. Construction with constrained Mass or (and) vertex position values + +4.1 Construction with constrained Mass, without vertex hypothesis + +Dauthers + p( -1, 0, 0) x: -0.062+/- 0.006 y: -1.358+/- 0.218 z: 27.147+/- 0.179 px: 0.625+/- 0.008 py: -0.029+/- 0.003 pz: -0.185+/- 0.003 M: 0.140+/- 0.000 p: 0.653+/- 0.008 pdg: -211 Q:-1 chi2/NDF : 1.50/ 1 + p( -1, 0, 0) x: -0.204+/- 0.015 y: 3.068+/- 0.299 z: -19.940+/- 0.335 px: 0.375+/- 0.004 py: 0.025+/- 0.003 pz: 0.190+/- 0.003 M: 0.140+/- 0.000 p: 0.422+/- 0.004 pdg: 211 Q: 1 chi2/NDF : 2.50/ 2 +Mass 0.498 +Particle K0 +p( -1, 0, 0) x: 58.492+/- 0.460 y: 0.069+/- 0.136 z: 9.856+/- 0.167 px: 0.995+/- 0.006 py: -0.004+/- 0.004 pz: 0.006+/- 0.004 M: 0.498 p: 0.995+/- 0.006 pdg: 0 Q: 0 chi2/NDF : 0.03/ 2 ND: 2:-1,-1 + Add parent Vertex + K0 with vertex p( -1, 0, 0) x: -0.001+/- 0.100 y: 0.038+/- 0.083 z: 9.958+/- 0.091 px: 0.999+/- 0.006 py: -0.000+/- 0.003 pz: 0.000+/- 0.003 S: 58.571+/- 0.579 M: 0.498+/- 0.000 t: 29.143+/- 0.555 p: 0.999+/- 0.006 pdg: 0 Q: 0 chi2/NDF : 3.17/ 4 ND: 2:-1,-1 + +4.2 Construction without constrained Mass, with vertex hypothesis + +Dauthers + p( -1, 0, 0) x: -0.062+/- 0.006 y: -1.358+/- 0.218 z: 27.147+/- 0.179 px: 0.625+/- 0.008 py: -0.029+/- 0.003 pz: -0.185+/- 0.003 M: 0.140+/- 0.000 p: 0.653+/- 0.008 pdg: -211 Q:-1 chi2/NDF : 1.50/ 1 + p( -1, 0, 0) x: -0.204+/- 0.015 y: 3.068+/- 0.299 z: -19.940+/- 0.335 px: 0.375+/- 0.004 py: 0.025+/- 0.003 pz: 0.190+/- 0.003 M: 0.140+/- 0.000 p: 0.422+/- 0.004 pdg: 211 Q: 1 chi2/NDF : 2.50/ 2 +PV + p( -1, 0, 0) x: 0.000+/- 0.100 y: 0.000+/- 0.100 z: 10.000+/- 0.100 M: 0.000 p: 0.000 pdg: 0 Q: 0 chi2/NDF : 1.01/ 1 +K0_1 + p( -1, 0, 0) x: -0.002+/- 0.100 y: 0.038+/- 0.083 z: 9.958+/- 0.091 px: 0.999+/- 0.008 py: -0.000+/- 0.003 pz: 0.000+/- 0.003 S: 58.575+/- 0.665 M: 0.498+/- 0.004 t: 29.147+/- 0.772 p: 0.999+/- 0.008 pdg: 0 Q: 0 chi2/NDF : 3.17/ 3 ND: 2:-1,-1 + +4.3 Construction with constrained Mass, with vertex hypothesis + +Dauthers + p( -1, 0, 0) x: -0.062+/- 0.006 y: -1.358+/- 0.218 z: 27.147+/- 0.179 px: 0.625+/- 0.008 py: -0.029+/- 0.003 pz: -0.185+/- 0.003 M: 0.140+/- 0.000 p: 0.653+/- 0.008 pdg: -211 Q:-1 chi2/NDF : 1.50/ 1 + p( -1, 0, 0) x: -0.204+/- 0.015 y: 3.068+/- 0.299 z: -19.940+/- 0.335 px: 0.375+/- 0.004 py: 0.025+/- 0.003 pz: 0.190+/- 0.003 M: 0.140+/- 0.000 p: 0.422+/- 0.004 pdg: 211 Q: 1 chi2/NDF : 2.50/ 2 +PV + p( -1, 0, 0) x: 0.000+/- 0.100 y: 0.000+/- 0.100 z: 10.000+/- 0.100 M: 0.000 p: 0.000 pdg: 0 Q: 0 chi2/NDF : 1.01/ 1 +Mass 0.498 +K0_2 + p( -1, 0, 0) x: -0.001+/- 0.100 y: 0.038+/- 0.083 z: 9.958+/- 0.091 px: 0.999+/- 0.006 py: -0.000+/- 0.003 pz: 0.000+/- 0.003 S: 58.571+/- 0.579 M: 0.498+/- 0.000 t: 29.143+/- 0.555 p: 0.999+/- 0.006 pdg: 0 Q: 0 chi2/NDF : 3.17/ 4 ND: 2:-1,-1 + +4.4 Construction K0_3(p2,p3) without constrained Mass, without vertex hypothesis + +Dauthers + p( -1, 0, 0) x: -0.062+/- 0.006 y: -1.358+/- 0.218 z: 27.147+/- 0.179 px: 0.625+/- 0.008 py: -0.029+/- 0.003 pz: -0.185+/- 0.003 M: 0.140+/- 0.000 p: 0.653+/- 0.008 pdg: -211 Q:-1 chi2/NDF : 1.50/ 1 + p( -1, 0, 0) x: -0.204+/- 0.015 y: 3.068+/- 0.299 z: -19.940+/- 0.335 px: 0.375+/- 0.004 py: 0.025+/- 0.003 pz: 0.190+/- 0.003 M: 0.140+/- 0.000 p: 0.422+/- 0.004 pdg: 211 Q: 1 chi2/NDF : 2.50/ 2 +K0_3 + p( -1, 0, 0) x: 58.499+/- 0.463 y: 0.071+/- 0.137 z: 9.856+/- 0.167 px: 0.994+/- 0.008 py: -0.004+/- 0.004 pz: 0.006+/- 0.004 M: 0.497+/- 0.004 p: 0.994+/- 0.008 pdg: 0 Q: 0 chi2/NDF : 0.01/ 1 ND: 2:-1,-1 + +This is the end of ROOT -- Goodbye + diff --git a/StRoot/KFParticleTest/KFParticleTest.C b/StRoot/KFParticleTest/KFParticleTest.C new file mode 100644 index 00000000000..eac76a6c7d7 --- /dev/null +++ b/StRoot/KFParticleTest/KFParticleTest.C @@ -0,0 +1,27 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +void KFParticleTest() { + if (! TClass::GetClass("KFParticle")) gSystem->Load("KFParticle"); + if (! TClass::GetClass("KFParticleTest")) gSystem->Load("KFParticleTest"); + KFParticleTest kfptest; + kfptest.RunTest(); +} diff --git a/StRoot/KFParticleTest/KFParticleTest.cxx b/StRoot/KFParticleTest/KFParticleTest.cxx new file mode 100644 index 00000000000..c81d4dfb97d --- /dev/null +++ b/StRoot/KFParticleTest/KFParticleTest.cxx @@ -0,0 +1,225 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "KFParticle.h" +#include "KFPTrack.h" +#include "KFPVertex.h" +#include "KFParticleSIMD.h" +#include "KFParticleTest.h" + +#include +#include +#include + +#ifndef KFParticleStandalone +ClassImp(KFParticleTest) +#endif + +std::ostream& operator<<(std::ostream& os, const KFParticle& 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; +} + +KFParticleTest::KFParticleTest():fMotherSingle(0),fMotherSIMD(0) +{ + fMotherSingle = new KFParticle(); + fMotherSIMD = new KFParticleSIMD(); +} + +KFParticleTest::~KFParticleTest() +{ + if(fMotherSingle) delete fMotherSingle; + if(fMotherSIMD) delete fMotherSIMD; +} + +void KFParticleTest::RunTest() +{ + RunTestSingle(); + RunTestSIMD(); +} + +void KFParticleTest::RunTestSingle() +{ + 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; + p4 += p2; + p4 += 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 KFParticle::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; +} + +void KFParticleTest::RunTestSIMD() +{ +} + +void KFParticleTest::CompareSingleAndSIMDResults() +{ +} + +void KFParticleTest::PrintTutorial() +{ +} diff --git a/StRoot/KFParticleTest/KFParticleTest.h b/StRoot/KFParticleTest/KFParticleTest.h new file mode 100644 index 00000000000..cc44220e62d --- /dev/null +++ b/StRoot/KFParticleTest/KFParticleTest.h @@ -0,0 +1,53 @@ +/* + * This file is part of KFParticle package + * Copyright (C) 2007-2019 FIAS Frankfurt Institute for Advanced Studies + * 2007-2019 Goethe University of Frankfurt + * 2007-2019 Ivan Kisel + * 2007-2019 Maksym Zyzak + * + * KFParticle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * KFParticle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KFParticleTest_H +#define KFParticleTest_H + +class KFParticle; +class KFParticleSIMD; + +class KFParticleTest +{ + public: + + KFParticleTest(); + virtual ~KFParticleTest(); + + void PrintTutorial(); + void RunTest(); + + private: + + void RunTestSingle(); + void RunTestSIMD(); + void CompareSingleAndSIMDResults(); + + KFParticle* fMotherSingle; + KFParticleSIMD* fMotherSIMD; + +#ifndef KFParticleStandalone + ClassDef( KFParticleTest, 1 ) +#endif +}; + +#endif //KFParticleTest_H + diff --git a/StRoot/KFParticleTest/results/kfparticletest.txt b/StRoot/KFParticleTest/results/kfparticletest.txt new file mode 100644 index 00000000000..ae78140793a --- /dev/null +++ b/StRoot/KFParticleTest/results/kfparticletest.txt @@ -0,0 +1,61 @@ +Try different constructors + +1. Construction from Vertex + +Vertex Particle p1 + x: 0.000 +/- 0.100 y: 0.000 +/- 0.100 z: 10.000 +/- 0.100 M: 0.000 p: 0.000 +/-100000000.000 pdg: 0 Q: 0 chi2/NDF: 1.010/ 1 +Set Field 4.980 + +2. Construction from Track + +Track Particle p2 + x: -0.062 +/- 0.006 y: -1.358 +/- 0.218 z: 27.147 +/- 0.179 px: 0.625 +/- 0.008 py: -0.029 +/- 0.003 pz: -0.185 +/- 0.003 M: 0.140 +/- 0.000 p: 0.653 +/- 0.008 pdg: 0 Q: -1 chi2/NDF: 1.500/ 1 + +3. Now we will create one more particle from track and call the construction from these 2 particles + +Track Particle p3 + x: -0.204 +/- 0.015 y: 3.068 +/- 0.299 z: -19.940 +/- 0.335 px: 0.375 +/- 0.004 py: 0.025 +/- 0.003 pz: 0.190 +/- 0.003 M: 0.140 +/-1000.000 p: 0.422 +/- 0.004 pdg: 0 Q: 1 chi2/NDF: 2.500/ 2 +Particle p4(p2,p3) + x: 58.509 +/- 0.384 y: 0.072 +/- 0.134 z: 9.855 +/- 0.159 px: 0.994 +/- 0.006 py: -0.004 +/- 0.003 pz: 0.006 +/- 0.004 M: 0.497 +/- 0.003 p: 0.994 +/- 0.006 pdg: 0 Q: 0 chi2/NDF: 0.012/ 1 + +4. Construction with constrained Mass or (and) vertex position values + +4.1 Construction with constrained Mass, without vertex hypothesis + +Dauthers + x: -0.062 +/- 0.006 y: -1.358 +/- 0.218 z: 27.147 +/- 0.179 px: 0.625 +/- 0.008 py: -0.029 +/- 0.003 pz: -0.185 +/- 0.003 M: 0.140 +/- 0.000 p: 0.653 +/- 0.008 pdg: 0 Q: -1 chi2/NDF: 1.500/ 1 + x: -0.204 +/- 0.015 y: 3.068 +/- 0.299 z: -19.940 +/- 0.335 px: 0.375 +/- 0.004 py: 0.025 +/- 0.003 pz: 0.190 +/- 0.003 M: 0.140 +/-1000.000 p: 0.422 +/- 0.004 pdg: 0 Q: 1 chi2/NDF: 2.500/ 2 +Mass 0.498 +Particle K0 + x: 58.533 +/- 0.365 y: 0.071 +/- 0.134 z: 9.849 +/- 0.156 px: 0.994 +/- 0.006 py: -0.004 +/- 0.003 pz: 0.006 +/- 0.004 M: 0.498 +/-1000.000 p: 0.994 +/- 0.006 pdg: 0 Q: 0 chi2/NDF: 0.056/ 2 + Add parent Vertex + K0 with vertex x: 58.638 +/- 0.363 y: 0.073 +/- 0.134 z: 9.898 +/- 0.155 px: 0.997 +/- 0.006 py: 0.001 +/- 0.003 pz: -0.002 +/- 0.003 S: 58.842 +/- 0.137 M: 0.498 +/- 0.000 t: 29.276 +/- 0.068 p: 0.997 +/- 0.006 pdg: 0 Q: 0 chi2/NDF: 16.961/ 4 + +4.2 Construction without constrained Mass, with vertex hypothesis + +Dauthers + x: -0.062 +/- 0.006 y: -1.358 +/- 0.218 z: 27.147 +/- 0.179 px: 0.625 +/- 0.008 py: -0.029 +/- 0.003 pz: -0.185 +/- 0.003 M: 0.140 +/- 0.000 p: 0.653 +/- 0.008 pdg: 0 Q: -1 chi2/NDF: 1.500/ 1 + x: -0.204 +/- 0.015 y: 3.068 +/- 0.299 z: -19.940 +/- 0.335 px: 0.375 +/- 0.004 py: 0.025 +/- 0.003 pz: 0.190 +/- 0.003 M: 0.140 +/-1000.000 p: 0.422 +/- 0.004 pdg: 0 Q: 1 chi2/NDF: 2.500/ 2 +PV + x: 0.000 +/- 0.100 y: 0.000 +/- 0.100 z: 10.000 +/- 0.100 M: 0.000 p: 0.000 +/-100000000.000 pdg: 0 Q: 0 chi2/NDF: 1.010/ 1 +K0_1 + x: 58.474 +/- 0.383 y: 0.073 +/- 0.134 z: 9.929 +/- 0.157 px: 0.993 +/- 0.006 py: 0.001 +/- 0.003 pz: -0.001 +/- 0.003 S: 58.860 +/- 0.137 M: 0.494 +/- 0.003 t: 29.076 +/- 0.168 p: 0.993 +/- 0.006 pdg: 0 Q: 0 chi2/NDF: 13.549/ 3 + +4.3 Construction with constrained Mass, with vertex hypothesis + +Dauthers + x: -0.062 +/- 0.006 y: -1.358 +/- 0.218 z: 27.147 +/- 0.179 px: 0.625 +/- 0.008 py: -0.029 +/- 0.003 pz: -0.185 +/- 0.003 M: 0.140 +/- 0.000 p: 0.653 +/- 0.008 pdg: 0 Q: -1 chi2/NDF: 1.500/ 1 + x: -0.204 +/- 0.015 y: 3.068 +/- 0.299 z: -19.940 +/- 0.335 px: 0.375 +/- 0.004 py: 0.025 +/- 0.003 pz: 0.190 +/- 0.003 M: 0.140 +/-1000.000 p: 0.422 +/- 0.004 pdg: 0 Q: 1 chi2/NDF: 2.500/ 2 +PV + x: 0.000 +/- 0.100 y: 0.000 +/- 0.100 z: 10.000 +/- 0.100 M: 0.000 p: 0.000 +/-100000000.000 pdg: 0 Q: 0 chi2/NDF: 1.010/ 1 +Mass 0.498 +K0_2 + x: 58.638 +/- 0.363 y: 0.073 +/- 0.134 z: 9.898 +/- 0.155 px: 0.997 +/- 0.006 py: 0.001 +/- 0.003 pz: -0.002 +/- 0.003 S: 58.842 +/- 0.137 M: 0.498 +/- 0.000 t: 29.276 +/- 0.068 p: 0.997 +/- 0.006 pdg: 0 Q: 0 chi2/NDF: 16.961/ 4 + +4.4 Construction K0_3(p2,p3) without constrained Mass, without vertex hypothesis + +Dauthers + x: -0.062 +/- 0.006 y: -1.358 +/- 0.218 z: 27.147 +/- 0.179 px: 0.625 +/- 0.008 py: -0.029 +/- 0.003 pz: -0.185 +/- 0.003 M: 0.140 +/- 0.000 p: 0.653 +/- 0.008 pdg: 0 Q: -1 chi2/NDF: 1.500/ 1 + x: -0.204 +/- 0.015 y: 3.068 +/- 0.299 z: -19.940 +/- 0.335 px: 0.375 +/- 0.004 py: 0.025 +/- 0.003 pz: 0.190 +/- 0.003 M: 0.140 +/-1000.000 p: 0.422 +/- 0.004 pdg: 0 Q: 1 chi2/NDF: 2.500/ 2 +K0_3 + x: 58.508 +/- 0.384 y: 0.071 +/- 0.134 z: 9.855 +/- 0.159 px: 0.994 +/- 0.006 py: -0.004 +/- 0.003 pz: 0.006 +/- 0.004 M: 0.497 +/- 0.003 p: 0.994 +/- 0.006 pdg: 0 Q: 0 chi2/NDF: 0.011/ 1 diff --git a/StRoot/StBFChain/BigFullChain.h b/StRoot/StBFChain/BigFullChain.h index 0a1d8b9eb15..596f782a056 100644 --- a/StRoot/StBFChain/BigFullChain.h +++ b/StRoot/StBFChain/BigFullChain.h @@ -1122,6 +1122,7 @@ Bfc_st BFC[] = { // standard chains {"clearDAQCTB" ,"" ,"","","" ,"" ,"clear DAQ CTB Hits for embedding",kFALSE}, {"NoInput" ,"" ,"","","" ,"" ,"No input file",kFALSE}, {"util" ,"" ,"","","","StAnalysisUtilities", "Load StAnalysisUtilities",kFALSE}, + {"KFParticle" ,"" ,"","","","KFParticle", "Load KFParticle",kFALSE}, {"StUtilities" ,"" ,"","","","StUtilities", "Load StUtilities",kFALSE}, {"FieldOn" ,"" ,"","MagF" ,"","" ,"Constant nominal field",kFALSE}, {"FieldOff" ,"" ,"","MagF" ,"","" ,"No Field option",kFALSE}, @@ -1311,6 +1312,7 @@ Bfc_st BFC[] = { // standard chains {"MuDST" ,"" ,"","MuDSTDeps,EmcUtil,TofUtil,BTofUtil,PmdUtil","" , "StMuDSTMakerNoStrange","Load MuDST library",kFALSE}, #endif /* __NoStrangeMuDst__ */ + {"PicoDeps" ,"","","MuDSTDeps", "", "StPicoEvent,StPicoDstMaker","Load PicoDST dependences",kFALSE}, {"picoEvt" ,"","","StEvent,Stu","", "StPicoEvent","Load picoEvent and dependencies",kFALSE}, {"picoDst" ,"","","picoEvt,EmcUtil,TofUtil,BTofUtil,PmdUtil","" , "StPicoDstMaker","Load PicoDST library",kFALSE}, @@ -1344,20 +1346,15 @@ Bfc_st BFC[] = { // standard chains {"------------","-----------","-----------","------------------------------------------","","","",kFALSE}, {"I/O Makers ","-----------","-----------","------------------------------------------","","","",kFALSE}, {"------------","-----------","-----------","------------------------------------------","","","",kFALSE}, - {"gstar" ,"geant" ,"","-fzin,-ntin,-geant,Simu,geantL","St_geant_Maker" - , "","gstar for 80 muon tracks with pT = 1GeV in |eta|<4",kFALSE}, - {"pythia" ,"geant" ,"","-gstar,-fzin,-ntin,-geant,geantL","St_geant_Maker" - , "Pythia6_4_26,bpythia","Load Pythia in starsim, set pp 510 GeV",kFALSE}, - {"Wenu" ,"" ,"","pythia","", "" ,"set pp 510 GeV -> W+/- -> e+/- nu/nubar",kFALSE}, - {"hijing" ,"geant" ,"","-gstar,-fzin,-ntin,-geant,geantL","St_geant_Maker" - ,"StarGeneratorUtil,StarGeneratorEvent,StarGeneratorBase,Hijing1_383" - , "Load Hijing in starsim, set AuAu200 GeV",kFALSE}, {"tdaq" ,"","","" ,"","",STAR_CHAIN_OBSOLETE,kFALSE}, {"miniDAQ" ,"","","" ,"","",STAR_CHAIN_OBSOLETE,kFALSE}, {"fzin" ,"geant","","Simu,-gstar,-ntin,-geant,geantL","St_geant_Maker","" , "read gstar fz-file",kFALSE}, {"UseXgeom","","","-geometry,-geomNoField,xgeometry","","","suppress mortran version of geometry",kFALSE}, {"in" ,"" ,"","" , "StIOMaker","StIOMaker","Read [DAQ|ROOT] input file",kFALSE}, + {"RMuDST" ,"","","CMuDST" ,"","","reads Common MuDST, do not disactivate if no output files",kFALSE}, + {"RpicoDST" ,"RPicoDst","","PicoDeps" ,"StPicoDstMaker","","read PicoDST",kFALSE}, + {"------------","-----------","-----------","------------------------------------------","","","",kFALSE}, {"Db makers ","-----------","-----------","------------------------------------------","","","",kFALSE}, {"------------","-----------","-----------","------------------------------------------","","","",kFALSE}, @@ -1394,7 +1391,15 @@ Bfc_st BFC[] = { // standard chains {"MAKERS ","-----------","-----------","------------------------------------------","","","",kFALSE}, {"------------","-----------","-----------","------------------------------------------","","","",kFALSE}, // for simulation on fly Event time stamp is set outside of the simulation makers - {"ntin" ,"geant","","paw,-fzin,-geant,-gstar,Simu,geantL,gstarLib","St_geant_Maker" + {"gstar" ,"geant" ,"","-fzin,-ntin,-geant,Simu,geantL","St_geant_Maker" + , "","gstar for 80 muon tracks with pT = 1GeV in |eta|<4",kFALSE}, + {"pythia" ,"geant" ,"","-gstar,-fzin,-ntin,-geant,geantL","St_geant_Maker" + , "Pythia6_4_26,bpythia","Load Pythia in starsim, set pp 510 GeV",kFALSE}, + {"Wenu" ,"" ,"","pythia","", "" ,"set pp 510 GeV -> W+/- -> e+/- nu/nubar",kFALSE}, + {"hijing" ,"geant" ,"","-gstar,-fzin,-ntin,-geant,geantL","St_geant_Maker" + ,"StarGeneratorUtil,StarGeneratorEvent,StarGeneratorBase,Hijing1_383" + , "Load Hijing in starsim, set AuAu200 GeV",kFALSE}, + {"ntin" ,"geant","","paw,-fzin,-geant,-gstar,Simu,geantL,gstarLib","St_geant_Maker" , "","read event generated Hbook nt-file",kFALSE}, {"PrepEmbed","","","geantEmb","StPrepEmbedMaker","St_geant_Maker" , "Prepare kinematics for embedding",kFALSE}, @@ -1806,8 +1811,10 @@ Bfc_st BFC[] = { // standard chains #else {"BeamBack" ,"","","StEvent" ,"","",STAR_CHAIN_OBSOLETE,kFALSE}, #endif - {"dEdxY2" ,"dEdxY2","","tpcDb,StEvent","StdEdxY2Maker","libMinuit,StdEdxY2Maker" - , "Bichsel method used for dEdx",kFALSE}, + {"LdEdxY2" ,"","","tpcDb,StEvent,MuDSTDeps", "","libMinuit,StPicoEvent,StdEdxY2Maker" + , "Load dEdx Maker",kFALSE}, + {"dEdxY2" ,"dEdxY2","","LdEdxY2","StdEdxY2Maker","", "Bichsel method used for dEdx",kFALSE}, + {"dEdxCalib" ,"","","dEdxY2,TTreeFile","" ,"","switch on dEdx calibration histograms",kFALSE}, {"CalcdNdx", "", "", "dEdxY2", "", "", "Option for StdEdxY2Maker to calculate dN/dx",kFALSE}, // Options in need to be done after the tracker // second wave of BTOF options needed after Sti @@ -1924,8 +1931,6 @@ Bfc_st BFC[] = { // standard chains #else /* ! __NoStrangeMuDst__ */ {"CMuDST" ,"","MuDSTChain","MuDst,Tree", "StMuDstMaker","","Writes Common MuDST",kFALSE}, #endif /* __NoStrangeMuDst__ */ - {"RMuDST" ,"","","CMuDST" ,"","","reads Common MuDST, do not disactivate if no output files",kFALSE}, - {"trgSimu" ,"","","" ,"StTriggerSimuMaker","StTriggerUtilities","trigger simu maker",kFALSE}, {"picoWrite" ,"","PicoChain","trgSimu,picoDst","StPicoDstMaker","" ,"Writes picoDST format",kFALSE}, @@ -1964,6 +1969,12 @@ Bfc_st BFC[] = { // standard chains , "StSvtPoolEventT,StSvtPoolSvtMatchedTree","Create SvtMatchedTree",kFALSE}, {"LAna" ,"","","in,detDb,StEvent,tpcDb","StLaserAnalysisMaker" , "StLaserAnalysisMaker","Laser data Analysis",kFALSE}, + {"RefMult" ,"","","", "","StRefMultCorr","Load StRefMultCorr",kFALSE}, + {"KFPInter" ,"","","KFParticle,RefMult,picoDeps", "","KFParticle,KFParticlePerformance," + "StKFParticleAnalysisMaker", "STAR KFParticle interface",kFALSE}, + {"KFPAna" ,"","","KFPInter","StKFParticleAnalysisMaker", "", "STAR KFParticle analysis",kFALSE}, + {"PicoAnalysis","","","KFPInter","StPicoAnalysisMaker" + , "KFParticlePerformance,StPicoAnalysisMaker","Pico Analysis",kFALSE}, {"EandBDir","","","in,StEvent,TpcHitMover,nodefault" , "StEandBDirMaker","MathMore,Spectrum,StEandBDirMaker", "get E&B direction",kFALSE}, {"SpinTag" ,"","","" ,"","",STAR_CHAIN_OBSOLETE,kFALSE}, @@ -1995,6 +2006,7 @@ Bfc_st BFC[] = { // standard chains {"Notpc_daq" ,"" ,"","-tpc_daq" ,"","","No tpc_daq",kFALSE}, {"analysis" ,"","","StEvent" ,"StAnalysisMaker","StAnalysisMaker","Example of Analysis",kFALSE}, {"NewTpcAlignment","","","" ,"","","Switch on new Tpc Alignment schema",kFALSE}, + {"quiet","","","","","", "make chain quiet", kFALSE}, {"------------","-----------","-----------","------------------------------------------","","","",kFALSE}, {"Aliased ","time stamps","-----------","------------------------------------------","","","",kFALSE}, {"------------","-----------","-----------","------------------------------------------","","","",kFALSE} diff --git a/StRoot/StBFChain/StBFChain.cxx b/StRoot/StBFChain/StBFChain.cxx index 3fbf49397b9..e801d2ffa52 100644 --- a/StRoot/StBFChain/StBFChain.cxx +++ b/StRoot/StBFChain/StBFChain.cxx @@ -218,6 +218,7 @@ Int_t StBFChain::Instantiate() if (! fNoChainOptions) return status; Long64_t maxsize = kMaxLong64; TTree::SetMaxTreeSize(maxsize); + if (GetOption("quiet")) gEnv->SetValue("quiet", 1); for (i = 1; i< fNoChainOptions; i++) {// Instantiate Makers if any if (! fBFC[i].Flag) continue; TString maker(fBFC[i].Maker); @@ -380,14 +381,44 @@ Int_t StBFChain::Instantiate() // Special makers already created or action which // need to take place before 'maker' is created. if (! mk) { - if (strlen(fBFC[i].Name) > 0) mk = New(fBFC[i].Maker,fBFC[i].Name); - else mk = New(fBFC[i].Maker); - if (! mk) { - LOG_FATAL << Form("StBFChain::Instantiate() problem with instantiation Maker=[%s] Name=[%s]",fBFC[i].Maker,fBFC[i].Name) << endm; - assert(mk); + if (maker == "StMuDstMaker" && GetOption("RMuDst")) { +#if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0) + mk = new StMuDstMaker(0,0,".",fInFile.Data(),"st:MuDst.root",1e9); +#else + ProcessLine(Form("new StMuDstMaker(0,0,\"\",\"%s\",\"st:MuDst.root\",1e9)",fInFile.Data())); + mk = GetMaker("MuDst"); +#endif +// if (GetOption("RMuDst")) +// NoMakersWithInput++; + } else if (maker == "StPicoDstMaker") { + Int_t io = 1; // IoWrite=1 + if (GetOption("RpicoDst")) { +// NoMakersWithInput++; + io = 2; // IoRead=2 +#if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0) + mk = new StPicoDstMaker(io,fInFile.Data()); +#else + ProcessLine(Form("new StPicoDstMaker(%i,\"%s\")",io,fInFile.Data())); +#endif + } else { +#if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0) + mk = new StPicoDstMaker(io,fFileOut.Data()); +#else + ProcessLine(Form("new StPicoDstMaker(%i,\"%s\")",io,fFileOut.Data())); +#endif + } +#if ROOT_VERSION_CODE < ROOT_VERSION(6,0,0) + mk = GetMaker("PicoDst"); +#endif + } else { + if (strlen(fBFC[i].Name) > 0) mk = New(fBFC[i].Maker,fBFC[i].Name); + else mk = New(fBFC[i].Maker); + if (! mk) { + LOG_FATAL << Form("StBFChain::Instantiate() problem with instantiation Maker=[%s] Name=[%s]",fBFC[i].Maker,fBFC[i].Name) << endm; + assert(mk); + } } } - { TString namec = mk->GetName(); int len = sizeof(fBFC[i].Name); diff --git a/StRoot/StChain/StChain.cxx b/StRoot/StChain/StChain.cxx index 6efd1e52180..ca0b3b5961d 100755 --- a/StRoot/StChain/StChain.cxx +++ b/StRoot/StChain/StChain.cxx @@ -39,6 +39,7 @@ #include #include "TROOT.h" #include "TError.h" +#include "TEnv.h" #include "TBrowser.h" #include "TBenchmark.h" #include @@ -139,6 +140,7 @@ Int_t StChain::EventLoop(Int_t jBeg,Int_t jEnd, StMaker *outMk) Double_t gTicks = (Double_t) sysconf(_SC_CLK_TCK); struct timespec ts; int jCur=0,iMake=0; + Bool_t quiet = gEnv->GetValue("quiet", 0); #ifdef STAR_TRACKING #ifdef OLDTRACKING // Add a record to MySQL tracking Db @@ -209,6 +211,7 @@ Int_t StChain::EventLoop(Int_t jBeg,Int_t jEnd, StMaker *outMk) if (iMake%10 == kStEOF || iMake%10==kStFatal) break; mNTotal++; evnt.Stop("QAInfo:"); + if (! quiet) { // evnt.Show("QAInfo:"); times(&cpt); userCpuTime = ((Double_t) cpt.tms_utime) / gTicks - userCpuTime; @@ -237,7 +240,7 @@ Int_t StChain::EventLoop(Int_t jBeg,Int_t jEnd, StMaker *outMk) LOG_QA << Form("QAInfo: Cpu Times: user / system / user children / system children = %8.2f / %8.2f / %8.2f / %8.2f seconds (tick = %8.2f, cps = %ld)", userCpuTime,systemCpuTime,childUserCpuTime,childSystemCpuTime,gTicks,CLOCKS_PER_SEC) << endm; LOG_QA << Form("QAInfo: Cpu Times: all threads = %15.9f seconds",tv_diff) << endm; - + } #ifdef STAR_TRACKING #ifdef OLDTRACKING // Add a record to MySQL tracking Db diff --git a/StRoot/StChain/StMaker.cxx b/StRoot/StChain/StMaker.cxx index a618283d578..6948903f239 100755 --- a/StRoot/StChain/StMaker.cxx +++ b/StRoot/StChain/StMaker.cxx @@ -26,6 +26,7 @@ #include "TClass.h" #include "TROOT.h" #include "TError.h" +#include "TEnv.h" #if 0 #include "THtml.h" #endif @@ -898,7 +899,7 @@ Int_t StMaker::Finish() Int_t StMaker::Make() { TURN_LOGGER(this); - + Bool_t quiet = gEnv->GetValue("quiet", 0); // Loop on all makers Int_t ret,run=-1,oldrun; TList *tl = GetMakeList(); @@ -937,7 +938,7 @@ Int_t StMaker::Make() ret = maker->Make(); assert((ret%10)>=0 && (ret%10)<=kStFatal); maker->EndMaker(ret); - + if (! quiet) { if (Debug() || ret) { #ifdef STAR_LOGGER LOG_INFO << "*** " << maker->ClassName() << "::Make() == " @@ -947,6 +948,7 @@ Int_t StMaker::Make() printf("*** %s::Make() == %s(%d) ***\n" ,maker->ClassName(),RetCodeAsString(ret),ret); #endif + } } maker->ResetBIT(kMakeBeg); StMkDeb::SetCurrent(curr); diff --git a/StRoot/StIOMaker/StIOMaker.cxx b/StRoot/StIOMaker/StIOMaker.cxx index 9c42271978e..99e1f60f934 100644 --- a/StRoot/StIOMaker/StIOMaker.cxx +++ b/StRoot/StIOMaker/StIOMaker.cxx @@ -6,6 +6,7 @@ #include #include "TClass.h" #include "TROOT.h" +#include "TEnv.h" #include "StMaker.h" #include "StIOMaker.h" #include "StTreeMaker/StTreeMaker.h" @@ -187,11 +188,12 @@ Int_t StIOMaker::Make(){ AGAIN: iret = MakeRead(); SetNumber(++fNumEvent); - + Bool_t quiet = gEnv->GetValue("quiet", 0); + if (! quiet) { LOG_QA << "StIOMaker: Event: " << GetIventNumber() << " Run: " << GetRunNumber() << " EventId: " << GetEventNumber() << endm; - + } if (fNumEvent > fMaxEvent) iret = kStEOF; if (iret != kStEOF) return iret; diff --git a/StRoot/StKFParticleAnalysisMaker/StFemtoDstMaker.cxx b/StRoot/StKFParticleAnalysisMaker/StFemtoDstMaker.cxx new file mode 100644 index 00000000000..f48ff837ad7 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StFemtoDstMaker.cxx @@ -0,0 +1,77 @@ +// $Id: StFemtoDstMaker.cxx,v 1.18 2007/10/27 17:42:59 fine Exp $ +// $Log: StFemtoDstMaker.cxx,v $ +#include "StFemtoDstMaker.h" +#include "StPicoDstMaker/StPicoDstMaker.h" +#include "StPicoEvent/StPicoDst.h" +#include "StPicoEvent/StPicoArrays.h" +#include "StChain/StChainOpt.h" +#include "StKFParticleInterface.h" +#include "TSystem.h" +#include "TClonesArray.h" +#include "TArrayC.h" +ClassImp(StFemtoDstMaker); +//_____________________________________________________________________________ +StFemtoDstMaker::~StFemtoDstMaker() {delete fStKFParticleInterface;} +//_____________________________________________________________________________ +Int_t StFemtoDstMaker::Init(){ + TTree *oldtree = StPicoDstMaker::instance()->tree(); + assert(oldtree); + TString fileOut = GetChainOpt()->GetFileOut(); + assert(fileOut != ""); + fileOut = gSystem->BaseName(fileOut); + Int_t l = fileOut.Index("."); + if (l < 0) l = fileOut.Length(); + fileOut = TString(fileOut.Data(),l); + fileOut.ReplaceAll("*",""); + fileOut += ".femtoDst.root"; + fOutFile = TFile::Open(fileOut,"recreate"); + fFemtoTree = oldtree->CloneTree(0); + fFemtoTree->CopyAddresses(oldtree); + fFemtoTree->AutoSave(); + fStKFParticleInterface = new StKFParticleInterface; + fStKFParticleInterface->SetTriggerMode(); + fStKFParticleInterface->SetSoftKaonPIDMode(); + fStKFParticleInterface->SetSoftTofPidMode(); + fStKFParticleInterface->SetChiPrimaryCut(10); //10); // 8 // 12 + return StMaker::Init(); +} +//_____________________________________________________________________________ +Int_t StFemtoDstMaker::Make(){ + fFemtoDst = StPicoDst::instance(); + if (! fFemtoDst) return kStOK; + vector triggeredTracks; + bool openCharmTrigger = false; +#ifdef __TFG__VERSION__ + bool isGoodEvent = fStKFParticleInterface->ProcessEvent(fFemtoDst, triggeredTracks); + if(isGoodEvent) openCharmTrigger = fStKFParticleInterface->OpenCharmTrigger(); +#endif /* __TFG__VERSION__ */ + if (! openCharmTrigger) { + for (UInt_t i = StPicoArrays::Track; i < StPicoArrays::NAllPicoArrays; i++) { +#ifdef __TFG__VERSION__ + StPicoDstMaker::instance()->picoArrays()[i]->Clear(); +#else /* ! __TFG__VERSION__ */ + StPicoDst::instance()->picoArray(i)->Clear(); +#endif /* __TFG__VERSION__ */ + } + } else { + TClonesArray *tracks = StPicoDst::instance()->picoArray(StPicoArrays::Track); + Int_t N = tracks->GetEntriesFast(); + TArrayC flags(N); + for (UInt_t i = 0; i < triggeredTracks.size(); i++) flags[triggeredTracks[i]] = kTRUE; + for (Int_t i = 0; i < N; i++) { + if (! flags[i]) tracks->RemoveAt(i); + } + tracks->Compress(); + } + fFemtoTree->Fill(); + return kStOK; +} +//________________________________________________________________________________ +Int_t StFemtoDstMaker::Finish() { + if (fOutFile) { + fOutFile->Write(); + fOutFile->Flush(); + SafeDelete(fOutFile); + } + return StMaker::Finish(); +} diff --git a/StRoot/StKFParticleAnalysisMaker/StFemtoDstMaker.h b/StRoot/StKFParticleAnalysisMaker/StFemtoDstMaker.h new file mode 100644 index 00000000000..ea077dcb289 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StFemtoDstMaker.h @@ -0,0 +1,33 @@ +// $Id: StFemtoDstMaker.h,v 1.16 2014/08/06 11:43:53 jeromel Exp $ + +#ifndef STAR_StFemtoDstMaker +#define STAR_StFemtoDstMaker +#ifndef StMaker_H +#include "StMaker.h" +#endif +#include "TTree.h" +#include "TFile.h" +class StPicoDst; +class StKFParticleInterface; +class StFemtoDstMaker : public StMaker { + private: + StPicoDst *fFemtoDst; + TTree *fFemtoTree; + StKFParticleInterface *fStKFParticleInterface; + TFile *fOutFile; + public: + StFemtoDstMaker(const char *name="FemtoDst"): StMaker(name), fFemtoDst(0), fFemtoTree(0), fStKFParticleInterface(0), fOutFile(0) {} + virtual ~StFemtoDstMaker(); + virtual Int_t Init(); + virtual Int_t Make(); + virtual Int_t Finish(); + virtual const char *GetCVS() const { + static const char cvs[]="Tag $Name: $ $Id: $ built " __DATE__ " " __TIME__ ; + return cvs; + } + + ClassDef(StFemtoDstMaker,0) +}; +#endif +// $Log: StFemtoDstMaker.h,v $ + diff --git a/StRoot/StKFParticleAnalysisMaker/StKFParticleAnalysisMaker.cxx b/StRoot/StKFParticleAnalysisMaker/StKFParticleAnalysisMaker.cxx new file mode 100644 index 00000000000..49034f98828 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StKFParticleAnalysisMaker.cxx @@ -0,0 +1,817 @@ +//*-- Author : Yuri Fisyak 02/02/2016 +#include "StKFParticleAnalysisMaker.h" +#include "TDirectory.h" +#include "TNtuple.h" +#include "TFile.h" +#include "TChain.h" +#include "TNtuple.h" +#include "TTree.h" +#include "TSystem.h" +//--- KF particle classes --- +#include "KFVertex.h" +#include "KFParticle.h" +#include "KFParticleSIMD.h" +#include "KFPTrack.h" +#include "KFParticleTopoReconstructor.h" +#include "KFPartEfficiencies.h" +#include "StKFParticleInterface.h" +#include "StKFParticlePerformanceInterface.h" +//--- Pico classes --- +#include "StPicoDstMaker/StPicoDstMaker.h" +#include "StPicoEvent/StPicoDst.h" +#include "StPicoEvent/StPicoEvent.h" +#include "StPicoEvent/StPicoTrack.h" +#include "StPicoEvent/StPicoBTofPidTraits.h" +//--- Mu classes --- +#include "StMuDSTMaker/COMMON/StMuDstMaker.h" +#include "StMuDSTMaker/COMMON/StMuDst.h" +#include "StMuDSTMaker/COMMON/StMuTrack.h" +//--- TMVA classes --- +#include "TMVA/GeneticAlgorithm.h" +#include "TMVA/GeneticFitter.h" +#include "TMVA/IFitterTarget.h" +#include "TMVA/Factory.h" +//--- StRefMult class --- +#include "StRefMultCorr/StRefMultCorr.h" +#include "StRefMultCorr/CentralityMaker.h" +ClassImp(StKFParticleAnalysisMaker); + +//________________________________________________________________________________ +StKFParticleAnalysisMaker::StKFParticleAnalysisMaker(const char *name) : StMaker(name), fNTrackTMVACuts(0), fIsPicoAnalysis(true), fdEdXMode(1), + fStoreTmvaNTuples(false), fProcessSignal(false), fCollectTrackHistograms(false), fCollectPIDHistograms(false),fCollectPVHistograms(false),fTMVAselection(false), + fFlowAnalysis(false), fFlowChain(NULL), fFlowRunId(-1), fFlowEventId(-1), fCentrality(-1), fFlowFiles(), fFlowMap(), + fRunCentralityAnalysis(0), fRefmultCorrUtil(0), fCentralityFile(""), fAnalyseDsPhiPi(false), fDecays(0), fIsProduce3DEfficiencyFile(false), f3DEfficiencyFile(""), + fStoreCandidates(false), fPartcileCandidate(), fIsStoreCandidate(KFPartEfficiencies::nParticles, false), fCandidateFileName("candidates.root"), fCandidateFile(nullptr), fCandidatesTree(nullptr) +{ + memset(mBeg,0,mEnd-mBeg+1); + + fNTuplePDG[0] = 421; + fNTuplePDG[1] = 411; + fNTuplePDG[2] = 431; + fNTuplePDG[3] = 4122; + fNTuplePDG[4] = 426; + fNTuplePDG[5] = 429; + fNTuplePDG[6] = 521; + fNTuplePDG[7] = 511; + + fNtupleNames[0] = "D0"; + fNtupleNames[1] = "DPlus"; + fNtupleNames[2] = "Ds"; + fNtupleNames[3] = "Lc"; + fNtupleNames[4] = "D0KK"; + fNtupleNames[5] = "D04"; + fNtupleNames[6] = "BPlus"; + fNtupleNames[7] = "B0"; + + vector trackCutNames; + trackCutNames.push_back("pt_"); + trackCutNames.push_back("chi2Primary_"); + trackCutNames.push_back("dEdXPi_"); + trackCutNames.push_back("dEdXK_"); + trackCutNames.push_back("dEdXP_"); + trackCutNames.push_back("ToFPi_"); + trackCutNames.push_back("ToFK_"); + trackCutNames.push_back("ToFP_"); + fNTrackTMVACuts = trackCutNames.size(); + + fDaughterNames[0].push_back("K"); fDaughterNames[0].push_back("Pi"); //D0 -> Kpi + fDaughterNames[1].push_back("K"); fDaughterNames[1].push_back("Pi1"); fDaughterNames[1].push_back("Pi2"); //D+ -> Kpipi + fDaughterNames[2].push_back("KPlus"); fDaughterNames[2].push_back("KMinus"); fDaughterNames[2].push_back("Pi"); //Ds -> KKpi + fDaughterNames[3].push_back("K"); fDaughterNames[3].push_back("Pi"); fDaughterNames[3].push_back("P"); //Lc -> pKpi + fDaughterNames[4].push_back("KPlus"); fDaughterNames[4].push_back("KMinus"); //D0 -> KK + fDaughterNames[5].push_back("K"); fDaughterNames[5].push_back("Pi1"); fDaughterNames[5].push_back("Pi2"); fDaughterNames[5].push_back("Pi3"); //D0 -> Kpipipi + fDaughterNames[6].push_back("PiD"); fDaughterNames[6].push_back("KD"); fDaughterNames[6].push_back("Pi"); //B+ -> D0_bpi + fDaughterNames[7].push_back("Pi1D"); fDaughterNames[7].push_back("KD"); fDaughterNames[7].push_back("Pi2D"); fDaughterNames[7].push_back("Pi"); //B0 -> D-pi+ + + for(int iDecay=0; iDecay=6 && iDecay<8) + { + fNtupleCutNames[iDecay] += "Chi2NDF_D:LdL_D:Chi2Topo_D:Chi2NDF:LdL:Chi2Topo:refMult"; + } + + SetTMVABins(iDecay); + } +} +//________________________________________________________________________________ +StKFParticleAnalysisMaker::~StKFParticleAnalysisMaker() +{ + SafeDelete(fStKFParticleInterface); + SafeDelete(fStKFParticlePerformanceInterface); +} + +//_____________________________________________________________________________ +Int_t StKFParticleAnalysisMaker::Init() +{ + TFile *f = GetTFile(); + if(f) + { + f->cd(); + BookVertexPlots(); + if(fCollectTrackHistograms) + fStKFParticleInterface->CollectTrackHistograms(); + if(fCollectPIDHistograms) + fStKFParticleInterface->CollectPIDHistograms(); + if(fCollectPVHistograms) + fStKFParticleInterface->CollectPVHistograms(); + } + + if(fTMVAselection || fStoreTmvaNTuples) + { + for(int iReader=0; iReader AddVariable( cutName.Data(), &fTMVAParticleParameters[iReader][iCut] ); + iCut++; + if(iCut == (fTMVAParticleParameters[iReader].size()-1)) break; + } + + fTMVAReader[iReader][iCentralityBin][iPtBin] -> BookMVA("BDT", fTMVACutFile[iReader][iCentralityBin][iPtBin].Data()); + } + } + } + } + + //Create file with NTuples for cut optimization + if(fStoreTmvaNTuples) + { + TFile* curFile = gFile; + TDirectory* curDirectory = gDirectory; + for(int iNtuple=0; iNtupleBranch("Candidates", &fPartcileCandidate, 32000, 0); + + gFile = curFile; + gDirectory = curDirectory; + } + + // fRefmultCorrUtil = CentralityMaker::instance()->getgRefMultCorr_P16id(); + // fRefmultCorrUtil->setVzForWeight(6, -6.0, 6.0); + // fRefmultCorrUtil->readScaleForWeight("/gpfs01/star/pwg/pfederic/qVectors/StRoot/StRefMultCorr/macros/weight_grefmult_VpdnoVtx_Vpd5_Run16.txt"); //for new StRefMultCorr, Run16, SL16j + + //Initialise the chain with files containing centrality and reaction plane + if(fFlowAnalysis) + { + std::cout << "StKFParticleAnalysisMaker: run flow analysis. Flow file list:"<Add(fFlowFiles[iFlowFile].Data()); + } + + fFlowChain->SetBranchStatus("*",0); + fFlowChain->SetBranchAddress("runid", &fFlowRunId); fFlowChain->SetBranchStatus("runid", 1); + fFlowChain->SetBranchAddress("eventid", &fFlowEventId); fFlowChain->SetBranchStatus("eventid", 1); + fFlowChain->SetBranchAddress("cent", &fCentrality); fFlowChain->SetBranchStatus("cent", 1); + + std::cout << "StKFParticleAnalysisMaker: number of entries in the flow chain" << fFlowChain->GetEntries() << std::endl; + for(int iEntry=0; iEntryGetEntries(); iEntry++) + { + fFlowChain->GetEvent(iEntry); + fFlowMap[GetUniqueEventId(fFlowRunId, fFlowEventId)] = iEntry; + } + } + return kStOK; +} +//________________________________________________________________________________ +Int_t StKFParticleAnalysisMaker::InitRun(Int_t runumber) +{ +// assert(StPicoDstMaker::instance()); +// if (StPicoDstMaker::instance()->IOMode() == StPicoDstMaker::ioRead) { + //TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO Ask Yuri +// StPicoDstMaker::instance()->SetStatus("*",0); +// const Char_t *ActiveBranches[] = { +// "MuEvent" +// ,"PrimaryVertices" +// ,"PrimaryTracks" +// ,"GlobalTracks" +// ,"StStMuMcVertex" +// ,"StStMuMcTrack" +// ,"CovPrimTrack" +// ,"CovGlobTrack" +// ,"StStMuMcVertex" +// ,"StStMuMcTrack" +// ,"KFTracks" +// ,"KFVertices" +// ,"StBTofHit" +// ,"StBTofHeader" +// }; +// Int_t Nb = sizeof(ActiveBranches)/sizeof(Char_t *); +// for (Int_t i = 0; i < Nb; i++) StPicoDstMaker::instance()->SetStatus(ActiveBranches[i],1); // Set Active braches +// } + return StMaker::InitRun(runumber); +} +//_____________________________________________________________________________ +void StKFParticleAnalysisMaker::PrintMem(const Char_t *opt) +{ + MemInfo_t info; + gSystem->GetMemInfo(&info); + cout << opt + << "\tMemory : Total = " << info.fMemTotal + << "\tUsed = " << info.fMemUsed + << "\tFree = " << info.fMemFree + << "\tSwap Total = " << info.fSwapTotal + << "\tUsed = " << info.fSwapUsed + << "\tFree = " << info.fSwapFree << endl; +} +//_____________________________________________________________________________ +void StKFParticleAnalysisMaker::BookVertexPlots() +{ + TDirectory *dirs[2] = {0}; + dirs[0] = TDirectory::CurrentDirectory(); assert(dirs[0]); + dirs[0]->cd(); + if (! dirs[0]->GetDirectory("Particles")) { + dirs[0]->mkdir("Particles"); + } + dirs[1] = dirs[0]->GetDirectory("Particles"); assert(dirs[1]); + dirs[1]->cd(); + PrintMem(dirs[1]->GetPath()); + + fStKFParticleInterface = new StKFParticleInterface; + for(unsigned int iDecay=0; iDecayAddDecayToReconstructionList( fDecays[iDecay] ); + bool storeMCHistograms = false; + if(!fIsPicoAnalysis && fProcessSignal) storeMCHistograms = true; + fStKFParticlePerformanceInterface = new StKFParticlePerformanceInterface(fStKFParticleInterface->GetTopoReconstructor(), storeMCHistograms, fIsProduce3DEfficiencyFile); + if(!f3DEfficiencyFile.IsNull()) { + fStKFParticlePerformanceInterface->Set3DEfficiency(f3DEfficiencyFile); + } + dirs[0]->cd(); + PrintMem(dirs[1]->GetPath()); +} +//_____________________________________________________________________________ +Int_t StKFParticleAnalysisMaker::Make() +{ + if(fIsPicoAnalysis) + { + fPicoDst = StPicoDst::instance(); + if(!fPicoDst) return kStOK; + } + else + { +#ifdef __TFG__VERSION__ + fMuDst = StMuDst::instance(); +#else /* !__TFG__VERSION__ */ + StMuDstMaker *muDstMaker = (StMuDstMaker *)GetTopChain()->GetMakerInheritsFrom("StMuDstMaker"); + if (muDstMaker) fMuDst = muDstMaker->muDst(); +#endif /* __TFG__VERSION__ */ + if(! fMuDst) return kStOK; + else { if(fMuDst->numberOfPrimaryVertices() == 0 ) return kStOK; } + } + + //find max global track index + int maxGBTrackIndex = -1; + if(fIsPicoAnalysis) + { + for(unsigned int iTrack = 0; iTrack < fPicoDst->numberOfTracks(); iTrack++) + { + StPicoTrack *gTrack = fPicoDst->track(iTrack); + if (! gTrack) continue; + int index = gTrack->id(); + if(index > maxGBTrackIndex) + maxGBTrackIndex = index; + } + } + else + { + for(unsigned int iTrack = 0; iTrack < fMuDst->numberOfGlobalTracks(); iTrack++) + { + StMuTrack *gTrack = fMuDst->globalTracks(iTrack); + if (! gTrack) continue; + int index = gTrack->id(); + if(index > maxGBTrackIndex) + maxGBTrackIndex = index; + } + } + vector mcTracks(0); + vector mcIndices(maxGBTrackIndex+1); + for(unsigned int iIndex=0; iIndex triggeredTracks; + bool isGoodEvent = false; + + //Process the event + if(maxGBTrackIndex > 0) + fStKFParticleInterface->ResizeTrackPidVectors(maxGBTrackIndex+1); + if(fIsPicoAnalysis) + isGoodEvent = fStKFParticleInterface->ProcessEvent(fPicoDst, triggeredTracks); + else + isGoodEvent = fStKFParticleInterface->ProcessEvent(fMuDst, mcTracks, mcIndices, fProcessSignal); + + //collect histograms + + if(isGoodEvent) + { + int centralityBin = -1; + float centralityWeight = 0.; + + if(fRunCentralityAnalysis) + { + fRefmultCorrUtil->init(fPicoDst->event()->runId()); + if(! (fRefmultCorrUtil->isBadRun(fPicoDst->event()->runId())) ) + { + fRefmultCorrUtil->initEvent(fPicoDst->event()->grefMult(), fPicoDst->event()->primaryVertex().z(), fPicoDst->event()->ZDCx()) ; + centralityBin = fRefmultCorrUtil->getCentralityBin9(); + centralityWeight = fRefmultCorrUtil->getWeight(); + } +// refmultCor = fRefmultCorrUtil->getRefMultCorr(); + } + + if(fTMVAselection) + { + for(int iParticle=0; iParticleGetNReconstructedParticles(); iParticle++) + { + KFParticle particle = fStKFParticleInterface->GetParticles()[iParticle]; + + for(int iReader=0; iReaderRemoveParticle(iParticle); + continue; + } + + if(fTMVAReader[iReader][iTMVACentralityBin][iTMVAPtBin]->EvaluateMVA("BDT") < fTMVACut[iReader][iTMVACentralityBin][iTMVAPtBin]) + fStKFParticleInterface->RemoveParticle(iParticle); + + if(fAnalyseDsPhiPi && abs(fStKFParticleInterface->GetParticles()[iParticle].GetPDG()) == 431) + { + KFParticle phi; + if(particle.GetPDG() == 431) + phi += fStKFParticleInterface->GetParticles()[particle.DaughterIds()[0]]; + else + phi += fStKFParticleInterface->GetParticles()[particle.DaughterIds()[1]]; + phi += fStKFParticleInterface->GetParticles()[particle.DaughterIds()[2]]; + float mass = 0.f, dmass = 0.f; + phi.GetMass(mass, dmass); + if( fabs(mass - 1.01946) > 0.015) + fStKFParticleInterface->RemoveParticle(iParticle); + } + } + } + } + } + +#if 1 + //clean clusters for hypernuclei candidates + int nTracks = 0; + std::vector isValidTrack(maxGBTrackIndex+1); + for(int iTrack=0; iTrackGetNReconstructedParticles(); iParticle++) { + const KFParticle particle = fStKFParticleInterface->GetParticles()[iParticle]; + + if(particle.NDaughters() == 1) + nTracks = iParticle + 1; + + if( (abs(particle.GetPDG()) > 3001) && (abs(particle.GetPDG()) <= 3029) && + !(particle.GetPDG() == 3008 || particle.GetPDG() == 3009 || particle.GetPDG() == 3010 || particle.GetPDG() == 3011) ) { + + KFParticle cluster = particle; + + std::vector trackIds; + bool isValidParticle = true; + for(int iD=0; iDGetParticles()[daughterId]; + const int daughterTrackId = daughter.DaughterIds()[0]; + trackIds.push_back(daughterTrackId); + isValidParticle &= isValidTrack[daughterTrackId]; + } + + for(int iTrack=0; iTrackGetParticles()[iTrack]; + + //check that not the same track + bool isSameTrack = false; + for(unsigned int iD=0; iDGetTopoReconstructor()->GetPrimVertex()) < chiprimCut) continue; + } + + // should be close to the initial position + const float chiSec2 = track.GetDeviationFromVertex(particle); + if(chiSec2 > 18) continue; + + const float dev = track.GetDeviationFromVertex(cluster); + if( dev > 10. ) continue; + + //add track to cluster + KFParticle clusterTmp = cluster; + clusterTmp += track; + if(clusterTmp.GetChi2()/float(clusterTmp.GetNDF()) < 3) { + cluster = clusterTmp; + trackIds.push_back(track.DaughterIds()[0]); + } + } + + if(cluster.NDaughters() > 5) { + fStKFParticleInterface->RemoveParticle(iParticle); + for(unsigned int iTrackId=0; iTrackIdGetNReconstructedParticles(); nTracks++) { + const KFParticle particle = fStKFParticleInterface->GetParticles()[nTracks]; + + if(particle.NDaughters() == 1) { + nTracks++; + break; + } + } +#endif + + // Clean hypernuclei candidates with large coordinate and mass errors + for(int iParticle=nTracks; iParticleGetNReconstructedParticles(); iParticle++) { + const KFParticle particle = fStKFParticleInterface->GetParticles()[iParticle]; + + if( (abs(particle.GetPDG()) > 3001) && (abs(particle.GetPDG()) <= 3103) ) { + + const float dmCut = (particle.NDaughters() == 2) ? 2.5e-3f : 2.0e-3f; + if(particle.GetErrMass() > dmCut) { + fStKFParticleInterface->RemoveParticle(iParticle); + } + float l, dl; + particle.GetDistanceToVertexLine(fStKFParticleInterface->GetTopoReconstructor()->GetPrimVertex(), l, dl); + if(dl > 3.f) { + fStKFParticleInterface->RemoveParticle(iParticle); + continue; + } + } + } + + //clean H3L, H4L, Ln, Lnn + for(int iParticle=0; iParticleGetNReconstructedParticles(); iParticle++) + { + KFParticle particle = fStKFParticleInterface->GetParticles()[iParticle]; + if((abs(particle.GetPDG()) > 3002) && (abs(particle.GetPDG()) <= 3203)) + { + for(int iD=0; iDGetParticles()[daughterId]; + + if(abs(daughter.GetPDG())!=211 && daughter.GetP() < 0.5) //TODO remove me + fStKFParticleInterface->RemoveParticle(iParticle); + } + } + + if((abs(particle.GetPDG()) >= 1003004) && (abs(particle.GetPDG()) <= 1003007)) + { + const float dmCut = 3.0e-3f; + if(particle.GetErrMass() > dmCut) { + fStKFParticleInterface->RemoveParticle(iParticle); + } + } + } + + + if(fStoreCandidates) { + KFPartEfficiencies parteff; + for(int iParticle=0; iParticleGetNReconstructedParticles(); iParticle++) { + const KFParticle particle = fStKFParticleInterface->GetParticles()[iParticle]; + if(particle.GetPDG() == -1) continue; + const int particleIndex = parteff.GetParticleIndex(particle.GetPDG()); + if(particleIndex == -1) continue; + + if(!fIsStoreCandidate[particleIndex]) continue; + + fPartcileCandidate = fStKFParticleInterface->GetTopoReconstructor()->GetPrimVertex(); + fCandidatesTree->Fill(); + + fPartcileCandidate = particle; + fCandidatesTree->Fill(); + + if(particle.NDaughters() == 1) continue; + + for(int iDaughter=0; iDaughterGetParticles()[particle.DaughterIds()[iDaughter]]; + fPartcileCandidate = daughter; + fCandidatesTree->Fill(); + + if(daughter.NDaughters() > 1) + { + for(int iGrandDaughter=0; iGrandDaughterGetParticles()[daughter.DaughterIds()[iGrandDaughter]]; + fPartcileCandidate = grandDaughter; + fCandidatesTree->Fill(); + } + } + } + } + } + int eventId = -1; + int runId = -1; + + if(fFlowAnalysis) + { + if(fIsPicoAnalysis) + { + runId = fPicoDst->event()->runId(); + eventId = fPicoDst->event()->eventId(); + } + else + { + runId = fMuDst->event()->runId(); + eventId = fMuDst->event()->eventId(); + } + + long entryId = GetUniqueEventId(runId, eventId); + std::map::iterator flowMapIterator = fFlowMap.find(entryId); + if (flowMapIterator != fFlowMap.end()) + { + fFlowChain->GetEvent(fFlowMap[GetUniqueEventId(runId, eventId)]); + centralityBin = fCentrality; + } + } + + centralityWeight = 1; + fStKFParticlePerformanceInterface->SetMCTracks(mcTracks); + fStKFParticlePerformanceInterface->SetMCIndexes(mcIndices); + fStKFParticlePerformanceInterface->SetCentralityBin(centralityBin); + fStKFParticlePerformanceInterface->SetCentralityWeight(centralityWeight); + Int_t nevent = 100000; + fStKFParticlePerformanceInterface->SetPrintEffFrequency(nevent); + fStKFParticlePerformanceInterface->PerformanceAnalysis(); + if(fStoreTmvaNTuples) + { + for(int iParticle=0; iParticleGetNReconstructedParticles(); iParticle++) + { + KFParticle particle; + bool isMCParticle = fStKFParticlePerformanceInterface->GetParticle(particle, iParticle); + + if( !( (fProcessSignal && isMCParticle) || (!fProcessSignal && !isMCParticle) ) ) continue; + + for(int iNTuple=0; iNTupleFill(fTMVAParticleParameters[iNTuple].data()); + } + } + } + } + } + + return kStOK; +} + +void StKFParticleAnalysisMaker::GetDaughterParameters(const int iReader, int& iDaughterTrack, int& iDaughterParticle, KFParticle& particle) +{ + if(particle.NDaughters() == 1) + { + fTMVAParticleParameters[iReader][iDaughterTrack*fNTrackTMVACuts] = particle.GetPt(); + fTMVAParticleParameters[iReader][iDaughterTrack*fNTrackTMVACuts+1] = particle.GetDeviationFromVertex(fStKFParticleInterface->GetTopoReconstructor()->GetPrimVertex()); + int trackId = particle.DaughterIds()[0]; + fTMVAParticleParameters[iReader][iDaughterTrack*fNTrackTMVACuts+2] = fStKFParticleInterface->GetdEdXNSigmaPion(trackId); + fTMVAParticleParameters[iReader][iDaughterTrack*fNTrackTMVACuts+3] = fStKFParticleInterface->GetdEdXNSigmaKaon(trackId); + fTMVAParticleParameters[iReader][iDaughterTrack*fNTrackTMVACuts+4] = fStKFParticleInterface->GetdEdXNSigmaProton(trackId); + fTMVAParticleParameters[iReader][iDaughterTrack*fNTrackTMVACuts+5] = fStKFParticleInterface->GetTofNSigmaPion(trackId); + fTMVAParticleParameters[iReader][iDaughterTrack*fNTrackTMVACuts+6] = fStKFParticleInterface->GetTofNSigmaKaon(trackId); + fTMVAParticleParameters[iReader][iDaughterTrack*fNTrackTMVACuts+7] = fStKFParticleInterface->GetTofNSigmaProton(trackId); + + iDaughterTrack++; + } + else if(particle.NDaughters() > 1) + { + int order[4] = {0, 1, 2, 3}; + if( particle.GetPDG() == -421 || particle.GetPDG() == -411 || particle.GetPDG() == -431 || + particle.GetPDG() == -429 || particle.GetPDG() == -4122) + { + order[0] = 1; + order[1] = 0; + } + + for(int iDaughter=0; iDaughterGetParticles()[daughterParticleIndex]; + //set pdg for correct order of cuts + if(particle.GetPDG() == 521 && daughter.GetPDG() == -1) daughter.SetPDG(-421); + if(particle.GetPDG() ==-521 && daughter.GetPDG() == -1) daughter.SetPDG( 421); + if(particle.GetPDG() == 511 && daughter.GetPDG() == -1) daughter.SetPDG(-411); + if(particle.GetPDG() ==-511 && daughter.GetPDG() == -1) daughter.SetPDG( 411); + + GetDaughterParameters(iReader, iDaughterTrack, iDaughterParticle, daughter); + } + + fTMVAParticleParameters[iReader][fDaughterNames[iReader].size()*fNTrackTMVACuts + iDaughterParticle*3] = particle.Chi2()/particle.NDF(); + + KFParticleSIMD tempSIMDParticle(particle); + float32_v l,dl; + KFParticleSIMD pv(fStKFParticleInterface->GetTopoReconstructor()->GetPrimVertex()); + tempSIMDParticle.GetDistanceToVertexLine(pv, l, dl); + fTMVAParticleParameters[iReader][fDaughterNames[iReader].size()*fNTrackTMVACuts + iDaughterParticle*3 + 1] = l[0]/dl[0]; + + tempSIMDParticle.SetProductionVertex(pv); + fTMVAParticleParameters[iReader][fDaughterNames[iReader].size()*fNTrackTMVACuts + iDaughterParticle*3 + 2] = + double(tempSIMDParticle.Chi2()[0])/double(tempSIMDParticle.NDF()[0]); + + iDaughterParticle++; + } +} + +void StKFParticleAnalysisMaker::GetParticleParameters(const int iReader, KFParticle& particle) +{ + bool isBMeson = abs(particle.GetPDG()) == 511 || abs(particle.GetPDG()) == 521; +// if( !isBMeson ) return; + + int iDaughterTrack = 0; + int iDaughterParticle = 0; + GetDaughterParameters(iReader, iDaughterTrack, iDaughterParticle, particle); + + int nDaughterParticleCut = 0; + if(isBMeson) nDaughterParticleCut += 3; + nDaughterParticleCut += fDaughterNames[iReader].size()*fNTrackTMVACuts; + + fTMVAParticleParameters[iReader][nDaughterParticleCut] = particle.Chi2()/particle.NDF(); + + KFParticleSIMD tempSIMDParticle(particle); + float32_v l,dl; + KFParticleSIMD pv(fStKFParticleInterface->GetTopoReconstructor()->GetPrimVertex()); + tempSIMDParticle.GetDistanceToVertexLine(pv, l, dl); + fTMVAParticleParameters[iReader][nDaughterParticleCut + 1] = l[0]/dl[0]; + + tempSIMDParticle.SetProductionVertex(pv); + fTMVAParticleParameters[iReader][nDaughterParticleCut + 2] = double(tempSIMDParticle.Chi2()[0])/double(tempSIMDParticle.NDF()[0]); + + if(fIsPicoAnalysis) + fTMVAParticleParameters[iReader][nDaughterParticleCut + 3] = fPicoDst->event()->refMult(); + else + fTMVAParticleParameters[iReader][nDaughterParticleCut + 3] = fMuDst->event()->refMult(); +} + +Int_t StKFParticleAnalysisMaker::Finish() +{ + if(fStoreTmvaNTuples) + { + TFile* curFile = gFile; + TDirectory* curDirectory = gDirectory; + for(int iNtuple=0; iNtuplecd(); + fCutsNTuple[iNtuple]->Write(); + } + gFile = curFile; + gDirectory = curDirectory; + } + + if(fStoreCandidates) + { + TFile* curFile = gFile; + TDirectory* curDirectory = gDirectory; + fCandidateFile->cd(); + fCandidatesTree->Write(); + gFile = curFile; + gDirectory = curDirectory; + } + + return kStOK; +} + +long StKFParticleAnalysisMaker::GetUniqueEventId(const int iRun, const int iEvent) const +{ + long id = 1000000000; + return id*(iRun%1000) + iEvent; +} + +int StKFParticleAnalysisMaker::GetTMVACentralityBin(int iReader, int centrality) +{ + for(unsigned int iBin=0; iBin= fTMVACentralityBins[iReader][iBin] && centrality < fTMVACentralityBins[iReader][iBin+1]) + return iBin; + return -1; +} + +int StKFParticleAnalysisMaker::GetTMVAPtBin(int iReader, double pt) +{ + for(unsigned int iBin=0; iBin= fTMVAPtBins[iReader][iBin] && pt < fTMVAPtBins[iReader][iBin+1]) + return iBin; + return -1; +} + +void StKFParticleAnalysisMaker::SetTMVACentralityBins(int iReader, TString bins) +{ + fTMVACentralityBins[iReader].clear(); + TString value; int firstSymbol = 0; + while(bins.Tokenize(value,firstSymbol,":")) + fTMVACentralityBins[iReader].push_back(value.Atoi()); +} + +void StKFParticleAnalysisMaker::SetTMVAPtBins(int iReader, TString bins) +{ + fTMVAPtBins[iReader].clear(); + TString value; int firstSymbol = 0; + while(bins.Tokenize(value,firstSymbol,":")) + fTMVAPtBins[iReader].push_back(value.Atof()); +} + +void StKFParticleAnalysisMaker::SetTMVABins(int iReader, TString centralityBins, TString ptBins) +{ + SetTMVACentralityBins(iReader, centralityBins); + SetTMVAPtBins(iReader, ptBins); + + const int nCentralityBins = fTMVACentralityBins[iReader].size() - 1; + const int nPtBins = fTMVAPtBins[iReader].size() - 1; + + fTMVACutFile[iReader].resize(nCentralityBins); + fTMVACut[iReader].resize(nCentralityBins); + fTMVAReader[iReader].resize(nCentralityBins); + + for(int iCentralityBin=0; iCentralityBin hFitDaughtersQA[iPart][iH] + [iPart][iH+8] + if(fStoreFitPullHistograms) "FitQAPull" : res, pull => hFitQAPull[iPart][iH][s] + [iPart][iH+8][s] + "Parameters" : + KFParticlePerformanceBase::CreateParameterHistograms(0,0,0) + if(IsCollect3DHistogram(iPart)) + KFParticlePerformanceBase::CreateParameterHistograms(4,4,0) "SignalReco", + KFParticlePerformanceBase::CreateParameterHistograms(5,5,0) "BGReco", + if(fStoreMCHistograms) + KFParticlePerformanceBase::CreateParameterHistograms(1,1,0) "Signal", + KFParticlePerformanceBase::CreateParameterHistograms(2,2,0) "Background", + KFParticlePerformanceBase::CreateParameterHistograms(3,3,0) "Ghost" + KFParticlePerformanceBase::CreateParameterHistograms(6,6,0) "MCSignal" + if(fStorePrimSecHistograms && plotPrimaryHistograms) "Primary" + if(fStorePrimSecHistograms && plotPrimaryHistograms) "Secondary" + "PrimaryVertexQA" + "Efficiency" + "Signal", "Pileup", "Signal_MCReconstructable", "Pileup_MCReconstructable", "PVTracksQA" + "FitQA" ,... + "TrackParameters" + + + +-------------------------------------------------------------------------------- + StKFParticleAnalysisMaker::InitRun + StKFParticleInterface::instance()->SetFixedTarget(St_beamInfoC::instance()->IsFixedTarget()); + +-------------------------------------------------------------------------------- + StKFParticleAnalysisMaker::Make + StKFParticleInterface::ProcessEvent(fPicoDst, triggeredTracks) + if(fCollectTrackHistograms && (isTofm2 || isETofm2) + Fill track parameters histograms + AddTrackToParticleList + FillPIDHistograms + Fill track parameters histograms + SetField + CleanPV + InitParticles + + AddPV + if(fCollectTrackHistograms) +or + StKFParticleInterface::ProcessEvent(fMuDst, mcTracks, mcIndices, fProcessSignal); + ... + StKFParticleInterface::PerformanceAnalysis + KFTopoPerformance::FillHistos + KFTopoPerformance::FillParticleParameters +================================================================================ +Indeces: +StRoot/KFParticle/KFParticleDef.h:36:#define NInputSets 8 + +StKFParticleInterface::fParticles [nGlobalTracks*10] + fParticlesPdg [nGlobalTracks*10] +ProcessEvent + m2TofArray(nGlobalTracks*2, -1.0e6f); + trakIdToI(nGlobalTracks*2); + trakIdToI[gTrack->id()] = iTrack; iTrack < nGlobalTracks; index = gTrack->id() + + vector totalPDG = GetPID(m2tof, track.GetP(), q, gTrack->dEdx(), dEdXPull, isTofm2, index); + AddTrackToParticleList(track, nHftHitsInTrack, index, totalPDG, primaryVertex, primaryTrackList, fNHftHits, fParticlesPdg, fParticles, nPartSaved, 0, 0, Chi2, NDF); + particle.SetId(index); + particles[nPartSaved] = particle; + InitParticles(); + KFParticleTopoReconstructor::Init(vector &particles, vector* pdg, vector* nPixelHits) + fKFParticleTopoReconstructor->Init( fParticles, &fParticlesPdg, &fNHftHits ); +KFParticleTopoReconstructor::fParticles diff --git a/StRoot/StKFParticleAnalysisMaker/StKFParticleAnalysisMaker.h b/StRoot/StKFParticleAnalysisMaker/StKFParticleAnalysisMaker.h new file mode 100644 index 00000000000..48e4c3658b2 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StKFParticleAnalysisMaker.h @@ -0,0 +1,154 @@ +// $Id: StKFParticleAnalysisMaker.h,v 1.16 2014/08/06 11:43:53 jeromel Exp $ +/*! + * \class StKFParticleAnalysisMaker + * \author Maksym Zyzak + * \date 2017/10/17 + * \brief class for analysis of PicoDst + */ +#ifndef STAR_StKFParticleAnalysisMaker +#define STAR_StKFParticleAnalysisMaker +//#define __DEVT__ +#ifndef StMaker_H +#include "StMaker.h" +#endif +#include "TMVA/Reader.h" + +#include "KFParticle.h" + +class StKFParticleInterface; +class StKFParticlePerformanceInterface; +// class KFParticle; +class StPicoDst; +class StMuDst; +class TNtuple; +class TFile; +class TChain; +class TTree; +class StRefMultCorr; + +class StKFParticleAnalysisMaker : public StMaker { + private: + static const int fNNTuples = 8; + Char_t mBeg[1]; //! + StMuDst *fMuDst; + StPicoDst *fPicoDst; //! + StKFParticleInterface *fStKFParticleInterface; //! + StKFParticlePerformanceInterface *fStKFParticlePerformanceInterface; //! + TNtuple* fCutsNTuple[fNNTuples]; + TFile* fNTupleFile[fNNTuples]; + int fNTuplePDG[fNNTuples]; + TString fNtupleNames[fNNTuples]; + TString fNtupleCutNames[fNNTuples]; + std::vector fDaughterNames[fNNTuples]; + vector< vector > fTMVACutFile[fNNTuples]; + vector< vector > fTMVACut[fNNTuples]; + vector< vector > fTMVAReader[fNNTuples]; + std::vector fTMVACentralityBins[fNNTuples]; + std::vector fTMVAPtBins[fNNTuples]; + Char_t mEnd[1]; //! + std::vector fTMVAParticleParameters[fNNTuples]; + int fNTrackTMVACuts; + bool fIsPicoAnalysis; + int fdEdXMode; + Bool_t fStoreTmvaNTuples; + Bool_t fProcessSignal; + Bool_t fCollectTrackHistograms; + Bool_t fCollectPIDHistograms; + Bool_t fCollectPVHistograms; + Bool_t fTMVAselection; + + //Centrality and flow + Bool_t fFlowAnalysis; + TChain* fFlowChain; + int fFlowRunId; + int fFlowEventId; + int fCentrality; + std::vector fFlowFiles; + std::map fFlowMap; + + bool fRunCentralityAnalysis; + StRefMultCorr *fRefmultCorrUtil; + TString fCentralityFile; + + bool fAnalyseDsPhiPi; + std::vector fDecays; + + bool fIsProduce3DEfficiencyFile; + TString f3DEfficiencyFile; + + void GetDaughterParameters(const int iReader, int& iDaughterTrack, int& iDaughterParticle, KFParticle& particle); + void GetParticleParameters(const int iReader, KFParticle& particle); + long GetUniqueEventId(const int iRun, const int iEvent) const; + + int GetTMVACentralityBin(int iReader, int centrality); + int GetTMVAPtBin(int iReader, double pt); + void SetTMVACentralityBins(int iReader, TString bins); + void SetTMVAPtBins(int iReader, TString bins); + void SetTMVABins(int iReader, TString centralityBins="-1:1000", TString ptBins="-1.:1000."); + + bool fStoreCandidates; + KFParticle fPartcileCandidate; + std::vector fIsStoreCandidate; + TString fCandidateFileName; + TFile* fCandidateFile; + TTree* fCandidatesTree; + + public: + StKFParticleAnalysisMaker(const char *name="KFParticleAnalysis"); + virtual ~StKFParticleAnalysisMaker(); + virtual Int_t Init(); + virtual Int_t InitRun(Int_t runumber); + void BookVertexPlots(); + virtual Int_t Make(); + virtual Int_t Finish(); + Bool_t Check(); + void AnalysePicoDst() { fIsPicoAnalysis = true; } + void AnalyseMuDst() { fIsPicoAnalysis = false; } + static void PrintMem(const Char_t *opt = ""); + virtual const char *GetCVS() const { + static const char cvs[]="Tag $Name: $ $Id: StKFParticleAnalysisMaker.h,v 1.0 2017/10/07 11:43:53 mzyzak Exp $ built " __DATE__ " " __TIME__ ; + return cvs; + } + void ProcessSignal() { fProcessSignal = true; } + void StoreTMVANtuples() { fStoreTmvaNTuples = true; } + void CollectTrackHistograms() { fCollectTrackHistograms = true; } + void CollectPIDHistograms() { fCollectPIDHistograms = true; } + void CollectPVHistograms() { fCollectPVHistograms = true; } + void UseTMVA() { fTMVAselection = true; } + void SetTMVABinsD0 (TString centralityBins, TString ptBins) { SetTMVABins(0, centralityBins, ptBins); } + void SetTMVABinsDPlus(TString centralityBins, TString ptBins) { SetTMVABins(1, centralityBins, ptBins); } + void SetTMVABinsDs (TString centralityBins, TString ptBins) { SetTMVABins(2, centralityBins, ptBins); } + void SetTMVABinsLc (TString centralityBins, TString ptBins) { SetTMVABins(3, centralityBins, ptBins); } + void SetTMVABinsD0KK (TString centralityBins, TString ptBins) { SetTMVABins(4, centralityBins, ptBins); } + void SetTMVABinsD04 (TString centralityBins, TString ptBins) { SetTMVABins(5, centralityBins, ptBins); } + void SetTMVABinsBPlus(TString centralityBins, TString ptBins) { SetTMVABins(6, centralityBins, ptBins); } + void SetTMVABinsB0 (TString centralityBins, TString ptBins) { SetTMVABins(7, centralityBins, ptBins); } + void SetTMVAcutsD0 (TString file, double cut, int iCentralityBin = 0, int iPtBin = 0) { fTMVACutFile[0][iCentralityBin][iPtBin] = file; fTMVACut[0][iCentralityBin][iPtBin] = cut; } + void SetTMVAcutsDPlus(TString file, double cut, int iCentralityBin = 0, int iPtBin = 0) { fTMVACutFile[1][iCentralityBin][iPtBin] = file; fTMVACut[1][iCentralityBin][iPtBin] = cut; } + void SetTMVAcutsDs (TString file, double cut, int iCentralityBin = 0, int iPtBin = 0) { fTMVACutFile[2][iCentralityBin][iPtBin] = file; fTMVACut[2][iCentralityBin][iPtBin] = cut; } + void SetTMVAcutsLc (TString file, double cut, int iCentralityBin = 0, int iPtBin = 0) { fTMVACutFile[3][iCentralityBin][iPtBin] = file; fTMVACut[3][iCentralityBin][iPtBin] = cut; } + void SetTMVAcutsD0KK (TString file, double cut, int iCentralityBin = 0, int iPtBin = 0) { fTMVACutFile[4][iCentralityBin][iPtBin] = file; fTMVACut[4][iCentralityBin][iPtBin] = cut; } + void SetTMVAcutsD04 (TString file, double cut, int iCentralityBin = 0, int iPtBin = 0) { fTMVACutFile[5][iCentralityBin][iPtBin] = file; fTMVACut[5][iCentralityBin][iPtBin] = cut; } + void SetTMVAcutsBPlus(TString file, double cut, int iCentralityBin = 0, int iPtBin = 0) { fTMVACutFile[6][iCentralityBin][iPtBin] = file; fTMVACut[6][iCentralityBin][iPtBin] = cut; } + void SetTMVAcutsB0 (TString file, double cut, int iCentralityBin = 0, int iPtBin = 0) { fTMVACutFile[7][iCentralityBin][iPtBin] = file; fTMVACut[7][iCentralityBin][iPtBin] = cut; } + + void RunFlowAnalysis() { fFlowAnalysis = true; } + void AddFlowFile(TString file) { fFlowFiles.push_back(file); } + + void RunCentralityAnalysis() { fRunCentralityAnalysis = true; } + void SetCentralityFile(TString file) { fCentralityFile = file; } + + void AnalyseDsPhiPi() { fAnalyseDsPhiPi = true; } + + void AddDecayToReconstructionList( int iDecay ); + + void Produce3DEfficiencyFile() { fIsProduce3DEfficiencyFile = true; } + void Set3DEfficiency(TString fileName) { f3DEfficiencyFile = fileName; } + + void SetCandidateFileName(TString name) { fCandidateFileName = name; } + void AddCandidateToStore(int pdg); + + ClassDef(StKFParticleAnalysisMaker,0) // +}; +#endif +// $Log: StKFParticleAnalysisMaker.h,v $ diff --git a/StRoot/StKFParticleAnalysisMaker/StKFParticleCandidateAnalysis.cxx b/StRoot/StKFParticleAnalysisMaker/StKFParticleCandidateAnalysis.cxx new file mode 100644 index 00000000000..20e67241509 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StKFParticleCandidateAnalysis.cxx @@ -0,0 +1,1208 @@ +#include "StKFParticleCandidateAnalysis.h" + +#include "TChain.h" +#include "TFile.h" +#include "TTree.h" +#include "TBranch.h" +#include "TDirectory.h" +#include "TMath.h" +#include "TH1D.h" +#include "TH2D.h" +#include "TH3D.h" + +#include +#include +#include + +#include "KFParticleSIMD.h" + +ClassImp(StKFParticleCandidateAnalysis) + +StKFParticleCandidateAnalysis::StKFParticleCandidateAnalysis(TString inputFile): + fCandidateFileChain(new TChain("Candidates")), fCandidate(new KFParticle), + fOutputHistoFile(nullptr), fOutputHistoDir(nullptr) +{ + fCandidateFileChain->Add(inputFile); + fCandidateFileChain->SetBranchStatus("*",0); + fCandidateFileChain->SetBranchAddress("Candidates", &fCandidate); + fCandidateFileChain->SetBranchStatus("Candidates", 1); + + TFile* curFile = gFile; + TDirectory* curDirectory = gDirectory; + +#if 1 + // fPdgMap[3004] = 0; + // fPdgMap[3005] = 1; + // fPdgMap[3006] = 2; + // fPdgMap[3007] = 3; + // fPdgMap[3012] = 4; + // fPdgMap[3013] = 5; + + // fPdgMap[3003] = 6; + // fPdgMap[3103] = 7; + // fPdgMap[3016] = 8; + // fPdgMap[3019] = 9; + // fPdgMap[3022] = 10; + // fPdgMap[3025] = 11; + + // fPdgMap[3203] = 12; + // fPdgMap[3040] = 13; + fPdgMap[3008] = 14; + // fPdgMap[3009] = 15; + // fPdgMap[3010] = 16; + // fPdgMap[3011] = 17; +#else + fPdgMap[1003006] = 18; + fPdgMap[1003007] = 19; + fPdgMap[1003004] = 20; + fPdgMap[1003005] = 21; +#endif + // fPdgMap[ 3312] = 22; + // fPdgMap[-3312] = 23; + // fPdgMap[ 3334] = 24; + // fPdgMap[-3334] = 25; + + const float pi = TMath::Pi(); + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 + TString particleName[NParticles]{ "H3L", "H4L", "He4L", "He5L", "H3Ldppi", "H4Ltppi", "LN", "LNN", "H6L", "He6L", "He7L", "Li7L", "LLN", "LLNN", "H4LL", "H4LL3", "H5LL", "He6LL", "He4L*", "He5L*", "H3L*", "H4L*", "Xi-", "Xi+", "Omega-", "Omega+"}; + float minM[NSets][NParticles]{ { 2.94, 3.86, 3.86, 4.81, 2.94, 3.86, 2.02, 2.94, 5.74, 5.74, 6.67, 6.67, 3.13, 4.06, 4.06, 4.06, 4.99, 5.95, 3.86, 4.81, 2.94, 3.86, 1.22, 1.22, 1.66, 1.66}, + { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 2.7, 3.6, 1.8, 2.7, 0.1, 0.1, 0.4, 0.4}, + { 2.7, 3.6, 2.7, 3.6, 1.8, 2.7, 1.8, 2.7, 5.5, 5.5, 6.5, 6.5, 2.94, 3.86, 3.86, 2.94, 4.81, 4.81, 1.07, 1.07, 1.07, 1.07, 1.0, 1.0, 1.0, 1.0}, + { 0, 0, 0.93, 0.93, 0.93, 0.93, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.93, 0, 0.93, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 1.07, 1.07, 1.07, 1.07, 0, 0, 0, 0, 0, 0, 0, 0, 2.7, 1.07, 0, 1.07, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 3.86, 4.81, 2.94, 3.86, 0, 0, 0, 0, 0, 0, 0, 0, 0.93, 4.06, 0, 5.95, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 2.94, 3.86, 2.01, 2.94, 0, 0, 0, 0, 0, 0, 0, 0, 1.07, 3.13, 0, 4.99, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 3.74, 4.66, 2.81, 3.74, 0, 0, 0, 0, 0, 0, 0, 0, 1.07, 3.92, 0, 5.81, 0, 0, 0, 0, 0, 0, 0, 0} + }; + float maxM[NSets][NParticles]{ { 3.19, 4.11, 4.11, 5.06, 3.19, 4.11, 2.27, 3.19, 5.95, 5.95, 6.92, 6.92, 3.38, 4.31, 4.31, 4.31, 5.24, 6.20, 4.11, 5.06, 3.19, 4.11, 1.42, 1.42, 1.68, 1.68}, + { 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 2.9, 3.8, 2.0, 2.9, 0.2, 0.2, 0.6, 0.6}, + { 2.9, 3.8, 2.9, 3.8, 2.0, 2.9, 2.0, 2.9, 5.7, 5.7, 6.7, 6.7, 3.19, 4.11, 4.11, 3.19, 5.06, 5.06, 1.32, 1.32, 1.32, 1.32, 1.2, 1.2, 1.2, 1.2}, + { 0, 0, 0.95, 0.95, 0.95, 0.95, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.95, 0, 0.95, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 1.32, 1.32, 1.32, 1.32, 0, 0, 0, 0, 0, 0, 0, 0, 2.9, 1.32, 0, 1.32, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 4.11, 5.06, 3.19, 4.11, 0, 0, 0, 0, 0, 0, 0, 0, 0.95, 4.31, 0, 6.20, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 3.19, 4.11, 2.26, 3.19, 0, 0, 0, 0, 0, 0, 0, 0, 1.32, 3.38, 0, 5.24, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 3.99, 4.91, 3.06, 3.99, 0, 0, 0, 0, 0, 0, 0, 0, 1.32, 4.17, 0, 6.06, 0, 0, 0, 0, 0, 0, 0, 0} + }; + + TString signalSet[NSignalSets]{"Total", "Signal", "BG"}; + TString setNames[NParticles][NSets]{ + {"mother", "pi", "He3", "", "", "", "", "" }, // H3L + {"mother", "pi", "He4", "", "", "", "", "" }, // H4L + {"mother", "pi", "He3", "p", "ppi", "fl", "fpi", "fp" }, // He4L + {"mother", "pi", "He4", "p", "ppi", "fl", "fpi", "fp" }, // He5L + {"mother", "pi", "d", "p", "ppi", "fl", "fpi", "fp" }, // H3L -> dppi + {"mother", "pi", "t", "p", "ppi", "fl", "fpi", "fp" }, // H4L -> tppi + {"mother", "pi", "d", "", "", "", "", "" }, // Ln + {"mother", "pi", "t", "", "", "", "", "" }, // Lnn + {"mother", "pi", "He6", "", "", "", "", "" }, // H6L + {"mother", "pi", "Li6", "", "", "", "", "" }, // He6L + {"mother", "pi", "Li7", "", "", "", "", "" }, // He7L + {"mother", "pi", "Be7", "", "", "", "", "" }, // Li7L + {"mother", "pi", "H3L", "", "", "", "", "" }, // LLn + {"mother", "pi", "H4L", "", "", "", "", "" }, // LLnn + {"mother", "pi", "He4L", "pi_d", "He3_d", "p_d", "ppi1", "ppi2" }, // H4LL -> He4L pi + {"mother", "pi", "H3L", "p", "ppi", "fl", "fpi", "fp" }, // H4LL -> H3L p pi + {"mother", "pi", "He5L", "", "", "", "", "" }, // H5LL + {"mother", "pi", "He5L", "p", "ppi", "fl", "fpi", "fp" }, // He6LL + {"mother", "He3","L", "", "", "", "", "" }, // He4L* + {"mother", "He4","L", "", "", "", "", "" }, // He5L* + {"mother", "d", "L", "", "", "", "", "" }, // H3L* + {"mother", "t", "L", "", "", "", "", "" }, // H4L* + {"mother", "pi", "L", "", "", "", "", "" }, // Xi- + {"mother", "pi", "L", "", "", "", "", "" }, // Xi+ + {"mother", "K", "L", "", "", "", "", "" }, // Omega- + {"mother", "K", "L", "", "", "", "", "" }, // Omega+ + }; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 + TString f1Name[NParticles]{"^{3}He","^{4}He","^{3}He","^{4}He","d","t","d","t","^{6}He","^{6}Li","^{7}Li","^{7}Be","^{3}_{#Lambda}H","^{4}_{#Lambda}H","^{4}_{#Lambda}He","^{3}_{#Lambda}H","^{5}_{#Lambda}He","^{5}_{#Lambda}He","^{3}He","^{4}He","d","t","#Lambda", "#bar{#Lambda}", "#Lambda", "#bar{#Lambda}"}; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 + TString f2Name[NParticles]{"","","p","p","p","p","","","","","","","","","","p","","p","","","","","","","",""}; + + + TString histoNames[NHistos-1]{"x", "y", "z", "px", "py", "pz", "pt", "p", + "dx", "dy", "dz", "dpx", "dpy", "dpz", "dpt", "dp", + "chi", "chiTopo", "chiPrim", "chiPrimXY", "l", "dl", "ldl", "r", + "ctau", "decayL", "phi", "theta", "rapidity", "mt", "extra"}; + // 1 2 3 4 5 6 7 8 + const int nBins[NHistos-1] { 200, 200, 500, 200, 200, 400, 50, 200, + 100, 100, 100, 100, 100, 100, 100, 100, + 200, 200, 1000, 1000, 200, 100, 1000, 100, + 100, 100, 100, 100, 60, 50, 1000 + }; + const float minX[NHistos-1]{ -100, -100, -250, -10, -10, -20, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -pi, 0, -3, 0, 0 + }; + const float maxX[NHistos-1]{ 100, 100, 250, 10, 10, 20, 5, 20, + 10, 10, 10, 0.2, 0.2, 0.2, 0.2, 0.2, + 20, 20, 1000, 1000, 200, 10, 100, 50, + 100, 100, pi, pi, 3, 5, 1 + }; + + TString outFileName = inputFile.ReplaceAll(".root", "_histos.root"); + + fOutputHistoFile = new TFile(outFileName, "RECREATE"); + fOutputHistoDir = fOutputHistoFile->mkdir("Particles"); + fOutputHistoDir->cd(); + { + for(int iParticle=0; iParticlesecond == iParticle) { + isParticleAdded = true; + break; + } + } + if(!isParticleAdded) continue; + + gDirectory->mkdir(particleName[iParticle]); + gDirectory->cd(particleName[iParticle]); + for(int iSignalSet=0; iSignalSetmkdir(signalSet[iSignalSet]); + gDirectory->cd(signalSet[iSignalSet]); + for(int iSet=0; iSetmkdir(setNames[iParticle][iSet]); + gDirectory->cd(setNames[iParticle][iSet]); + { + gDirectory->mkdir("parameters"); + gDirectory->cd("parameters"); + for(int iHisto=0; iHisto<8; iHisto++) { + fHistos[iParticle][iSignalSet][iSet][iHisto] = + new TH1D(histoNames[iHisto], histoNames[iHisto], nBins[iHisto], minX[iHisto], maxX[iHisto]); + } + gDirectory->cd(".."); + gDirectory->mkdir("errors"); + gDirectory->cd("errors"); + for(int iHisto=8; iHisto<16; iHisto++) { + fHistos[iParticle][iSignalSet][iSet][iHisto] = + new TH1D(histoNames[iHisto], histoNames[iHisto], nBins[iHisto], minX[iHisto], maxX[iHisto]); + } + gDirectory->cd(".."); + for(int iHisto=16; iHistocd(".."); + } + gDirectory->cd(".."); + } + const int nBinsM = 250; + //ctau - M + fHistos2D[iParticle][0] = new TH2D("ctauM", "ctauM", + nBins[24], minX[24], maxX[24], + nBinsM, minM[0][iParticle], maxM[0][iParticle]); + fHistos2D[iParticle][0]->GetXaxis()->SetTitle("c#tau"); + fHistos2D[iParticle][0]->GetYaxis()->SetTitle("m [GeV/c]"); + + fHistos2D[iParticle][1] = new TH2D("Armenteros", "Armenteros", + 4000, -2.f, 2.f, + 1000, 0.f, 1.f); + fHistos2D[iParticle][1]->GetXaxis()->SetTitle("#alpha (p_{L}^{+}-p_{L}^{-})/(p_{L}^{+}+p_{L}^{-})"); + fHistos2D[iParticle][1]->GetYaxis()->SetTitle("q_{t} [GeV/c]"); + + fHistos2D[iParticle][2] = new TH2D("ChiTopoVsM", "ChiTopoVsM", + 100, 0.f, 1.f, + nBinsM, minM[0][iParticle], maxM[0][iParticle]); + fHistos2D[iParticle][2]->GetXaxis()->SetTitle("prob"); + fHistos2D[iParticle][2]->GetYaxis()->SetTitle("M [GeV^{2}/c^{2}]"); + + fHistos2D[iParticle][3] = new TH2D("MPl", "MPl", + 400, -2.f, 2.f, + nBinsM, minM[0][iParticle], maxM[0][iParticle]); + fHistos2D[iParticle][3]->GetXaxis()->SetTitle("#alpha (p_{L}^{+}-p_{L}^{-})/(p_{L}^{+}+p_{L}^{-})"); + fHistos2D[iParticle][3]->GetYaxis()->SetTitle("m [GeV/c]"); + + //y-pt-M and y-mt-M + fHistos3D[iParticle][0] = new TH3D("y-pt-m", "y-pt-m", + nBins[28], minX[28], maxX[28], + nBins[6], minX[6], maxX[6], + nBinsM, minM[0][iParticle], maxM[0][iParticle]); + fHistos3D[iParticle][1] = new TH3D("y-mt-m", "y-mt-m", + nBins[28], minX[28], maxX[28], + nBins[29], minX[29], maxX[29], + nBinsM, minM[0][iParticle], maxM[0][iParticle]); + //Dalitz + if(!f2Name[iParticle].IsNull()) + { + TString f1piName="m_{"; f1piName+=f1Name[iParticle]; f1piName+="#pi} [GeV/c]"; + TString f2piName="m_{"; f2piName+=f2Name[iParticle]; f2piName+="#pi} [GeV/c]"; + TString f1f2Name="m_{"; f1f2Name+=f1Name[iParticle]; f1f2Name+=f2Name[iParticle]; f1f2Name+="} [GeV/c]"; + TString f1f2piName="m_{"; f1f2piName+=f1Name[iParticle]; f1f2piName+=f2Name[iParticle]; f1f2piName+="#pi} [GeV/c]"; + + fHistos3D[iParticle][2] = new TH3D("dalitz0", "dalitz0", + 100, minM[7][iParticle], maxM[7][iParticle]-0.15, + 100, minM[4][iParticle], maxM[4][iParticle]-0.15, + nBinsM, minM[0][iParticle], maxM[0][iParticle]); + fHistos3D[iParticle][2]->GetXaxis()->SetTitle(f1f2Name); + fHistos3D[iParticle][2]->GetYaxis()->SetTitle(f2piName); + fHistos3D[iParticle][2]->GetZaxis()->SetTitle(f1f2piName); + + fHistos3D[iParticle][3] = new TH3D("dalitz1", "dalitz1", + 100, minM[6][iParticle], maxM[6][iParticle]-0.15, + 100, minM[4][iParticle], maxM[4][iParticle]-0.15, + nBinsM, minM[0][iParticle], maxM[0][iParticle]); + fHistos3D[iParticle][3]->GetXaxis()->SetTitle(f1piName); + fHistos3D[iParticle][3]->GetYaxis()->SetTitle(f2piName); + fHistos3D[iParticle][3]->GetZaxis()->SetTitle(f1f2piName); + + fHistos3D[iParticle][4] = new TH3D("dalitz2", "dalitz2", + 100, minM[7][iParticle], maxM[7][iParticle]-0.15, + 100, minM[6][iParticle], maxM[6][iParticle]-0.15, + nBinsM, minM[0][iParticle], maxM[0][iParticle]); + fHistos3D[iParticle][4]->GetXaxis()->SetTitle(f1f2Name); + fHistos3D[iParticle][4]->GetYaxis()->SetTitle(f1piName); + fHistos3D[iParticle][4]->GetZaxis()->SetTitle(f1f2piName); + } + + gDirectory->cd(".."); //main folder + } + } + + gFile = curFile; + gDirectory = curDirectory; +} + +void StKFParticleCandidateAnalysis::Run() { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 + // H3L H4L He4L He5L H3L H4L LN LNN H6L He6L He7L Li7L LLN LLNN H4LL H4LL H5L He6LL He4L* He5L* H3L* H4L* Xi- Xi+ Omega- Omega+ + float peakM[NParticles] {2.9912, 3.9224, 3.9215, 4.8399, 2.9910, 3.9223, 2.0450, 2.9800, 5.7800, 5.7800, 6.7150, 6.7110, 3.169, 4.1100, 4.1100, 4.1100, 5.0200, 5.9700, 3.9217, 4.8402, 2.9914, 3.9227, 1.32171, 1.32171, 1.67245, 1.67245}; + float sigmaM[NParticles]{0.0017, 0.0018, 0.0014, 0.0015, 0.0015, 0.0012, 0.0018, 0.0018, 0.0018, 0.0018, 0.0018, 0.0018, 0.005, 0.0015, 0.0015, 0.0015, 0.0015, 0.0015, 0.0013, 0.0013, 0.0013, 0.0013, 0.00200, 0.00200, 0.00200, 0.00200}; + + int nnn=0; + for(int iParticle=0; iParticleGetEntries(); ) { + std::vector particles; // 0 - mother, 1... - daughters + + fCandidateFileChain->GetEvent(iParticle); + KFParticle pv = *fCandidate; + iParticle++; + fCandidateFileChain->GetEvent(iParticle); + particles.push_back(*fCandidate); + iParticle++; + + bool badDaughters = false; + + for(int iDaughter=0; iDaughterGetEvent(iParticle); + // float pvPosition[3]{pv.X(), pv.Y(), pv.Z()}; + // fCandidate->TransportToPoint(pvPosition); + particles.push_back(*fCandidate); + const int nGrandDaughters = fCandidate->NDaughters(); + iParticle++; + + if(nGrandDaughters > 1) + { + for(int iGrandDaughter=0; iGrandDaughterGetEvent(iParticle); + particles.push_back(*fCandidate); + iParticle++; + } + } + + badDaughters = badDaughters || (fCandidate->GetErrZ() > 2.999f); + } + + // for(int i=0; i 0.f && particles[0].Covariance(1,1) > 0.f && + // particles[0].Covariance(2,2) > 0.f && particles[0].Covariance(3,3) > 0.f && + // particles[0].Covariance(4,4) > 0.f && particles[0].Covariance(5,5) > 0.f && + // particles[0].Covariance(6,6) > 0.f; + // if(!isOk) continue; + // if(particles[0].GetDeviationFromVertexXY(pv) < 0.f) continue; + // if(particles[0].GetDeviationFromVertex(pv) < 0.f) continue; + + // const float probChiPrim = TMath::Prob(particles[0].GetDeviationFromVertexXY(pv), 4) * + // (1. - TMath::Prob(particles[1].GetDeviationFromVertexXY(pv), 4)) * + // (1. - TMath::Prob(particles[2].GetDeviationFromVertexXY(pv), 4)); + // if(probChiPrim < 0.001f) continue; + + if(particles[0].GetPDG() >= 1003004 && particles[0].GetPDG() <= 1003007) { + KFParticle part0; + part0.SetConstructMethod(2); + KFParticle lambda = particles[2]; + lambda.SetProductionVertex(pv); + // lambda.SetNonlinearMassConstraint(1.115683); + part0 += lambda; + + part0.NDF() += 3; + part0 += particles[1]; + + particles[0] = part0; + } + + if(particleIndex >= 12 && particleIndex <= 17 && 0) { + + KFParticle fragment = particles[2]; + KFParticle pion = particles[1]; + + const float massConst = particleIndex == 12 || particleIndex == 15 ? 2.991 : particleIndex == 13 ? 3.9224 : 3.9215; + const float massSigma = particleIndex == 14 ? 0.0014 : 0.00175; + float mF, dmF; + fragment.GetMass(mF, dmF); + if(dmF > 0.0025f) continue; + if(fabsf(mF - massConst) > 2. * massSigma) continue; + float lf, dlf; + fragment.GetDistanceToVertexLine(pv,lf,dlf); + if(lf > 50.f) continue; + + fragment.SetNonlinearMassConstraint(massConst); + + KFParticle mother; + mother += fragment; + mother += pion; + particles[0] = mother; + + fragment.SetProductionVertex(pv); + const float probTopo = TMath::Prob(fragment.Chi2(), fragment.NDF()); + const float mass0 = particles[0].GetMass(); + // if(probTopo < 0.01) continue; + fHistos2D[particleIndex][2]->Fill(probTopo, mass0); + + // float a, da; + // particles[0].GetDistanceToVertexLine(pv,a,da); + // if(a / da < 10.f) continue; + + + float g, dg; + particles[2].GetDistanceToVertexLineWithDirection(particles[0],g,dg); + if(dg > 10000.f) continue; + // if(g/dg < 1.f) continue; + + // particles[2].GetDistanceToVertexLineWithDirection(pv,g,dg); + // if(dg > 3.f) continue; + + // particles[0].GetDistanceToVertexLineWithDirection(pv,g,dg); + // if(dg > 3.f) continue; + + // float l0, l2, dl; + // particles[0].GetDistanceToVertexLine(pv,l0,dl); + // particles[2].GetDistanceToVertexLine(pv,l2,dl); + // if(l2 < l0) continue; + + + // if(particles[2].GetDeviationFromVertex(pv) > 18.f) continue; + // if(particles[2].GetDeviationFromVertexXY(pv) > 18.f) continue; + + KFParticle topo = particles[0]; + topo.SetProductionVertex(pv); + if(topo.Chi2()/topo.NDF() > 3.f) continue; + if(topo.Chi2() < 0.f) continue; + } + + // 0 - H4LL + // 1 - pi- + // 2 - He4L + // 3 - pi- + // 4 - He3 + // 5 - p + if(particleIndex == 14) + { + + float g, dg; + particles[0].GetDistanceToVertexLineWithDirection(pv,g,dg); + if(g/dg < 5.) continue; + + float a, da; + particles[2].GetDistanceToVertexLineWithDirection(particles[0],a,da); + if(da > 10000.f) continue; + + // if(particles[0].GetPt() > 3. || particles[0].GetPt() < 1.) continue; + // if(particles[2].GetPt() < 1.) continue; + + // if(particles[1].GetDistanceFromParticle(particles[2]) > 2.) continue; + + if(particles[1].GetDeviationFromVertex(pv) < 8.) continue; + + if( particles[0].Chi2() / particles[0].NDF() > 3.) continue; + KFParticle h4lTopo = particles[0]; + h4lTopo.SetProductionVertex(pv); + if( h4lTopo.Chi2() / h4lTopo.NDF() > 5.) continue; + + // if( particles[2].Chi2() / particles[2].NDF() > 3.) continue; + + // KFParticle he4lTopo = particles[2]; + // he4lTopo.SetProductionVertex(pv); + // if( he4lTopo.Chi2() / he4lTopo.NDF() > 3.) continue; + + // if( particles[3].GetDeviationFromVertex(pv) < 8. ) continue; + // if( particles[1].GetDeviationFromVertex(pv) < 18. ) continue; + // if( particles[5].GetDeviationFromVertex(pv) < 18. ) continue; + + if(particles[5].GetP() < 0.5) continue; + float lHe4L, dlHe4L; + particles[2].GetDistanceToVertexLine(pv, lHe4L, dlHe4L); + if(dlHe4L > 3.f) continue; + float mHe4L, dmHe4L; + particles[2].GetMass(mHe4L, dmHe4L); + if(dmHe4L > 0.0025f) continue; + if(fabsf(mHe4L - 3.92151F) > 2.F * 0.0014) continue; + // if(!( (mHe4L > 3.92431f && mHe4L < 3.92711f) || (mHe4L > 3.91591f && mHe4L < 3.91871f) ) ) continue; + + KFParticle He3p; + He3p += particles[4]; + He3p += particles[5]; + if(He3p.GetMass() > 3.76f) continue; + + KFParticle ppi1; + ppi1 += particles[5]; + ppi1 += particles[3]; + + KFParticle ppi2; + ppi2 += particles[5]; + ppi2 += particles[1]; + + KFParticle topoPPi1 = ppi1; + topoPPi1.SetProductionVertex(pv); + topoPPi1.SetNonlinearMassConstraint(1.115683); + const float probTopoPPi1 = TMath::Prob(topoPPi1.Chi2(), topoPPi1.NDF()); + + bool isLambda = (probTopoPPi1 > 0.1f) || ((probTopoPPi1 > 0.005f && particles[4].GetDeviationFromVertex(pv) < 8.f)); + + KFParticle topoPPi2 = ppi2; + topoPPi2.SetProductionVertex(pv); + topoPPi2.SetNonlinearMassConstraint(1.115683); + const float probTopoPPi2 = TMath::Prob(topoPPi2.Chi2(), topoPPi2.NDF()); + isLambda |= probTopoPPi2 > 0.1f; + + // bool isLambda = probTopoPPi1 > 0.1f || probTopoPPi2 > 0.1f; + if(isLambda) continue; + + particles.push_back(ppi1); + particles.push_back(ppi2); + } + + + const float mass = particles[0].GetMass(); + const bool isSignal = ( mass > peakM[particleIndex] - 3*sigmaM[particleIndex] ) && + ( mass < peakM[particleIndex] + 3*sigmaM[particleIndex] ); + const bool isBG = (( mass > peakM[particleIndex] - 6*sigmaM[particleIndex] ) && + ( mass < peakM[particleIndex] - 3*sigmaM[particleIndex] ) ) || + (( mass > peakM[particleIndex] + 3*sigmaM[particleIndex] ) && + ( mass < peakM[particleIndex] + 6*sigmaM[particleIndex] ) ); + + if(particles[0].NDaughters()==3) { + + float l,dl; + + KFParticle ppi; + ppi += particles[1]; + ppi += particles[3]; + particles.push_back(ppi); + const float mppi = ppi.GetMass(); + + KFParticle fl; + // fl.X() = pv.X(); + // fl.Y() = pv.Y(); + // fl.Z() = pv.Z(); + // fl.Covariance(0,0) = pv.Covariance(0,0); + // fl.Covariance(1,1) = pv.Covariance(1,1); + // fl.Covariance(2,2) = pv.Covariance(2,2); + // fl.Chi2() = 0.f; + // fl.NDF() = 0; + fl += particles[2]; + KFParticle ppi_mc = ppi; + ppi_mc.SetNonlinearMassConstraint(1.115683); + fl += ppi_mc; + particles.push_back(fl); + fl.GetDistanceToVertexLine(pv,l,dl); + + KFParticle fpi; + fpi += particles[2]; + fpi += particles[1]; + particles.push_back(fpi); + + KFParticle fp; + fp += particles[2]; + fp += particles[3]; + particles.push_back(fp); + fp.GetDistanceToVertexLine(pv,l,dl); + + KFParticle topoPPi = ppi; + topoPPi.SetProductionVertex(pv); + topoPPi.SetNonlinearMassConstraint(1.115683); + const float probTopoPPi = TMath::Prob(topoPPi.Chi2(), topoPPi.NDF()); + + bool isLambda = probTopoPPi > 0.01f; + if(particleIndex == 4) { + isLambda |= (probTopoPPi > 0.0005f && particles[2].GetDeviationFromVertex(pv) < 8.f); + } + else { + isLambda |= (probTopoPPi > 0.005f && particles[2].GetDeviationFromVertex(pv) < 8.f); + } + + if( isLambda ) continue; + + fHistos2D[particleIndex][2]->Fill(probTopoPPi, mass); + + fHistos3D[particleIndex][2]->Fill(fp.GetMass(), mppi, mass); + fHistos3D[particleIndex][3]->Fill(fpi.GetMass(), mppi, mass); + fHistos3D[particleIndex][4]->Fill(fp.GetMass(), fpi.GetMass(), mass); + } + + // Armenteros + { + KFParticle posDaughter, negDaughter; + float vertex[3]{particles[0].GetX(), particles[0].GetY(), particles[0].GetZ()}; + if(particles[0].NDaughters()==2) + { + if(particles[1].GetQ() > 0) + { + posDaughter = particles[1]; + negDaughter = particles[2]; + } + else + { + negDaughter = particles[1]; + posDaughter = particles[2]; + } + + if(particles[0].GetPDG() >= 1003004 && particles[0].GetPDG() <= 1003007) { + negDaughter.SetNonlinearMassConstraint(1.115683); + negDaughter.SetProductionVertex(pv); + posDaughter.SetProductionVertex(pv); + vertex[0] = pv.X(); + vertex[1] = pv.Y(); + vertex[2] = pv.Z(); + } + } + else + { + // posDaughter = particles[2]; + // negDaughter += particles[1]; + // negDaughter += particles[3]; + // negDaughter.SetNonlinearMassConstraint(1.115683); + // vertex[0] = pv.X(); + // vertex[1] = pv.Y(); + // vertex[2] = pv.Z(); + + KFParticle fp; + fp.X() = particles[0].X(); + fp.Y() = particles[0].Y(); + fp.Z() = particles[0].Z(); + fp.Covariance(0,0) = particles[0].Covariance(0,0); + fp.Covariance(1,1) = particles[0].Covariance(1,1); + fp.Covariance(2,2) = particles[0].Covariance(2,2); + fp.Chi2() = 0.f; + fp.NDF() = 0; + fp += particles[2]; + fp += particles[3]; + posDaughter = fp; + negDaughter = particles[1]; + } + posDaughter.TransportToPoint(vertex); + negDaughter.TransportToPoint(vertex); + float QtAlpha[2]; + KFParticle::GetArmenterosPodolanski(posDaughter, negDaughter, QtAlpha ); + fHistos2D[particleIndex][1]->Fill(QtAlpha[1],QtAlpha[0],1); + fHistos2D[particleIndex][3]->Fill(QtAlpha[1],mass,1); + } + + float ctau0{0.f}, y0{0.f}, pt0{0.f}, mt0{0.f}; + + for(unsigned int iSet=0; iSet= 12 && particleIndex <= 21 && iSet == 2) + // topo.SetProductionVertex(particles[0]); + // else + topo.SetProductionVertex(pv); + + const float chiPrim = part.GetDeviationFromVertex(pv); + const float chiPrimXY = part.GetDeviationFromVertexXY(pv); + float l, dl; + part.GetDistanceToVertexLine(pv, l, dl); + float decayL, decayLError; + topo.GetDecayLength(decayL,decayLError); + float ct, ctError; + topo.GetLifeTime(ct,ctError); + float m, mError; + part.GetMass(m, mError); + float pt = part.GetPt(); + float mt = sqrt(pt*pt+m*m) - m; + if(iSet==0) { + ctau0 = ct; + y0 = topo.GetRapidity(); + pt0 = pt; + mt0 = mt; + } + + float cosV = TMath::Prob(part.Chi2(), part.NDF()); + + float values[NHistos] = { part.X(), part.Y(), part.Z(), + part.Px(), part.Py(), part.Pz(), pt, part.GetP(), + part.GetErrX(), part.GetErrY(), part.GetErrZ(), + part.GetErrPx(), part.GetErrPy(), part.GetErrPz(), + part.GetErrPt(), part.GetErrP(), + part.Chi2()/part.NDF(), topo.Chi2()/topo.NDF(), chiPrim, chiPrimXY, + l, dl, l/dl, part.GetR(), ct, decayL, + topo.GetPhi(), topo.GetTheta(), topo.GetRapidity(), mt, cosV, + m}; + + for(int iSignalSet=0; iSignalSetFill(values[iHisto]); + } + } + } + + fHistos2D[particleIndex][0]->Fill(ctau0, mass); + fHistos3D[particleIndex][0]->Fill(y0, pt0, mass); + fHistos3D[particleIndex][1]->Fill(y0, mt0, mass); + + nnn++; + // if(nnn == 1000000) break; + } + + //Store histograms + TFile* curFile = gFile; + TDirectory* curDirectory = gDirectory; + + fOutputHistoFile->cd(); + WriteHistosCurFile(fOutputHistoDir); + + gFile = curFile; + gDirectory = curDirectory; +} + +void StKFParticleCandidateAnalysis::RunMixedEvent() { + + KFParticle::SetField(-4.98677f); + KFParticleSIMD::SetField(-4.98677f); + + for(int iIndex=20; iIndex<=20; iIndex++) + { + struct PVCoordinates { + float m_x; + float m_y; + float m_z; + + bool operator==(const PVCoordinates& pv) const { + return (pv.m_x == m_x) && (pv.m_y == m_y) && (pv.m_z == m_z); + } + }; + + struct Event { + std::vector m_f; + std::vector m_L; + std::vector m_M; + KFParticle pv; + + void clear() { + m_f.clear(); + m_L.clear(); + m_M.clear(); + } + }; + + std::vector events; + Event event; + PVCoordinates pvCoordinates{0.f, 0.f, 0.f}; + + int nnn = 0; + + const int nCandidates = fCandidateFileChain->GetEntries(); + + for(int iParticle=0; iParticle < nCandidates; ) + { + std::vector particles; // 0 - mother, 1... - daughters + + fCandidateFileChain->GetEvent(iParticle); + KFParticle pv = *fCandidate; + iParticle++; + fCandidateFileChain->GetEvent(iParticle); + particles.push_back(*fCandidate); + iParticle++; + + bool badDaughters = false; + + for(int iDaughter=0; iDaughterGetEvent(iParticle); + particles.push_back(*fCandidate); + iParticle++; + badDaughters = badDaughters || (fCandidate->GetErrZ() > 2.999f); + } + + if(badDaughters) continue; + + // if(particles[0].GetMass() < 3.05) continue; + + const int particleIndex = ParticleIndex(particles[0].GetPDG()); + if(particleIndex != iIndex) continue; + + // if(pv.NDaughters() < 150) continue; + + const PVCoordinates currentPvCoordinates{pv.X(), pv.Y(), pv.Z()}; + + const float pvPoint[3]{pv.X(), pv.Y(), pv.Z()}; + // particles[2].SetNonlinearMassConstraint(1.115683); + particles[1].TransportToPoint(pvPoint); + particles[2].TransportToPoint(pvPoint); + + if(event.m_L.size() == 0) { + pvCoordinates = currentPvCoordinates; + event.m_M.push_back(particles[0]); + event.m_f.push_back(particles[1]); + event.m_L.push_back(particles[2]); + event.pv = pv; + } else if( (currentPvCoordinates == pvCoordinates) ) { + // event.m_M.push_back(particles[0]); // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + // event.m_f.push_back(particles[1]); // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + // event.m_L.push_back(particles[2]); // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + } else { + events.push_back(event); + event.clear(); + + pvCoordinates = currentPvCoordinates; + event.m_M.push_back(particles[0]); + event.m_f.push_back(particles[1]); + event.m_L.push_back(particles[2]); + event.pv = pv; + } + + if(events.size() == 1000 || iParticle >= nCandidates) { + + std::map nUsed; + for(const auto event: events) { + for(uint32_t iP=0; iP 0) continue; + + KFParticle fragment = fragment0; + + fragment.X() += event1.pv.X() - event2.pv.X(); + fragment.Y() += event1.pv.Y() - event2.pv.Y(); + fragment.Z() += event1.pv.Z() - event2.pv.Z(); + + KFParticleSIMD pvS(const_cast(event1.pv)); + KFParticleSIMD fragmentS(fragment); + KFParticleSIMD lambdaS(const_cast(lambda)); + lambdaS.SetNonlinearMassConstraint(1.115683f); + lambdaS.TransportToPoint(pvS.Parameters()); + + if(fragment.GetDeviationFromVertex(event1.pv) > 18.f) continue; + + KFParticleSIMD part00; + part00 += fragmentS; + part00 += lambdaS; + bool isOk = part00.Chi2()[0] / part00.NDF()[0] < 3.f; + isOk &= part00.Chi2()[0] == part00.Chi2()[0]; + isOk &= part00.Chi2()[0] > 0.f; + isOk &= std::isfinite(part00.Chi2()[0]); + + float32_v lv(1.e8f); + float32_v dlv(1.e8f); + mask32_v isParticleFromVertex; + part00.GetDistanceToVertexLine(pvS, lv, dlv, &isParticleFromVertex); + isOk &= (lv[0] < 200.f); + + if(!isOk) continue; + + KFParticle part000; + part00.GetKFParticle(part000); + if(part000.GetErrMass() > 0.003f) continue; + + float p1p2 = fragment.Px()*lambda.Px() + fragment.Py()*lambda.Py() + fragment.Pz()*lambda.Pz(); + float p12 = fragment.Px()*fragment.Px() + fragment.Py()*fragment.Py() + fragment.Pz()*fragment.Pz(); + float p22 = lambda.Px()*lambda.Px() + lambda.Py()*lambda.Py() + lambda.Pz()*lambda.Pz(); + if(p1p2 <= -p12 || p1p2 <= -p22) continue; + + KFParticle part0; + part0.SetConstructMethod(2); + KFParticle lambda0 = lambda; + lambda0.SetProductionVertex(event1.pv); + part0 += lambda0; + part0.NDF() += 3; + part0 += fragment; + + const float mass = part0.GetMass(); + + // Armenteros + { + float QtAlpha[2]; + KFParticle::GetArmenterosPodolanski(fragment, lambda, QtAlpha ); + fHistos2D[particleIndex][1]->Fill(QtAlpha[1],QtAlpha[0]); + fHistos2D[particleIndex][3]->Fill(QtAlpha[1],mass); + } + + KFParticle particles[3]{part0, fragment, lambda}; + for(int iSet=0; iSet<1; iSet++) + { + KFParticle part = particles[iSet]; + KFParticle topo = particles[iSet]; + topo.SetProductionVertex(event1.pv); + + const float chiPrim = part.GetDeviationFromVertex(event1.pv); + const float chiPrimXY = part.GetDeviationFromVertexXY(event1.pv); + float l, dl; + part.GetDistanceToVertexLine(event1.pv, l, dl); + float decayL, decayLError; + topo.GetDecayLength(decayL,decayLError); + float ct, ctError; + topo.GetLifeTime(ct,ctError); + float m, mError; + part.GetMass(m, mError); + float pt = part.GetPt(); + float mt = sqrt(pt*pt+m*m) - m; + float cosV = TMath::Prob(part.Chi2(), part.NDF()); + + float values[NHistos] = { part.X(), part.Y(), part.Z(), + part.Px(), part.Py(), part.Pz(), pt, part.GetP(), + part.GetErrX(), part.GetErrY(), part.GetErrZ(), + part.GetErrPx(), part.GetErrPy(), part.GetErrPz(), + part.GetErrPt(), part.GetErrP(), + part.Chi2()/part.NDF(), topo.Chi2()/topo.NDF(), chiPrim, chiPrimXY, + l, dl, l/dl, part.GetR(), ct, decayL, + topo.GetPhi(), topo.GetTheta(), topo.GetRapidity(), mt, cosV, + m}; + + for(int iHisto=0; iHistoFill(values[iHisto]); + } + } + + nnn++; + if(nnn % 10000 == 0) std::cout << nnn << '\n'; + + nUsed[&fragment0]++; + nUsed[&lambda]++; + // break; + } + if(nUsed[&lambda] > 0) break; + } + } + } + events.clear(); + } + } + } + + //Store histograms + TFile* curFile = gFile; + TDirectory* curDirectory = gDirectory; + + fOutputHistoFile->cd(); + WriteHistosCurFile(fOutputHistoDir); + + gFile = curFile; + gDirectory = curDirectory; +} + +inline void Mix(float& a, float& b, const float sinA, const float cosA) +{ + const float x = a; + const float y = b; + a = x * cosA - y * sinA; + b = x * sinA + y * cosA; +} + +void RotateXY(KFParticle& particle, const float alpha) +{ + const float cosA = std::cos(alpha); + const float sinA = std::sin(alpha); + + Mix(particle.Px(), particle.Py(), sinA, cosA); + + Mix(particle.Covariance(6), particle.Covariance(10), sinA, cosA); + Mix(particle.Covariance(7), particle.Covariance(11), sinA, cosA); + Mix(particle.Covariance(8), particle.Covariance(12), sinA, cosA); + Mix(particle.Covariance(18), particle.Covariance(19), sinA, cosA); + Mix(particle.Covariance(24), particle.Covariance(25), sinA, cosA); + + const float c9 = particle.Covariance(9); + const float c13 = particle.Covariance(13); + const float c14 = particle.Covariance(14); + particle.Covariance(9) = (c9 * cosA - c13 * sinA) * cosA - (c13 * cosA - c14 * sinA) * sinA; + particle.Covariance(13) = (c13 * cosA + c9 * sinA) * cosA - (c13 * sinA + c14 * cosA) * sinA; + particle.Covariance(14) = (c13 * cosA + c9 * sinA) * sinA + (c13 * sinA + c14 * cosA) * cosA; +} + +void StKFParticleCandidateAnalysis::RunRotatedBG() { + + std::srand(0); + + int nnn = 0; + + for(int iParticle=0; iParticleGetEntries(); ) + { + if(nnn % 10000 == 0) std::cout << nnn << '\n'; + + std::vector particles1; // 0 - mother, 1... - daughters + + fCandidateFileChain->GetEvent(iParticle); + KFParticle pv = *fCandidate; + iParticle++; + fCandidateFileChain->GetEvent(iParticle); + particles1.push_back(*fCandidate); + iParticle++; + + bool badDaughters = false; + + for(int iDaughter=0; iDaughterGetEvent(iParticle); + particles1.push_back(*fCandidate); + iParticle++; + badDaughters = badDaughters || (fCandidate->GetErrZ() > 2.999f); + } + + if(badDaughters) continue; + + // if(particles1[0].GetMass() < 3.01) continue; + + const int particleIndex = ParticleIndex(particles1[0].GetPDG()); + if(particleIndex < 18 || particleIndex > 21) continue; + + int nCombinations = 0; + constexpr int nEventsToMix = 1; + + KFParticle part2 = particles1[2]; + part2.SetNonlinearMassConstraint(1.115683); + + const int nRotates = 1000; + for(uint32_t iRotate=0; iRotate= 18 && particleIndex <= 21) + { + KFParticle& fragment = part1; + KFParticle& lambda = part2; + + KFParticleSIMD pvS(const_cast(pv)); + KFParticleSIMD fragmentS(fragment); + KFParticleSIMD lambdaS(const_cast(lambda)); + + if(fragment.GetDeviationFromVertex(pv) > 18.f) continue; + + KFParticle part000; + KFParticleSIMD part00; + part00 += fragmentS; + part00 += lambdaS; + if(part00.Chi2()[0] / part00.NDF()[0] > 3.f) continue; + if(part00.Chi2()[0] != part00.Chi2()[0]) continue; + if(part00.Chi2()[0] < 0.f) continue; + + part00.GetKFParticle(part000); + if(part000.GetErrMass() > 0.003f) continue; + + float p1p2 = fragment.Px()*lambda.Px() + fragment.Py()*lambda.Py() + fragment.Pz()*lambda.Pz(); + float p12 = fragment.Px()*fragment.Px() + fragment.Py()*fragment.Py() + fragment.Pz()*fragment.Pz(); + float p22 = lambda.Px()*lambda.Px() + lambda.Py()*lambda.Py() + lambda.Pz()*lambda.Pz(); + if(p1p2 <= -p12 || p1p2 < -p22) continue; + + part0.SetConstructMethod(2); + part0.X() = pv.X(); + part0.Y() = pv.Y(); + part0.Z() = pv.Z(); + part0.Covariance(0,0) = pv.Covariance(0,0); + part0.Covariance(1,1) = pv.Covariance(1,1); + part0.Covariance(2,2) = pv.Covariance(2,2); + part0.Covariance(1,0) = pv.Covariance(1,0); + part0.Covariance(2,0) = pv.Covariance(2,0); + part0.Covariance(2,1) = pv.Covariance(2,1); + part0.Chi2() = 0.f; + part0.NDF() = 0; + part0 += fragment; + part0 += lambda; + } + + const float mass = part0.GetMass(); + + // Armenteros + { + float QtAlpha[2]; + KFParticle::GetArmenterosPodolanski(part1, part2, QtAlpha ); + fHistos2D[particleIndex][1]->Fill(QtAlpha[1],QtAlpha[0],1); + fHistos2D[particleIndex][3]->Fill(QtAlpha[1],mass,1); + } + + KFParticle particles[3]{part0, part1, part2}; + for(int iSet=0; iSet<1; iSet++) + { + KFParticle part = particles[iSet]; + KFParticle topo = particles[iSet]; + topo.SetProductionVertex(pv); + + const float chiPrim = part.GetDeviationFromVertex(pv); + const float chiPrimXY = part.GetDeviationFromVertexXY(pv); + float l, dl; + part.GetDistanceToVertexLine(pv, l, dl); + float decayL, decayLError; + topo.GetDecayLength(decayL,decayLError); + float ct, ctError; + topo.GetLifeTime(ct,ctError); + float m, mError; + part.GetMass(m, mError); + float pt = part.GetPt(); + float mt = sqrt(pt*pt+m*m) - m; + float cosV = TMath::Prob(part.Chi2(), part.NDF()); + + float values[NHistos] = { part.X(), part.Y(), part.Z(), + part.Px(), part.Py(), part.Pz(), pt, part.GetP(), + part.GetErrX(), part.GetErrY(), part.GetErrZ(), + part.GetErrPx(), part.GetErrPy(), part.GetErrPz(), + part.GetErrPt(), part.GetErrP(), + part.Chi2()/part.NDF(), topo.Chi2()/topo.NDF(), chiPrim, chiPrimXY, + l, dl, l/dl, part.GetR(), ct, decayL, + topo.GetPhi(), topo.GetTheta(), topo.GetRapidity(), mt, cosV, + m}; + + for(int iHisto=0; iHistoFill(values[iHisto]); + } + } + nCombinations++; + if(nCombinations == nEventsToMix) break; + } + + nnn++; + // if(nnn == 1000000) break; + } + + //Store histograms + TFile* curFile = gFile; + TDirectory* curDirectory = gDirectory; + + fOutputHistoFile->cd(); + WriteHistosCurFile(fOutputHistoDir); + + gFile = curFile; + gDirectory = curDirectory; +} + +void StKFParticleCandidateAnalysis::WriteHistosCurFile( TObject *obj ){ + if( !obj->IsFolder() ) obj->Write(); + else{ + TDirectory *cur = TDirectory::CurrentDirectory(); + TFile *currentFile = TFile::CurrentFile(); + + TDirectory *sub = cur->GetDirectory(obj->GetName()); + sub->cd(); + TList *listSub = (static_cast(obj))->GetList(); + TIter it(listSub); + while( TObject *obj1=it() ) WriteHistosCurFile(obj1); + cur->cd(); + TFile::CurrentFile() = currentFile; + TDirectory::CurrentDirectory() = cur; + } +} + +void StKFParticleCandidateAnalysis::CheckMath() { + + auto print = [](const KFParticle& p){ + for(uint32_t i=0; i<8; i++) { + std::cout << std::scientific << std::setprecision(10) << p.GetParameter(i) << " "; + } + std::cout << '\n'; + + for(uint32_t i=0; i<8; i++) { + for(uint32_t j=0; j<=i; j++){ + std::cout << p.GetCovariance(i, j) << " "; + } + std::cout << '\n'; + } + std::cout << '\n'; + }; + + for(int iParticle=0; iParticleGetEntries(); ) + { + std::vector particles; // 0 - mother, 1... - daughters + + fCandidateFileChain->GetEvent(iParticle); + KFParticle pv = *fCandidate; + iParticle++; + fCandidateFileChain->GetEvent(iParticle); + particles.push_back(*fCandidate); + iParticle++; + + bool badDaughters = false; + + for(int iDaughter=0; iDaughterGetEvent(iParticle); + particles.push_back(*fCandidate); + iParticle++; + badDaughters = badDaughters || (fCandidate->GetErrZ() > 2.999f); + } + + if(badDaughters) continue; + + const int particleIndex = ParticleIndex(particles[0].GetPDG()); + if(particleIndex < 18 || particleIndex > 21) continue; + + KFParticle& fragment = particles[1]; + KFParticle& lambda = particles[2]; + + lambda.SetNonlinearMassConstraint(1.115683f); + + KFParticleSIMD pvS(const_cast(pv)); + KFParticleSIMD fragmentS(fragment); + KFParticleSIMD lambdaS(const_cast(lambda)); + + KFParticleSIMD part00; + part00 += fragmentS; + part00 += lambdaS; + KFParticle part000; + part00.GetKFParticle(part000); + + KFParticle part0; + part0 += fragment; + part0 += lambda; + + if(part0.Chi2() / part0.NDF() < 3.f && part000.Chi2() / part000.NDF() >= 3.f) { + std::cout << "\nscalar\n"; + print(part0); + std::cout << "simd\n"; + print(part000); + std::cin.get(); + } + } +} diff --git a/StRoot/StKFParticleAnalysisMaker/StKFParticleCandidateAnalysis.h b/StRoot/StKFParticleAnalysisMaker/StKFParticleCandidateAnalysis.h new file mode 100644 index 00000000000..191798360fb --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StKFParticleCandidateAnalysis.h @@ -0,0 +1,58 @@ +#ifndef STAR_StKFParticleCandidateAnalysisMaker +#define STAR_StKFParticleCandidateAnalysisMaker + +#include "KFParticle.h" + +#include "TString.h" +#include "TObject.h" + +#include + +class TChain; +class TFile; +class TDirectory; +class TH1D; +class TH2D; +class TH3D; + +class StKFParticleCandidateAnalysis: public TObject { + public: + StKFParticleCandidateAnalysis(TString inputFile="candidates.root"); + virtual ~StKFParticleCandidateAnalysis() { if(fCandidate) delete fCandidate; } + + void Run(); + void RunMixedEvent(); + void RunRotatedBG(); + + void CheckMath(); + + private: + int ParticleIndex(int pdg) { + std::map::iterator it; + it=fPdgMap.find(pdg); + if(it != fPdgMap.end()) return it->second; + else return -1; + } + void WriteHistosCurFile( TObject *obj ); + + TChain* fCandidateFileChain; + KFParticle* fCandidate; + + TFile* fOutputHistoFile; + TDirectory* fOutputHistoDir; + static const int NParticles = 26; + static const int NSignalSets = 3; // total, signal and BG + static const int NSets = 8; + static const int NHistos = 32; + TH1D* fHistos[NParticles][NSignalSets][NSets][NHistos]; + static const int NHistos2D = 4; + TH2D* fHistos2D[NParticles][NHistos2D]; + static const int NHistos3D = 5; + TH3D* fHistos3D[NParticles][NHistos3D]; + + std::map fPdgMap; + + ClassDef(StKFParticleCandidateAnalysis, 1) +}; + +#endif // STAR_StKFParticleCandidateAnalysisMaker diff --git a/StRoot/StKFParticleAnalysisMaker/StKFParticleInterface.cxx b/StRoot/StKFParticleAnalysisMaker/StKFParticleInterface.cxx new file mode 100644 index 00000000000..ef5f9d76f64 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StKFParticleInterface.cxx @@ -0,0 +1,2620 @@ +#include "StKFParticleInterface.h" + +#include "KFParticleTopoReconstructor.h" +#include "KFMCTrack.h" + +#include "TMath.h" +#include "TArrayD.h" +#include "TH1F.h" +#include "TH2F.h" + +#include "StPicoDstMaker/StPicoDstMaker.h" +#include "StPicoEvent/StPicoHelix.h" +#include "StPicoEvent/StPicoPhysicalHelix.h" +#include "StPicoEvent/StPicoArrays.h" +#include "StPicoEvent/StPicoDst.h" +#include "StPicoEvent/StPicoEvent.h" +#include "StPicoEvent/StPicoTrack.h" +#include "StPicoEvent/StPicoBTofPidTraits.h" +#include "StPicoEvent/StPicoETofPidTraits.h" +#include "StPicoEvent/StPicoTrackCovMatrix.h" + +#include "StBichsel/Bichsel.h" +#include "StBichsel/StdEdxModel.h" +#include "StProbPidTraits.h" +#include "StMuDSTMaker/COMMON/StMuBTofHit.h" +#include "StMuDSTMaker/COMMON/StMuMcVertex.h" +#include "StMuDSTMaker/COMMON/StMuMcTrack.h" +#include "StMuDSTMaker/COMMON/StMuPrimaryVertex.h" +#include +#include +#include + +#define USETOF +#define FXT + +ClassImp(StKFParticleInterface); + +StKFParticleInterface *StKFParticleInterface::fgStKFParticleInterface = 0; +StKFParticleInterface::StKFParticleInterface(): + fKFParticleTopoReconstructor(0), fParticles(0), fParticlesPdg(0), fNHftHits(0), fBeamSpot(), + fCollectTrackHistograms(false), fCollectPIDHistograms(false), fCollectPVHistograms(false), + fStrictTofPID(true), fCleanKaonsWitTof(true), fUseETof(false), fdEdXMode(1), fTriggerMode(false), + fChiPrimaryCut(18.6f), fChiPrimaryCutFragments(0.f), fChiPrimaryMaxCut(2e4f), fCleanLowPVTrackEvents(false), fUseHFTTracksOnly(false) +{ + fKFParticleTopoReconstructor = new KFParticleTopoReconstructor(); + fgStKFParticleInterface = this; + // set default cuts + SetPrimaryProbCut(0.0001); // 0.01% to consider primary track as a secondary; +} + +StKFParticleInterface::~StKFParticleInterface() +{ + if(fKFParticleTopoReconstructor) delete fKFParticleTopoReconstructor; + fgStKFParticleInterface = 0; +} + +void StKFParticleInterface::SetField(float field) +{ + if(fKFParticleTopoReconstructor) + fKFParticleTopoReconstructor->SetField(field); +} +void StKFParticleInterface::SetBeamLine(KFParticle& p) +{ + if(fKFParticleTopoReconstructor) + fKFParticleTopoReconstructor->SetBeamLine(p); +} + +void StKFParticleInterface::SetBeamSpot(const TString beamSpotMode) +{ + fBeamSpot.NDF() = -1; + + if(beamSpotMode == TString("2018_3AGeV")) { + fBeamSpot.Covariance(0,0) = 0.2173 * 0.2173; + fBeamSpot.Covariance(1,1) = 0.1362 * 0.1362; + fBeamSpot.Covariance(2,2) = 0.1674 * 0.1674; + + fBeamSpot.X() = -0.008f; + fBeamSpot.Y() = -2.02f; + fBeamSpot.Z() = 200.7f; + } + else if(beamSpotMode == TString("2019_3AGeV")) { + fBeamSpot.Covariance(0,0) = 0.1632 * 0.1632; + fBeamSpot.Covariance(1,1) = 0.1347 * 0.1347; + fBeamSpot.Covariance(2,2) = 0.1908 * 0.1908; + + fBeamSpot.X() = -0.6577f; + fBeamSpot.Y() = -1.986f; + fBeamSpot.Z() = 199.8f; + } + else if(beamSpotMode == TString("2019_4AGeV")) { + fBeamSpot.Covariance(0,0) = 0.1665 * 0.1665; + fBeamSpot.Covariance(1,1) = 0.125 * 0.125; + fBeamSpot.Covariance(2,2) = 0.2 * 0.2; + + fBeamSpot.X() = -0.427f; + fBeamSpot.Y() = -1.994f; + fBeamSpot.Z() = 199.9f; + } + else if(beamSpotMode == TString("2019_7AGeV")) { + fBeamSpot.Covariance(0,0) = 0.18 * 0.18; + fBeamSpot.Covariance(1,1) = 0.122 * 0.122; + fBeamSpot.Covariance(2,2) = 0.2449 * 0.2449; + + fBeamSpot.X() = -0.45f; + fBeamSpot.Y() = -1.994f; + fBeamSpot.Z() = 200.2f; + } + else if(beamSpotMode == TString("2019_31AGeV")) { + fBeamSpot.Covariance(0,0) = 0.1549 * 0.1549; + fBeamSpot.Covariance(1,1) = 0.1239 * 0.1239; + fBeamSpot.Covariance(2,2) = 0.2762 * 0.2762; + + fBeamSpot.X() = -0.2851f; + fBeamSpot.Y() = -1.978f; + fBeamSpot.Z() = 200.3f; + } + else if(beamSpotMode == TString("2020_5AGeV")) { + fBeamSpot.Covariance(0,0) = 0.1595 * 0.1595; + fBeamSpot.Covariance(1,1) = 0.122 * 0.122; + fBeamSpot.Covariance(2,2) = 0.1837 * 0.1837; + + fBeamSpot.X() = -0.3592f; + fBeamSpot.Y() = -2.038f; + fBeamSpot.Z() = 200.2f; + + fUseETof = true; + } + else if(beamSpotMode == TString("2020_7AGeV")) { + fBeamSpot.Covariance(0,0) = 0.1869 * 0.1869; + fBeamSpot.Covariance(1,1) = 0.1235 * 0.1235; + fBeamSpot.Covariance(2,2) = 0.2276 * 0.2276; + + fBeamSpot.X() = -0.3125f; + fBeamSpot.Y() = -2.045f; + fBeamSpot.Z() = 200.3f; + + fUseETof = true; + } + else if(beamSpotMode == TString("2020_9AGeV")) { + fBeamSpot.Covariance(0,0) = 0.2395 * 0.2395; + fBeamSpot.Covariance(1,1) = 0.1239 * 0.1239; + fBeamSpot.Covariance(2,2) = 0.242 * 0.242; + + fBeamSpot.X() = -0.2838f; + fBeamSpot.Y() = -2.042f; + fBeamSpot.Z() = 200.3f; + + fUseETof = true; + } + else if(beamSpotMode == TString("2020_13AGeV")) { + fBeamSpot.Covariance(0,0) = 0.1967 * 0.1967; + fBeamSpot.Covariance(1,1) = 0.1285 * 0.1285; + fBeamSpot.Covariance(2,2) = 0.2656 * 0.2656; + + fBeamSpot.X() = -0.2365f; + fBeamSpot.Y() = -2.026f; + fBeamSpot.Z() = 200.4f; + + fUseETof = true; + } + else if(beamSpotMode == TString("2020_19AGeV")) { + fBeamSpot.Covariance(0,0) = 0.2083 * 0.2083; + fBeamSpot.Covariance(1,1) = 0.1216 * 0.1216; + fBeamSpot.Covariance(2,2) = 0.255 * 0.255; + + fBeamSpot.X() = -0.1866f; + fBeamSpot.Y() = -2.021f; + fBeamSpot.Z() = 200.4f; + + fUseETof = true; + } + else if(beamSpotMode == TString("2020_31AGeV")) { + fBeamSpot.Covariance(0,0) = 0.1636 * 0.1636; + fBeamSpot.Covariance(1,1) = 0.1169 * 0.1169; + fBeamSpot.Covariance(2,2) = 0.2701 * 0.2701; + + fBeamSpot.X() = -0.1827f; + fBeamSpot.Y() = -2.014f; + fBeamSpot.Z() = 200.4f; + + fUseETof = true; + } + else if(beamSpotMode == TString("2021_3AGeV")) { + fBeamSpot.Covariance(0,0) = 0.1549 * 0.1549; + fBeamSpot.Covariance(1,1) = 0.1041 * 0.1041; + fBeamSpot.Covariance(2,2) = 0.1553 * 0.1553; + + fBeamSpot.X() = 0.4037f; + fBeamSpot.Y() = -2.054f; + fBeamSpot.Z() = 200.3f; + + // fUseETof = true; + } + else { + fBeamSpot.Covariance(0,0) = 0.26f; + fBeamSpot.Covariance(1,1) = 0.14f; + fBeamSpot.Covariance(2,2) = 0.20f; + + fBeamSpot.X() = 0.f; + fBeamSpot.Y() = -2.0f; + fBeamSpot.Z() = 200.f; + } +} + +void StKFParticleInterface::InitParticles() +{ + fKFParticleTopoReconstructor->Init( fParticles, &fParticlesPdg, &fNHftHits ); + Int_t NPV = fKFParticleTopoReconstructor->NPrimaryVertices(); + fKFParticleTopoReconstructor->GetKFParticleFinder()->Init(NPV); + fKFParticleTopoReconstructor->FillPVIndices(); +} + +#ifdef __kfpAtFirstHit__ +void StKFParticleInterface::InitParticlesAtFirstAndLastHit() +{ + KFPTrackVector ftracksAtFirstHit; + KFPTrackVector ftracksAtLastHit; + int nTracks = fParticlesAtLastHit.size(); + ftracksAtFirstHit.Resize(nTracks); + ftracksAtLastHit.Resize(nTracks); + for(int iTr=0; iTrInit( ftracksAtFirstHit, ftracksAtLastHit ); + Int_t NPV = fKFParticleTopoReconstructor->NPrimaryVertices(); + fKFParticleTopoReconstructor->GetKFParticleFinder()->Init(NPV); + fKFParticleTopoReconstructor->FillPVIndices(); +} +#endif + +void StKFParticleInterface::ReconstructParticles() +{ + fKFParticleTopoReconstructor->SortTracks(); + fKFParticleTopoReconstructor->ReconstructParticles(); + +} + +void StKFParticleInterface::ReconstructTopology() +{ + fKFParticleTopoReconstructor->Init( fParticles, &fParticlesPdg ); + fKFParticleTopoReconstructor->ReconstructPrimVertex(0); + fKFParticleTopoReconstructor->SortTracks(); + fKFParticleTopoReconstructor->ReconstructParticles(); +} + +void StKFParticleInterface::AddPV(const KFVertex &pv, const vector &tracks) { + fKFParticleTopoReconstructor->AddPV(pv, tracks); + fKFParticleTopoReconstructor->FillPVIndices(); +} +void StKFParticleInterface::CleanPV() { + fKFParticleTopoReconstructor->CleanPV(); +} + +void StKFParticleInterface::AddPV(const KFVertex &pv) { + fKFParticleTopoReconstructor->AddPV(pv); +} + +void StKFParticleInterface::AddParticle(const KFParticle &p) { + fKFParticleTopoReconstructor->AddParticle(p); +} + +void StKFParticleInterface::AddCandidate(const KFParticle& candidate, int iPV) { + fKFParticleTopoReconstructor->AddCandidate(candidate, iPV); +} +void StKFParticleInterface::AddDecayToReconstructionList(Int_t pdg) { + fKFParticleTopoReconstructor->GetKFParticleFinder()->AddDecayToReconstructionList(pdg); +} +std::vector const &StKFParticleInterface::GetParticles() const { return fKFParticleTopoReconstructor->GetParticles(); } +void StKFParticleInterface::RemoveParticle(const int iParticle) { fKFParticleTopoReconstructor->RemoveParticle(iParticle); } +const std::vector* StKFParticleInterface::GetSecondaryCandidates() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetSecondaryCandidates(); } // Get secondary particles with the mass constraint +const std::vector& StKFParticleInterface::GetSecondaryK0() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetSecondaryK0(); } // Get secondary particles with the mass constraint +const std::vector& StKFParticleInterface::GetSecondaryLambda() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetSecondaryLambda(); } // Get secondary particles with the mass constraint +const std::vector& StKFParticleInterface::GetSecondaryAntiLambda() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetSecondaryAntiLambda(); } // Get secondary particles with the mass constraint +const std::vector& StKFParticleInterface::GetSecondaryGamma() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetSecondaryGamma(); } // Get secondary particles with the mass constraint +const std::vector& StKFParticleInterface::GetSecondaryPi0() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetSecondaryPi0(); } // Get secondary particles with the mass constraint +const std::vector< std::vector >* StKFParticleInterface::GetPrimaryCandidates() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetPrimaryCandidates(); } // Get primary particles with the mass constraint +const std::vector< std::vector >* StKFParticleInterface::GetPrimaryTopoCandidates() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetPrimaryTopoCandidates(); } // Get primary particles with the topologigal constraint +const std::vector< std::vector >* StKFParticleInterface::GetPrimaryTopoMassCandidates() const {return fKFParticleTopoReconstructor->GetKFParticleFinder()->GetPrimaryTopoMassCandidates();} // Get primary particles with the topologigal and mass constraint + +KFParticleFinder* StKFParticleInterface::GetKFParticleFinder() { return fKFParticleTopoReconstructor->GetKFParticleFinder(); } +void StKFParticleInterface::SetMaxDistanceBetweenParticlesCut(float cut) { GetKFParticleFinder()->SetMaxDistanceBetweenParticlesCut(cut); } +void StKFParticleInterface::SetLCut(float cut) { GetKFParticleFinder()->SetLCut(cut); } +void StKFParticleInterface::SetChiPrimaryCut2D(float cut) { GetKFParticleFinder()->SetChiPrimaryCut2D(cut); } +void StKFParticleInterface::SetChi2Cut2D(float cut) { GetKFParticleFinder()->SetChi2Cut2D(cut); } +void StKFParticleInterface::SetLdLCut2D(float cut) { GetKFParticleFinder()->SetLdLCut2D(cut); } +void StKFParticleInterface::SetLdLCutXiOmega(float cut) { GetKFParticleFinder()->SetLdLCutXiOmega(cut); } +void StKFParticleInterface::SetChi2TopoCutXiOmega(float cut) { GetKFParticleFinder()->SetChi2TopoCutXiOmega(cut); } +void StKFParticleInterface::SetChi2CutXiOmega(float cut) { GetKFParticleFinder()->SetChi2CutXiOmega(cut); } +void StKFParticleInterface::SetChi2TopoCutResonances(float cut) { GetKFParticleFinder()->SetChi2TopoCutResonances(cut); } +void StKFParticleInterface::SetChi2CutResonances(float cut) { GetKFParticleFinder()->SetChi2CutResonances(cut); } +void StKFParticleInterface::SetPtCutLMVM(float cut) { GetKFParticleFinder()->SetPtCutLMVM(cut); } +void StKFParticleInterface::SetPCutLMVM(float cut) { GetKFParticleFinder()->SetPCutLMVM(cut); } +void StKFParticleInterface::SetPtCutJPsi(float cut) { GetKFParticleFinder()->SetPtCutJPsi(cut); } +void StKFParticleInterface::SetPtCutCharm(float cut) { GetKFParticleFinder()->SetPtCutCharm(cut); } +void StKFParticleInterface::SetChiPrimaryCutCharm(float cut) { GetKFParticleFinder()->SetChiPrimaryCutCharm(cut); } +void StKFParticleInterface::SetLdLCutCharmManybodyDecays(float cut) { GetKFParticleFinder()->SetLdLCutCharmManybodyDecays(cut); } +void StKFParticleInterface::SetChi2TopoCutCharmManybodyDecays(float cut) { GetKFParticleFinder()->SetChi2TopoCutCharmManybodyDecays(cut); } +void StKFParticleInterface::SetChi2CutCharmManybodyDecays(float cut) { GetKFParticleFinder()->SetChi2CutCharmManybodyDecays(cut); } +void StKFParticleInterface::SetLdLCutCharm2D(float cut) { GetKFParticleFinder()->SetLdLCutCharm2D(cut); } +void StKFParticleInterface::SetChi2TopoCutCharm2D(float cut) { GetKFParticleFinder()->SetChi2TopoCutCharm2D(cut); } +void StKFParticleInterface::SetChi2CutCharm2D(float cut) { GetKFParticleFinder()->SetChi2CutCharm2D(cut); } +void StKFParticleInterface::SetSecondaryCuts(const float sigmaMass, const float chi2Topo, const float ldl) { GetKFParticleFinder()->SetSecondaryCuts(sigmaMass, chi2Topo, ldl); } + +double StKFParticleInterface::InversedChi2Prob(double p, int ndf) const +{ + double epsilon = 1.e-14; + double chi2Left = 0.f; + double chi2Right = 10000.f; + + double probLeft = p - TMath::Prob(chi2Left, ndf); + + double chi2Centr = (chi2Left+chi2Right)/2.f; + double probCentr = p - TMath::Prob( chi2Centr, ndf); + + while( TMath::Abs(chi2Right-chi2Centr)/chi2Centr > epsilon ) + { + if(probCentr * probLeft > 0.f) + { + chi2Left = chi2Centr; + probLeft = probCentr; + } + else + { + chi2Right = chi2Centr; + } + + chi2Centr = (chi2Left+chi2Right)/2.f; + probCentr = p - TMath::Prob( chi2Centr, ndf); + } + + return chi2Centr; +} + +void StKFParticleInterface::SetPrimaryProbCut(float prob) +{ + fKFParticleTopoReconstructor->SetChi2PrimaryCut( InversedChi2Prob(prob, 2) ); +} + +void StKFParticleInterface::CollectTrackHistograms() +{ + TDirectory *dirs[2] = {0}; + dirs[0] = TDirectory::CurrentDirectory(); assert(dirs[0]); + dirs[0]->cd(); + if (! dirs[0]->GetDirectory("Tracks")) { + dirs[0]->mkdir("Tracks"); + } + dirs[1] = dirs[0]->GetDirectory("Tracks"); assert(dirs[1]); + dirs[1]->cd(); + + fTrackHistograms2D[0] = (TH2F *) dirs[1]->Get("hdEdX"); + if (! fTrackHistograms2D[0]) fTrackHistograms2D[0] = new TH2F("hdEdX", "hdEdX", 1000, 0, 10, 200, 0, 200); + + fTrackHistograms2D[1] = (TH2F *) dirs[1]->Get("hdEdXPos"); + if (! fTrackHistograms2D[1]) fTrackHistograms2D[1] = new TH2F("hdEdXPos", "hdEdXPos", 1000, 0, 10, 200, 0, 200); + + fTrackHistograms2D[2] = (TH2F *) dirs[1]->Get("hdEdXNeg"); + if (! fTrackHistograms2D[2]) fTrackHistograms2D[2] = new TH2F("hdEdXNeg", "hdEdXNeg", 1000, 0, 10, 200, 0, 200); + + fTrackHistograms2D[3] = (TH2F *) dirs[1]->Get("hdEdXwithToF"); + if (! fTrackHistograms2D[3]) fTrackHistograms2D[3] = new TH2F("hdEdXwithToF", "hdEdXwithToF", 1000, 0, 10, 200, 0, 200); + + fTrackHistograms2D[4] = (TH2F *) dirs[1]->Get("hTofPID"); + if (! fTrackHistograms2D[4]) fTrackHistograms2D[4] = new TH2F("hTofPID", "hTofPID", 300, 0, 15, 2100, -1, 20); + + fTrackHistograms[0] = (TH1F *) dirs[1]->Get("hNHFTHits"); + if (! fTrackHistograms[0]) fTrackHistograms[0] = new TH1F("hNHFTHits", "hNHFTHits",11, -0.5, 10.5); + + fTrackHistograms[1] = (TH1F *) dirs[1]->Get("hPVError"); + if (! fTrackHistograms[1]) fTrackHistograms[1] = new TH1F("hPVError", "hPVError", 10000, 0, 1); + + fTrackHistograms2D[5] = (TH2F *) dirs[1]->Get("hPVErrorVsNTracks"); + if (! fTrackHistograms2D[5]) fTrackHistograms2D[5] = new TH2F("hPVErrorVsNTracks", "hPVErrorVsNTracks", 1000, 0, 1000, 1000, 0, 0.5); + + fTrackHistograms2D[6] = (TH2F *) dirs[1]->Get("hPVErrorVsNPVTracks"); + if (! fTrackHistograms2D[6]) fTrackHistograms2D[6] = new TH2F("hPVErrorVsNPVTracks", "hPVErrorVsNPVTracks", 1000, 0, 1000, 1000, 0, 0.5); + + fTrackHistograms[2] = (TH1F *) dirs[1]->Get("hPrimaryRatio"); + if (! fTrackHistograms[2]) fTrackHistograms[2] = new TH1F("hPrimaryRatio", "hPrimaryRatio", 100, 0, 1); + + fTrackHistograms2D[7] = (TH2F *) dirs[1]->Get("hSecondaryVsPrimaryTracks"); + if (! fTrackHistograms2D[7]) fTrackHistograms2D[7] = new TH2F("hSecondaryVsPrimaryTracks", "hSecondaryVsPrimaryTracks", 200, 0, 1000, 200, 0, 1000); + + fTrackHistograms2D[8] = (TH2F *) dirs[1]->Get("hdEdXTofPID"); + if (! fTrackHistograms2D[8]) fTrackHistograms2D[8] = new TH2F("hdEdXTofPID", "hdEdXTofPID", 200, 0, 200, 2100, -1, 20); + + fTrackHistograms2D[9] = (TH2F *) dirs[1]->Get("hETofPID"); + if (! fTrackHistograms2D[9]) fTrackHistograms2D[9] = new TH2F("hETofPID", "ETofPID", 300, 0, 15, 2100, -1, 20); + + fTrackHistograms2D[10] = (TH2F *) dirs[1]->Get("hdEdXETofPID"); + if (! fTrackHistograms2D[10]) fTrackHistograms2D[10] = new TH2F("hdEdXETofPID", "hdEdXETofPID", 200, 0, 200, 2100, -1, 20); + + dirs[0]->cd(); + + fCollectTrackHistograms = true; +} + +void StKFParticleInterface::CollectPIDHistograms() +{ + TDirectory *dirs[3] = {0}; + dirs[0] = TDirectory::CurrentDirectory(); assert(dirs[0]); + dirs[0]->cd(); + if (! dirs[0]->GetDirectory("Tracks")) { + dirs[0]->mkdir("Tracks"); + } + dirs[1] = dirs[0]->GetDirectory("Tracks"); assert(dirs[1]); + dirs[1]->cd(); + + int pdgTrackHisto[NTrackHistoFolders] = { 11, -11, 13, -13, 211, -211, 321, -321, 2212, -2212, + 1000010020, -1000010020, 1000010030, -1000010030, + 1000020030, -1000020030, 1000020040, -1000020040, + 1000020060, -1000020060, 1000030060, -1000030060, + 1000030070, -1000030070, 1000040070, -1000040070 }; + TString trackFolderName[NTrackHistoFolders] = {"e-", "e+", "mu-", "mu+", "pi+", "pi-", "K+", "K-", "p", "p-", + "d", "d-", "t", "t-", "He3", "He3-", "He4", "He4-", + "He6", "He6-", "Li6", "Li6-", "Li7", "Li7-", "Be7", "Be7-"}; + + for(int iTrackHisto=0; iTrackHistoGetDirectory(trackFolderName[iTrackHisto].Data())) + dirs[1]->mkdir(trackFolderName[iTrackHisto].Data()); + + dirs[2] = dirs[1]->GetDirectory(trackFolderName[iTrackHisto].Data()); assert(dirs[2]); + dirs[2]->cd(); + + fTrackPdgToHistoIndex[ pdgTrackHisto[iTrackHisto] ] = iTrackHisto; + + fHistodEdXTracks[iTrackHisto] = (TH2F *) dirs[2]->Get("hdEdX"); + if (! fHistodEdXTracks[iTrackHisto]) fHistodEdXTracks[iTrackHisto] = new TH2F("hdEdX", "hdEdX", 1000, 0, 10, 200, 0, 200); + + fHistodEdXwithToFTracks[iTrackHisto] = (TH2F *) dirs[2]->Get("hdEdXwithToF"); + if (! fHistodEdXwithToFTracks[iTrackHisto]) fHistodEdXwithToFTracks[iTrackHisto] = new TH2F("hdEdXwithToF", "hdEdXwithToF", 1000, 0, 10, 200, 0, 200); + + fHistoTofPIDTracks[iTrackHisto] = (TH2F *) dirs[2]->Get("hTofPID"); + if (! fHistoTofPIDTracks[iTrackHisto]) fHistoTofPIDTracks[iTrackHisto] = new TH2F("hTofPID", "hTofPID", 300, 0, 15, 1100, -1, 10); + + fHistoMomentumTracks[iTrackHisto] = (TH1F *) dirs[2]->Get("hMomentum"); + if (! fHistoMomentumTracks[iTrackHisto]) fHistoMomentumTracks[iTrackHisto] = new TH1F("hMomentum", "hMomentum", 1000, 0, 10); + fHistodEdXPull[iTrackHisto] = (TH2F *) dirs[2]->Get("hdEdXPull"); + if (! fHistodEdXPull[iTrackHisto]) fHistodEdXPull[iTrackHisto] = new TH2F("hdEdXPull", "hdEdXPull", 500, 0, 10, 300, -30, 30); + + fHistodEdXZ[iTrackHisto] = (TH2F *) dirs[2]->Get("hdEdXZ"); + if (! fHistodEdXZ[iTrackHisto]) fHistodEdXZ[iTrackHisto] = new TH2F("hdEdXZ", "hdEdXZ", 500, -5, 5, 140, -1, 6); + dirs[1]->cd(); + } + + dirs[0]->cd(); + + fCollectPIDHistograms = true; +} + +void StKFParticleInterface::CollectPVHistograms() +{ + TDirectory* mainDir = TDirectory::CurrentDirectory(); assert(mainDir); + if (! mainDir->GetDirectory("PrimaryVertices")) { + mainDir->mkdir("PrimaryVertices"); + } + TDirectory* pvDir = mainDir->GetDirectory("PrimaryVertices"); + pvDir->cd(); + + int iHisto = 0; + + // 0 + TString title("X"); + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 4000, -200, 200); + iHisto++; + + // 1 + title = "Y"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 4000, -200, 200); + iHisto++; + + // 2 + title = "R"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 2000, 0, 200); + iHisto++; + + // 3 + title = "Z"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 4400, -220, 220); + iHisto++; + + // 4 + title = "NTracks"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 1000, 0, 1000); + iHisto++; + + // 5 + title = "NTracksMain"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 1000, 0, 1000); + iHisto++; + + // 6 + title = "NTracksPileup"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 1000, 0, 1000); + iHisto++; + + // 7 + title = "NPV"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 10, 0, 10); + iHisto++; + + // 8 + title = "PrimaryFraction"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 100, 0, 1); + iHisto++; + + // 9 + title = "PileupFraction"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 100, 0, 1); + iHisto++; + + // 10 + title = "RestFraction"; + fPVHistograms[iHisto] = (TH1F*) pvDir->Get(title); + if (! fPVHistograms[iHisto]) fPVHistograms[iHisto] = new TH1F(title, title, 100, 0, 1); + iHisto++; + + int iHisto2D = 0; + + title = "XY"; + fPVHistograms2D[iHisto2D] = (TH2F *) pvDir->Get(title); + if (! fPVHistograms2D[iHisto2D]) fPVHistograms2D[iHisto2D] = new TH2F(title, title, 800, -40, 40, 800, -40, 40); + iHisto2D++; + + title = "ZR"; + fPVHistograms2D[iHisto2D] = (TH2F *) pvDir->Get(title); + if (! fPVHistograms2D[iHisto2D]) fPVHistograms2D[iHisto2D] = new TH2F(title, title, 4400, -220, 220, 400, -40, 40); + iHisto2D++; + + title = "ZRTracks"; + fPVHistograms2D[iHisto2D] = (TH2F *) pvDir->Get(title); + if (! fPVHistograms2D[iHisto2D]) fPVHistograms2D[iHisto2D] = new TH2F(title, title, 440, -220, 220, 400, 0, 200); + iHisto2D++; + + title = "ZRTracksRest"; + fPVHistograms2D[iHisto2D] = (TH2F *) pvDir->Get(title); + if (! fPVHistograms2D[iHisto2D]) fPVHistograms2D[iHisto2D] = new TH2F(title, title, 440, -220, 220, 400, 0, 200); + iHisto2D++; + + mainDir->cd(); + + fCollectPVHistograms = true; +} + +bool StKFParticleInterface::IsGoodPV(const KFVertex& pv) +{ + bool isGoodPV = (pv.X() > -0.3) && (pv.X() < -0.1) && + (pv.Y() > -0.27) && (pv.Y() < -0.1); + return isGoodPV; +} + +bool StKFParticleInterface::GetTrack(const StDcaGeometry& dcaG, KFPTrack& track, int q, int index) +{ + Double_t xyzp[6], CovXyzp[21]; + dcaG.GetXYZ(xyzp,CovXyzp); + + bool goodTrack=1; + for(int iPar=0; iPar<6; iPar++) + goodTrack = goodTrack && finite(xyzp[iPar]); + for(int iC=0; iC<21; iC++) + goodTrack = goodTrack && finite(CovXyzp[iC]); + goodTrack &= goodTrack && CovXyzp[0] >=0.f && CovXyzp[0] < 100.f; + goodTrack &= goodTrack && CovXyzp[2] >=0.f && CovXyzp[2] < 100.f; + goodTrack &= goodTrack && CovXyzp[5] >=0.f && CovXyzp[5] < 100.f; + goodTrack &= goodTrack && CovXyzp[9] >=0.f && CovXyzp[9] < 1.f; + goodTrack &= goodTrack && CovXyzp[14] >=0.f && CovXyzp[14] < 1.f; + goodTrack &= goodTrack && CovXyzp[20] >=0.f && CovXyzp[20] < 1.f; + if(!goodTrack) return false; + + track.SetParameters(xyzp); + track.SetCovarianceMatrix(CovXyzp); + track.SetNDF(1); + // track.SetChi2(GlobalTracks_mChiSqXY[k]); + track.SetID(index); + + track.SetCharge(q); + return true; +} + +std::vector StKFParticleInterface::GetTofPID(double m2, double p, int q, const int trackId) +{ + static const int order = 4; + static const double parMean[6][order+1] = { { 0.02283190,-0.01482910, 0.01883130,-0.01824250, 0.00409811 }, //pi+ + { 0.24842500,-0.00699781,-0.00991387, 0.01327170,-0.00694824 }, //K+ + { 0.863211 , 0.0264171 ,-0.0230833 , 0.00239637, 0.000262309 }, //p + { 0.0224095 ,-0.0123235 , 0.0145216 ,-0.0149944 , 0.00325952 }, //pi- + { 0.250696 ,-0.0151308 , 0.00437457, 0.00516669,-0.00529184 }, //K- + { 0.886912 ,-0.0298543 , 0.0449904 ,-0.0286879 , 0.00541963 }};//p- + static const double parSigma[6][order+1] = { { 0.0112498,-0.0400571, 0.0733615,-0.0316505, 0.00629469 }, //pi+ + { 0.0154830,-0.0396312, 0.0719647,-0.0290683, 0.00637164 }, //K+ + { 0.114465 ,-0.287213 , 0.356536 ,-0.169257 , 0.0299844 }, //p + { 0.0111682,-0.0394877, 0.0718342,-0.0302914, 0.00587317 }, //pi- + { 0.0157322,-0.0402606, 0.0716639,-0.0272101, 0.00564467 }, //K- + { 0.0899438,-0.211922 , 0.273122 ,-0.129597 , 0.0231844 }};//p- + double pMax = 2.; + double nSigmas[3]; + for(int iHypothesys = 0; iHypothesys<3; iHypothesys++) + { + double x = p; + if(x>=pMax) x = pMax; + + int iSet = iHypothesys; + if(q<0) + iSet += 3; + double mean = 0; + for(int iTerm=0; iTerm<=order; iTerm++) + mean += parMean[iSet][iTerm]*TMath::Power(x,iTerm); + + double sigma = 0; + for(int iTerm=0; iTerm<=order; iTerm++) + sigma += parSigma[iSet][iTerm]*TMath::Power(x,iTerm); + + nSigmas[iHypothesys] = fabs((m2 - mean)/sigma); + fTrackPidTof[iHypothesys][trackId] = nSigmas[iHypothesys]; + } + + double minNSigma = nSigmas[0]; + int minHypothesis = 0; + for(int iHypothesys=1; iHypothesys<3; iHypothesys++) + { + if(minNSigma > nSigmas[iHypothesys]) + { + minNSigma = nSigmas[iHypothesys]; + minHypothesis = iHypothesys; + } + } + + int pdgHypothesis[3] = {211, 321, 2212}; + vector tofPID; + + if(fStrictTofPID) + { + if(minNSigma < 3) + tofPID.push_back(pdgHypothesis[minHypothesis]*q); + } + else + { + for(int iHypothesys=0; iHypothesys<3; iHypothesys++) + if(nSigmas[iHypothesys] < 3) + tofPID.push_back(pdgHypothesis[iHypothesys]*q); + } + + return tofPID; +} + +std::vector StKFParticleInterface::GetPID(double m2, double p, int q, double dEdX, double dEdXPull[8], bool isBTofm2, bool isETofm2, const int trackId) +{ + const bool isTofm2 = isBTofm2 || isETofm2; + + vector ToFPDG; + if(isBTofm2) + ToFPDG = GetTofPID(m2, p, q, trackId); + + for(int iPdg=0; iPdg<3; iPdg++) + fTrackPidTpc[iPdg][trackId] = dEdXPull[iPdg+1]; + + vector dEdXPDG; + float nSigmaCut = 3.f; //TODO + +#if 1 + bool checkKTof = false; + if(fCleanKaonsWitTof) + // checkKTof = (p > 0.5) && (p < 2.); + checkKTof = (p > 0.5); + bool checkKHasTof = 0; + for(uint32_t iTofPDG=0; iTofPDG totalPDG; + if(!isBTofm2) + totalPDG = dEdXPDG; + else + { + for(uint32_t iPDG=0; iPDG m2Lower[iPID] && m2 < m2Upper[iPID])) || !useTof ) + { + if( p < pLimit[iPID] ) + { + double lowerBound = exp(pL[iPID][0] + pL[iPID][1] * logP + pL[iPID][2] * logP2 + pL[iPID][3] * logP3); + double upperBound = exp(pU[iPID][0] + pU[iPID][1] * logP + pU[iPID][2] * logP2 + pU[iPID][3] * logP3); + + if(dEdX > lowerBound && dEdX < upperBound) + { + totalPDG.push_back(outPID[iPID]*q); + } + } + else if(dEdXPull[iPID + 5] < nSigmaCut && dEdX < 8.) + { + totalPDG.push_back(outPID[iPID]*q); + } + } + } + + if(p > 0.3) + { + for(int iPID=2; iPID<8; iPID++) + { + if(iPID >= 4 && ! isTofm2) break; + + if( p < pLimit[iPID] ) + { + double lowerBound = exp(pL[iPID][0] + pL[iPID][1] * logP + pL[iPID][2] * logP2 + pL[iPID][3] * logP3); + double upperBound = exp(pU[iPID][0] + pU[iPID][1] * logP + pU[iPID][2] * logP2 + pU[iPID][3] * logP3); + + if(dEdX > lowerBound && dEdX < upperBound) + { + if( !isTofm2 || (isTofm2 && (m2 > m2Lower[iPID] && m2 < m2Upper[iPID]) ) ) + { + totalPDG.push_back(outPID[iPID]*q); + } + } + } + else if( p >= pLimit[iPID] && dEdX > dedxLower[iPID] && dEdX < dedxUpper[iPID] ) + { + if( !isTofm2 || (isTofm2 && (m2 > m2Lower[iPID] && m2 < m2Upper[iPID]) ) ) + { + totalPDG.push_back(outPID[iPID]*q); + } + } + } + } + + if(totalPDG.size() == 0) + totalPDG.push_back(-1); + + return totalPDG; +} + +inline void Mix2(float& a, float& b, const float sinA, const float cosA) +{ + const float x = a; + const float y = b; + a = x * cosA - y * sinA; + b = x * sinA + y * cosA; +} + +void RotateXY2(KFParticle& particle, const float alpha) +{ + const float cosA = std::cos(alpha); + const float sinA = std::sin(alpha); + + Mix2(particle.Px(), particle.Py(), sinA, cosA); + + Mix2(particle.Covariance(6), particle.Covariance(10), sinA, cosA); + Mix2(particle.Covariance(7), particle.Covariance(11), sinA, cosA); + Mix2(particle.Covariance(8), particle.Covariance(12), sinA, cosA); + Mix2(particle.Covariance(18), particle.Covariance(19), sinA, cosA); + Mix2(particle.Covariance(24), particle.Covariance(25), sinA, cosA); + + const float c9 = particle.Covariance(9); + const float c13 = particle.Covariance(13); + const float c14 = particle.Covariance(14); + particle.Covariance(9) = (c9 * cosA - c13 * sinA) * cosA - (c13 * cosA - c14 * sinA) * sinA; + particle.Covariance(13) = (c13 * cosA + c9 * sinA) * cosA - (c13 * sinA + c14 * cosA) * sinA; + particle.Covariance(14) = (c13 * cosA + c9 * sinA) * sinA + (c13 * sinA + c14 * cosA) * cosA; +} + +void StKFParticleInterface::AddTrackToParticleList(const KFPTrack& track, int nHftHitsInTrack, int index, const std::vector& totalPDG, KFVertex& pv, + std::vector& primaryTrackList, std::vector& nHftHits, std::vector& particlesPdg, std::vector& particles, int& nPartSaved, + const KFPTrack* trackAtLastHit, std::vector* particlesAtLastHit) +{ + for(uint32_t iPDG=0; iPDG= 1000000000)) + { + if(fTriggerMode) continue; + primaryTrackList.push_back(nPartSaved); + } + + if(fTriggerMode && chiPrim > fChiPrimaryMaxCut) continue; + + particle.SetId(index); + particles[nPartSaved] = particle; + +#ifdef __kfpAtFirstHit__ + if(trackAtLastHit && particlesAtLastHit){ + KFPTrack trackPDGAtLastHit = *trackAtLastHit; + + if(abs(pdg) == 1000020030 || abs(pdg) == 1000020040 || abs(pdg) == 1000020060) { + trackPDGAtLastHit.SetCharge( trackPDGAtLastHit.Charge()*2.f ); + trackPDGAtLastHit.SetPx( trackPDGAtLastHit.GetPx()*2.f ); + trackPDGAtLastHit.SetPy( trackPDGAtLastHit.GetPy()*2.f ); + trackPDGAtLastHit.SetPz( trackPDGAtLastHit.GetPz()*2.f ); + for(int iIndex=0; iIndex<9; iIndex++){ + const int iC = index2[iIndex]; + trackPDGAtLastHit.SetCovariance( iC, trackPDGAtLastHit.GetCovariance(iC)*2.f ); + } + for(int iIndex=0; iIndex<6; iIndex++){ + const int iC = index4[iIndex]; + trackPDGAtLastHit.SetCovariance( iC, trackPDGAtLastHit.GetCovariance(iC)*4.f ); + } + } + if(abs(pdg) == 1000030060 || abs(pdg) == 1000030070) { + trackPDGAtLastHit.SetCharge( trackPDGAtLastHit.Charge()*3.f ); + trackPDGAtLastHit.SetPx( trackPDGAtLastHit.GetPx()*3.f ); + trackPDGAtLastHit.SetPy( trackPDGAtLastHit.GetPy()*3.f ); + trackPDGAtLastHit.SetPz( trackPDGAtLastHit.GetPz()*3.f ); + for(int iIndex=0; iIndex<9; iIndex++) { + const int iC = index2[iIndex]; + trackPDGAtLastHit.SetCovariance( iC, trackPDGAtLastHit.GetCovariance(iC)*3.f ); + } + for(int iIndex=0; iIndex<6; iIndex++) { + const int iC = index4[iIndex]; + trackPDGAtLastHit.SetCovariance( iC, trackPDGAtLastHit.GetCovariance(iC)*9.f ); + } + } + if(abs(pdg) == 1000040070) { + trackPDGAtLastHit.SetCharge( trackPDGAtLastHit.Charge()*4.f ); + trackPDGAtLastHit.SetPx( trackPDGAtLastHit.GetPx()*4.f ); + trackPDGAtLastHit.SetPy( trackPDGAtLastHit.GetPy()*4.f ); + trackPDGAtLastHit.SetPz( trackPDGAtLastHit.GetPz()*4.f ); + for(int iIndex=0; iIndex<9; iIndex++) { + const int iC = index2[iIndex]; + trackPDGAtLastHit.SetCovariance( iC, trackPDGAtLastHit.GetCovariance(iC)*4.f ); + } + for(int iIndex=0; iIndex<6; iIndex++) { + const int iC = index4[iIndex]; + trackPDGAtLastHit.SetCovariance( iC, trackPDGAtLastHit.GetCovariance(iC)*16.f ); + } + } + + particlesAtLastHit->at(nPartSaved) = KFParticle(trackPDGAtLastHit, pdg); + particlesAtLastHit->at(nPartSaved).SetId(index); + } +#endif + + particlesPdg[nPartSaved] = pdg; + + nPartSaved++; + } +} + +void StKFParticleInterface::FillPIDHistograms(StPicoTrack *gTrack, const std::vector& pdgVector, const bool isTofm2, float m2tof) +{ + float momentum = gTrack->gPtot(); + for(uint32_t iPdg = 0; iPdg= NTrackHistoFolders) ) + { + fHistoMomentumTracks[iTrackHisto] -> Fill(momentum); + fHistodEdXTracks[iTrackHisto] -> Fill(momentum, gTrack->dEdx()); + if(isTofm2) + { + fHistodEdXwithToFTracks[iTrackHisto] -> Fill(momentum, gTrack->dEdx()); + fHistoTofPIDTracks[iTrackHisto] -> Fill(momentum, m2tof); + if(abs(pdg)==211) + { + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(0.139570, fdEdXMode, 1)); + float betaGamma = TMath::Log10(momentum/0.139570); + float z = gTrack->dEdxPull(0.139570, fdEdXMode, 1)*gTrack->dEdxError(); + fHistodEdXZ[iTrackHisto]->Fill(betaGamma, z); + + betaGamma = TMath::Log10(momentum/5.485799e-4); + z = gTrack->nSigmaElectron()*gTrack->dEdxError(); + fHistodEdXZ[0]->Fill(betaGamma, z); + } + if(abs(pdg)==321) + { + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(0.493677, fdEdXMode, 1)); + float betaGamma = TMath::Log10(momentum/0.493677); + float z = gTrack->dEdxPull(0.493677, fdEdXMode, 1)*gTrack->dEdxError(); + fHistodEdXZ[iTrackHisto]->Fill(betaGamma, z); + } + if(abs(pdg)==2212) + { + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(0.938272, fdEdXMode, 1)); + float betaGamma = TMath::Log10(momentum/0.938272); + float z = gTrack->dEdxPull(0.938272, fdEdXMode, 1)*gTrack->dEdxError(); + fHistodEdXZ[iTrackHisto]->Fill(betaGamma, z); + } + if(abs(pdg)==1000010020) + { + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(1.876124, fdEdXMode, 1)); + float betaGamma = TMath::Log10(momentum/1.876124); + float z = gTrack->dEdxPull(1.876124, fdEdXMode, 1)*gTrack->dEdxError(); + fHistodEdXZ[iTrackHisto]->Fill(betaGamma, z); + } + if(abs(pdg)==1000010030) + { + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(2.809432, fdEdXMode, 1)); + float betaGamma = TMath::Log10(momentum/2.809432); + float z = gTrack->dEdxPull(2.809432, fdEdXMode, 1)*gTrack->dEdxError(); + fHistodEdXZ[iTrackHisto]->Fill(betaGamma, z); + } + if(abs(pdg)==1000020030) + { + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(2.809413, fdEdXMode, 2)); + float betaGamma = TMath::Log10(momentum/2.809413); + float z = gTrack->dEdxPull(2.809413, fdEdXMode, 2)*gTrack->dEdxError(); + fHistodEdXZ[iTrackHisto]->Fill(betaGamma, z); + } + if(abs(pdg)==1000020040) + { + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(3.728400, fdEdXMode, 2)); + float betaGamma = TMath::Log10(momentum/3.728400); + float z = gTrack->dEdxPull(3.728400, fdEdXMode, 2)*gTrack->dEdxError(); + fHistodEdXZ[iTrackHisto]->Fill(betaGamma, z); + } + } + } + } +} + +void StKFParticleInterface::FillPIDHistograms(StMuTrack *gTrack, const std::vector& pdgVector, const bool isTofm2, float m2tof) +{ + float momentum = gTrack->p().mag(); + for(uint32_t iPdg = 0; iPdg= NTrackHistoFolders) ) + { + fHistoMomentumTracks[iTrackHisto] -> Fill(momentum); + fHistodEdXTracks[iTrackHisto] -> Fill(momentum, gTrack->dEdx()*1.e6); + if(isTofm2) + { + fHistodEdXwithToFTracks[iTrackHisto] -> Fill(momentum, gTrack->dEdx()*1.e6); + fHistoTofPIDTracks[iTrackHisto] -> Fill(momentum, m2tof); + + if(abs(pdg)==211) + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(0.139570, fdEdXMode, 1)); + if(abs(pdg)==321) + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(0.493677, fdEdXMode, 1)); + if(abs(pdg)==2212) + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(0.938272, fdEdXMode, 1)); + if(abs(pdg)==1000010020) + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(1.876124, fdEdXMode, 1)); + if(abs(pdg)==1000010030) + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(2.809432, fdEdXMode, 1)); + if(abs(pdg)==1000020030) + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(2.809413, fdEdXMode, 2)); + if(abs(pdg)==1000020040) + fHistodEdXPull[iTrackHisto] -> Fill(momentum, gTrack->dEdxPull(3.728400, fdEdXMode, 2)); + } + } + } +} + +bool StKFParticleInterface::OpenCharmTrigger() +{ + bool triggerDMesons = false; + if(fKFParticleTopoReconstructor->NPrimaryVertices() == 0) return false; + + for(uint32_t iParticle=0; iParticleGetPrimVertex()); + tempSIMDPart.GetDistanceToVertexLine(pv, l, dl); + + if(abs(particle.GetPDG()) == 411) + triggerDMesons = (l[0] < 0.4); + else + triggerDMesons = (l[0] < 0.2); + } + } + + return triggerDMesons; +} + +void StKFParticleInterface::OpenCharmTriggerCompression(int nTracksTriggered, int nTracksInEvent, bool triggerDMesons) +{ + static int nTriggeredEvents = 0; + static int nTracksInEventTriggered = 0; + static int nTracksInEventTotal = 0; + static int nEvents = 0; + nEvents++; + nTracksInEventTotal += nTracksInEvent; + if(triggerDMesons) + { + nTriggeredEvents++; + nTracksInEventTriggered += nTracksTriggered; + std::cout << "N Events " << nEvents << " N triggered events " << nTriggeredEvents << " ratio " << (double(nEvents)/double(nTriggeredEvents)) << std::endl; + std::cout << "N Tracks " << nTracksInEventTotal << " N triggered events " << nTracksInEventTriggered << " ratio " << (double(nTracksInEventTotal)/double(nTracksInEventTriggered)) << std::endl; + } +} + +void StKFParticleInterface::ResizeTrackPidVectors(const int nTracks) +{ + for(int iHypothesis=0; iHypothesis<3; iHypothesis++) + { + fTrackPidTof[iHypothesis].clear(); + fTrackPidTof[iHypothesis].resize(nTracks, -1); + + fTrackPidTpc[iHypothesis].clear(); + fTrackPidTpc[iHypothesis].resize(nTracks, -1); + } +} + +bool StKFParticleInterface::ProcessEvent(StPicoDst* picoDst, std::vector& triggeredTracks) +{ + triggeredTracks.resize(0); + + //read PV from pico Event + KFVertex primaryVertex; + vector primaryTrackList; + + StPicoEvent* picoEvent = picoDst->event(); + if(!picoEvent) return 0; + + const TVector3 picoPV = picoEvent->primaryVertex(); + const TVector3 picoPVError = picoEvent->primaryVertexError(); + + KFPVertex primVtx_tmp; + primVtx_tmp.SetXYZ(picoPV.x(), picoPV.y(), picoPV.z()); + double dx = picoPVError.x(); + double dy = picoPVError.y(); + double dz = picoPVError.z(); + primVtx_tmp.SetCovarianceMatrix( dx*dx, 0, dy*dy, 0, 0, dz*dz ); + primaryVertex = KFVertex(primVtx_tmp); +// if(!IsGoodPV(primaryVertex)) return 0; + + +#ifdef FXT + KFVertex myPV; + std::vector isPileup; + std::vector pileupPv; + if(!FindFixedTargetPV(picoDst, myPV, pileupPv, isPileup)) return 0; + primaryVertex = myPV; +#endif + + + Int_t nGlobalTracks = picoDst->numberOfTracks( ); + + fParticles.resize(nGlobalTracks*10); + fNHftHits.resize(nGlobalTracks*10); + fParticlesPdg.resize(nGlobalTracks*10); + int nPartSaved = 0; + int nUsedTracks = 0; + + std::vector trakIdToI(nGlobalTracks*2); + + for (Int_t iTrack = 0; iTrack < nGlobalTracks; iTrack++) + { + StPicoTrack *gTrack = picoDst->track(iTrack); + +// if ( (gTrack->status() != 0) && !(gTrack->isPrimary()) ) continue; //TODO + + if (! gTrack) continue; + if (! gTrack->charge()) continue; + if ( gTrack->nHitsFit() < 15) continue; +// if ( gTrack->nHitsFit() < 10) continue; +#ifdef FXT + if ( gTrack->dEdxError() < 0.01 || gTrack->dEdxError() > 0.15 ) continue; +#else + if ( gTrack->dEdxError() < 0.04 || gTrack->dEdxError() > 0.12 ) continue; +#endif + const uint32_t index = gTrack->id(); + +#ifdef FXT + if(isPileup[index]) continue; +#endif + + if(index >= trakIdToI.size()) trakIdToI.resize(index+1); + trakIdToI[index] = iTrack; + + int nHftHitsInTrack = 0; + if(gTrack->hasPxl1Hit()) nHftHitsInTrack++; + if(gTrack->hasPxl2Hit()) nHftHitsInTrack++; + if(gTrack->hasIstHit()) nHftHitsInTrack++; +// if(gTrack->hasSstHit()) nHftHitsInTrack++; + + //FIXME temporary solution!!! + nHftHitsInTrack = gTrack->nHitsFit(); + + if(fCollectTrackHistograms) fTrackHistograms[0]->Fill(nHftHitsInTrack); + +// if(fUseHFTTracksOnly && nHftHitsInTrack < 3) continue; + if(fUseHFTTracksOnly && !gTrack->hasIstHit()) continue; + + StPicoTrackCovMatrix *cov = picoDst->trackCovMatrix(iTrack); + const StDcaGeometry dcaG = cov->dcaGeometry(); + Int_t q = 1; if (gTrack->charge() < 0) q = -1; + KFPTrack track; + if( !GetTrack(dcaG, track, q, index) ) continue; + + KFParticle ppp(track, 211); + const float ccc = ppp.GetDeviationFromVertex(primaryVertex); + const bool isCollectPID = ccc < 18.f; + + if(fCollectTrackHistograms && isCollectPID) + { + fTrackHistograms2D[0]->Fill(track.GetP(), gTrack->dEdx()); + if(q>0) fTrackHistograms2D[1]->Fill(track.GetP(), gTrack->dEdx()); + else fTrackHistograms2D[2]->Fill(track.GetP(), gTrack->dEdx()); + } + + double m2tof = -1.e6; + bool isBTofm2 = false; + bool isETofm2 = false; +#ifdef USETOF + if(gTrack->bTofPidTraitsIndex() >= 0) + { + const StPicoBTofPidTraits* btofPid = picoDst->btofPidTraits(gTrack->bTofPidTraitsIndex()); + double betaTof2 = btofPid->btofBeta() * btofPid->btofBeta(); + if(fabs(betaTof2) > 1.e-6) + { + m2tof = track.GetP()*track.GetP()*(1./betaTof2 - 1.); + isBTofm2 = true; + } +// else +// { +// const TVector3 & tofPoint = btofPid->btofHitPos(); +// StPicoPhysicalHelix innerHelix = gTrack->helix(picoEvent->bField()); +// double lengthTof = fabs( innerHelix.pathLength( tofPoint )); +// +// double timeTof = btofPid->btof(); +// if(timeTof > 0. && lengthTof > 0.) +// { +// m2tof = track.GetP()*track.GetP()*(1./((lengthTof/timeTof/29.9792458)*(lengthTof/timeTof/29.9792458))-1.); +// isBTofm2 = true; +// } +// } + + if(fCollectTrackHistograms && isCollectPID) + { + fTrackHistograms2D[3]->Fill(track.GetP(), gTrack->dEdx()); + fTrackHistograms2D[4]->Fill(track.GetP(), m2tof); + fTrackHistograms2D[8]->Fill(gTrack->dEdx(), m2tof); + } + } + + if(fUseETof && gTrack->eTofPidTraitsIndex() >= 0) + { + const StPicoETofPidTraits* etofPid = picoDst->etofPidTraits(gTrack->eTofPidTraitsIndex()); + double betaTof2 = etofPid->beta() * etofPid->beta(); + if(fabs(betaTof2) > 1.e-6) + { + m2tof = track.GetP()*track.GetP()*(1./betaTof2 - 1.); + isETofm2 = true; + } + if(fCollectTrackHistograms && isCollectPID && isETofm2) + { + fTrackHistograms2D[3]->Fill(track.GetP(), gTrack->dEdx()); + fTrackHistograms2D[9]->Fill(track.GetP(), m2tof); + fTrackHistograms2D[10]->Fill(gTrack->dEdx(), m2tof); + } + } +#endif + double dEdXPull[12] = { fabs(gTrack->dEdxPull(5.109989461E-04, fdEdXMode, 1)), //0 - e + fabs(gTrack->dEdxPull(0.1056583745, fdEdXMode, 1)), //1 - mu + fabs(gTrack->dEdxPull(0.139570, fdEdXMode, 1)), //2 - pi + fabs(gTrack->dEdxPull(0.493677, fdEdXMode, 1)), //3 - K + fabs(gTrack->dEdxPull(0.938272, fdEdXMode, 1)), //4 - p + fabs(gTrack->dEdxPull(1.876124, fdEdXMode, 1)), //5 - d + fabs(gTrack->dEdxPull(2.809432, fdEdXMode, 1)), //6 - t + fabs(gTrack->dEdxPull(2.809413, fdEdXMode, 2)), //7 - He3 + fabs(gTrack->dEdxPull(3.728400, fdEdXMode, 2)), //8 - He4 + fabs(gTrack->dEdxPull(1.197449, fdEdXMode, 1)), //9 - Sigma + fabs(gTrack->dEdxPull(1.32171, fdEdXMode, 1)), //10- Xi + fabs(gTrack->dEdxPull(1.67245, fdEdXMode, 1))}; //11- Omega + + vector totalPDG = GetPID(m2tof, track.GetP(), q, gTrack->dEdx(), dEdXPull, isBTofm2, isETofm2, index); + + int nPartSaved0 = nPartSaved; + AddTrackToParticleList(track, nHftHitsInTrack, index, totalPDG, primaryVertex, primaryTrackList, fNHftHits, fParticlesPdg, fParticles, nPartSaved); + + if(nPartSaved > nPartSaved0) + triggeredTracks.push_back(iTrack); + + //fill PID histograms if they are created + if(fCollectPIDHistograms && isCollectPID) + { + vector selectedPdg; + for(int iPdg = nPartSaved0; iPdgFill( double(nPrimary)/double(nUsedTracks) ); + fTrackHistograms2D[7]->Fill( nPrimary, (nUsedTracks - nPrimary) ); + } + + if( fCleanLowPVTrackEvents && ( 10*nPrimary < (nUsedTracks - nPrimary) ) ) return 0; + if( fCleanLowPVTrackEvents && sqrt(dx*dx + dy*dy) > 0.45 ) return 0; + +#ifdef FXT + if( fCleanLowPVTrackEvents && !(primaryVertex.Z() > 196. && primaryVertex.Z() < 204.) ) return 0; + if( fCleanLowPVTrackEvents && !(primaryVertex.X() > -2.5 && primaryVertex.X() < 2. ) ) return 0; + if( fCleanLowPVTrackEvents && !(primaryVertex.Y() > -4. && primaryVertex.Y() < 0. ) ) return 0; + + if( fCleanLowPVTrackEvents && ( (nUsedTracks - nPrimary) > 150 ) ) return 0; +#else + if( fCleanLowPVTrackEvents && primaryVertex.GetR() > 2.5 ) return 0; +#endif + + const Double_t field = picoEvent->bField(); + SetField(field); + + CleanPV(); + InitParticles(); + + //read PV + AddPV(primaryVertex, primaryTrackList); + if(fCollectTrackHistograms) + { + fTrackHistograms[1]->Fill(sqrt(dx*dx + dy*dy)); + fTrackHistograms2D[5]->Fill( nPartSaved, sqrt(dx*dx + dy*dy) ); + fTrackHistograms2D[6]->Fill( primaryTrackList.size(), sqrt(dx*dx + dy*dy) ); + } + +// #ifdef FXT +// vector pileupTrackList; +// for(uint32_t iPileupPv=0; iPileupPv& mcTracks, vector& mcIndices, bool processSignal) +{ +#ifdef __TFG__VERSION__ + mcTracks.resize(muDst->numberOfMcTracks()); + for (uint32_t iMCTrack=0; iMCTracknumberOfMcTracks(); iMCTrack++) + { + StMuMcTrack *mcTrack = muDst->MCtrack(iMCTrack); + if (! mcTrack) continue; + KFMCTrack &mcTrackKF = mcTracks[iMCTrack]; + mcTrack->FillKFMCTrack(mcTrackKF); + mcTrackKF.SetNMCPixelPoints(mcTrack->No_ist_hit() + mcTrack->No_ssd_hit() + mcTrack->No_pix_hit()); + } +#else + mcTracks.resize(0); +#endif /* __TFG__VERSION__ */ + //read PV + KFVertex primaryVertex; + vector primaryTrackList; + + float bestRank=-1000000; + // int bestPV=-1; + double dx = 0., dy = 0., dz = 0.; + for(uint32_t iPV=0; iPVnumberOfPrimaryVertices(); iPV++) + { + StMuPrimaryVertex *Vtx = muDst->primaryVertex(iPV); + if(!Vtx) continue; + if (bestRank < Vtx->ranking()) { + bestRank = Vtx->ranking(); + // bestPV = iPV; + } + else continue; + + //convert StMuPrimaryVertex to KFVertex + KFPVertex kfVertex; + kfVertex.SetXYZ(Vtx->position().x(), Vtx->position().y(), Vtx->position().z()); + dx = Vtx->posError().x(); + dy = Vtx->posError().y(); + dz = Vtx->posError().z(); + kfVertex.SetCovarianceMatrix( dx*dx, 0, dy*dy, 0, 0, dz*dz ); + UShort_t noTracks = Vtx->noTracks(); + kfVertex.SetNContributors(noTracks); + kfVertex.SetChi2(Vtx->chiSquared()); + primaryVertex = KFVertex(kfVertex); + } +// if(!IsGoodPV(primaryVertex)) return 0; + + Int_t nGlobalTracks = muDst->numberOfGlobalTracks(); + + fParticles.resize(nGlobalTracks*10); +#ifdef __kfpAtFirstHit__ + fParticlesAtLastHit.resize(nGlobalTracks*10); +#endif + fNHftHits.resize(nGlobalTracks*10); + fParticlesPdg.resize(nGlobalTracks*10); + int nPartSaved = 0; + int nUsedTracks = 0; + + std::vector trakIdToI(nGlobalTracks*2); + + for (Int_t iTrack = 0; iTrack < nGlobalTracks; iTrack++) + { + StMuTrack *gTrack = muDst->globalTracks(iTrack); + if (! gTrack) continue; + if (! gTrack->charge()) continue; + if ( gTrack->flag() < 100 || gTrack->flag()%100 == 11) continue; // bad fit or short track pointing to EEMC + if ( gTrack->flag() > 1000) continue; // pile up track in TPC + if ( gTrack->nHitsFit() < 15) continue; + if ( gTrack->probPidTraits().dEdxErrorFit() < 0.04 || gTrack->probPidTraits().dEdxErrorFit() > 0.12 ) continue; + + int nHftHitsInTrack = gTrack->nHitsFit(kIstId) + gTrack->nHitsFit(kSsdId) + gTrack->nHitsFit(kPxlId); + if(fCollectTrackHistograms) fTrackHistograms[0]->Fill(nHftHitsInTrack); + if(fUseHFTTracksOnly && nHftHitsInTrack < 3) continue; + + const uint32_t index = gTrack->id(); + + if(index >= trakIdToI.size()) trakIdToI.resize(index+1); + trakIdToI[index] = iTrack; + + int mcIndex = gTrack->idTruth()-1; + if(mcIndex >= int(mcTracks.size())) + mcIndex = -1; + if(mcIndex > -1) { + if(!processSignal) continue; + } + else if(processSignal) continue; + + Int_t q = 1; if (gTrack->charge() < 0) q = -1; +#ifdef __kfpAtFirstHit__ + KFPTrack track = gTrack->kfpTrackAtFirstHit(); + KFPTrack trackAtLastHit = gTrack->kfpTrackAtLastHit(); +#else + Int_t dcaGeometryIndex = gTrack->index2Cov(); + if (dcaGeometryIndex < 0) continue; + StDcaGeometry *dcaG = StMuDst::instance()->covGlobTracks(dcaGeometryIndex); + if (! dcaG) continue; + + KFPTrack track; + if( !GetTrack(*dcaG, track, q, index) ) continue; +#endif + + if(fCollectTrackHistograms) + { + fTrackHistograms2D[0]->Fill(track.GetP(), gTrack->dEdx()*1.e6); + if(q>0) fTrackHistograms2D[1]->Fill(track.GetP(), gTrack->dEdx()*1.e6); + else fTrackHistograms2D[2]->Fill(track.GetP(), gTrack->dEdx()*1.e6); + } + + const StMuBTofPidTraits &btofPid = gTrack->btofPidTraits(); + double timeTof = btofPid.timeOfFlight(); + double lengthTof = btofPid.pathLength(); +// if(lengthTof < 0.) +// { +// const StThreeVectorF & tofPoint = btofPid.position(); +// const StThreeVectorF & dcaPoint = gTrack->dca(bestPV); +// StPhysicalHelixD innerHelix = gTrack->helix(); +// double dlDCA = fabs( innerHelix.pathLength( StThreeVector(dcaPoint.x(), dcaPoint.y(), dcaPoint.z()) ) ); +// StPhysicalHelixD outerHelix = gTrack->outerHelix(); +// double dlTOF = fabs( outerHelix.pathLength( StThreeVector(tofPoint.x(), tofPoint.y(), tofPoint.z()) ) ); +// +// double l = gTrack->length(); +// lengthTof = l + dlDCA + dlTOF; +// } +// if(lengthTof < 0.) +// { +// const StThreeVectorF & tofPoint = btofPid.position(); +// StPhysicalHelixD innerHelix = dcaG->helix(); +// StMuPrimaryVertex *pv = muDst->primaryVertex(bestPV); +// lengthTof = fabs( innerHelix.pathLength( StThreeVector(tofPoint.x(), tofPoint.y(), tofPoint.z()) ) ) + +// fabs( innerHelix.pathLength( StThreeVector(pv->position().x(), +// pv->position().y(), +// pv->position().z()) ) ); +// } + double m2tof = -1.e6; + bool isTofm2 = false; +#ifdef USETOF + if(timeTof > 0. && lengthTof > 0.) + { + m2tof = track.GetP()*track.GetP()*(1./((lengthTof/timeTof/29.9792458)*(lengthTof/timeTof/29.9792458))-1.); + isTofm2 = true; + + if(fCollectTrackHistograms) + { + fTrackHistograms2D[3]->Fill(track.GetP(), gTrack->dEdx()*1.e6); + fTrackHistograms2D[4]->Fill(track.GetP(), m2tof); + } + } +#endif + double dEdXPull[12] = { fabs(gTrack->nSigmaElectron()), //0 - e + fabs(gTrack->dEdxPull(0.1056583745, fdEdXMode, 1)), //1 - mu + fabs(gTrack->nSigmaPion()), //2 - pi + fabs(gTrack->nSigmaKaon()), //3 - K + fabs(gTrack->nSigmaProton()), //4 - p + fabs(gTrack->dEdxPull(1.876124, fdEdXMode, 1)), //5 - d + fabs(gTrack->dEdxPull(2.809432, fdEdXMode, 1)), //6 - t + fabs(gTrack->dEdxPull(2.809413, fdEdXMode, 2)), //7 - He3 + fabs(gTrack->dEdxPull(3.728400, fdEdXMode, 2)), //8 - He4 + fabs(gTrack->dEdxPull(1.197449, fdEdXMode, 1)), //9 - Sigma + fabs(gTrack->dEdxPull(1.32171, fdEdXMode, 1)), //10- Xi + fabs(gTrack->dEdxPull(1.67245, fdEdXMode, 1)) //11- Omega + }; + + vector totalPDG = GetPID(m2tof, track.GetP(), q, gTrack->dEdx()*1.e6, dEdXPull, isTofm2, false, index); + + int nPartSaved0 = nPartSaved; + uint32_t nPrimaryTracks = primaryTrackList.size(); +#ifdef __kfpAtFirstHit__ + AddTrackToParticleList(track, nHftHitsInTrack, index, totalPDG, primaryVertex, primaryTrackList, fNHftHits, fParticlesPdg, fParticles, nPartSaved, &trackAtLastHit, &fParticlesAtLastHit); +#else + AddTrackToParticleList(track, nHftHitsInTrack, index, totalPDG, primaryVertex, primaryTrackList, fNHftHits, fParticlesPdg, fParticles, nPartSaved); +#endif + + + if(nPartSaved > nPartSaved0) + mcIndices[index] = mcIndex; + + //fill PID histograms if they are created + //Histograms are filled for secondary tracks only!!! + if(fCollectPIDHistograms && (nPrimaryTracks == primaryTrackList.size())) + { + vector selectedPdg; + for(int iPdg = nPartSaved0; iPdgFill( double(nPrimary)/double(nUsedTracks) ); + fTrackHistograms2D[7]->Fill( nPrimary, (nUsedTracks - nPrimary) ); + } + + if( fCleanLowPVTrackEvents && ( 10*nPrimary < (nUsedTracks - nPrimary) ) ) return 0; + if( fCleanLowPVTrackEvents && sqrt(dx*dx + dy*dy) > 0.45 ) return 0; +#ifdef FXT + if( fCleanLowPVTrackEvents && !(primaryVertex.Z() > 196. && primaryVertex.Z() < 204.) ) return 0; + if( fCleanLowPVTrackEvents && !(primaryVertex.X() > -2.5 && primaryVertex.X() < 2. ) ) return 0; + if( fCleanLowPVTrackEvents && !(primaryVertex.Y() > -4. && primaryVertex.Y() < 0. ) ) return 0; + + if( fCleanLowPVTrackEvents && ( (nUsedTracks - nPrimary) > 150 ) ) return 0; +#else + if( fCleanLowPVTrackEvents && primaryVertex.GetR() > 2.5 ) return 0; +#endif + + //TODO remove coefficient !!!! + const Double_t field = muDst->event()->magneticField() * 0.998f; + SetField(field); + + CleanPV(); +#ifdef __kfpAtFirstHit__ + InitParticlesAtFirstAndLastHit(); +#else + InitParticles(); +#endif + + //read PV + AddPV(primaryVertex, primaryTrackList); + if(fCollectTrackHistograms) + { + fTrackHistograms[1]->Fill(sqrt(dx*dx + dy*dy)); + fTrackHistograms2D[5]->Fill( nPartSaved, sqrt(dx*dx + dy*dy) ); + fTrackHistograms2D[6]->Fill( primaryTrackList.size(), sqrt(dx*dx + dy*dy) ); + } + //reconstruct short-lived particles + ReconstructParticles(); + + return 1; +} + + +struct pvIndex { + pvIndex(float d, int j):chi(d), i(j) {} + float chi; + int i; +}; + +static bool sortPVIndices(const pvIndex& a, const pvIndex& b) { return a.chi < b.chi; } + +bool StKFParticleInterface::FitPV(KFVertex& pv, bool isFirstSeed, const KFPTrackVector& tracks, + std::vector& pvTrackIndices, std::vector& isUsed) +{ + std::vector candidateIndices; + candidateIndices.reserve(tracks.Size()); + + pvTrackIndices.clear(); + pvTrackIndices.reserve(tracks.Size()); + + isUsed.clear(); + isUsed.resize(tracks.Size(), false); + + KFParticleSIMD trackSIMD; + KFParticleSIMD pvSIMD(pv); + for(int iTrack=0; iTrack < tracks.Size(); iTrack+=SimdLen) { + + trackSIMD.Load(tracks, iTrack); + + const float32_v deviation = trackSIMD.GetDeviationFromVertex(pvSIMD); + + for(int iV=0; iV= tracks.Size()) break; + + if((deviation[iV]==deviation[iV]) && (deviation[iV] >= 0.f && deviation[iV] < 200.f)) + candidateIndices.push_back(pvIndex(deviation[iV], iTr)); + } + } + + std::sort(candidateIndices.begin(), candidateIndices.end(), sortPVIndices); + + const int nCandidates = candidateIndices.size(); + + if(nCandidates > 2) { + + vector vFlags(nCandidates, false); + + KFVertex primaryVertex; + primaryVertex.SetConstructMethod(0); + for(int iCandidate = 0; iCandidate < nCandidates; iCandidate++) { + + KFParticle particle; + const int iTrack = candidateIndices[iCandidate].i; + + particle.Q() = tracks.Q()[iTrack]; + + particle.X() = tracks.X()[iTrack]; + particle.Y() = tracks.Y()[iTrack]; + particle.Z() = tracks.Z()[iTrack]; + particle.Px() = tracks.Px()[iTrack]; + particle.Py() = tracks.Py()[iTrack]; + particle.Pz() = tracks.Pz()[iTrack]; + + particle.Covariance( 0) = tracks.Covariance( 0)[iTrack]; + particle.Covariance( 1) = tracks.Covariance( 1)[iTrack]; + particle.Covariance( 2) = tracks.Covariance( 2)[iTrack]; + particle.Covariance( 3) = tracks.Covariance( 3)[iTrack]; + particle.Covariance( 4) = tracks.Covariance( 4)[iTrack]; + particle.Covariance( 5) = tracks.Covariance( 5)[iTrack]; + particle.Covariance( 6) = tracks.Covariance( 6)[iTrack]; + particle.Covariance( 7) = tracks.Covariance( 7)[iTrack]; + particle.Covariance( 8) = tracks.Covariance( 8)[iTrack]; + particle.Covariance( 9) = tracks.Covariance( 9)[iTrack]; + particle.Covariance(10) = tracks.Covariance(10)[iTrack]; + particle.Covariance(11) = tracks.Covariance(11)[iTrack]; + particle.Covariance(12) = tracks.Covariance(12)[iTrack]; + particle.Covariance(13) = tracks.Covariance(13)[iTrack]; + particle.Covariance(14) = tracks.Covariance(14)[iTrack]; + particle.Covariance(15) = tracks.Covariance(15)[iTrack]; + particle.Covariance(16) = tracks.Covariance(16)[iTrack]; + particle.Covariance(17) = tracks.Covariance(17)[iTrack]; + particle.Covariance(18) = tracks.Covariance(18)[iTrack]; + particle.Covariance(19) = tracks.Covariance(19)[iTrack]; + particle.Covariance(20) = tracks.Covariance(20)[iTrack]; + + KFVertex tmpPV = primaryVertex; + tmpPV += particle; + const float dChi2 = tmpPV.Chi2() - primaryVertex.Chi2(); + if(dChi2 < 6.f) { + primaryVertex = tmpPV; + vFlags[iCandidate] = true; + } + } + + pv = primaryVertex; + + pvSIMD = KFParticleSIMD(pv); + + for(int iTrack=0; iTrack < tracks.Size(); iTrack+=SimdLen) { + trackSIMD.Load(tracks, iTrack); + + const float32_v deviation = trackSIMD.GetDeviationFromVertex(pvSIMD); + + for(int iV=0; iV= tracks.Size()) break; + + if((deviation[iV]==deviation[iV]) && (deviation[iV] >= 0.f && deviation[iV] < 50.f)) { + pvTrackIndices.push_back(iTr); + isUsed[iTr] = true; + } + } + } + + if( (isFirstSeed && primaryVertex.NDF() >= 1) || (!isFirstSeed && primaryVertex.NDF() > 7)) + { + return true; + } + } + + return false; +} + +inline void InvertCholetsky2(float a[3]) +{ + const float d0 = 1.f/a[0]; + const float u01 = a[1]*d0; + const float d1 = 1.f/(a[2] - u01*a[1]); + + a[2] = d1; + a[1] = -d1*u01; + a[0] = d0 - a[1]*u01; +} + +struct Point3D { + Point3D() = default; + Point3D(const KFParticle& p) { + m_r[0] = p.X(); m_r[1] = p.Y(); m_r[2] = p.Z(); + m_C[0] = p.GetCovariance(0); + m_C[1] = p.GetCovariance(1); m_C[2] = p.GetCovariance(2); + m_C[3] = p.GetCovariance(3); m_C[4] = p.GetCovariance(4); m_C[5] = p.GetCovariance(5); + } + + inline float GetDeviation(const Point3D& p) const { + float s[6]{ m_C[0] + p.m_C[0], + m_C[1] + p.m_C[1], m_C[2] + p.m_C[2], + m_C[3] + p.m_C[3], m_C[4] + p.m_C[4], m_C[5] + p.m_C[5] }; + KFParticle::InvertCholetsky3(s); + const float dr[3]{ p.m_r[0] - m_r[0], p.m_r[1] - m_r[1], p.m_r[2] - m_r[2] }; + return (s[0]*dr[0] + s[1]*dr[1] + s[3]*dr[2])*dr[0] + +(s[1]*dr[0] + s[2]*dr[1] + s[4]*dr[2])*dr[1] + +(s[3]*dr[0] + s[4]*dr[1] + s[5]*dr[2])*dr[2]; + } + + inline void Filter(const Point3D& p) { + const float r[3]{m_r[0], m_r[1], m_r[2]}; + const float c[6]{m_C[0], m_C[1], m_C[2], m_C[3], m_C[4], m_C[5]}; + + float s[6]{ c[0] + p.m_C[0], + c[1] + p.m_C[1], c[2] + p.m_C[2], + c[3] + p.m_C[3], c[4] + p.m_C[4], c[5] + p.m_C[5] }; + KFParticle::InvertCholetsky3(s); + + const float k[3][3]{ {c[0]*s[0] + c[1]*s[1] + c[3]*s[3], c[0]*s[1] + c[1]*s[2] + c[3]*s[4], c[0]*s[3] + c[1]*s[4] + c[3]*s[5]}, + {c[1]*s[0] + c[2]*s[1] + c[4]*s[3], c[1]*s[1] + c[2]*s[2] + c[4]*s[4], c[1]*s[3] + c[2]*s[4] + c[4]*s[5]}, + {c[3]*s[0] + c[4]*s[1] + c[5]*s[3], c[3]*s[1] + c[4]*s[2] + c[5]*s[4], c[3]*s[3] + c[4]*s[4] + c[5]*s[5]} }; + const float dr[3]{ p.m_r[0] - r[0], p.m_r[1] - r[1], p.m_r[2] - r[2] }; + + const float dChi2 = (s[0]*dr[0] + s[1]*dr[1] + s[3]*dr[2])*dr[0] + +(s[1]*dr[0] + s[2]*dr[1] + s[4]*dr[2])*dr[1] + +(s[3]*dr[0] + s[4]*dr[1] + s[5]*dr[2])*dr[2]; + + if((m_chi2 + dChi2) / float(m_ndf + 3) < 10.f) { + m_r[0] = r[0] + k[0][0]*dr[0] + k[0][1]*dr[1] + k[0][2]*dr[2]; + m_r[1] = r[1] + k[1][0]*dr[0] + k[1][1]*dr[1] + k[1][2]*dr[2]; + m_r[2] = r[2] + k[2][0]*dr[0] + k[2][1]*dr[1] + k[2][2]*dr[2]; + + m_C[0] = c[0] - k[0][0]*c[0] - k[0][1]*c[1] - k[0][2]*c[3]; + m_C[1] = c[1] - k[1][0]*c[0] - k[1][1]*c[1] - k[1][2]*c[3]; + m_C[2] = c[2] - k[1][0]*c[1] - k[1][1]*c[2] - k[1][2]*c[4]; + m_C[3] = c[3] - k[2][0]*c[0] - k[2][1]*c[1] - k[2][2]*c[3]; + m_C[4] = c[4] - k[2][0]*c[1] - k[2][1]*c[2] - k[2][2]*c[4]; + m_C[5] = c[5] - k[2][0]*c[3] - k[2][1]*c[4] - k[2][2]*c[5]; + + m_chi2 += dChi2; + m_ndf += 3; + } + } + + static bool compare(const Point3D& a, const Point3D& b) { + return (a.m_ndf > b.m_ndf) || (a.m_ndf == b.m_ndf && a.m_chi2 < b.m_chi2); + } + + KFParticle convertToKFParticle(const float) const { + KFParticle p; + p.X() = m_r[0]; + p.Y() = m_r[1]; + p.Z() = m_r[2]; + p.Covariance(0) = m_C[0]; + p.Covariance(1) = m_C[1]; + p.Covariance(2) = m_C[2]; + p.Covariance(3) = m_C[3]; + p.Covariance(4) = m_C[4]; + p.Covariance(5) = m_C[5]; + return p; + } + + float m_r[3]{0.f}; + float m_C[6]{0.f}; + float m_chi2{0.f}; + int m_ndf{-2}; +}; + +struct Point2D { + inline float GetDeviation(const Point2D& p) const { + float s[3]{ m_C[0] + p.m_C[0], m_C[1] + p.m_C[1], m_C[2] + p.m_C[2] }; + InvertCholetsky2(s); + const float dr[2]{ p.m_r[0] - m_r[0], p.m_r[1] - m_r[1] }; + return s[0]*dr[0]*dr[0] + s[1]*dr[0]*dr[1]*2.f + s[2]*dr[1]*dr[1]; + } + + inline void Filter(const Point2D& p) { + const float r[2]{m_r[0], m_r[1]}; + const float c[3]{m_C[0], m_C[1], m_C[2]}; + + float s[3]{ c[0] + p.m_C[0], c[1] + p.m_C[1], c[2] + p.m_C[2] }; + InvertCholetsky2(s); + + const float k[2][2]{ {c[0] * s[0] + c[1] * s[1], c[0] * s[1] + c[1] * s[2]}, + {c[1] * s[0] + c[2] * s[1], c[1] * s[1] + c[2] * s[2]} }; + const float dr[2]{ p.m_r[0] - r[0], p.m_r[1] - r[1] }; + + const float dChi2 = s[0]*dr[0]*dr[0] + s[1]*dr[0]*dr[1]*2.f + s[2]*dr[1]*dr[1]; + + if((m_chi2 + dChi2) / float(m_ndf + 2) < 10.f) { + m_r[0] = r[0] + k[0][0] * dr[0] + k[0][1] * dr[1]; + m_r[1] = r[1] + k[1][0] * dr[0] + k[1][1] * dr[1]; + + m_C[0] = c[0] - k[0][0] * c[0] - k[0][1] * c[1]; + m_C[1] = c[1] - k[1][0] * c[0] - k[1][1] * c[1]; + m_C[2] = c[2] - k[1][0] * c[1] - k[1][1] * c[2]; + + m_chi2 += dChi2; + m_ndf += 2; + } + } + + static bool compare(const Point2D& a, const Point2D& b) { + return (a.m_ndf > b.m_ndf) || (a.m_ndf == b.m_ndf && a.m_chi2 < b.m_chi2); + } + + float m_r[2]{0.f}; + float m_C[3]{0.f}; + float m_chi2{0.f}; + int m_ndf{-2}; +}; + +struct PointXY: public Point2D { + PointXY() = default; + PointXY(const KFParticle& p) { + m_r[0] = p.X(); m_r[1] = p.Y(); + m_C[0] = p.GetCovariance(0); + m_C[1] = p.GetCovariance(1); m_C[2] = p.GetCovariance(2); + } + + KFParticle convertToKFParticle(const float z0) const { + KFParticle p; + p.X() = m_r[0]; + p.Y() = m_r[1]; + p.Z() = z0; + p.Covariance(0) = m_C[0]; + p.Covariance(1) = m_C[1]; + p.Covariance(2) = m_C[2]; + p.Covariance(5) = 9.f; + return p; + } +}; + +struct PointPhiZ: public Point2D { + PointPhiZ() = default; + PointPhiZ(const KFParticle& p) { + const float x = p.X(); + const float y = p.Y(); + const float x2 = x*x; + const float y2 = y*y; + const float r2 = x2 + y2; + const float r4 = r2 * r2; + + const float phi = atan2(y, x); + + const float cPhiPhi = (y2 * p.GetCovariance(0) - 2.f*x*y * p.GetCovariance(1) + x2 * p.GetCovariance(2)) / r4; + const float cPhiZ = (x * p.GetCovariance(4) - y * p.GetCovariance(3)) / r2; + + m_r[0] = phi; m_r[1] = p.Z(); + m_C[0] = cPhiPhi; + m_C[1] = cPhiZ; m_C[2] = p.GetCovariance(5); + } + + KFParticle convertToKFParticle(const float r) const { + const float x = r * cos(m_r[0]); + const float y = r * sin(m_r[0]); + + KFParticle p; + p.X() = x; + p.Y() = y; + p.Z() = m_r[1]; + p.Covariance(0) = y*y * m_C[0]; + p.Covariance(1) = -x*y * m_C[0]; + p.Covariance(2) = x*x * m_C[0]; + p.Covariance(3) = -y * m_C[1]; + p.Covariance(4) = x * m_C[1]; + p.Covariance(5) = m_C[2]; + + return p; + } +}; + +struct Position{ + Position(const int i, const float value, const float error2): + m_i(i), m_value(value), m_error2(error2) {} + int m_i; + float m_value; + float m_error2; + static bool compare(const Position& a, const Position& b) { return a.m_value > b.m_value; } +}; + +template +void getPoints( + const KFPTrackVector& tracks, const KFVertex& beamPosition, const float R, const float dR, + std::vector& points, std::vector& zHisto); + +template<> void getPoints( + const KFPTrackVector& tracks, const KFVertex& beamPosition, const float R, const float dR, + std::vector& points, std::vector& zHisto) +{ + KFParticleSIMD trackSIMD; + const float32_v beamXY[2]{beamPosition.X(), beamPosition.Y()}; + + for(int iTrack=0; iTrack < tracks.Size(); iTrack+=SimdLen) { + trackSIMD.Load(tracks, iTrack); + + const float32_v ds = trackSIMD.GetDStoPointXY(beamXY); + float32_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + trackSIMD.TransportToDS(ds, dsdr); + + for(int iV=0; iV<4; iV++) { + if(iTrack + iV >= tracks.Size()) continue; + KFParticle tmp; + trackSIMD.GetKFParticle(tmp, iV); + tmp.SetId(iTrack + iV); + + const float dx = tmp.X() - beamPosition.X(); + const float dy = tmp.Y() - beamPosition.Y(); + const float xError2 = tmp.GetCovariance(0) + 0.01f; + const float yError2 = tmp.GetCovariance(2) + 0.01f; + if( (dx*dx > 10.f*xError2) || (dy*dy > 10.f*yError2) ) continue; + if( tmp.GetCovariance(0) > 25.f || tmp.GetCovariance(2) > 25.f || tmp.GetCovariance(5) > 25.f) + continue; + + zHisto.push_back(Position(zHisto.size(), tmp.Z(), tmp.GetCovariance(2,2))); + points.push_back(tmp); + } + } +} + +template<> void getPoints( + const KFPTrackVector& tracks, const KFVertex& beamPosition, const float R, const float dR, + std::vector& points, std::vector& zHisto) +{ + KFParticleSIMD trackSIMD; + for(int iTrack=0; iTrack < tracks.Size(); iTrack+=SimdLen) { + trackSIMD.Load(tracks, iTrack); + KFParticleSIMD p1 = trackSIMD; + KFParticleSIMD p2 = trackSIMD; + float32_v ds[2]{0.f, 0.f}; + p1.GetDStoCylinder(R, ds); + float32_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + p1.TransportToDS(ds[0], dsdr); + p2.TransportToDS(ds[1], dsdr); + + const mask32_v saveFirstPoint = (p1.GetR() > R-dR) && (p1.GetR() < R+dR) && (p1.Z() > -200.f); + for(int iV=0; iV<4; iV++) { + if(!saveFirstPoint[iV]) continue; + if(iTrack + iV >= tracks.Size()) continue; + KFParticle tmp; + p1.GetKFParticle(tmp, iV); + if( tmp.GetCovariance(0) > 25.f || tmp.GetCovariance(2) > 25.f || tmp.GetCovariance(5) > 25.f) + continue; + tmp.SetId(iTrack + iV); + zHisto.push_back(Position(zHisto.size(), tmp.Z(), tmp.GetCovariance(2,2))); + points.push_back(tmp); + } + const mask32_v saveSecondPoint = (p2.GetR() > R-dR) && (p2.GetR() < R+dR) && (p2.Z() > -200.f) && + (abs(p1.Z() - p2.Z()) > 1.e-4f); + for(int iV=0; iV<4; iV++) { + if(!saveSecondPoint[iV]) continue; + if(iTrack + iV >= tracks.Size()) continue; + KFParticle tmp; + p2.GetKFParticle(tmp, iV); + if( tmp.GetCovariance(0) > 25.f || tmp.GetCovariance(2) > 25.f || tmp.GetCovariance(5) > 25.f) + continue; + tmp.SetId(iTrack + iV); + zHisto.push_back(Position(zHisto.size(), tmp.Z(), tmp.GetCovariance(2,2))); + points.push_back(tmp); + } + } +} + +template<> void getPoints( + const KFPTrackVector& tracks, const KFVertex&, const float Z, const float dZ, + std::vector& points, std::vector& zHisto) +{ + KFParticleSIMD trackSIMD; + + for(int iTrack=0; iTrack < tracks.Size(); iTrack+=SimdLen) { + trackSIMD.Load(tracks, iTrack); + + const float32_v ds = trackSIMD.GetDStoPointZBz(Z); + float32_v dsdr[6] = {0.f,0.f,0.f,0.f,0.f,0.f}; + trackSIMD.TransportToDS(ds, dsdr); + + for(int iV=0; iV<4; iV++) { + if(iTrack + iV >= tracks.Size()) continue; + KFParticle tmp; + trackSIMD.GetKFParticle(tmp, iV); + tmp.SetId(iTrack + iV); + + const float dz = tmp.Z() - Z; + if( fabs(dz) > dZ ) continue; + if( tmp.GetR() > 30.f ) continue; + if( tmp.GetR() < 3.5f ) continue; + if( tmp.GetCovariance(0) > 25.f || tmp.GetCovariance(2) > 25.f || tmp.GetCovariance(5) > 25.f) + continue; + float rrr, drrr; + tmp.GetR(rrr, drrr); + zHisto.push_back(Position(zHisto.size(), rrr, drrr*drrr)); + points.push_back(tmp); + } + } +} + + + +template +inline void cleanCluster(std::vector& cluster, const std::vector& points) +{ + struct Clean { + Clean(): m_i(-1), m_id(-1) {} + Clean(const int i, const int id): m_i(i), m_id(id) {} + static bool compare(const Clean& a, const Clean& b) { + return (a.m_id > b.m_id) || (a.m_id == b.m_id && a.m_i > b.m_i); + } + int m_i; + int m_id; + }; + + std::vector clean(cluster.size()); + for(uint32_t i=0; i +inline void cleanCluster(std::vector& cluster, const std::vector& points) {} + +template<> +inline void cleanCluster(std::vector& cluster, const std::vector& points) {} + +template +void StKFParticleInterface::FindPileup(const KFPTrackVector& tracks, const KFVertex& beamPosition, + std::vector& vertices, std::vector>& vertexTracks, const float X, const float dX) +{ + vertices.clear(); + vertexTracks.clear(); + + std::vector points; + std::vector zHisto; + getPoints(tracks, beamPosition, X, dX, points, zHisto); + std::sort(zHisto.begin(), zHisto.end(), Position::compare); + + // find Z-clusters around each track + std::vector> neighbours(zHisto.size()); + for(uint32_t iZ=0; iZ 25.f) continue; + for(uint32_t iZNext = 0; iZNext 25.f) continue; + const float dz = currentPoint.m_value - nextPoint.m_value; + const float zError2 = currentPoint.m_error2 + nextPoint.m_error2; + if(dz * dz < zError2 * 9 && fabs(dz) < 10.f) { + neighbours[iZ].push_back(nextPoint.m_i); + } + } + if(neighbours[iZ].size() > 0) { + neighbours[iZ].push_back(currentPoint.m_i); + std::sort(neighbours[iZ].begin(), neighbours[iZ].end()); + } + } + + // merge clusters + for(int i=0; i<2; i++) + for(uint32_t iZ=0; iZ merged; + std::set_union(current.begin(), current.end(), + next.begin(), next.end(), + std::back_inserter(merged)); + + const int intersection = current.size() + next.size() - merged.size(); + + if( 0.5f * float(min(current.size(), next.size())) < float(intersection) ) { + current = merged; + next.clear(); + } + } + } + + std::vector isUsed(tracks.Size(), false); + std::vector candidateVertices; + std::vector> candidateVertexTracks; + + for(uint32_t iZ=0; iZ zCluster = neighbours[iZ]; + if(zCluster.size() > 2) { + std::vector projections(zCluster.size()); + for(uint32_t iPoint=0; iPoint seeds; + seeds.reserve(zCluster.size()); + for(uint32_t iFirstPoint=0; iFirstPoint 18.6f ) continue; + + phiZVertex.Filter(projections[iPoint]); + } + phiZSeed = phiZVertex; + } + + if( (phiZSeed.m_ndf >= 4) && (phiZSeed.m_chi2/float(phiZSeed.m_ndf) < 10.f) ) { + seeds.push_back(phiZSeed); + } + } + + std::sort(seeds.begin(), seeds.end(), T::compare); + + cleanCluster(zCluster, points); + + for(uint32_t iSeed=0; iSeed currentVertexTracks; + + for(uint32_t iPoint=0; iPoint < zCluster.size(); iPoint++) { + const KFParticle& point = points[zCluster[iPoint]]; + if(isUsed[point.Id()]) continue; + if(point.GetDeviationFromVertex(seed) > 18.6f) continue; + + KFParticle vertexTmp = vertex; + vertexTmp += point; + if(! (vertexTmp.X() == vertexTmp.X()) ) continue; + + vertex = vertexTmp; + currentVertexTracks.push_back(point.Id()); + nTracksInVertex++; + } + + if(nTracksInVertex > 4 && vertex.Chi2() / vertex.NDF() < 5.f) { + candidateVertices.push_back(vertex); + candidateVertexTracks.push_back(currentVertexTracks); + for(uint32_t iUsed=0; iUsed& t): m_vertex(&v), m_tracks(&t) {} + + static bool compare(const PVCandidate& a, const PVCandidate& b) { + return a.m_tracks->size() > b.m_tracks->size(); + } + + KFVertex* m_vertex; + std::vector* m_tracks; + }; + + std::vector candidates; + for(uint32_t iCandidate=0; iCandidate vertexTrackIds = *(candidates[iCandidate].m_tracks); + + KFParticleSIMD trackSIMD; + KFParticleSIMD pvSIMD(vertex); + for(int iTrack=0; iTrack < tracks.Size(); iTrack+=SimdLen) { + trackSIMD.Load(tracks, iTrack); + const float32_v deviation = trackSIMD.GetDeviationFromVertex(pvSIMD); + for(int iV=0; iV= tracks.Size()) break; + + if((deviation[iV]==deviation[iV]) && (deviation[iV] >= 0.f && deviation[iV] < 18.6f)) { + vertexTrackIds.push_back(iTr); + isUsed[iTr] = true; + } + } + } + + vertices.push_back(vertex); + vertexTracks.push_back(vertexTrackIds); + } +} + +void StKFParticleInterface::FillPVHistos(const KFVertex& vertex, const std::vector& tracks, const bool isMainVertex) { + if(fCollectPVHistograms) { + fPVHistograms[0]->Fill(vertex.X()); + fPVHistograms[1]->Fill(vertex.Y()); + fPVHistograms[2]->Fill(vertex.GetR()); + fPVHistograms[3]->Fill(vertex.Z()); + fPVHistograms[4]->Fill(tracks.size()); + + if(isMainVertex) { + fPVHistograms[5]->Fill(tracks.size()); + } else { + fPVHistograms[6]->Fill(tracks.size()); + } + + fPVHistograms2D[0]->Fill(vertex.X(), vertex.Y()); + fPVHistograms2D[1]->Fill(vertex.Z(), vertex.GetR() * vertex.Y()/fabs(vertex.Y())); + } +} + +void StKFParticleInterface::CleanTracks(KFPTrackVector& tracks, std::vector& isUsed, const int nUsed) { + KFPTrackVector tracksLeft; + tracksLeft.Resize(tracks.Size() - nUsed); + + int iLeft = 0; + for(int iTrack=0; iTrack& vertices, std::vector>& verticesTracks, + int& nPV, int& nPileup, std::vector& isPileup, std::vector& pileupPv) +{ + std::vector isUsed(tracks.Size(), false); + int nUsed = 0; + + for(uint32_t iVertex=0; iVertex& vertexTracks = verticesTracks[iVertex]; + + for(uint32_t iTrack=0; iTrack -2.5f && vertex.X() < 2.f) && (vertex.Y() > -3.f && vertex.Y() < 0.f) ) { + pileupPv.push_back(vertex); + } + + for(uint32_t iIndex=0; iIndex& pileupPv, std::vector& isPileup) +{ + KFPTrackVector tracks; + tracks.Resize(picoDst->numberOfTracks()); + + pileupPv.clear(); + + int NTracks = 0; + int maxIndex = 0; + + for(uint32_t iTrack=0; iTracknumberOfTracks(); iTrack++) { + StPicoTrack *gTrack = picoDst->track(iTrack); + if (! gTrack) continue; + if (! gTrack->charge()) continue; + + StPicoTrackCovMatrix *cov = picoDst->trackCovMatrix(iTrack); + const StDcaGeometry dcaG = cov->dcaGeometry(); + const int q = (gTrack->charge() < 0) ? -1 : 1; + const int index = gTrack->id(); + maxIndex = (index > maxIndex) ? index : maxIndex; + KFPTrack track; + if( !GetTrack(dcaG, track, q, index) ) continue; + + for(int iP=0; iP<6; iP++) + tracks.SetParameter(track.GetParameter(iP), iP, NTracks); + for(int iC=0; iC<21; iC++) + tracks.SetCovariance(track.GetCovariance(iC), iC, NTracks); + tracks.SetId(index, NTracks); + tracks.SetQ(q, NTracks); + + NTracks++; + + if(fCollectPVHistograms) { + fPVHistograms2D[2]->Fill(track.GetZ(), sqrt(track.GetX()*track.GetX() + track.GetY()*track.GetY())); + } + } + + tracks.Resize(NTracks); + isPileup.resize(maxIndex+1, false); + + int nPV = 0; + int nPrimary = 0; + int nPileup = 0; + + // 1. Find the main vertex + + KFVertex primaryVertex = fBeamSpot; + std::vector pvTrackIndices; + std::vector isUsed; + const bool isPVFound = FitPV(primaryVertex, true, tracks, pvTrackIndices, isUsed); + if(isPVFound) { + pv = primaryVertex; + FillPVHistos(primaryVertex, pvTrackIndices, true); + nPrimary += pvTrackIndices.size(); + nPV++; + } + CleanTracks(tracks, isUsed, pvTrackIndices.size()); + + // 2. Find pileup vertices + + std::vector pileupVertices; + std::vector> pileupVertexTracks; + FindPileup(tracks, fBeamSpot, pileupVertices, pileupVertexTracks); + CleanPileupTracks(tracks, pileupVertices, pileupVertexTracks, nPV, nPileup, isPileup, pileupPv); + + // 3. Find pipe vertices +// KFPTrackVector tracks0 = tracks; + std::vector pipeVertices; + std::vector> pipeVertexTracks; + FindPileup(tracks, fBeamSpot, pipeVertices, pipeVertexTracks); + CleanPileupTracks(tracks, pipeVertices, pipeVertexTracks, nPV, nPileup, isPileup, pileupPv); + + // 4. Find flanec vertices + + std::vector flanecVertices1; + std::vector> flanecVertexTracks1; + FindPileup(tracks, fBeamSpot, flanecVertices1, flanecVertexTracks1, 55.5f, 2.f); + CleanPileupTracks(tracks, flanecVertices1, flanecVertexTracks1, nPV, nPileup, isPileup, pileupPv); + + std::vector flanecVertices2; + std::vector> flanecVertexTracks2; + FindPileup(tracks, fBeamSpot, flanecVertices2, flanecVertexTracks2, -55.5f, 2.f); + CleanPileupTracks(tracks, flanecVertices2, flanecVertexTracks2, nPV, nPileup, isPileup, pileupPv); + + if(fCollectPVHistograms) { + fPVHistograms[ 7]->Fill(nPV); + fPVHistograms[ 8]->Fill(float(nPrimary)/float(NTracks)); + fPVHistograms[ 9]->Fill(float(nPileup)/float(NTracks)); + fPVHistograms[10]->Fill(float(NTracks - nPrimary - nPileup)/float(NTracks)); + + for(int iTrack=0; iTrackFill(tracks.Z()[iTrack], + sqrt(tracks.X()[iTrack]*tracks.X()[iTrack] + tracks.Y()[iTrack]*tracks.Y()[iTrack])); + } + + return isPVFound; +} + diff --git a/StRoot/StKFParticleAnalysisMaker/StKFParticleInterface.h b/StRoot/StKFParticleAnalysisMaker/StKFParticleInterface.h new file mode 100644 index 00000000000..128261d4d21 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StKFParticleInterface.h @@ -0,0 +1,214 @@ +#ifndef StKFParticleInterface_H +#define StKFParticleInterface_H +#include +#include + +#include "KFParticle.h" +#include "TObject.h" +#include "StMuDSTMaker/COMMON/StMuTrack.h" + +class KFParticleTopoReconstructor; +class KFParticleFinder; +class KFTopoPerformance; +class KFVertex; +class StPicoDst; +class StPicoTrack; +class StMuTrack; +class KFMCTrack; +class StMuDst; +class StDcaGeometry; +class KFPTrack; +class KFPTrackVector; +class TH1F; +class TH2F; + +class StKFParticleInterface: public TObject +{ + public: + + StKFParticleInterface(); + virtual ~StKFParticleInterface(); + + void InitParticles(); +#ifdef __kfpAtFirstHit__ + void InitParticlesAtFirstAndLastHit(); +#endif + void ReconstructParticles(); + void ReconstructTopology(); + + const std::vector &GetParticles() const; + void RemoveParticle(const int iParticle); + const std::vector* GetSecondaryCandidates() const; // Get secondary particles with the mass constraint + const std::vector& GetSecondaryK0() const; + const std::vector& GetSecondaryLambda() const; + const std::vector& GetSecondaryAntiLambda() const; + const std::vector& GetSecondaryGamma() const; + const std::vector& GetSecondaryPi0() const; + const std::vector< std::vector >* GetPrimaryCandidates() const; // Get primary particles with the mass constraint + const std::vector< std::vector >* GetPrimaryTopoCandidates() const; // Get primary particles with the topologigal constraint + const std::vector< std::vector >* GetPrimaryTopoMassCandidates() const; // Get primary particles with the topologigal and mass constraint + void SetParticles(std::vector& particles) + { + fParticles = particles; + if(fParticlesPdg.size() != fParticles.size()) + { + fParticlesPdg.clear(); + fParticlesPdg.resize(fParticles.size(), -1); + } + } + void SetParticlesPdg(std::vector& pdg) { fParticlesPdg = pdg;} + void SetHftHits(std::vector& nHftHits) { fNHftHits = nHftHits; } + + void SetField(float field); + void SetBeamLine(KFParticle& p); + void SetBeamSpot(const TString beamSpotMode); + + void CleanPV(); + void AddPV(const KFVertex &pv, const std::vector &tracks); + void AddPV(const KFVertex &pv); + void AddParticle(const KFParticle& p); + void AddCandidate(const KFParticle& candidate, int iPV = -1); + void AddDecayToReconstructionList(Int_t pdg); + const KFParticleTopoReconstructor* GetTopoReconstructor() { return fKFParticleTopoReconstructor; } + + void SetPrimaryProbCut(float prob); + + bool ProcessEvent(StPicoDst* picoDst, std::vector& goodTracks); + bool ProcessEvent(StMuDst* muDst, std::vector& mcTracks, std::vector& mcIndices, bool processSignal); + bool OpenCharmTrigger(); + void OpenCharmTriggerCompression(int nTracksTriggered, int nTracksInEvent, bool triggerDMesons); + + //Histograms + void CollectTrackHistograms(); + void CollectPIDHistograms(); + void CollectPVHistograms(); + + //PID hypothesis, should be resized from outside + void ResizeTrackPidVectors(const int nTracks); + const float GetdEdXNSigmaPion(const int trackId) const { return fTrackPidTpc[0][trackId]; } + const float GetdEdXNSigmaKaon(const int trackId) const { return fTrackPidTpc[1][trackId]; } + const float GetdEdXNSigmaProton(const int trackId) const { return fTrackPidTpc[2][trackId]; } + const float GetTofNSigmaPion(const int trackId) const { return fTrackPidTof[0][trackId]; } + const float GetTofNSigmaKaon(const int trackId) const { return fTrackPidTof[1][trackId]; } + const float GetTofNSigmaProton(const int trackId) const { return fTrackPidTof[2][trackId]; } + + //PID cuts + void SetStrictTofPidMode() { fStrictTofPID = true; } + void SetSoftTofPidMode() { fStrictTofPID = false; } + void SetSoftKaonPIDMode() { fCleanKaonsWitTof = false; } + void UseCorrecteddEdX() { fdEdXMode = 2; } + void SetTriggerMode() { fTriggerMode = true; } + //KF Particle Finder cuts + void SetChiPrimaryCut(float cut) { fChiPrimaryCut = cut; } + void SetChiPrimaryCutFragments(float cut) { fChiPrimaryCutFragments = cut; } + void SetChiPrimaryMaxCut(float cut) { fChiPrimaryMaxCut = cut; } + //Event cuts + void CleanLowPVTrackEvents() { fCleanLowPVTrackEvents = true; } + void UseHFTTracksOnly() { fUseHFTTracksOnly = true; } + + KFParticleFinder* GetKFParticleFinder(); + //KF Particle Finder cuts + void SetMaxDistanceBetweenParticlesCut(float cut); + void SetLCut(float cut); + void SetChiPrimaryCut2D(float cut); + void SetChi2Cut2D(float cut); + void SetLdLCut2D(float cut); + void SetLdLCutXiOmega(float cut); + void SetChi2TopoCutXiOmega(float cut); + void SetChi2CutXiOmega(float cut); + void SetChi2TopoCutResonances(float cut); + void SetChi2CutResonances(float cut); + void SetPtCutLMVM(float cut); + void SetPCutLMVM(float cut); + void SetPtCutJPsi(float cut); + void SetPtCutCharm(float cut); + void SetChiPrimaryCutCharm(float cut); + void SetLdLCutCharmManybodyDecays(float cut); + void SetChi2TopoCutCharmManybodyDecays(float cut); + void SetChi2CutCharmManybodyDecays(float cut); + void SetLdLCutCharm2D(float cut); + void SetChi2TopoCutCharm2D(float cut); + void SetChi2CutCharm2D(float cut); + void SetSecondaryCuts(const float sigmaMass, const float chi2Topo, const float ldl); + static StKFParticleInterface *instance() {return fgStKFParticleInterface;} + private: + + double InversedChi2Prob(double p, int ndf) const; + bool IsGoodPV(const KFVertex& pv); + bool GetTrack(const StDcaGeometry& dcaG, KFPTrack& track, int q, int index); + std::vector GetTofPID(double m2, double p, int q, const int trackId); + std::vector GetPID(double m2, double p, int q, double dEdX, double dEdXPull[8], bool isBTofm2, bool isETofm2, const int trackId); + void AddTrackToParticleList(const KFPTrack& track, int nHftHitsInTrack, int index, const std::vector& totalPDG, KFVertex& pv, std::vector& primaryTrackList, + std::vector& nHftHits, std::vector& particlesPdg, std::vector& particles, int& nPartSaved, + const KFPTrack* trackAtLastHit=nullptr, std::vector* particlesAtLastHit=nullptr); + void FillPIDHistograms(StPicoTrack *gTrack, const std::vector& pdgVector, const bool isTofm2, float m2tof); + void FillPIDHistograms(StMuTrack *gTrack, const std::vector& pdgVector, const bool isTofm2, float m2tof); + + void FillPVHistos(const KFVertex& vertex, const std::vector& tracks, const bool isMainVertex = false); + void CleanTracks(KFPTrackVector& tracks, std::vector& isUsed, const int nUsed); + void CleanPileupTracks(KFPTrackVector& tracks, const std::vector& vertices, std::vector>& verticesTracks, + int& nPV, int& nPileup, std::vector& isPileup, std::vector& pileupPv); + + bool FitPV(KFVertex& pv, bool isFirstSeed, const KFPTrackVector& tracks, + std::vector& pvTrackIndices, std::vector& isUsed); + template + void FindPileup(const KFPTrackVector& tracks, const KFVertex& beamPosition, + std::vector& vertices, std::vector>& vertexTracks, const float X = 4.f, const float dX = 0.5f); + bool FindFixedTargetPV(StPicoDst* picoDst, KFVertex& pv, std::vector& pileupPv, std::vector& isPileup); + + KFParticleTopoReconstructor* fKFParticleTopoReconstructor; + std::vector fParticles; +#ifdef __kfpAtFirstHit__ + std::vector fParticlesAtLastHit; +#endif + std::vector fParticlesPdg; + std::vector fNHftHits; + + KFParticle fBeamSpot; + + //histograms + bool fCollectTrackHistograms; + bool fCollectPIDHistograms; + bool fCollectPVHistograms; + //0 - N HFT hits in track, 1 - PV error distribution, 2 - NPrimTracks/NAllTracks + TH1F* fTrackHistograms[3]; + // 0 - dEdX, 1 - dEdX positive tracks, 2 - dEdX negative tracks, 3 - dEdX tracks with ToF, 4 - ToF PID, 5 - PV errors vs N tracks, 6 - PV errors vs N PV tracks, 7 - N secondary vs N prim, 8 - M2 vs dEdx, 9 - dEdX with EToF, 10 - EToF PID + TH2F* fTrackHistograms2D[11]; + + + TH1F* fPVHistograms[11]; + TH2F* fPVHistograms2D[4]; + + //PID histograms + static const int NTrackHistoFolders = 26; + TH2F* fHistodEdXTracks[NTrackHistoFolders]; + TH2F* fHistodEdXwithToFTracks[NTrackHistoFolders]; + TH2F* fHistoTofPIDTracks[NTrackHistoFolders]; + TH1F* fHistoMomentumTracks[NTrackHistoFolders]; + TH2F* fHistodEdXPull[NTrackHistoFolders]; + TH2F* fHistodEdXZ[NTrackHistoFolders]; + std::map fTrackPdgToHistoIndex; + + //PID information with respect to the trackID + std::vector fTrackPidTof[3]; + std::vector fTrackPidTpc[3]; + + //PID cuts + bool fStrictTofPID; + bool fCleanKaonsWitTof; + bool fUseETof; + int fdEdXMode; + //trigger cuts + bool fTriggerMode; + //KF Particle Finder cuts + float fChiPrimaryCut; + float fChiPrimaryCutFragments; + float fChiPrimaryMaxCut; + static StKFParticleInterface* fgStKFParticleInterface; + //Event cuts + bool fCleanLowPVTrackEvents; + bool fUseHFTTracksOnly; + ClassDef(StKFParticleInterface,1) +}; + +#endif //#ifndef StKFParticleInterface_H diff --git a/StRoot/StKFParticleAnalysisMaker/StKFParticlePerformanceInterface.cxx b/StRoot/StKFParticleAnalysisMaker/StKFParticlePerformanceInterface.cxx new file mode 100644 index 00000000000..c7a21094494 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StKFParticlePerformanceInterface.cxx @@ -0,0 +1,132 @@ +#include "StKFParticlePerformanceInterface.h" + +#include "KFParticleTopoReconstructor.h" +#include "KFTopoPerformance.h" + +#include "TFile.h" +#include "TDirectory.h" + +ClassImp(StKFParticlePerformanceInterface) + +StKFParticlePerformanceInterface::StKFParticlePerformanceInterface(const KFParticleTopoReconstructor* tr, bool storeMCHistograms, bool produce3DEfficiencyFile, TString outFileName): + fOutFileName(outFileName), fOutFile(0), fEfffileName("Efficiency.txt"),fKFTopoPerformance(0), fMCTracks(0), fMCIndexes(0) +{ + fKFTopoPerformance = new KFTopoPerformance(); + fKFTopoPerformance->SetTopoReconstructor(tr); + + TFile* curFile = TFile::CurrentFile(); + TDirectory* curDirectory = TDirectory::CurrentDirectory(); + if (fOutFileName == "") fOutFileName = "StKFParticleFinderQA.root"; + if(! curFile) fOutFile = new TFile(fOutFileName.Data(),"RECREATE"); + TDirectory *dir = TDirectory::CurrentDirectory(); + if(!storeMCHistograms) + fKFTopoPerformance->DoNotStoreMCHistograms(); + if(storeMCHistograms && produce3DEfficiencyFile) { + fKFTopoPerformance->DoNotStorePrimSecHistograms(); + fKFTopoPerformance->DoNotStoreZRHistograms(); + fKFTopoPerformance->Store3DEfficiency(); + } + fKFTopoPerformance->CreateHistos("",dir,tr->GetKFParticleFinder()->GetReconstructionList()); + + TFile::CurrentFile() = curFile; + TDirectory::CurrentDirectory() = curDirectory; +} + +StKFParticlePerformanceInterface::~StKFParticlePerformanceInterface() +{ + if(fKFTopoPerformance) + { +#if 1 + TDirectory *curr = TDirectory::CurrentDirectory(); + TFile *currentFile = TFile::CurrentFile(); + if (currentFile && currentFile->IsWritable()) { + fOutFile->cd(); + if (fKFTopoPerformance->GetHistosDirectory()) { + WriteHistosCurFile(fKFTopoPerformance->GetHistosDirectory()); + } + if(!(fOutFileName == "")) + { + fOutFile->Close(); + fOutFile->Delete(); + } + } + TFile::CurrentFile() = currentFile; + TDirectory::CurrentDirectory() = curr; +#else + if (fOutFile && fOutFile->IsWritable()) fOutFile->Write(); +#endif + + std::fstream eff(fEfffileName.Data(),std::fstream::out); + eff << fKFTopoPerformance->fParteff; + eff.close(); + } + SafeDelete(fKFTopoPerformance); +} + +void StKFParticlePerformanceInterface::PerformanceAnalysis() +{ + if ( fKFTopoPerformance ) + { + fKFTopoPerformance->SetMCTracks(fMCTracks); + fKFTopoPerformance->SetTrackMatch(fMCIndexes); + + fKFTopoPerformance->CheckMCTracks(); + fKFTopoPerformance->MatchTracks(); + fKFTopoPerformance->FillHistos(); + } +} +#if 1 +void StKFParticlePerformanceInterface::WriteHistosCurFile( TObject *obj ){ + + if( !obj->IsFolder() ) obj->Write(); + else{ + TDirectory *cur = TDirectory::CurrentDirectory(); + TFile *currentFile = TFile::CurrentFile(); + + TDirectory *sub = cur->GetDirectory(obj->GetName()); + sub->cd(); + TList *listSub = (static_cast(obj))->GetList(); + TIter it(listSub); + while( TObject *obj1=it() ) WriteHistosCurFile(obj1); + cur->cd(); + TFile::CurrentFile() = currentFile; + TDirectory::CurrentDirectory() = cur; + } +} +#endif +void StKFParticlePerformanceInterface::SetPrintEffFrequency(Int_t n) +{ + fKFTopoPerformance->SetPrintEffFrequency(n); +} + +void StKFParticlePerformanceInterface::SetCentralityBin(const int iBin) +{ + fKFTopoPerformance->SetCentralityBin(iBin); +} + +void StKFParticlePerformanceInterface::SetCentralityWeight(const float weight) +{ + fKFTopoPerformance->SetCentralityWeight(weight); +} + +int StKFParticlePerformanceInterface::GetNReconstructedParticles() +{ + return fKFTopoPerformance->GetTopoReconstructor()->GetParticles().size(); +} + +bool StKFParticlePerformanceInterface::GetParticle(KFParticle& particle, const int iParticle) +{ + if(iParticle<0 || iParticle>=int(fKFTopoPerformance->GetTopoReconstructor()->GetParticles().size())) + { + std::cout << "Error!!! StKFParticlePerformanceInterface::GetParticle() iParticle " << iParticle << " size " << GetNReconstructedParticles() << std::endl; + return 0; + } + particle = fKFTopoPerformance->GetTopoReconstructor()->GetParticles()[iParticle]; + bool isMatched = fKFTopoPerformance->ParticlesMatch()[iParticle].IsMatchedWithPdg(); + return isMatched; +} + +void StKFParticlePerformanceInterface::Set3DEfficiency(TString fileName) +{ + fKFTopoPerformance->Set3DEfficiency(fileName); +} diff --git a/StRoot/StKFParticleAnalysisMaker/StKFParticlePerformanceInterface.h b/StRoot/StKFParticleAnalysisMaker/StKFParticlePerformanceInterface.h new file mode 100644 index 00000000000..cdeaea1afe8 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/StKFParticlePerformanceInterface.h @@ -0,0 +1,52 @@ +#ifndef StKFParticlePerformanceInterface_H +#define StKFParticlePerformanceInterface_H + +#include "KFMCTrack.h" + +#include "TObject.h" +#include "TString.h" + +#include + +class KFTopoPerformance; +class KFParticleTopoReconstructor; +class KFParticle; +class TFile; + +class StKFParticlePerformanceInterface: public TObject +{ + public: + StKFParticlePerformanceInterface(const KFParticleTopoReconstructor* tr, bool storeMCHistograms = true, bool produce3DEfficiencyFile = false, TString outFileName=""); + ~StKFParticlePerformanceInterface(); + + void PerformanceAnalysis(); + + void SetMCTracks(std::vector& mcTracks) { fMCTracks = mcTracks; } + void SetMCIndexes(std::vector& mcIndex) { fMCIndexes = mcIndex;} + + void SetEffFileName(const TString& name) { fEfffileName = name; } + void SetPrintEffFrequency(Int_t n = 100); + void SetCentralityBin(const int iBin); + void SetCentralityWeight(const float weight); + + int GetNReconstructedParticles(); + bool GetParticle(KFParticle& particle, const int iParticle); + + void Set3DEfficiency(TString fileName); + private: +#if 1 + void WriteHistosCurFile( TObject *obj ); +#endif + //output file with histograms + TString fOutFileName; + TFile* fOutFile; + TString fEfffileName; + + KFTopoPerformance* fKFTopoPerformance; + std::vector fMCTracks; + std::vector fMCIndexes; + + ClassDef(StKFParticlePerformanceInterface,1) +}; + +#endif //#ifndef StKFParticlePerformanceInterface_H diff --git a/StRoot/StKFParticleAnalysisMaker/femtoAnalysis.C b/StRoot/StKFParticleAnalysisMaker/femtoAnalysis.C new file mode 100644 index 00000000000..c0fd932e4d8 --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/femtoAnalysis.C @@ -0,0 +1,111 @@ +/* + FPE_OFF + root.exe -q -b -x femtoAnalysis.C +*/ +void femtoAnalysis(Int_t N = 1000000, + const Char_t *input = "/gpfs01/star/pwg_tasks/tfg02/2021/RF/TFG21c.B/7p7GeV_2021/031/22031042/hlt_22031042_10_01_000.picoDst.root", + const Char_t *output = "femto.root", + int year = 2016, + TString flowFileList = "", + bool isPico = true) // list of files with centrality and reaction plane, files should be separated with ";" +{ +#if !defined(__CINT__) + std::cout << "This code cannot be compiled" << std::endl; +#else + // gSystem->SetFPEMask(kInvalid | kDivByZero | kOverflow ); + gROOT->LoadMacro("lMuDst.C"); + lMuDst(-1,input,"RpicoDst,mysql,kfpAna,quiet,nodefault",output); + + + std::cout << "KFParticleAnalysis: running analysis for the year " << year << "." << std::endl; + StKFParticleAnalysisMaker* kfpAnalysis = (StKFParticleAnalysisMaker*) StMaker::GetTopChain()->Maker("KFParticleAnalysis"); + kfpAnalysis->AnalyseDsPhiPi(); +// kfpAnalysis->CollectPIDHistograms(); +// kfpAnalysis->CollectTrackHistograms(); + + kfpAnalysis->AddDecayToReconstructionList( 310); + kfpAnalysis->AddDecayToReconstructionList( 100321); + kfpAnalysis->AddDecayToReconstructionList(-100321); + kfpAnalysis->AddDecayToReconstructionList( 200321); + kfpAnalysis->AddDecayToReconstructionList(-200321); + kfpAnalysis->AddDecayToReconstructionList( 3122); + kfpAnalysis->AddDecayToReconstructionList(-3122); + kfpAnalysis->AddDecayToReconstructionList( 3312); + kfpAnalysis->AddDecayToReconstructionList(-3312); + kfpAnalysis->AddDecayToReconstructionList( 3334); + kfpAnalysis->AddDecayToReconstructionList(-3334); + + kfpAnalysis->AddDecayToReconstructionList( 22); + kfpAnalysis->AddDecayToReconstructionList( 111); + kfpAnalysis->AddDecayToReconstructionList( 333); +// kfpAnalysis->AddDecayToReconstructionList( 313); +// kfpAnalysis->AddDecayToReconstructionList( -313); +// kfpAnalysis->AddDecayToReconstructionList( 323); +// kfpAnalysis->AddDecayToReconstructionList( -323); + kfpAnalysis->AddDecayToReconstructionList( 3324); + kfpAnalysis->AddDecayToReconstructionList(-3324); + + kfpAnalysis->AddDecayToReconstructionList( 3000); + kfpAnalysis->AddDecayToReconstructionList( 3001); + kfpAnalysis->AddDecayToReconstructionList( 3003); + kfpAnalysis->AddDecayToReconstructionList( 3103); + kfpAnalysis->AddDecayToReconstructionList( 3004); + kfpAnalysis->AddDecayToReconstructionList( 3005); + kfpAnalysis->AddDecayToReconstructionList( 3006); + kfpAnalysis->AddDecayToReconstructionList( 3007); + kfpAnalysis->AddDecayToReconstructionList( 3012); + kfpAnalysis->AddDecayToReconstructionList( 3013); + + kfpAnalysis->AddDecayToReconstructionList( 1003004); + kfpAnalysis->AddDecayToReconstructionList( 1003005); + kfpAnalysis->AddDecayToReconstructionList( 1003006); + kfpAnalysis->AddDecayToReconstructionList( 1003007); + + chain->Init(); + + if(isPico) + { + StKFParticleInterface::instance()->CleanLowPVTrackEvents(); +// StKFParticleInterface::instance()->UseHFTTracksOnly(); + } + + StKFParticleInterface::instance()->SetSoftKaonPIDMode(); + StKFParticleInterface::instance()->SetSoftTofPidMode(); + + +// StKFParticleInterface::instance()->SetChiPrimaryMaxCut(5.e3); + StKFParticleInterface::instance()->SetChiPrimaryCut(18.f); + StKFParticleInterface::instance()->SetChiPrimaryCutFragments(8.f); + + StKFParticleInterface::instance()->SetMaxDistanceBetweenParticlesCut(1); +// StKFParticleInterface::instance()->SetLCut(0.3f); + StKFParticleInterface::instance()->SetLCut(0.f); + + StKFParticleInterface::instance()->SetChiPrimaryCut2D(0); + StKFParticleInterface::instance()->SetChi2Cut2D(3); + StKFParticleInterface::instance()->SetLdLCut2D(5); + + StKFParticleInterface::instance()->SetChi2CutXiOmega(3); + StKFParticleInterface::instance()->SetChi2TopoCutXiOmega(3); + StKFParticleInterface::instance()->SetLdLCutXiOmega(5); + + StKFParticleInterface::instance()->SetChi2CutCharmManybodyDecays(3); + StKFParticleInterface::instance()->SetChi2TopoCutCharmManybodyDecays(3); + StKFParticleInterface::instance()->SetLdLCutCharmManybodyDecays(5); + + StPicoDstMaker* maker = (StPicoDstMaker *) StMaker::GetTopChain()->Maker("PicoDst"); + if (! maker) return; + maker->SetStatus("*",1); + TChain *tree = maker->chain(); + Long64_t nentries = tree->GetEntries(); + if (nentries <= 0) return; + Long64_t nevent = N; + nevent = TMath::Min(nevent,nentries); + cout << nentries << " events in chain " << nevent << " will be read." << endl; + TString Y("y"); Y += year; + new StGoodTrigger(Y); + chain->SetAttr(".Privilege",1,"StPicoDstMaker::*") + chain->EventLoop(nevent); +#endif + +} diff --git a/StRoot/StKFParticleAnalysisMaker/femtoDst.C b/StRoot/StKFParticleAnalysisMaker/femtoDst.C new file mode 100644 index 00000000000..7c16f4600ac --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/femtoDst.C @@ -0,0 +1,61 @@ +/* + FPE_OFF + root.exe -q -b -x femtoDst.C +*/ +void femtoDst(Int_t N = 10000000, const Char_t *input = "/net/l404/data/fisyak/Pico/2016/125/17125034/st_physics_17125034_raw_5500079.picoDst.root", const Char_t *output = "") { +#if !defined(__CINT__) + std::cout << "This code cannot be compiled" << std::endl; +#else + // gSystem->SetFPEMask(kInvalid | kDivByZero | kOverflow ); + gROOT->LoadMacro("lMuDst.C"); + lMuDst(0,input,"ry2016,RpicoDst,FemtoDst,mysql,nodefault,quiet",0,output); + StKFParticleInterface::instance()->SetTriggerMode(); + StKFParticleInterface::instance()->SetSoftKaonPIDMode(); + StKFParticleInterface::instance()->SetSoftTofPidMode(); + StKFParticleInterface::instance()->SetChiPrimaryCut(8); + + StKFParticleInterface::instance()->SetPtCutCharm(0.5); + StKFParticleInterface::instance()->SetChiPrimaryCutCharm(8); + StKFParticleInterface::instance()->SetLdLCutCharmManybodyDecays(3); + StKFParticleInterface::instance()->SetChi2TopoCutCharmManybodyDecays(10); + StKFParticleInterface::instance()->SetChi2CutCharmManybodyDecays(3); + StKFParticleInterface::instance()->SetLdLCutCharm2D(3); + StKFParticleInterface::instance()->SetChi2TopoCutCharm2D(10); + StKFParticleInterface::instance()->SetChi2CutCharm2D(3); + + StKFParticleInterface::instance()->AddDecayToReconstructionList( 421); + StKFParticleInterface::instance()->AddDecayToReconstructionList( -421); + StKFParticleInterface::instance()->AddDecayToReconstructionList( 426); + StKFParticleInterface::instance()->AddDecayToReconstructionList( 429); + StKFParticleInterface::instance()->AddDecayToReconstructionList( -429); + StKFParticleInterface::instance()->AddDecayToReconstructionList( 411); + StKFParticleInterface::instance()->AddDecayToReconstructionList( -411); + StKFParticleInterface::instance()->AddDecayToReconstructionList( 431); + StKFParticleInterface::instance()->AddDecayToReconstructionList( -431); + StKFParticleInterface::instance()->AddDecayToReconstructionList( 4122); + StKFParticleInterface::instance()->AddDecayToReconstructionList(-4122); + maker = (StPicoDstMaker *) StMaker::GetTopChain()->Maker("PicoDst"); + if (! maker) return; + maker->SetStatus("*",1); + TChain *tree = maker->chain(); + Long64_t nentries = tree->GetEntries(); + if (nentries <= 0) return; + Long64_t nevent = N; + nevent = TMath::Min(nevent,nentries); + cout << nentries << " events in chain " << nevent << " will be read." << endl; + // TTree::SetMaxTreeSize(1000000000); // 1.0GB + ((StBFChain *) StMaker::GetTopChain())->EventLoop(nevent); +#endif + +} +/* + 368257423 Nov 22 22:40 /net/l404/data/fisyak/Pico/2016/125/17125034/st_physics_17125034_raw_5500079.picoDst.root + SetChiPrimaryCut(8) 48219329 Feb 5 14:52 st_physics_17125034_raw_5500079.femtoDst.root.8 => 7.64 + SetChiPrimaryCut(10) 36044394 Feb 5 15:14 st_physics_17125034_raw_5500079.femtoDst.root.10 => 10.22 + SetChiPrimaryCut(12) 27451026 Feb 5 15:19 st_physics_17125034_raw_5500079.femtoDst.root => 13.4 + SetChiPrimaryCut(8) 48196298 Feb 6 12:41 st_physics_17125034_raw_5500079.femtoDst.root.8.1e4 => 7.64 +chiMax < 1e4 + SetChiPrimaryCut(8) 31186265 Feb 6 15:32 st_physics_17125034_raw_5500079.femtoDst.root => 11.81 +chiMax < 1e4 + SetChiPrimaryCut(10) 23326256 Feb 6 15:43 st_physics_17125034_raw_5500079.femtoDst.root => 15.78 + */ diff --git a/StRoot/StKFParticleAnalysisMaker/kfpAnalysis.C b/StRoot/StKFParticleAnalysisMaker/kfpAnalysis.C new file mode 100644 index 00000000000..6b4a43cb65c --- /dev/null +++ b/StRoot/StKFParticleAnalysisMaker/kfpAnalysis.C @@ -0,0 +1,239 @@ +/* + FPE_OFF + root.exe -q -b -x kfpAnalysis.C +*/ +class StGoodTrigger; +//void kfpAnalysis(Int_t N = 1000000, const Char_t *input = "/net/l404/data/fisyak/Pico/2016/125/17125034/st_physics_17125034_raw_5500079.picoDst.root", const Char_t *output = "picoAna.root", const Char_t *triggerSet = "y2016") { +//void kfpAnalysis(Int_t N = 1000000, const Char_t *input = "st_physics_adc_17125034_raw_1000007.femtoDst.root", const Char_t *output = "picoAna.root", const Char_t *triggerSet = "y2016") { +//void kfpAnalysis(Int_t N = 1000000, const Char_t *input = "/star/data01/pwg_tasks/picoDs/*picoDst.root", const Char_t *output = "picoAna.root", const Char_t *triggerSet = "y2011") { +//void kfpAnalysis(Int_t N = 1000000, const Char_t *input = "./st_mtd_19110005_raw_3500041.picoDst.root", const Char_t *output = "picoAna.root", const Char_t *triggerSet = "y2018") { +//void kfpAnalysis(Int_t N = 100000, const Char_t *input = "/gpfs01/star/pwg_tasks/tfg02/2010/11GeV/*picoDst.root", const Char_t *output = "picoAna2011AuAu11.root", const Char_t *triggerSet = "y2011") { +//void kfpAnalysis(Int_t N = 10000000, const Char_t *input = "/net/l401/data/scratch1/reco/2020/TFG19m/RF/11p5GeV/*picoDst.root", const Char_t *output = "picoAna2020AuAu11p5GeV.root", const Char_t *triggerSet = "y2020") { +//void kfpAnalysis(Int_t N = 1000, const Char_t *input = "/gpfs01/star/pwg_tasks/tfg02/2010/11GeV/st_physics_11148001_raw_1010001.picoDst.root", const Char_t *output = "picoAna2011AuAu11.root", const Char_t *triggerSet = "y2011") { +//void kfpAnalysis(Int_t N = 1000, const Char_t *input = "/gpfs01/star/pwg/fisyak/Pico/2010AuAu11/11148001.picoDst.root", const Char_t *output = "picoAna2011AuAu11.root", const Char_t *triggerSet = "y2011") { +//void kfpAnalysis(Int_t N = 10000000, const Char_t *input = "/net/l401/data/scratch1/reco/2020/TFG19m/RF/11p5GeV.B/347/20347034/hlt_20347034_13_02_000.picoDst.root", const Char_t *output = "Ana2020AuAu11p5GeV.root", const Char_t *triggerSet = "y2020", Bool_t idNdx = kFALSE) { +//void kfpAnalysis(Int_t N = 10000000, const Char_t *input = "./*.picoDst.root", const Char_t *output = "Ana.root", const Char_t *triggerSet = "y2022", Bool_t idNdx = kFALSE) { +void kfpAnalysis(Int_t N = 10000000, + // const Char_t *input = "/star/data102/reco/production_OO_200GeV_2021/ReversedFullField/P23ib/2021/136/22136010/st_physics_22136010_raw_1500002.picoDst.root", + const Char_t *input = "*.picoDst.root", + const Char_t *output = "Ana.root", const Char_t *triggerSet = "y2019", Bool_t idNdx = kFALSE) { +#if !defined(__CINT__) + std::cout << "This code cannot be compiled" << std::endl; +#else + // gSystem->SetFPEMask(kInvalid | kDivByZero | kOverflow ); + Bool_t isPico = kTRUE; + if (TString(input).Contains("MuDst")) isPico = kFALSE; + gROOT->LoadMacro("lMuDst.C"); + TString Chain("r"); + Chain += triggerSet; + // if (! isPico) Chain += ",RMuDst"; + if (! isPico) {Chain += ",RMuDst";} //,PicoWrite"; isPico = kTRUE;} + else {Chain += ",RpicoDst";} + Chain += ",kfpAna,mysql,detDb,nodefault,LdEdxY2,quiet,MuDST"; + // lMuDst(0,input,"ry2016,RpicoDst,mysql,PicoAnalysis,quiet,nodefault",output); + lMuDst(-1,input,Chain,output); +//________________________________________________________________________________ +// from /gpfs01/star/pwg/mzyzak/2019_2_2/Template/femtoAnalysis.C +// StKFParticleInterface::instance()->SetChiPrimaryCut(10); +// StKFParticleInterface::instance()->SetPtCutCharm(0.7); +// StKFParticleInterface::instance()->SetChi2TopoCutCharmManybodyDecays(2); +// StKFParticleInterface::instance()->SetSoftKaonPIDMode(); +// StKFParticleInterface::instance()->SetSoftTofPidMode(); + std::cout << "KFParticleAnalysis: running analysis for triggerSet " << triggerSet << "." << std::endl; + StKFParticleAnalysisMaker* kfpAnalysis = (StKFParticleAnalysisMaker*) StMaker::GetTopChain()->Maker("KFParticleAnalysis"); + if (! isPico) kfpAnalysis->ProcessSignal(); // requires MC info + kfpAnalysis->AnalyseDsPhiPi(); + kfpAnalysis->CollectPIDHistograms(); + kfpAnalysis->CollectPVHistograms(); + kfpAnalysis->CollectTrackHistograms(); + + kfpAnalysis->AddDecayToReconstructionList( 310); // K0 + // kfpAnalysis->AddDecayToReconstructionList( 100321); // K -> 3pi + // kfpAnalysis->AddDecayToReconstructionList(-100321); + // kfpAnalysis->AddDecayToReconstructionList( 200321); // K+3piK + // kfpAnalysis->AddDecayToReconstructionList(-200321); + kfpAnalysis->AddDecayToReconstructionList( 3122); // Lambda + kfpAnalysis->AddDecayToReconstructionList(-3122); // Lambda_bar + kfpAnalysis->AddDecayToReconstructionList( 3312); // Xi- + kfpAnalysis->AddDecayToReconstructionList(-3312); // Xi+ + kfpAnalysis->AddDecayToReconstructionList( 3334); // Omega- + kfpAnalysis->AddDecayToReconstructionList(-3334); // Omega+ + + kfpAnalysis->AddDecayToReconstructionList( 22); // gamma + kfpAnalysis->AddDecayToReconstructionList( 111); // pi0 + kfpAnalysis->AddDecayToReconstructionList( 333); // phi +#if 0 + // + kfpAnalysis->AddDecayToReconstructionList( 113); // rho + kfpAnalysis->AddDecayToReconstructionList( 313); // K*0 + kfpAnalysis->AddDecayToReconstructionList(-313); // K*0_bar + kfpAnalysis->AddDecayToReconstructionList( 323); // K*+ + kfpAnalysis->AddDecayToReconstructionList(-323); // K*- + + kfpAnalysis->AddDecayToReconstructionList( 3212); // Sigma0 + kfpAnalysis->AddDecayToReconstructionList( 3124); // Lambda* + kfpAnalysis->AddDecayToReconstructionList( 3124); // Lambda* + kfpAnalysis->AddDecayToReconstructionList( 3224); // Sigma*+ + kfpAnalysis->AddDecayToReconstructionList( 3114); // Sigma*- + kfpAnalysis->AddDecayToReconstructionList( 3324); // Xi*0 + kfpAnalysis->AddDecayToReconstructionList(-3324); // Xi*0 +#endif +// Hyoer Nuclears + kfpAnalysis->AddDecayToReconstructionList( 3004); // H3L + kfpAnalysis->AddDecayToReconstructionList( 3005); // H4L + kfpAnalysis->AddDecayToReconstructionList( 3006); // He4L + kfpAnalysis->AddDecayToReconstructionList( 3007); // He5L +#if 0 + kfpAnalysis->AddDecayToReconstructionList( 3000); // LL + kfpAnalysis->AddDecayToReconstructionList( 3001); // Lppi + kfpAnalysis->AddDecayToReconstructionList( 3003); // Ln + // kfpAnalysis->AddDecayToReconstructionList(-3003); // Ln_bar + kfpAnalysis->AddDecayToReconstructionList( 3103); // Lnn + kfpAnalysis->AddDecayToReconstructionList( 3203); // LLn + kfpAnalysis->AddDecayToReconstructionList( 3008); // H4LL + kfpAnalysis->AddDecayToReconstructionList( 3009); // H4LL + + kfpAnalysis->AddDecayToReconstructionList( 3012); // H3L_{dppi} + kfpAnalysis->AddDecayToReconstructionList( 3013); // H4L_{tppi} +#endif + +#if 0 + kfpAnalysis->AddDecayToReconstructionList( 9001); // pi+pi+ + kfpAnalysis->AddDecayToReconstructionList(-9001); // pi-pi- + kfpAnalysis->AddDecayToReconstructionList( 9002); // pi+K+ + kfpAnalysis->AddDecayToReconstructionList(-9002); // pi-K- + kfpAnalysis->AddDecayToReconstructionList( 9003); // K+K+ + kfpAnalysis->AddDecayToReconstructionList(-9003); // K-K- + kfpAnalysis->AddDecayToReconstructionList( 9004); // pK+ + kfpAnalysis->AddDecayToReconstructionList(-9004); // p-K- + kfpAnalysis->AddDecayToReconstructionList( 1003004); // H3L* + kfpAnalysis->AddDecayToReconstructionList( 1003005); // H4L* + kfpAnalysis->AddDecayToReconstructionList( 1003006); // He4L* + kfpAnalysis->AddDecayToReconstructionList( 1003007); // He5L* +#endif + + StMaker *dbMk = chain->GetMaker("db"); + if (dbMk) { + dbMk->SetDebug(1); + } + chain->Init(); +#if 0 + // StKFParticleInterface::instance()->SetUsedx2(kTRUE); // old dE/dx calibration before SL + // if(isPico) + // { + if (triggerSet != "y2022") { + StKFParticleInterface::instance()->CleanLowPVTrackEvents(); + StMuDst::SetMaxTrackDca(10.0); // dEdxW24 for pp510GeV_2022 + } + // StKFParticleInterface::instance()->UseHFTTracksOnly(); + //} + + StKFParticleInterface::instance()->SetSoftKaonPIDMode(); + StKFParticleInterface::instance()->SetSoftTofPidMode(); + +// StKFParticleInterface::instance()->SetChiPrimaryMaxCut(5.e3); +// StKFParticleInterface::instance()->SetChiPrimaryCut(12); + StKFParticleInterface::instance()->SetChiPrimaryCut(18.f); + StKFParticleInterface::instance()->SetChiPrimaryCutFragments(8.f); + + StKFParticleInterface::instance()->SetMaxDistanceBetweenParticlesCut(1); + StKFParticleInterface::instance()->SetLCut(0.f); + + // StKFParticleInterface::instance()->SetChiPrimaryCut2D(8); + StKFParticleInterface::instance()->SetChiPrimaryCut2D(0); + StKFParticleInterface::instance()->SetChi2Cut2D(3); + StKFParticleInterface::instance()->SetLdLCut2D(5); + + StKFParticleInterface::instance()->SetChi2CutXiOmega(3); + StKFParticleInterface::instance()->SetChi2TopoCutXiOmega(3); + StKFParticleInterface::instance()->SetLdLCutXiOmega(5); + + StKFParticleInterface::instance()->SetChi2CutCharmManybodyDecays(3); + StKFParticleInterface::instance()->SetChi2TopoCutCharmManybodyDecays(3); + StKFParticleInterface::instance()->SetLdLCutCharmManybodyDecays(5); +#else /* Maksym /gpfs01/star/pwg/mzyzak/kaons/Template/femtoAnalysis.C Oct 27 2024 */ + if(isPico) + { + StKFParticleInterface::instance()->CleanLowPVTrackEvents(); +// StKFParticleInterface::instance()->UseHFTTracksOnly(); + } + + StKFParticleInterface::instance()->SetSoftKaonPIDMode(); + StKFParticleInterface::instance()->SetSoftTofPidMode(); + + +// StKFParticleInterface::instance()->SetChiPrimaryMaxCut(5.e3); + StKFParticleInterface::instance()->SetChiPrimaryCut(18.f); + // StKFParticleInterface::instance()->SetChiPrimaryCutFragments(0.f); // TODO + StKFParticleInterface::instance()->SetChiPrimaryCutFragments(18.f); // TODO + // StKFParticleInterface::instance()->SetSecondaryCuts(3.f, 5.f, 0.f); // TODO + + StKFParticleInterface::instance()->SetMaxDistanceBetweenParticlesCut(1); + StKFParticleInterface::instance()->SetLCut(0.f); + + StKFParticleInterface::instance()->SetChiPrimaryCut2D(0); + StKFParticleInterface::instance()->SetChi2Cut2D(3); + StKFParticleInterface::instance()->SetLdLCut2D(5.f); // TODO + // StKFParticleInterface::instance()->SetLdLCut2D(0); // TODO + + StKFParticleInterface::instance()->SetChi2CutXiOmega(3); + StKFParticleInterface::instance()->SetChi2TopoCutXiOmega(3); + StKFParticleInterface::instance()->SetLdLCutXiOmega(5); + + StKFParticleInterface::instance()->SetChi2CutCharmManybodyDecays(3); + StKFParticleInterface::instance()->SetChi2TopoCutCharmManybodyDecays(3); + StKFParticleInterface::instance()->SetLdLCutCharmManybodyDecays(5); + + StKFParticleInterface::instance()->SetBeamSpot("2020_5AGeV"); + // StKFParticleInterface::instance()->SetBeamSpot(); +#endif + +// StKFParticleInterface::instance()->SetSecondaryCuts(3, 3, 5); +//________________________________________________________________________________ + + if (idNdx) { + cout << "StKFParticleInterface::instance()->SetdEdXType(2); // dNdx" << endl; + StKFParticleInterface::instance()->SetdEdXType(2); // dNdx + } + TTree *tree = 0; + if (! isPico) { + StKFParticleAnalysisMaker *ana = ( StKFParticleAnalysisMaker *) chain->Maker("KFParticleAnalysis"); + if (! ana) return; + ana->AnalyseMuDst(); + StMuDstMaker * MuMk = (StMuDstMaker *) StMaker::GetTopChain()->Maker("MuDst"); + if (! MuMk) return; + MuMk->SetStatus("*",1); + tree = MuMk->chain(); + // enum PicoVtxMode {NotSet=0, Default=1, Vpd=2, VpdOrDefault=3, Mtd=4, FXT=5}; + StMuDst::setVtxMode(3); // 2019 AuAu 19GeV + StMuDst::SetVxXYrange(-0.4,0.4, -0.6, 0.0); + StMuDst::SetVxZrange(-150.,150.); + } else { + StPicoDstMaker * picoMk = (StPicoDstMaker *) StMaker::GetTopChain()->Maker("PicoDst"); + if (! picoMk) return; + picoMk->SetStatus("*",1); + tree = picoMk->chain(); + } + if (! tree ) { + cout << "No MuDst/PicoDst tree. Exit." << endl; + return; + } + Long64_t nentries = tree->GetEntries(); + cout << "no. events in tree. " <SetAttr(".Privilege",1,"StPicoDstMaker::*"); + chain->EventLoop(nevent); +#endif + +} diff --git a/StRoot/StMuDSTMaker/COMMON/StMuDst.cxx b/StRoot/StMuDSTMaker/COMMON/StMuDst.cxx index 2849cf2e86c..c10af459dfb 100644 --- a/StRoot/StMuDSTMaker/COMMON/StMuDst.cxx +++ b/StRoot/StMuDSTMaker/COMMON/StMuDst.cxx @@ -95,10 +95,11 @@ TClonesArray** StMuDst::eztArrays = 0; Int_t StMuDst::mCurrVertexId = -2; TObjArray* StMuDst::mCurrPrimaryTracks = 0; +StMuDst *StMuDst::fgMuDst = 0; StMuDst::StMuDst() { DEBUGMESSAGE(""); - /* no-op */ + fgMuDst = this; } //----------------------------------------------------------------------- diff --git a/StRoot/StMuDSTMaker/COMMON/StMuDst.h b/StRoot/StMuDSTMaker/COMMON/StMuDst.h index 5ea0c335326..1b730c4e0d3 100644 --- a/StRoot/StMuDSTMaker/COMMON/StMuDst.h +++ b/StRoot/StMuDSTMaker/COMMON/StMuDst.h @@ -171,6 +171,8 @@ class StMuDst : public TObject { void fixTofTrackIndices(); void fixETofTrackIndices(); void fixMtdTrackIndices(); + static StMuDst *instance() {return fgMuDst;} + void SetInstance() {fgMuDst = this;} void setMtdArray(StMtdCollection *mtd_coll); @@ -181,6 +183,7 @@ class StMuDst : public TObject { protected: + static StMuDst *fgMuDst; //! /// array of TClonesArrays static TClonesArray** arrays; #ifndef __NO_STRANGE_MUDST__ diff --git a/StRoot/StPicoDstMaker/StPicoDstMaker.cxx b/StRoot/StPicoDstMaker/StPicoDstMaker.cxx index 4e114feba2a..53a25fa0e9f 100644 --- a/StRoot/StPicoDstMaker/StPicoDstMaker.cxx +++ b/StRoot/StPicoDstMaker/StPicoDstMaker.cxx @@ -106,8 +106,8 @@ #include "TH1.h" #include "TH2.h" static Int_t _debug = 0; -StPicoDstMaker *StPicoDstMaker::fgPicoDstMaker = 0; #endif /* __TFG__VERSION__ */ +StPicoDstMaker *StPicoDstMaker::fgPicoDstMaker = 0; #include "StPicoDstMaker/StPicoUtilities.h" //_________________ @@ -135,9 +135,7 @@ mBField(0), createArrays(); std::fill_n(mStatusArrays, sizeof(mStatusArrays) / sizeof(mStatusArrays[0]), 1); -#if defined (__TFG__VERSION__) fgPicoDstMaker = this; -#endif /* __TFG__VERSION__ */ } //_________________ @@ -153,9 +151,7 @@ StPicoDstMaker::~StPicoDstMaker() { delete mChain; delete mPicoDst; -#if defined (__TFG__VERSION__) fgPicoDstMaker = 0; -#endif /* __TFG__VERSION__ */ } //_________________ diff --git a/StRoot/StPicoDstMaker/StPicoDstMaker.h b/StRoot/StPicoDstMaker/StPicoDstMaker.h index e5f91085fb2..89edbfc65ce 100644 --- a/StRoot/StPicoDstMaker/StPicoDstMaker.h +++ b/StRoot/StPicoDstMaker/StPicoDstMaker.h @@ -138,6 +138,7 @@ class StPicoDstMaker : public StMaker { /// 9 is the higher compression level. void setCompression(int comp = 9); + static StPicoDstMaker *instance() { return fgPicoDstMaker; } #if defined (__TFG__VERSION__) PicoVtxMode vtxMode() { return StMuDst::instance()->vtxMode(); } void setVtxMode(const PicoVtxMode vtxMode) @@ -152,7 +153,6 @@ class StPicoDstMaker : public StMaker { void SetVxZrange(Double_t zmin = -70, Double_t zmax = 70.) { StMuDst::instance()->SetVxZrange(zmin, zmax); } void SetVxRmax(Double_t rmax = 2) { StMuDst::instance()->SetVxRmax(rmax); } - static StPicoDstMaker *instance() { return fgPicoDstMaker; } TClonesArray** picoArrays() { return mPicoArrays; } #else /* ! __TFG__VERSION__ */ @@ -339,9 +339,7 @@ class StPicoDstMaker : public StMaker { /// FMS filler StPicoFmsFiller mFmsFiller; -#if defined (__TFG__VERSION__) static StPicoDstMaker *fgPicoDstMaker; //! -#endif /// Get CVS status virtual const char *GetCVS() const { diff --git a/StRoot/StPicoEvent/StPicoDst.cxx b/StRoot/StPicoEvent/StPicoDst.cxx index 7c243deed22..3d9a769c6a7 100644 --- a/StRoot/StPicoEvent/StPicoDst.cxx +++ b/StRoot/StPicoEvent/StPicoDst.cxx @@ -24,7 +24,7 @@ #include "StPicoDst.h" //MUST be the last one TClonesArray** StPicoDst::picoArrays = 0; - +StPicoDst *StPicoDst::fgPicoDst = 0; //_________________ void StPicoDst::unset() { picoArrays = 0; diff --git a/StRoot/StPicoEvent/StPicoDst.h b/StRoot/StPicoEvent/StPicoDst.h index 7448d35b7ec..54265809815 100644 --- a/StRoot/StPicoEvent/StPicoDst.h +++ b/StRoot/StPicoEvent/StPicoDst.h @@ -41,15 +41,12 @@ class StPicoDst { public: -#if defined (__TFG__VERSION__) + /// Default constructor StPicoDst() { fgPicoDst = this;} + /// Destructor virtual ~StPicoDst() {fgPicoDst = 0;} +#if defined (__TFG__VERSION__) virtual Bool_t IsGoodTrigger() const; -#else /* ! __TFG__VERSION__ */ - /// Default constructor - StPicoDst() { /* emtpy */} - /// Destructor - ~StPicoDst() { /* empty*/ } #endif /// Set the pointers to the TClonesArrays @@ -174,18 +171,14 @@ class StPicoDst { /// Print MC track info static void printMcTracks(); -#if defined (__TFG__VERSION__) static StPicoDst *instance() {return fgPicoDst;} -#endif /* __TFG__VERSION__ */ private: /// Array of TClonesArrays static TClonesArray** picoArrays; -#if defined (__TFG__VERSION__) static StPicoDst *fgPicoDst; //! -#endif /* __TFG__VERSION__ */ }; #endif diff --git a/StRoot/StPicoEvent/StPicoTrack.cxx b/StRoot/StPicoEvent/StPicoTrack.cxx index 3024b453da8..79ab00d3d94 100644 --- a/StRoot/StPicoEvent/StPicoTrack.cxx +++ b/StRoot/StPicoEvent/StPicoTrack.cxx @@ -12,14 +12,11 @@ #include "StPicoMessMgr.h" #include "StPicoTrack.h" -#if defined (__TFG__VERSION__) #include "TF1.h" #include "St_base/StMessMgr.h" -#include "StMuDSTMaker/COMMON/StMuTrack.h" #include "StBichsel/Bichsel.h" #include "StBichsel/StdEdxModel.h" #include "StBichsel/StdEdxPull.h" -#endif /* __TFG__VERSION__ */ ClassImp(StPicoTrack) @@ -212,7 +209,6 @@ StPicoPhysicalHelix StPicoTrack::helix(Float_t const B) const { static_cast( charge() ) ); } -#if defined (__TFG__VERSION__) //_________________ Float_t StPicoTrack::dEdxPull(Float_t mass, UChar_t fit, Int_t charge) const { Float_t z = -999.; @@ -408,7 +404,6 @@ Float_t StPicoTrack::dEdxPullToF(Float_t mass, UChar_t fit, Int_t charge) const return z; } -#endif /* __TFG__VERSION__ */ //_________________ Float_t StPicoTrack::gDCAs(TVector3 point) const { diff --git a/StRoot/StPicoEvent/StPicoTrack.h b/StRoot/StPicoEvent/StPicoTrack.h index cb488716b0c..89b952972c9 100644 --- a/StRoot/StPicoEvent/StPicoTrack.h +++ b/StRoot/StPicoEvent/StPicoTrack.h @@ -27,9 +27,7 @@ #include "StarClassLibrary/PhysicalConstants.h" #endif -#if defined (__TFG__VERSION__) #include "StPicoTrackCovMatrix.h" -#endif /* __TFG__VERSION__ */ //_________________ class StPicoTrack : public TObject { @@ -117,14 +115,12 @@ class StPicoTrack : public TObject { /// Return dE/dx error of the track (in GeV/cm) Float_t dEdxError() const { return mDedxError; } -#if defined (__TFG__VERSION__) Float_t dEdxPull(Float_t mass, UChar_t fit = 1, Int_t charge = 1) const; Float_t dEdxPullToF(Float_t mass, UChar_t fit = 1, Int_t charge = 1) const; Float_t dEdxPullPion() const { return dEdxPull(0.13956995,1); } Float_t dEdxPullKaon() const { return dEdxPull(0.493677,1); } Float_t dEdxPullProton() const { return dEdxPull(0.93827231,1); } Float_t dEdxPullElectron() const { return dEdxPull(0.51099907e-3,1); } -#endif /// Return dN/dx of the track Float_t dNdx() const { return mDnDx; } /// Return dN/dx error of the track diff --git a/StRoot/StPicoEvent/StPicoTrackCovMatrix.cxx b/StRoot/StPicoEvent/StPicoTrackCovMatrix.cxx index 2163fc40ab3..35b2ef2ec51 100644 --- a/StRoot/StPicoEvent/StPicoTrackCovMatrix.cxx +++ b/StRoot/StPicoEvent/StPicoTrackCovMatrix.cxx @@ -67,7 +67,6 @@ Bool_t StPicoTrackCovMatrix::isBadCovMatrix() { mCorr[5]==0 && mCorr[6]==0 && mCorr[7]==0 && mCorr[8]==0 && mCorr[9]==0 ); } -#if defined (__TFG__VERSION__) //_________________ StDcaGeometry &StPicoTrackCovMatrix::dcaGeometry() const { static StDcaGeometry a; @@ -85,4 +84,3 @@ StDcaGeometry &StPicoTrackCovMatrix::dcaGeometry() const { a.set(params(), errMatrix); return *&a; } -#endif /* __TFG__VERSION__ */ diff --git a/StRoot/StPicoEvent/StPicoTrackCovMatrix.h b/StRoot/StPicoEvent/StPicoTrackCovMatrix.h index 3be256163fd..4ca1253737f 100644 --- a/StRoot/StPicoEvent/StPicoTrackCovMatrix.h +++ b/StRoot/StPicoEvent/StPicoTrackCovMatrix.h @@ -4,9 +4,7 @@ // ROOT headers #include "TObject.h" -#if defined (__TFG__VERSION__) #include "StEvent/StDcaGeometry.h" -#endif /* __TFG__VERSION__ */ //_________________ class StPicoTrackCovMatrix : public TObject { @@ -52,10 +50,8 @@ class StPicoTrackCovMatrix : public TObject { /// matrix in MuDst Bool_t isBadCovMatrix(); -#if defined (__TFG__VERSION__) /// DCA geometry StDcaGeometry &dcaGeometry() const; -#endif /* __TFG__VERSION__ */ // // Setters diff --git a/StRoot/StarRoot/KFParticle.cxx b/StRoot/StarRoot/KFParticle.cxx deleted file mode 100644 index d082882d216..00000000000 --- a/StRoot/StarRoot/KFParticle.cxx +++ /dev/null @@ -1,350 +0,0 @@ -//---------------------------------------------------------------------------- -// Implementation of 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 KFParticleCore -// -// -= Copyright © ALICE HLT Group =- -//____________________________________________________________________________ - - -#include "KFParticle.h" -#include "TDatabasePDG.h" -#include "TParticlePDG.h" -#include "MTrack.h" -#include "MVertex.h" -ClassImp(KFParticle); - -Double_t KFParticle::fgBz = -5.; //* Bz compoment of the magnetic field - -void KFParticle::Create( const Double_t Param[], const Double_t Cov[], Int_t Charge, Int_t PID ) -{ - // Constructor from "cartesian" track, PID hypothesis should be provided - // - // Param[6] = { X, Y, Z, Px, Py, Pz } - position and momentum - // Cov [21] = lower-triangular part of the covariance matrix: - // - // ( 0 . . . . . ) - // ( 1 2 . . . . ) - // Cov. matrix = ( 3 4 5 . . . ) - numbering of covariance elements in Cov[] - // ( 6 7 8 9 . . ) - // ( 10 11 12 13 14 . ) - // ( 15 16 17 18 19 20 ) - Double_t C[21]; - for( int i=0; i<21; i++ ) C[i] = Cov[i]; - - TParticlePDG* particlePDG = TDatabasePDG::Instance()->GetParticle(PID); - Double_t mass = (particlePDG) ? particlePDG->Mass() :0.13957; - - KFParticleBase::Initialize( Param, C, Charge, mass, PID ); -} - -KFParticle::KFParticle( const MTrack &track, Int_t PID ) -{ - // Constructor from ALICE track, PID hypothesis should be provided - - track.XvYvZv(fP); - track.PxPyPz(fP+3); - fQ = track.Charge(); - track.GetCovarianceXYZPxPyPz( fC ); - Create(fP,fC,fQ,PID); -} - -KFParticle::KFParticle( const MVertex &vertex ) -{ - // Constructor from ALICE vertex - - vertex.GetXYZ( fP ); - vertex.GetCovarianceMatrix( fC ); - fChi2 = vertex.GetChi2(); - fNDF = 2*vertex.GetNContributors() - 3; - fQ = 0; - fAtProductionVertex = 0; - fIsLinearized = 0; - fSFromDecay = 0; -} - -void KFParticle::GetExternalTrackParam( const KFParticleBase &p, Double_t &X, Double_t &Alpha, Double_t P[5] ) -{ - // Conversion to AliExternalTrackParam parameterization - - Double_t cosA = p.GetPx(), sinA = p.GetPy(); - Double_t pt = TMath::Sqrt(cosA*cosA + sinA*sinA); - Double_t pti = 0; - if( pt<1.e-4 ){ - cosA = 1; - sinA = 0; - } else { - pti = 1./pt; - cosA*=pti; - sinA*=pti; - } - Alpha = TMath::ATan2(sinA,cosA); - X = p.GetX()*cosA + p.GetY()*sinA; - P[0]= p.GetY()*cosA - p.GetX()*sinA; - P[1]= p.GetZ(); - P[2]= 0; - P[3]= p.GetPz()*pti; - P[4]= p.GetQ()*pti; -} - -Bool_t KFParticle::GetDistanceFromVertexXY( const Double_t vtx[], const Double_t Cv[], Double_t &val, Double_t &err ) const -{ - //* Calculate DCA distance from vertex (transverse impact parameter) in XY - //* v = [xy], Cv=[Cxx,Cxy,Cyy ]-covariance matrix - - Bool_t ret = 0; - - Double_t mP[8]; - Double_t mC[36]; - - Transport( GetDStoPoint(vtx), mP, mC ); - - Double_t dx = mP[0] - vtx[0]; - Double_t dy = mP[1] - vtx[1]; - Double_t px = mP[3]; - Double_t py = mP[4]; - Double_t pt = TMath::Sqrt(px*px + py*py); - Double_t 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; - } - - Double_t h0 = -ey; - Double_t h1 = ex; - Double_t h3 = (dy*ey + dx*ex)*ey/pt; - Double_t 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 = TMath::Sqrt(TMath::Abs(err)); - - return ret; -} - -Bool_t KFParticle::GetDistanceFromVertexXY( const Double_t vtx[], Double_t &val, Double_t &err ) const -{ - return GetDistanceFromVertexXY( vtx, 0, val, err ); -} - - -Bool_t KFParticle::GetDistanceFromVertexXY( const KFParticle &Vtx, Double_t &val, Double_t &err ) const -{ - //* Calculate distance from vertex [cm] in XY-plane - - return GetDistanceFromVertexXY( Vtx.fP, Vtx.fC, val, err ); -} - -Bool_t KFParticle::GetDistanceFromVertexXY( const MVertex &Vtx, Double_t &val, Double_t &err ) const -{ - //* Calculate distance from vertex [cm] in XY-plane - - return GetDistanceFromVertexXY( KFParticle(Vtx), val, err ); -} - -Double_t KFParticle::GetDistanceFromVertexXY( const Double_t vtx[] ) const -{ - //* Calculate distance from vertex [cm] in XY-plane - Double_t val, err; - GetDistanceFromVertexXY( vtx, 0, val, err ); - return val; -} - -Double_t KFParticle::GetDistanceFromVertexXY( const KFParticle &Vtx ) const -{ - //* Calculate distance from vertex [cm] in XY-plane - - return GetDistanceFromVertexXY( Vtx.fP ); -} - -Double_t KFParticle::GetDistanceFromVertexXY( const MVertex &Vtx ) const -{ - //* Calculate distance from vertex [cm] in XY-plane - - return GetDistanceFromVertexXY( KFParticle(Vtx).fP ); -} - -Double_t KFParticle::GetDistanceFromParticleXY( const KFParticle &p ) const -{ - //* Calculate distance to other particle [cm] - - Double_t dS, dS1; - GetDStoParticleXY( p, dS, dS1 ); - Double_t mP[8], mC[36], mP1[8], mC1[36]; - Transport( dS, mP, mC ); - p.Transport( dS1, mP1, mC1 ); - Double_t dx = mP[0]-mP1[0]; - Double_t dy = mP[1]-mP1[1]; - return TMath::Sqrt(dx*dx+dy*dy); -} - -Double_t KFParticle::GetDeviationFromParticleXY( const KFParticle &p ) const -{ - //* Calculate sqrt(Chi2/ndf) deviation from other particle - - Double_t dS, dS1; - GetDStoParticleXY( p, dS, dS1 ); - Double_t mP1[8], mC1[36]; - p.Transport( dS1, mP1, mC1 ); - - Double_t d[2]={ fP[0]-mP1[0], fP[1]-mP1[1] }; - - Double_t sigmaS = .1+10.*TMath::Sqrt( (d[0]*d[0]+d[1]*d[1] )/ - (mP1[3]*mP1[3]+mP1[4]*mP1[4] ) ); - - Double_t 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 )*TMath::Sqrt(2./1.); -} - - -Double_t KFParticle::GetDeviationFromVertexXY( const Double_t vtx[], const Double_t Cv[] ) const -{ - //* Calculate sqrt(Chi2/ndf) deviation from vertex - //* v = [xyz], Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix - - Double_t val, err; - Bool_t problem = GetDistanceFromVertexXY( vtx, Cv, val, err ); - if( problem || err<1.e-20 ) return 1.e4; - else return val/err; -} - - -Double_t KFParticle::GetDeviationFromVertexXY( const KFParticle &Vtx ) const -{ - //* Calculate sqrt(Chi2/ndf) deviation from vertex - //* v = [xyz], Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix - - return GetDeviationFromVertexXY( Vtx.fP, Vtx.fC ); -} - -Double_t KFParticle::GetDeviationFromVertexXY( const MVertex &Vtx ) const -{ - //* Calculate sqrt(Chi2/ndf) deviation from vertex - //* v = [xyz], Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix - - KFParticle v(Vtx); - return GetDeviationFromVertexXY( v.fP, v.fC ); -} - -Double_t KFParticle::GetAngle ( const KFParticle &p ) const -{ - //* Calculate the opening angle between two particles - - Double_t dS, dS1; - GetDStoParticle( p, dS, dS1 ); - Double_t mP[8], mC[36], mP1[8], mC1[36]; - Transport( dS, mP, mC ); - p.Transport( dS1, mP1, mC1 ); - Double_t n = TMath::Sqrt( mP[3]*mP[3] + mP[4]*mP[4] + mP[5]*mP[5] ); - Double_t n1= TMath::Sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] + mP1[5]*mP1[5] ); - n*=n1; - Double_t a = 0; - if( n>1.e-8 ) a = ( mP[3]*mP1[3] + mP[4]*mP1[4] + mP[5]*mP1[5] )/n; - if (TMath::Abs(a)<1.) a = TMath::ACos(a); - else a = (a>=0) ?0 :TMath::Pi(); - return a; -} - -Double_t KFParticle::GetAngleXY( const KFParticle &p ) const -{ - //* Calculate the opening angle between two particles in XY plane - - Double_t dS, dS1; - GetDStoParticleXY( p, dS, dS1 ); - Double_t mP[8], mC[36], mP1[8], mC1[36]; - Transport( dS, mP, mC ); - p.Transport( dS1, mP1, mC1 ); - Double_t n = TMath::Sqrt( mP[3]*mP[3] + mP[4]*mP[4] ); - Double_t n1= TMath::Sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] ); - n*=n1; - Double_t a = 0; - if( n>1.e-8 ) a = ( mP[3]*mP1[3] + mP[4]*mP1[4] )/n; - if (TMath::Abs(a)<1.) a = TMath::ACos(a); - else a = (a>=0) ?0 :TMath::Pi(); - return a; -} - -Double_t KFParticle::GetAngleRZ( const KFParticle &p ) const -{ - //* Calculate the opening angle between two particles in RZ plane - - Double_t dS, dS1; - GetDStoParticle( p, dS, dS1 ); - Double_t mP[8], mC[36], mP1[8], mC1[36]; - Transport( dS, mP, mC ); - p.Transport( dS1, mP1, mC1 ); - Double_t nr = TMath::Sqrt( mP[3]*mP[3] + mP[4]*mP[4] ); - Double_t n1r= TMath::Sqrt( mP1[3]*mP1[3] + mP1[4]*mP1[4] ); - Double_t n = TMath::Sqrt( nr*nr + mP[5]*mP[5] ); - Double_t n1= TMath::Sqrt( n1r*n1r + mP1[5]*mP1[5] ); - n*=n1; - Double_t a = 0; - if( n>1.e-8 ) a = ( nr*n1r +mP[5]*mP1[5])/n; - if (TMath::Abs(a)<1.) a = TMath::ACos(a); - else a = (a>=0) ?0 :TMath::Pi(); - return a; -} - - -/* - -#include "AliExternalTrackParam.h" - -void KFParticle::GetDStoParticleALICE( const KFParticleBase &p, - Double_t &DS, Double_t &DS1 ) - const -{ - DS = DS1 = 0; - Double_t x1, a1, x2, a2; - Double_t par1[5], par2[5], cov[15]; - for(int i=0; i<15; i++) cov[i] = 0; - cov[0] = cov[2] = cov[5] = cov[9] = cov[14] = .001; - - GetExternalTrackParam( *this, x1, a1, par1 ); - GetExternalTrackParam( p, x2, a2, par2 ); - - AliExternalTrackParam t1(x1,a1, par1, cov); - AliExternalTrackParam t2(x2,a2, par2, cov); - - Double_t xe1=0, xe2=0; - t1.GetDCA( &t2, -GetFieldAlice(), xe1, xe2 ); - t1.PropagateTo( xe1, -GetFieldAlice() ); - t2.PropagateTo( xe2, -GetFieldAlice() ); - - Double_t xyz1[3], xyz2[3]; - t1.GetXYZ( xyz1 ); - t2.GetXYZ( xyz2 ); - - DS = GetDStoPoint( xyz1 ); - DS1 = p.GetDStoPoint( xyz2 ); - - return; -} -*/ diff --git a/StRoot/StarRoot/KFParticle.h b/StRoot/StarRoot/KFParticle.h deleted file mode 100644 index 7b9bce99987..00000000000 --- a/StRoot/StarRoot/KFParticle.h +++ /dev/null @@ -1,916 +0,0 @@ -//--------------------------------------------------------------------------------- -// 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 Group =- -//_________________________________________________________________________________ - -#ifndef KFParticle_H -#define KFParticle_H - -#include "KFParticleBase.h" -#include "TMath.h" - -class MTrack; -class MVertex; - -class KFParticle :public KFParticleBase -{ - - public: - - //* - //* INITIALIZATION - //* - - //* Set magnetic field for all particles - - static void SetField( Double_t Bz ); - - //* 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 Double_t Param[], const Double_t Cov[], Int_t Charge, Int_t PID ); - - //* Initialisation from ALICE track, PID hypothesis shoould be provided - - KFParticle( const MTrack &track, Int_t PID ); - virtual void Clear(Option_t *option ="") {KFParticleBase::Clear(option);} - - //* Initialisation from VVertex - KFParticle( const MVertex &vertex ); - //* Initialise covariance matrix and set current parameters to 0.0 -#if 0 - void Initialize(); -#endif - - //* Set decay vertex parameters for linearisation - - void SetVtxGuess( Double_t x, Double_t y, Double_t z ); - - //* - //* ACCESSORS - //* - - //* Simple accessors - - Double_t GetX () const ; //* x of current position - Double_t GetY () const ; //* y of current position - Double_t GetZ () const ; //* z of current position - Double_t GetPx () const ; //* x-compoment of 3-momentum - Double_t GetPy () const ; //* y-compoment of 3-momentum - Double_t GetPz () const ; //* z-compoment of 3-momentum - Double_t GetE () const ; //* energy - Double_t GetS () const ; //* decay length / momentum - Short_t GetQ () const ; //* charge - Double_t GetChi2 () const ; //* chi^2 - Short_t GetNDF () const ; //* Number of Degrees of Freedom - Double_t GetParameter ( Int_t i ) const ; - Double_t GetCovariance( Int_t i ) const ; - Double_t GetCovariance( Int_t i, Int_t j ) const ; - //* Accessors with calculations, value returned w/o error flag - - Double_t GetP () const; //* momentum - Double_t GetPt () const; //* transverse momentum - Double_t GetEta () const; //* pseudorapidity - Double_t GetPhi () const; //* phi - Double_t GetMomentum () const; //* momentum (same as GetP() ) - Double_t GetMass () const; //* mass - Double_t GetDecayLength () const; //* decay length - Double_t GetDecayLengthXY () const; //* decay length in XY - Double_t GetLifeTime () const; //* life time - Double_t GetR () const; //* distance to the origin - - //* Accessors to estimated errors - - Double_t GetErrX () const ; //* x of current position - Double_t GetErrY () const ; //* y of current position - Double_t GetErrZ () const ; //* z of current position - Double_t GetErrPx () const ; //* x-compoment of 3-momentum - Double_t GetErrPy () const ; //* y-compoment of 3-momentum - Double_t GetErrPz () const ; //* z-compoment of 3-momentum - Double_t GetErrE () const ; //* energy - Double_t GetErrS () const ; //* decay length / momentum - Double_t GetErrP () const ; //* momentum - Double_t GetErrPt () const ; //* transverse momentum - Double_t GetErrEta () const ; //* pseudorapidity - Double_t GetErrPhi () const ; //* phi - Double_t GetErrMomentum () const ; //* momentum - Double_t GetErrMass () const ; //* mass - Double_t GetErrDecayLength () const ; //* decay length - Double_t GetErrDecayLengthXY () const ; //* decay length in XY - Double_t GetErrLifeTime () const ; //* life time - Double_t GetErrR () const ; //* distance to the origin - - //* Accessors with calculations( &value, &estimated sigma ) - //* error flag returned (0 means no error during calculations) - - Int_t GetP ( Double_t &P, Double_t &SigmaP ) const ; //* momentum - Int_t GetPt ( Double_t &Pt, Double_t &SigmaPt ) const ; //* transverse momentum - Int_t GetEta ( Double_t &Eta, Double_t &SigmaEta ) const ; //* pseudorapidity - Int_t GetPhi ( Double_t &Phi, Double_t &SigmaPhi ) const ; //* phi - Int_t GetMomentum ( Double_t &P, Double_t &SigmaP ) const ; //* momentum - Int_t GetMass ( Double_t &M, Double_t &SigmaM ) const ; //* mass - Int_t GetDecayLength ( Double_t &L, Double_t &SigmaL ) const ; //* decay length - Int_t GetDecayLengthXY ( Double_t &L, Double_t &SigmaL ) const ; //* decay length in XY - Int_t GetLifeTime ( Double_t &T, Double_t &SigmaT ) const ; //* life time - Int_t GetR ( Double_t &R, Double_t &SigmaR ) const ; //* R - - - //* - //* MODIFIERS - //* - - Double_t & X () ; - Double_t & Y () ; - Double_t & Z () ; - Double_t & Px () ; - Double_t & Py () ; - Double_t & Pz () ; - Double_t & E () ; - Double_t & S () ; - Short_t & Q () ; - Double_t & Chi2 () ; - Short_t & NDF () ; - - Double_t & Parameter ( Int_t i ) ; - Double_t & Covariance( Int_t i ) ; - Double_t & Covariance( Int_t i, Int_t j ) ; - Double_t * Parameters () ; - Double_t * CovarianceMatrix() ; - - //* - //* 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 ); - - //* Set production vertex - - void SetProductionVertex( const KFParticle &Vtx ); - - //* Set mass constraint - - void SetMassConstraint( Double_t Mass, Double_t SigmaMass = 0 ); - - //* Set no decay length for resonances - - void SetNoDecayLength(); - - //* Everything in one go - - void Construct( const KFParticle *vDaughters[], Int_t NDaughters, - const KFParticle *ProdVtx=0, Double_t Mass=-1, Bool_t IsConstrained=0 ); - - //* - //* 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 close to xyz[] point - - void TransportToPoint( const Double_t xyz[] ); - - //* Transport the particle close to VVertex - - void TransportToVertex( const MVertex &v ); - - //* Transport the particle close to another particle p - - void TransportToParticle( const KFParticle &p ); - - //* Transport the particle on dS parameter (SignedPath/Momentum) - - void TransportToDS( Double_t dS ); - - //* Get dS to a certain space point - - Double_t GetDStoPoint( const Double_t xyz[] ) const ; - - //* Get dS to other particle p (dSp for particle p also returned) - - void GetDStoParticle( const KFParticle &p, - Double_t &DS, Double_t &DSp ) const ; - - //* Get dS to other particle p in XY-plane - - void GetDStoParticleXY( const KFParticleBase &p, - Double_t &DS, Double_t &DSp ) const ; - - //* - //* OTHER UTILITIES - //* - - - //* Calculate distance from another object [cm] - - Double_t GetDistanceFromVertex( const Double_t vtx[] ) const ; - Double_t GetDistanceFromVertex( const KFParticle &Vtx ) const ; - Double_t GetDistanceFromVertex( const MVertex &Vtx ) const ; - Double_t GetDistanceFromParticle( const KFParticle &p ) const ; - //* Calculate sqrt(Chi2/ndf) deviation from another object - //* ( v = [xyz]-vertex, Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix ) - - Double_t GetDeviationFromVertex( const Double_t v[], const Double_t Cv[]=0 ) const ; - Double_t GetDeviationFromVertex( const KFParticle &Vtx ) const ; - Double_t GetDeviationFromVertex( const MVertex &Vtx ) const ; - Double_t GetDeviationFromParticle( const KFParticle &p ) const ; - - //* Calculate distance from another object [cm] in XY-plane - - Bool_t GetDistanceFromVertexXY( const Double_t vtx[], Double_t &val, Double_t &err ) const ; - Bool_t GetDistanceFromVertexXY( const Double_t vtx[], const Double_t Cv[], Double_t &val, Double_t &err ) const ; - Bool_t GetDistanceFromVertexXY( const KFParticle &Vtx, Double_t &val, Double_t &err ) const ; - Bool_t GetDistanceFromVertexXY( const MVertex &Vtx, Double_t &val, Double_t &err ) const ; - - Double_t GetDistanceFromVertexXY( const Double_t vtx[] ) const ; - Double_t GetDistanceFromVertexXY( const KFParticle &Vtx ) const ; - Double_t GetDistanceFromVertexXY( const MVertex &Vtx ) const ; - Double_t 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 ) - - Double_t GetDeviationFromVertexXY( const Double_t v[], const Double_t Cv[]=0 ) const ; - Double_t GetDeviationFromVertexXY( const KFParticle &Vtx ) const ; - Double_t GetDeviationFromVertexXY( const MVertex &Vtx ) const ; - Double_t GetDeviationFromParticleXY( const KFParticle &p ) const ; - - //* Calculate opennig angle between two particles - - Double_t GetAngle ( const KFParticle &p ) const ; - Double_t GetAngleXY( const KFParticle &p ) const ; - Double_t GetAngleRZ( const KFParticle &p ) const ; - - //* Subtract the particle from the vertex - - void SubtractFromVertex( KFParticle &v ) const ; - - //* Special method for creating gammas - - void ConstructGamma( const KFParticle &daughter1, - const KFParticle &daughter2 ); - protected: - - //* - //* INTERNAL STUFF - //* - - //* Method to access ALICE field - - static Double_t GetFieldAlice(); - - //* Other methods required by the abstract KFParticleBase class - - void GetFieldValue( const Double_t xyz[], Double_t B[] ) const ; - void GetDStoParticle( const KFParticleBase &p, Double_t &DS, Double_t &DSp )const ; - void Transport( Double_t dS, Double_t P[], Double_t C[] ) const ; - static void GetExternalTrackParam( const KFParticleBase &p, Double_t &X, Double_t &Alpha, Double_t P[5] ) ; - - //void GetDStoParticleALICE( const KFParticleBase &p, Double_t &DS, Double_t &DS1 ) const; - - - private: - - static Double32_t fgBz; //! * Bz compoment of the magnetic field - - - ClassDef(KFParticle,1) -}; -#ifndef __CINT__ - - -//--------------------------------------------------------------------- -// -// Inline implementation of the KFParticle methods -// -//--------------------------------------------------------------------- - - -inline void KFParticle::SetField( Double_t Bz ) -{ - fgBz = Bz;//!!! -} - - -inline KFParticle::KFParticle( const KFParticle &d1, - const KFParticle &d2 ) -{ - KFParticle mother; - mother+= d1; - mother+= d2; - *this = mother; -} - -inline KFParticle::KFParticle( const KFParticle &d1, - const KFParticle &d2, - const KFParticle &d3 ) -{ - 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 ) -{ - KFParticle mother; - mother+= d1; - mother+= d2; - mother+= d3; - mother+= d4; - *this = mother; -} -#if 0 -inline void KFParticle::Initialize() -{ - KFParticleBase::Initialize(); -} -#endif -inline void KFParticle::SetVtxGuess( Double_t x, Double_t y, Double_t z ) -{ - KFParticleBase::SetVtxGuess(x,y,z); -} - -inline Double_t KFParticle::GetX () const -{ - return KFParticleBase::GetX(); -} - -inline Double_t KFParticle::GetY () const -{ - return KFParticleBase::GetY(); -} - -inline Double_t KFParticle::GetZ () const -{ - return KFParticleBase::GetZ(); -} - -inline Double_t KFParticle::GetPx () const -{ - return KFParticleBase::GetPx(); -} - -inline Double_t KFParticle::GetPy () const -{ - return KFParticleBase::GetPy(); -} - -inline Double_t KFParticle::GetPz () const -{ - return KFParticleBase::GetPz(); -} - -inline Double_t KFParticle::GetE () const -{ - return KFParticleBase::GetE(); -} - -inline Double_t KFParticle::GetS () const -{ - return KFParticleBase::GetS(); -} - -inline Short_t KFParticle::GetQ () const -{ - return KFParticleBase::GetQ(); -} - -inline Double_t KFParticle::GetChi2 () const -{ - return KFParticleBase::GetChi2(); -} - -inline Short_t KFParticle::GetNDF () const -{ - return KFParticleBase::GetNDF(); -} -inline Double_t KFParticle::GetParameter ( Int_t i ) const -{ - return KFParticleBase::GetParameter(i); -} - -inline Double_t KFParticle::GetCovariance( Int_t i ) const -{ - return KFParticleBase::GetCovariance(i); -} - -inline Double_t KFParticle::GetCovariance( Int_t i, Int_t j ) const -{ - return KFParticleBase::GetCovariance(i,j); -} - -inline Double_t KFParticle::GetP () const -{ - Double_t par, err; - if( KFParticleBase::GetMomentum( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetPt () const -{ - Double_t par, err; - if( KFParticleBase::GetPt( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetEta () const -{ - Double_t par, err; - if( KFParticleBase::GetEta( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetPhi () const -{ - Double_t par, err; - if( KFParticleBase::GetPhi( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetMomentum () const -{ - Double_t par, err; - if( KFParticleBase::GetMomentum( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetMass () const -{ - Double_t par, err; - if( KFParticleBase::GetMass( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetDecayLength () const -{ - Double_t par, err; - if( KFParticleBase::GetDecayLength( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetDecayLengthXY () const -{ - Double_t par, err; - if( KFParticleBase::GetDecayLengthXY( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetLifeTime () const -{ - Double_t par, err; - if( KFParticleBase::GetLifeTime( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetR () const -{ - Double_t par, err; - if( KFParticleBase::GetR( par, err ) ) return 0; - else return par; -} - -inline Double_t KFParticle::GetErrX () const -{ - return TMath::Sqrt(TMath::Abs( GetCovariance(0,0) )); -} - -inline Double_t KFParticle::GetErrY () const -{ - return TMath::Sqrt(TMath::Abs( GetCovariance(1,1) )); -} - -inline Double_t KFParticle::GetErrZ () const -{ - return TMath::Sqrt(TMath::Abs( GetCovariance(2,2) )); -} - -inline Double_t KFParticle::GetErrPx () const -{ - return TMath::Sqrt(TMath::Abs( GetCovariance(3,3) )); -} - -inline Double_t KFParticle::GetErrPy () const -{ - return TMath::Sqrt(TMath::Abs( GetCovariance(4,4) )); -} - -inline Double_t KFParticle::GetErrPz () const -{ - return TMath::Sqrt(TMath::Abs( GetCovariance(5,5) )); -} - -inline Double_t KFParticle::GetErrE () const -{ - return TMath::Sqrt(TMath::Abs( GetCovariance(6,6) )); -} - -inline Double_t KFParticle::GetErrS () const -{ - return TMath::Sqrt(TMath::Abs( GetCovariance(7,7) )); -} - -inline Double_t KFParticle::GetErrP () const -{ - Double_t par, err; - if( KFParticleBase::GetMomentum( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrPt () const -{ - Double_t par, err; - if( KFParticleBase::GetPt( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrEta () const -{ - Double_t par, err; - if( KFParticleBase::GetEta( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrPhi () const -{ - Double_t par, err; - if( KFParticleBase::GetPhi( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrMomentum () const -{ - Double_t par, err; - if( KFParticleBase::GetMomentum( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrMass () const -{ - Double_t par, err; - if( KFParticleBase::GetMass( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrDecayLength () const -{ - Double_t par, err; - if( KFParticleBase::GetDecayLength( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrDecayLengthXY () const -{ - Double_t par, err; - if( KFParticleBase::GetDecayLengthXY( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrLifeTime () const -{ - Double_t par, err; - if( KFParticleBase::GetLifeTime( par, err ) ) return 1.e10; - else return err; -} - -inline Double_t KFParticle::GetErrR () const -{ - Double_t par, err; - if( KFParticleBase::GetR( par, err ) ) return 1.e10; - else return err; -} - -inline Int_t KFParticle::GetP( Double_t &P, Double_t &SigmaP ) const -{ - return KFParticleBase::GetMomentum( P, SigmaP ); -} -inline Int_t KFParticle::GetPt( Double_t &Pt, Double_t &SigmaPt ) const -{ - return KFParticleBase::GetPt( Pt, SigmaPt ); -} - -inline Int_t KFParticle::GetEta( Double_t &Eta, Double_t &SigmaEta ) const -{ - return KFParticleBase::GetEta( Eta, SigmaEta ); -} - -inline Int_t KFParticle::GetPhi( Double_t &Phi, Double_t &SigmaPhi ) const -{ - return KFParticleBase::GetPhi( Phi, SigmaPhi ); -} - -inline Int_t KFParticle::GetMomentum( Double_t &P, Double_t &SigmaP ) const -{ - return KFParticleBase::GetMomentum( P, SigmaP ); -} - -inline Int_t KFParticle::GetMass( Double_t &M, Double_t &SigmaM ) const -{ - return KFParticleBase::GetMass( M, SigmaM ); -} - -inline Int_t KFParticle::GetDecayLength( Double_t &L, Double_t &SigmaL ) const -{ - return KFParticleBase::GetDecayLength( L, SigmaL ); -} - -inline Int_t KFParticle::GetDecayLengthXY( Double_t &L, Double_t &SigmaL ) const -{ - return KFParticleBase::GetDecayLengthXY( L, SigmaL ); -} - -inline Int_t KFParticle::GetLifeTime( Double_t &T, Double_t &SigmaT ) const -{ - return KFParticleBase::GetLifeTime( T, SigmaT ); -} - -inline Int_t KFParticle::GetR( Double_t &R, Double_t &SigmaR ) const -{ - return KFParticleBase::GetR( R, SigmaR ); -} -inline Double_t & KFParticle::X() -{ - return KFParticleBase::X(); -} - -inline Double_t & KFParticle::Y() -{ - return KFParticleBase::Y(); -} - -inline Double_t & KFParticle::Z() -{ - return KFParticleBase::Z(); -} - -inline Double_t & KFParticle::Px() -{ - return KFParticleBase::Px(); -} - -inline Double_t & KFParticle::Py() -{ - return KFParticleBase::Py(); -} - -inline Double_t & KFParticle::Pz() -{ - return KFParticleBase::Pz(); -} - -inline Double_t & KFParticle::E() -{ - return KFParticleBase::E(); -} - -inline Double_t & KFParticle::S() -{ - return KFParticleBase::S(); -} - -inline Short_t & KFParticle::Q() -{ - return KFParticleBase::Q(); -} - -inline Double_t & KFParticle::Chi2() -{ - return KFParticleBase::Chi2(); -} - -inline Short_t & KFParticle::NDF() -{ - return KFParticleBase::NDF(); -} - -inline Double_t & KFParticle::Parameter ( Int_t i ) -{ - return KFParticleBase::Parameter(i); -} - -inline Double_t & KFParticle::Covariance( Int_t i ) -{ - return KFParticleBase::Covariance(i); -} - -inline Double_t & KFParticle::Covariance( Int_t i, Int_t j ) -{ - return KFParticleBase::Covariance(i,j); -} -inline Double_t * KFParticle::Parameters () -{ - return fP; -} - -inline Double_t * KFParticle::CovarianceMatrix() -{ - return fC; -} - -inline void KFParticle::operator +=( const KFParticle &Daughter ) -{ - KFParticleBase::operator +=( Daughter ); -} - - -inline void KFParticle::AddDaughter( const KFParticle &Daughter ) -{ - KFParticleBase::AddDaughter( Daughter ); -} - -inline void KFParticle::SetProductionVertex( const KFParticle &Vtx ) -{ - KFParticleBase::SetProductionVertex( Vtx ); -} - -inline void KFParticle::SetMassConstraint( Double_t Mass, Double_t SigmaMass ) -{ - KFParticleBase::SetMassConstraint( Mass, SigmaMass ); -} - -inline void KFParticle::SetNoDecayLength() -{ - KFParticleBase::SetNoDecayLength(); -} - -inline void KFParticle::Construct( const KFParticle *vDaughters[], Int_t NDaughters, - const KFParticle *ProdVtx, Double_t Mass, Bool_t IsConstrained ) -{ - KFParticleBase::Construct( ( const KFParticleBase**)vDaughters, NDaughters, - ( const KFParticleBase*)ProdVtx, Mass, IsConstrained ); -} - -inline void KFParticle::TransportToDecayVertex() -{ - KFParticleBase::TransportToDecayVertex(); -} - -inline void KFParticle::TransportToProductionVertex() -{ - KFParticleBase::TransportToProductionVertex(); -} -inline void KFParticle::TransportToPoint( const Double_t xyz[] ) -{ - TransportToDS( GetDStoPoint(xyz) ); -} - -inline void KFParticle::TransportToVertex( const MVertex &v ) -{ - TransportToPoint( KFParticle(v).fP ); -} - -inline void KFParticle::TransportToParticle( const KFParticle &p ) -{ - Double_t dS, dSp; - GetDStoParticle( p, dS, dSp ); - TransportToDS( dS ); -} - -inline void KFParticle::TransportToDS( Double_t dS ) -{ - KFParticleBase::TransportToDS( dS ); -} - -inline Double_t KFParticle::GetDStoPoint( const Double_t xyz[] ) const -{ - return KFParticleBase::GetDStoPointBz( GetFieldAlice(), xyz ); -} - - -inline void KFParticle::GetDStoParticle( const KFParticle &p, - Double_t &DS, Double_t &DSp ) const -{ - GetDStoParticleXY( p, DS, DSp ); -} - - -inline Double_t KFParticle::GetDistanceFromVertex( const Double_t vtx[] ) const -{ - return KFParticleBase::GetDistanceFromVertex( vtx ); -} - -inline Double_t KFParticle::GetDeviationFromVertex( const Double_t v[], - const Double_t Cv[] ) const -{ - return KFParticleBase::GetDeviationFromVertex( v, Cv); -} - -inline Double_t KFParticle::GetDistanceFromVertex( const KFParticle &Vtx ) const -{ - return KFParticleBase::GetDistanceFromVertex( Vtx ); -} - -inline Double_t KFParticle::GetDeviationFromVertex( const KFParticle &Vtx ) const -{ - return KFParticleBase::GetDeviationFromVertex( Vtx ); -} - -inline Double_t KFParticle::GetDistanceFromVertex( const MVertex &Vtx ) const -{ - return GetDistanceFromVertex( KFParticle(Vtx) ); -} - -inline Double_t KFParticle::GetDeviationFromVertex( const MVertex &Vtx ) const -{ - return GetDeviationFromVertex( KFParticle(Vtx) ); -} -inline Double_t KFParticle::GetDistanceFromParticle( const KFParticle &p ) const -{ - return KFParticleBase::GetDistanceFromParticle( p ); -} -inline Double_t KFParticle::GetDeviationFromParticle( const KFParticle &p ) const -{ - return KFParticleBase::GetDeviationFromParticle( p ); -} - -inline void KFParticle::SubtractFromVertex( KFParticle &v ) const -{ - KFParticleBase::SubtractFromVertex( v ); -} - -inline Double_t KFParticle::GetFieldAlice() -{ - return fgBz; -} - -inline void KFParticle::GetFieldValue( const Double_t * /*xyz*/, Double_t B[] ) const -{ - B[0] = B[1] = 0; - B[2] = GetFieldAlice(); -} - -inline void KFParticle::GetDStoParticle( const KFParticleBase &p, - Double_t &DS, Double_t &DSp )const -{ - GetDStoParticleXY( p, DS, DSp ); -} - -inline void KFParticle::GetDStoParticleXY( const KFParticleBase &p, - Double_t &DS, Double_t &DSp ) const -{ - KFParticleBase::GetDStoParticleBz( GetFieldAlice(), p, DS, DSp ) ; - //GetDStoParticleALICE( p, DS, DSp ) ; -} - -inline void KFParticle::Transport( Double_t dS, Double_t P[], Double_t C[] ) const -{ - KFParticleBase::TransportBz( GetFieldAlice(), dS, P, C ); -} - -inline void KFParticle::ConstructGamma( const KFParticle &daughter1, - const KFParticle &daughter2 ) -{ - KFParticleBase::ConstructGammaBz( daughter1, daughter2, GetFieldAlice() ); -} -#endif /* ! __CINT__ */ -#endif diff --git a/StRoot/StarRoot/KFParticleBase.cxx b/StRoot/StarRoot/KFParticleBase.cxx deleted file mode 100644 index 7003f96b52c..00000000000 --- a/StRoot/StarRoot/KFParticleBase.cxx +++ /dev/null @@ -1,2261 +0,0 @@ -//--------------------------------------------------------------------------------- -// Implementation of the KFParticleBase 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 describes general mathematics which is used by KFParticle class -// -// -= Copyright © ALICE HLT Group =- -//_________________________________________________________________________________ - -#include -#include "KFParticleBase.h" -#include "TMath.h" -#include "Riostream.h" -#include "TString.h" -#include "TRSymMatrix.h" -#include "TRVector.h" -ClassImp(KFParticleBase); -static Int_t _debug = 0; - - -KFParticleBase::KFParticleBase() :fID(0), fParentID(0), fQ(0), fNDF(-3), fChi2(0), fSFromDecay(0), fAtProductionVertex(0), fIsLinearized(0), - fIdTruth(0), fQuality(0), fIdParentMcVx(0), fPDG(0) -{ - //* Constructor - Clear(); - Initialize(); -} - -void KFParticleBase::Initialize( const Double_t Param[], const Double_t Cov[], Int_t Charge, Double_t Mass, Int_t PID ) -{ - // Constructor from "cartesian" track, particle mass hypothesis should be provided - // - // Param[6] = { X, Y, Z, Px, Py, Pz } - position and momentum - // Cov [21] = lower-triangular part of the covariance matrix: - // - // ( 0 . . . . . ) - // ( 1 2 . . . . ) - // Cov. matrix = ( 3 4 5 . . . ) - numbering of covariance elements in Cov[] - // ( 6 7 8 9 . . ) - // ( 10 11 12 13 14 . ) - // ( 15 16 17 18 19 20 ) - fPDG = PID; - for( Int_t i=0; i<6 ; i++ ) fP[i] = Param[i]; - for( Int_t i=0; i<21; i++ ) fC[i] = Cov[i]; - - Double_t energy = TMath::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; - fIsLinearized = 0; - fSFromDecay = 0; - - Double_t energyInv = 1./energy; - Double_t - 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] ) ); - if (_debug) { - std::cout << "KFParticle::Create " << *this << std::endl; - } -} - -void KFParticleBase::Initialize() -{ - //* Initialise covariance matrix and set current parameters to 0.0 -} -void KFParticleBase::Clear(Option_t *option) { - memset(fBeg,0,fEnd-fBeg+1); - fC[0] = fC[2] = fC[5] = 100.; - fC[35] = 1.; - fNDF = -3; -} -void KFParticleBase::SetVtxGuess( Double_t x, Double_t y, Double_t z ) -{ - //* Set decay vertex parameters for linearisation - - fVtxGuess[0] = x; - fVtxGuess[1] = y; - fVtxGuess[2] = z; - fIsLinearized = 1; -} - - -Int_t KFParticleBase::GetMomentum( Double_t &p, Double_t &error ) const -{ - //* Calculate particle momentum - - Double_t x = fP[3]; - Double_t y = fP[4]; - Double_t z = fP[5]; - Double_t x2 = x*x; - Double_t y2 = y*y; - Double_t z2 = z*z; - Double_t p2 = x2+y2+z2; - p = TMath::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>0 && p>1.e-4 ){ - error = TMath::Sqrt(error)/p; - return 0; - } - return 1; -} - -Int_t KFParticleBase::GetPt( Double_t &pt, Double_t &error ) const -{ - //* Calculate particle transverse momentum - - Double_t px = fP[3]; - Double_t py = fP[4]; - Double_t px2 = px*px; - Double_t py2 = py*py; - Double_t pt2 = px2+py2; - pt = TMath::Sqrt(pt2); - error = (px2*fC[9] + py2*fC[14] + 2*px*py*fC[13] ); - if( error>0 && pt>1.e-4 ){ - error = TMath::Sqrt(error)/pt; - return 0; - } - error = 1.e10; - return 1; -} - -Int_t KFParticleBase::GetEta( Double_t &eta, Double_t &error ) const -{ - //* Calculate particle pseudorapidity - - Double_t px = fP[3]; - Double_t py = fP[4]; - Double_t pz = fP[5]; - Double_t pt2 = px*px + py*py; - Double_t p2 = pt2 + pz*pz; - Double_t p = TMath::Sqrt(p2); - Double_t a = p + pz; - Double_t b = p - pz; - eta = 1.e10; - if( b > 1.e-8 ){ - Double_t c = a/b; - if( c>1.e-8 ) eta = 0.5*TMath::Log(c); - } - Double_t h3 = -px*pz; - Double_t h4 = -py*pz; - Double_t pt4 = pt2*pt2; - Double_t 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 = TMath::Sqrt(error/p2pt4); - return 0; - } - - error = 1.e10; - return 1; -} - -Int_t KFParticleBase::GetPhi( Double_t &phi, Double_t &error ) const -{ - //* Calculate particle polar angle - - Double_t px = fP[3]; - Double_t py = fP[4]; - Double_t px2 = px*px; - Double_t py2 = py*py; - Double_t pt2 = px2 + py2; - phi = TMath::ATan2(py,px); - error = (py2*fC[9] + px2*fC[14] - 2*px*py*fC[13] ); - if( error>0 && pt2>1.e-4 ){ - error = TMath::Sqrt(error)/pt2; - return 0; - } - error = 1.e10; - return 1; -} - -Int_t KFParticleBase::GetR( Double_t &r, Double_t &error ) const -{ - //* Calculate distance to the origin - - Double_t x = fP[0]; - Double_t y = fP[1]; - Double_t x2 = x*x; - Double_t y2 = y*y; - r = TMath::Sqrt(x2 + y2); - error = (x2*fC[0] + y2*fC[2] - 2*x*y*fC[1] ); - if( error>0 && r>1.e-4 ){ - error = TMath::Sqrt(error)/r; - return 0; - } - error = 1.e10; - return 1; -} - -Int_t KFParticleBase::GetMass( Double_t &m, Double_t &error ) const -{ - //* Calculate particle mass - - // s = sigma^2 of m2/2 - - Double_t 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] ) ) - ); - Double_t m2 = TMath::Abs(fP[6]*fP[6] - fP[3]*fP[3] - fP[4]*fP[4] - fP[5]*fP[5]); - m = TMath::Sqrt(m2); - if( m>1.e-10 ){ - if( s>=0 ){ - error = TMath::Sqrt(s)/m; - return 0; - } - } - error = 1.e20; - return 1; -} - - -Int_t KFParticleBase::GetDecayLength( Double_t &l, Double_t &error ) const -{ - //* Calculate particle decay length [cm] - - Double_t x = fP[3]; - Double_t y = fP[4]; - Double_t z = fP[5]; - Double_t t = fP[7]; - Double_t x2 = x*x; - Double_t y2 = y*y; - Double_t z2 = z*z; - Double_t p2 = x2+y2+z2; - l = t*TMath::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 = TMath::Sqrt(TMath::Abs(error)); - return 0; - } - error = 1.e20; - return 1; -} - -Int_t KFParticleBase::GetDecayLengthXY( Double_t &l, Double_t &error ) const -{ - //* Calculate particle decay length in XY projection [cm] - - Double_t x = fP[3]; - Double_t y = fP[4]; - Double_t t = fP[7]; - Double_t x2 = x*x; - Double_t y2 = y*y; - Double_t pt2 = x2+y2; - l = t*TMath::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 = TMath::Sqrt(TMath::Abs(error)); - return 0; - } - error = 1.e20; - return 1; -} - - -Int_t KFParticleBase::GetLifeTime( Double_t &tauC, Double_t &error ) const -{ - //* Calculate particle decay time [s] - - Double_t m, dm; - GetMass( m, dm ); - Double_t 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; - if( error > 0 ){ - error = TMath::Sqrt( error ); - return 0; - } - error = 1.e20; - return 1; -} - - -void KFParticleBase::operator +=( const KFParticleBase &Daughter ) -{ - //* Add daughter via operator+= - - AddDaughter( Daughter ); -} - -Double_t KFParticleBase::GetSCorrection( const Double_t Part[], const Double_t XYZ[] ) -{ - //* Get big enough correction for S error to let the particle Part be fitted to XYZ point - - Double_t d[3] = { XYZ[0]-Part[0], XYZ[1]-Part[1], XYZ[2]-Part[2] }; - Double_t p2 = Part[3]*Part[3]+Part[4]*Part[4]+Part[5]*Part[5]; - Double_t sigmaS = (p2>1.e-4) ? ( .1+3.*TMath::Sqrt( d[0]*d[0]+d[1]*d[1]+d[2]*d[2]) )/TMath::Sqrt(p2) : 1.; - return sigmaS; -} - -void KFParticleBase::GetMeasurement( const Double_t XYZ[], Double_t m[], Double_t V[] ) const -{ - //* Get additional covariances V used during measurement - - Double_t b[3]; - GetFieldValue( XYZ, b ); - const Double_t kCLight = 0.000299792458; - b[0]*=kCLight; b[1]*=kCLight; b[2]*=kCLight; - - Transport( GetDStoPoint(XYZ), m, V ); - - Double_t sigmaS = GetSCorrection( m, XYZ ); - - Double_t h[6]; - - h[0] = m[3]*sigmaS; - h[1] = m[4]*sigmaS; - h[2] = m[5]*sigmaS; - h[3] = ( h[1]*b[2]-h[2]*b[1] )*GetQ(); - h[4] = ( h[2]*b[0]-h[0]*b[2] )*GetQ(); - h[5] = ( h[0]*b[1]-h[1]*b[0] )*GetQ(); - - 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]; - - V[ 6]+= h[3]*h[0]; - V[ 7]+= h[3]*h[1]; - V[ 8]+= h[3]*h[2]; - V[ 9]+= h[3]*h[3]; - - V[10]+= h[4]*h[0]; - V[11]+= h[4]*h[1]; - V[12]+= h[4]*h[2]; - V[13]+= h[4]*h[3]; - V[14]+= h[4]*h[4]; - - V[15]+= h[5]*h[0]; - V[16]+= h[5]*h[1]; - V[17]+= h[5]*h[2]; - V[18]+= h[5]*h[3]; - V[19]+= h[5]*h[4]; - V[20]+= h[5]*h[5]; -} - - -void KFParticleBase::AddDaughter( const KFParticleBase &Daughter ) -{ - //* Add daughter - if( fNDF<-1 ){ // first daughter -> just copy - fNDF = -1; - fQ = Daughter.GetQ(); - - if( Daughter.fC[35]>0 ){ //TODO Check this: only the first daughter is used here! - Daughter.GetMeasurement( fVtxGuess, fP, fC ); - } else { - for( Int_t i=0; i<8; i++ ) fP[i] = Daughter.fP[i]; - for( Int_t i=0; i<36; i++ ) fC[i] = Daughter.fC[i]; - } - fSFromDecay = 0; - return; - } - -// TransportToDecayVertex(); - - Double_t b[3]; - Int_t maxIter = 1; - - if( !fIsLinearized ){ - if( fNDF==-1 ){ - Double_t ds, ds1; - GetDStoParticle(Daughter, ds, ds1); - TransportToDS( ds ); - Double_t m[8]; - Double_t mCd[36]; - Daughter.Transport( ds1, m, mCd ); - fVtxGuess[0] = .5*( fP[0] + m[0] ); - fVtxGuess[1] = .5*( fP[1] + m[1] ); - fVtxGuess[2] = .5*( fP[2] + m[2] ); - } else { - fVtxGuess[0] = fP[0]; - fVtxGuess[1] = fP[1]; - fVtxGuess[2] = fP[2]; - } - maxIter = 3; - } - - for( Int_t iter=0; iter0 ){ - Daughter.GetMeasurement( fVtxGuess, m, mV ); - } else { - for( Int_t i=0; i<8; i++ ) m[i] = Daughter.fP[i]; - for( Int_t i=0; i<36; i++ ) mV[i] = Daughter.fC[i]; - } - - //* - - Double_t mS[6]= { ffC[0]+mV[0], - ffC[1]+mV[1], ffC[2]+mV[2], - ffC[3]+mV[3], ffC[4]+mV[4], ffC[5]+mV[5] }; - InvertCholetsky3(mS); - //* Residual (measured - estimated) - - Double_t zeta[3] = { m[0]-ffP[0], m[1]-ffP[1], m[2]-ffP[2] }; - - - //* CHt = CH' - D' - - Double_t mCHt0[7], mCHt1[7], mCHt2[7]; - - mCHt0[0]=ffC[ 0] ; mCHt1[0]=ffC[ 1] ; mCHt2[0]=ffC[ 3] ; - mCHt0[1]=ffC[ 1] ; mCHt1[1]=ffC[ 2] ; mCHt2[1]=ffC[ 4] ; - mCHt0[2]=ffC[ 3] ; mCHt1[2]=ffC[ 4] ; mCHt2[2]=ffC[ 5] ; - mCHt0[3]=ffC[ 6]-mV[ 6]; mCHt1[3]=ffC[ 7]-mV[ 7]; mCHt2[3]=ffC[ 8]-mV[ 8]; - mCHt0[4]=ffC[10]-mV[10]; mCHt1[4]=ffC[11]-mV[11]; mCHt2[4]=ffC[12]-mV[12]; - mCHt0[5]=ffC[15]-mV[15]; mCHt1[5]=ffC[16]-mV[16]; mCHt2[5]=ffC[17]-mV[17]; - mCHt0[6]=ffC[21]-mV[21]; mCHt1[6]=ffC[22]-mV[22]; mCHt2[6]=ffC[23]-mV[23]; - - //* Kalman gain K = mCH'*S - - Double_t 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]; - } - - //* New estimation of the vertex position - - if( iter update the particle - - //* Add the daughter momentum to the particle momentum - - ffP[ 3] += m[ 3]; - ffP[ 4] += m[ 4]; - ffP[ 5] += m[ 5]; - ffP[ 6] += m[ 6]; - - ffC[ 9] += mV[ 9]; - ffC[13] += mV[13]; - ffC[14] += mV[14]; - ffC[18] += mV[18]; - ffC[19] += mV[19]; - ffC[20] += mV[20]; - ffC[24] += mV[24]; - ffC[25] += mV[25]; - ffC[26] += mV[26]; - ffC[27] += mV[27]; - - - //* New estimation of the vertex position r += K*zeta - - for(Int_t i=0;i<7;++i) - fP[i] = ffP[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] = ffC[k] - (k0[i]*mCHt0[j] + k1[i]*mCHt1[j] + k2[i]*mCHt2[j] ); - } - } - - //* 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 ) -{ - //* Set production vertex for the particle, when the particle was not used in the vertex fit - - const Double_t *m = Vtx.fP, *mV = Vtx.fC; - - Bool_t noS = ( fC[35]<=0 ); // no decay length allowed - - if( noS ){ - TransportToDecayVertex(); - fP[7] = 0; - fC[28] = 0; fC[29] = 0; fC[30] = 0; fC[31] = 0; fC[32] = 0; fC[33] = 0; fC[35] = 0; fC[35] = 0; - } else { - TransportToDS( GetDStoPoint( m ) ); - fP[7] = -fSFromDecay; - Convert(1); - } - - Double_t mAi[6]; - for(int i=0; i<6; i++) mAi[i] = fC[i]; - InvertCholetsky3(mAi); - //InvertCholetsky3( fC, mAi ); - - Double_t mB[5][3]; - - mB[0][0] = fC[ 6]*mAi[0] + fC[ 7]*mAi[1] + fC[ 8]*mAi[3]; - mB[0][1] = fC[ 6]*mAi[1] + fC[ 7]*mAi[2] + fC[ 8]*mAi[4]; - mB[0][2] = fC[ 6]*mAi[3] + fC[ 7]*mAi[4] + fC[ 8]*mAi[5]; - - mB[1][0] = fC[10]*mAi[0] + fC[11]*mAi[1] + fC[12]*mAi[3]; - mB[1][1] = fC[10]*mAi[1] + fC[11]*mAi[2] + fC[12]*mAi[4]; - mB[1][2] = fC[10]*mAi[3] + fC[11]*mAi[4] + fC[12]*mAi[5]; - - mB[2][0] = fC[15]*mAi[0] + fC[16]*mAi[1] + fC[17]*mAi[3]; - mB[2][1] = fC[15]*mAi[1] + fC[16]*mAi[2] + fC[17]*mAi[4]; - mB[2][2] = fC[15]*mAi[3] + fC[16]*mAi[4] + fC[17]*mAi[5]; - - mB[3][0] = fC[21]*mAi[0] + fC[22]*mAi[1] + fC[23]*mAi[3]; - mB[3][1] = fC[21]*mAi[1] + fC[22]*mAi[2] + fC[23]*mAi[4]; - mB[3][2] = fC[21]*mAi[3] + fC[22]*mAi[4] + fC[23]*mAi[5]; - - mB[4][0] = fC[28]*mAi[0] + fC[29]*mAi[1] + fC[30]*mAi[3]; - mB[4][1] = fC[28]*mAi[1] + fC[29]*mAi[2] + fC[30]*mAi[4]; - mB[4][2] = fC[28]*mAi[3] + fC[29]*mAi[4] + fC[30]*mAi[5]; - - Double_t z[3] = { m[0]-fP[0], m[1]-fP[1], m[2]-fP[2] }; - - { - Double_t mAVi[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] }; - - //if( !InvertCholetsky3( mAVi, mAVi ) ) - InvertCholetsky3( mAVi); - { - - Double_t dChi2 = ( +(mAVi[0]*z[0] + mAVi[1]*z[1] + mAVi[3]*z[2])*z[0] - +(mAVi[1]*z[0] + mAVi[2]*z[1] + mAVi[4]*z[2])*z[1] - +(mAVi[3]*z[0] + mAVi[4]*z[1] + mAVi[5]*z[2])*z[2] ); - - // Take Abs(dChi2) here. Negative value of 'det' or 'dChi2' shows that the particle - // was not used in the production vertex fit - - fChi2+= TMath::Abs( dChi2 ); - } - fNDF += 2; - } - - fP[0] = m[0]; - fP[1] = m[1]; - fP[2] = m[2]; - fP[3]+= mB[0][0]*z[0] + mB[0][1]*z[1] + mB[0][2]*z[2]; - fP[4]+= mB[1][0]*z[0] + mB[1][1]*z[1] + mB[1][2]*z[2]; - fP[5]+= mB[2][0]*z[0] + mB[2][1]*z[1] + mB[2][2]*z[2]; - fP[6]+= mB[3][0]*z[0] + mB[3][1]*z[1] + mB[3][2]*z[2]; - fP[7]+= mB[4][0]*z[0] + mB[4][1]*z[1] + mB[4][2]*z[2]; - - Double_t d0, d1, d2; - - fC[0] = mV[0]; - fC[1] = mV[1]; - fC[2] = mV[2]; - fC[3] = mV[3]; - fC[4] = mV[4]; - fC[5] = mV[5]; - - d0= mB[0][0]*mV[0] + mB[0][1]*mV[1] + mB[0][2]*mV[3] - fC[ 6]; - d1= mB[0][0]*mV[1] + mB[0][1]*mV[2] + mB[0][2]*mV[4] - fC[ 7]; - d2= mB[0][0]*mV[3] + mB[0][1]*mV[4] + mB[0][2]*mV[5] - fC[ 8]; - - fC[ 6]+= d0; - fC[ 7]+= d1; - fC[ 8]+= d2; - fC[ 9]+= d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - - d0= mB[1][0]*mV[0] + mB[1][1]*mV[1] + mB[1][2]*mV[3] - fC[10]; - d1= mB[1][0]*mV[1] + mB[1][1]*mV[2] + mB[1][2]*mV[4] - fC[11]; - d2= mB[1][0]*mV[3] + mB[1][1]*mV[4] + mB[1][2]*mV[5] - fC[12]; - - fC[10]+= d0; - fC[11]+= d1; - fC[12]+= d2; - fC[13]+= d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - fC[14]+= d0*mB[1][0] + d1*mB[1][1] + d2*mB[1][2]; - - d0= mB[2][0]*mV[0] + mB[2][1]*mV[1] + mB[2][2]*mV[3] - fC[15]; - d1= mB[2][0]*mV[1] + mB[2][1]*mV[2] + mB[2][2]*mV[4] - fC[16]; - d2= mB[2][0]*mV[3] + mB[2][1]*mV[4] + mB[2][2]*mV[5] - fC[17]; - - fC[15]+= d0; - fC[16]+= d1; - fC[17]+= d2; - fC[18]+= d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - fC[19]+= d0*mB[1][0] + d1*mB[1][1] + d2*mB[1][2]; - fC[20]+= d0*mB[2][0] + d1*mB[2][1] + d2*mB[2][2]; - - d0= mB[3][0]*mV[0] + mB[3][1]*mV[1] + mB[3][2]*mV[3] - fC[21]; - d1= mB[3][0]*mV[1] + mB[3][1]*mV[2] + mB[3][2]*mV[4] - fC[22]; - d2= mB[3][0]*mV[3] + mB[3][1]*mV[4] + mB[3][2]*mV[5] - fC[23]; - - fC[21]+= d0; - fC[22]+= d1; - fC[23]+= d2; - fC[24]+= d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - fC[25]+= d0*mB[1][0] + d1*mB[1][1] + d2*mB[1][2]; - fC[26]+= d0*mB[2][0] + d1*mB[2][1] + d2*mB[2][2]; - fC[27]+= d0*mB[3][0] + d1*mB[3][1] + d2*mB[3][2]; - - d0= mB[4][0]*mV[0] + mB[4][1]*mV[1] + mB[4][2]*mV[3] - fC[28]; - d1= mB[4][0]*mV[1] + mB[4][1]*mV[2] + mB[4][2]*mV[4] - fC[29]; - d2= mB[4][0]*mV[3] + mB[4][1]*mV[4] + mB[4][2]*mV[5] - fC[30]; - - fC[28]+= d0; - fC[29]+= d1; - fC[30]+= d2; - fC[31]+= d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - fC[32]+= d0*mB[1][0] + d1*mB[1][1] + d2*mB[1][2]; - fC[33]+= d0*mB[2][0] + d1*mB[2][1] + d2*mB[2][2]; - fC[34]+= d0*mB[3][0] + d1*mB[3][1] + d2*mB[3][2]; - fC[35]+= d0*mB[4][0] + d1*mB[4][1] + d2*mB[4][2]; - - if( noS ){ - fP[7] = 0; - fC[28] = 0;fC[29] = 0;fC[30] = 0;fC[31] = 0;fC[32] = 0;fC[33] = 0;fC[35] = 0;fC[35] = 0; - } else { - TransportToDS( fP[7] ); - Convert(0); - } - - fSFromDecay = 0; -} - - - -void KFParticleBase::SetMassConstraint( Double_t Mass, Double_t SigmaMass ) -{ - //* Set hard( SigmaMass=0 ) or soft (SigmaMass>0) mass constraint - - Double_t m2 = Mass*Mass; // measurement, weighted by Mass - Double_t s2 = m2*SigmaMass*SigmaMass; // sigma^2 - - Double_t p2 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; - Double_t e0 = TMath::Sqrt(m2+p2); - - Double_t 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; - - Double_t zeta = e0*e0 - e0*fP[6]; - zeta = m2 - (fP[6]*fP[6]-p2); - - Double_t 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 - - Double_t w2 = 1./( s2 + s2_est ); - fChi2 += zeta*zeta*w2; - fNDF += 1; - for( Int_t i=0, ii=0; i<8; ++i ){ - Double_t ki = mCHt[i]*w2; - fP[i]+= ki*zeta; - for(Int_t j=0;j<=i;++j) fC[ii++] -= ki*mCHt[j]; - } -} - - -void KFParticleBase::SetNoDecayLength() -{ - //* Set no decay length for resonances - - TransportToDecayVertex(); - - Double_t h[8]; - h[0] = h[1] = h[2] = h[3] = h[4] = h[5] = h[6] = 0; - h[7] = 1; - - Double_t zeta = 0 - fP[7]; - for(Int_t i=0;i<8;++i) zeta -= h[i]*(fP[i]-fP[i]); - - Double_t 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 ){ - Double_t 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] = 0;fC[29] = 0;fC[30] = 0;fC[31] = 0;fC[32] = 0;fC[33] = 0;fC[35] = 0;fC[35] = 0; -} - - -void KFParticleBase::Construct( const KFParticleBase* vDaughters[], Int_t NDaughters, - const KFParticleBase *Parent, Double_t Mass, Bool_t IsConstrained ) -{ - //* Full reconstruction in one go - - Int_t maxIter = 1; - Bool_t wasLinearized = fIsLinearized; - if( !fIsLinearized || IsConstrained ){ - //fVtxGuess[0] = fVtxGuess[1] = fVtxGuess[2] = 0; //!!!! - fVtxGuess[0] = GetX(); - fVtxGuess[1] = GetY(); - fVtxGuess[2] = GetZ(); - fIsLinearized = 1; - maxIter = 3; - } - - Double_t constraintC[6]; - - if( IsConstrained ){ - for(Int_t i=0;i<6;++i) constraintC[i]=fC[i]; - } else { - for(Int_t i=0;i<6;++i) constraintC[i]=0.; - constraintC[0] = constraintC[2] = constraintC[5] = 100.; - } - - - for( Int_t iter=0; iter=0 ) SetMassConstraint( Mass ); - if( Parent ) SetProductionVertex( *Parent ); -} - - -void KFParticleBase::Convert( Bool_t ToProduction ) -{ - //* Tricky function - convert the particle error along its trajectory to - //* the value which corresponds to its production/decay vertex - //* It is done by combination of the error of decay length with the position errors - - Double_t fld[3]; - { - GetFieldValue( fP, fld ); - const Double_t kCLight = fQ*0.000299792458; - fld[0]*=kCLight; fld[1]*=kCLight; fld[2]*=kCLight; - } - - Double_t h[6]; - - h[0] = fP[3]; - h[1] = fP[4]; - h[2] = fP[5]; - if( ToProduction ){ h[0]=-h[0]; h[1]=-h[1]; h[2]=-h[2]; } - h[3] = h[1]*fld[2]-h[2]*fld[1]; - h[4] = h[2]*fld[0]-h[0]*fld[2]; - h[5] = h[0]*fld[1]-h[1]*fld[0]; - - Double_t c; - - c = fC[28]+h[0]*fC[35]; - fC[ 0]+= h[0]*(c+fC[28]); - fC[28] = c; - - fC[ 1]+= h[1]*fC[28] + h[0]*fC[29]; - c = fC[29]+h[1]*fC[35]; - fC[ 2]+= h[1]*(c+fC[29]); - fC[29] = c; - - fC[ 3]+= h[2]*fC[28] + h[0]*fC[30]; - fC[ 4]+= h[2]*fC[29] + h[1]*fC[30]; - c = fC[30]+h[2]*fC[35]; - fC[ 5]+= h[2]*(c+fC[30]); - fC[30] = c; - - fC[ 6]+= h[3]*fC[28] + h[0]*fC[31]; - fC[ 7]+= h[3]*fC[29] + h[1]*fC[31]; - fC[ 8]+= h[3]*fC[30] + h[2]*fC[31]; - c = fC[31]+h[3]*fC[35]; - fC[ 9]+= h[3]*(c+fC[31]); - fC[31] = c; - - fC[10]+= h[4]*fC[28] + h[0]*fC[32]; - fC[11]+= h[4]*fC[29] + h[1]*fC[32]; - fC[12]+= h[4]*fC[30] + h[2]*fC[32]; - fC[13]+= h[4]*fC[31] + h[3]*fC[32]; - c = fC[32]+h[4]*fC[35]; - fC[14]+= h[4]*(c+fC[32]); - fC[32] = c; - - fC[15]+= h[5]*fC[28] + h[0]*fC[33]; - fC[16]+= h[5]*fC[29] + h[1]*fC[33]; - fC[17]+= h[5]*fC[30] + h[2]*fC[33]; - fC[18]+= h[5]*fC[31] + h[3]*fC[33]; - fC[19]+= h[5]*fC[32] + h[4]*fC[33]; - c = fC[33]+h[5]*fC[35]; - fC[20]+= h[5]*(c+fC[33]); - fC[33] = c; - - fC[21]+= h[0]*fC[34]; - fC[22]+= h[1]*fC[34]; - fC[23]+= h[2]*fC[34]; - fC[24]+= h[3]*fC[34]; - fC[25]+= h[4]*fC[34]; - fC[26]+= h[5]*fC[34]; -} - - -void KFParticleBase::TransportToDecayVertex() -{ - //* Transport the particle to its decay vertex - - if( fSFromDecay != 0 ) TransportToDS( -fSFromDecay ); - if( fAtProductionVertex ) Convert(0); - fAtProductionVertex = 0; -} - -void KFParticleBase::TransportToProductionVertex() -{ - //* Transport the particle to its production vertex - - if( fSFromDecay != -fP[7] ) TransportToDS( -fSFromDecay-fP[7] ); - if( !fAtProductionVertex ) Convert( 1 ); - fAtProductionVertex = 1; -} - - -void KFParticleBase::TransportToDS( Double_t dS ) -{ - //* Transport the particle on dS parameter (SignedPath/Momentum) - - Transport( dS, fP, fC ); - fSFromDecay+= dS; -} - - -Double_t KFParticleBase::GetDStoPointLine( const Double_t xyz[] ) const -{ - //* Get dS to a certain space point without field - - Double_t p2 = fP[3]*fP[3] + fP[4]*fP[4] + fP[5]*fP[5]; - if( p2<1.e-4 ) p2 = 1; - return ( fP[3]*(xyz[0]-fP[0]) + fP[4]*(xyz[1]-fP[1]) + fP[5]*(xyz[2]-fP[2]) )/p2; -} - - -Double_t KFParticleBase::GetDStoPointBz( Double_t B, const Double_t xyz[] ) - const -{ - - //* Get dS to a certain space point for Bz field - const Double_t kCLight = 0.000299792458; - Double_t bq = B*fQ*kCLight; - Double_t pt2 = fP[3]*fP[3] + fP[4]*fP[4]; - if( pt2<1.e-4 ) return 0; - Double_t dx = xyz[0] - fP[0]; - Double_t dy = xyz[1] - fP[1]; - Double_t a = dx*fP[3]+dy*fP[4]; - Double_t dS; - - if( TMath::Abs(bq)<1.e-8 ) dS = a/pt2; - else dS = TMath::ATan2( bq*a, pt2 + bq*(dy*fP[3] -dx*fP[4]) )/bq; - - if(0){ - - Double_t px = fP[3]; - Double_t py = fP[4]; - Double_t pz = fP[5]; - Double_t ss[2], g[2][5]; - - ss[0] = dS; - ss[1] = -dS; - for( Int_t i=0; i<2; i++){ - Double_t bs = bq*ss[i]; - Double_t c = TMath::Cos(bs), s = TMath::Sin(bs); - Double_t cB,sB; - if( TMath::Abs(bq)>1.e-8){ - cB= (1-c)/bq; - sB= s/bq; - }else{ - const Double_t kOvSqr6 = 1./TMath::Sqrt(6.); - sB = (1.-bs*kOvSqr6)*(1.+bs*kOvSqr6)*ss[i]; - cB = .5*sB*bs; - } - g[i][0] = fP[0] + sB*px + cB*py; - g[i][1] = fP[1] - cB*px + sB*py; - g[i][2] = fP[2] + ss[i]*pz; - g[i][3] = + c*px + s*py; - g[i][4] = - s*px + c*py; - } - - Int_t i=0; - - Double_t dMin = 1.e10; - for( Int_t j=0; j<2; j++){ - Double_t xx = g[j][0]-xyz[0]; - Double_t yy = g[j][1]-xyz[1]; - Double_t zz = g[j][2]-xyz[2]; - Double_t d = xx*xx + yy*yy + zz*zz; - if( d1.e-8 ){ - dS+=c/pp2; - } - } - return dS; -} - - -void KFParticleBase::GetDStoParticleBz( Double_t B, const KFParticleBase &p, - Double_t &DS, Double_t &DS1 ) - const -{ - //* Get dS to another particle for Bz field - Double_t px = fP[3]; - Double_t py = fP[4]; - Double_t pz = fP[5]; - - Double_t px1 = p.fP[3]; - Double_t py1 = p.fP[4]; - Double_t pz1 = p.fP[5]; - - const Double_t kCLight = 0.000299792458; - - Double_t bq = B*fQ*kCLight; - Double_t bq1 = B*p.fQ*kCLight; - Double_t s=0, ds=0, s1=0, ds1=0; - - if( TMath::Abs(bq)>1.e-8 || TMath::Abs(bq1)>1.e-8 ){ - - Double_t dx = (p.fP[0] - fP[0]); - Double_t dy = (p.fP[1] - fP[1]); - Double_t d2 = (dx*dx+dy*dy); - - Double_t p2 = (px *px + py *py); - Double_t p21 = (px1*px1 + py1*py1); - - Double_t a = (px*py1 - py*px1); - Double_t b = (px*px1 + py*py1); - - Double_t ldx = bq*bq1*dx - bq1*py + bq*py1 ; - Double_t ldy = bq*bq1*dy + bq1*px - bq*px1 ; - Double_t l2 = ldx*ldx + ldy*ldy; - - Double_t cS = bq1*p2 + bq*bq1*(dy* px - dx* py) - bq*b; - Double_t cS1= bq*p21 - bq*bq1*(dy*px1 - dx*py1) - bq1*b; - - Double_t ca = bq*bq*bq1*d2 +2*( cS + bq*bq*(py1*dx-px1*dy)) ; - Double_t ca1 = bq*bq1*bq1*d2 +2*( cS1 - bq1*bq1*(py*dx-px*dy)) ; - - Double_t sa = 4*l2*p2 - ca*ca; - Double_t sa1 = 4*l2*p21 - ca1*ca1; - - if(sa<0) sa=0; - if(sa1<0)sa1=0; - - if( TMath::Abs(bq)>1.e-8){ - s = TMath::ATan2( bq*( bq1*(dx*px +dy*py) + a ) , cS )/bq; - ds = TMath::ATan2(TMath::Sqrt(sa),ca)/bq; - } else { - s = ( (dx*px + dy*py) + (py*px1-px*py1)/bq1)/p2; - ds = s*s - (d2-2*(px1*dy-py1*dx)/bq1)/p2; - if( ds<0 ) ds = 0; - ds = TMath::Sqrt(ds); - } - - if( TMath::Abs(bq1)>1.e-8){ - s1 = TMath::ATan2( -bq1*( bq*(dx*px1+dy*py1) + a), cS1 )/bq1; - ds1 = TMath::ATan2(TMath::Sqrt(sa1),ca1)/bq1; - } else { - s1 = (-(dx*px1 + dy*py1) + (py*px1-px*py1)/bq)/p21; - ds1 = s1*s1 - (d2+2*(px*dy-py*dx)/bq)/p21; - if( ds1<0 ) ds1 = 0; - ds1 = TMath::Sqrt(ds1); - } - } - - Double_t ss[2], ss1[2], g[2][5],g1[2][5]; - - ss[0] = s + ds; - ss[1] = s - ds; - ss1[0] = s1 + ds1; - ss1[1] = s1 - ds1; - for( Int_t i=0; i<2; i++){ - Double_t bs = bq*ss[i]; - Double_t c = TMath::Cos(bs), sss = TMath::Sin(bs); - Double_t cB,sB; - if( TMath::Abs(bq)>1.e-8){ - cB= (1-c)/bq; - sB= sss/bq; - }else{ - const Double_t kOvSqr6 = 1./TMath::Sqrt(6.); - sB = (1.-bs*kOvSqr6)*(1.+bs*kOvSqr6)*ss[i]; - cB = .5*sB*bs; - } - g[i][0] = fP[0] + sB*px + cB*py; - g[i][1] = fP[1] - cB*px + sB*py; - g[i][2] = fP[2] + ss[i]*pz; - g[i][3] = + c*px + sss*py; - g[i][4] = - sss*px + c*py; - - bs = bq1*ss1[i]; - c = TMath::Cos(bs); sss = TMath::Sin(bs); - if( TMath::Abs(bq1)>1.e-8){ - cB= (1-c)/bq1; - sB= sss/bq1; - }else{ - const Double_t kOvSqr6 = 1./TMath::Sqrt(6.); - sB = (1.-bs*kOvSqr6)*(1.+bs*kOvSqr6)*ss1[i]; - cB = .5*sB*bs; - } - - g1[i][0] = p.fP[0] + sB*px1 + cB*py1; - g1[i][1] = p.fP[1] - cB*px1 + sB*py1; - g1[i][2] = p.fP[2] + ss[i]*pz1; - g1[i][3] = + c*px1 + sss*py1; - g1[i][4] = - sss*px1 + c*py1; - } - - Int_t i=0, i1=0; - - Double_t dMin = 1.e10; - for( Int_t j=0; j<2; j++){ - for( Int_t j1=0; j1<2; j1++){ - Double_t xx = g[j][0]-g1[j1][0]; - Double_t yy = g[j][1]-g1[j1][1]; - Double_t zz = g[j][2]-g1[j1][2]; - Double_t d = xx*xx + yy*yy + zz*zz; - if( d1.e-8 ){ - DS+=(a*b-pp21*c)/det; - DS1+=(a*c-pp2*b)/det; - } - } -} - - - -void KFParticleBase::TransportCBM( Double_t dS, - Double_t P[], Double_t C[] ) const -{ - //* Transport the particle on dS, output to P[],C[], for CBM field - - if( fQ==0 ){ - TransportLine( dS, P, C ); - return; - } - - const Double_t kCLight = 0.000299792458; - - Double_t c = fQ*kCLight; - - // construct coefficients - - Double_t - px = fP[3], - py = fP[4], - pz = fP[5]; - - Double_t 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 - - Double_t fld[3][3]; - Double_t 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] ); - - Double_t ssy1 = ( 7*fld[0][1] + 6*fld[1][1]-fld[2][1] )*c*dS*dS/96.; - Double_t 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.; - - Double_t c2[3][3] = { { 5, -4, -1},{ 44, 80, -4},{ 11, 44, 5} }; // /=360. - Double_t 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.; - - } - - Double_t 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]; - - MultQSQt( mJ[0], fC, C); - -} - - -void KFParticleBase::TransportBz( Double_t b, Double_t t, - Double_t p[], Double_t e[] ) const -{ - //* Transport the particle on dS, output to P[],C[], for Bz field - - const Double_t kCLight = 0.000299792458; - b = b*fQ*kCLight; - Double_t bs= b*t; - Double_t s = TMath::Sin(bs), c = TMath::Cos(bs); - Double_t sB, cB; - if( TMath::Abs(bs)>1.e-10){ - sB= s/b; - cB= (1-c)/b; - }else{ - const Double_t kOvSqr6 = 1./TMath::Sqrt(6.); - sB = (1.-bs*kOvSqr6)*(1.+bs*kOvSqr6)*t; - cB = .5*sB*bs; - } - - Double_t px = fP[3]; - Double_t py = fP[4]; - Double_t pz = fP[5]; - - p[0] = fP[0] + sB*px + cB*py; - p[1] = fP[1] - cB*px + sB*py; - p[2] = fP[2] + t*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]; - - /* - Double_t mJ[8][8] = { {1,0,0, sB, cB, 0, 0, 0 }, - {0,1,0, -cB, sB, 0, 0, 0 }, - {0,0,1, 0, 0, t, 0, 0 }, - {0,0,0, c, s, 0, 0, 0 }, - {0,0,0, -s, c, 0, 0, 0 }, - {0,0,0, 0, 0, 1, 0, 0 }, - {0,0,0, 0, 0, 0, 1, 0 }, - {0,0,0, 0, 0, 0, 0, 1 } }; - Double_t mA[8][8]; - for( Int_t k=0,i=0; i<8; i++) - for( Int_t j=0; j<=i; j++, k++ ) mA[i][j] = mA[j][i] = fC[k]; - - Double_t mJC[8][8]; - for( Int_t i=0; i<8; i++ ) - for( Int_t j=0; j<8; j++ ){ - mJC[i][j]=0; - for( Int_t k=0; k<8; k++ ) mJC[i][j]+=mJ[i][k]*mA[k][j]; - } - - for( Int_t k=0,i=0; i<8; i++) - for( Int_t j=0; j<=i; j++, k++ ){ - e[k] = 0; - for( Int_t l=0; l<8; l++ ) e[k]+=mJC[i][l]*mJ[j][l]; - } - - return; - */ - - Double_t - c6=fC[6], c7=fC[7], c8=fC[8], c17=fC[17], c18=fC[18], - c24 = fC[24], c31 = fC[31]; - - Double_t - cBC13 = cB*fC[13], - mJC13 = c7 - cB*fC[9] + sB*fC[13], - mJC14 = fC[11] - cBC13 + sB*fC[14], - mJC23 = c8 + t*c18, - mJC24 = fC[12] + t*fC[19], - mJC33 = c*fC[9] + s*fC[13], - mJC34 = c*fC[13] + s*fC[14], - mJC43 = -s*fC[9] + c*fC[13], - mJC44 = -s*fC[13] + c*fC[14]; - - - e[0]= fC[0] + 2*(sB*c6 + cB*fC[10]) + (sB*fC[9] + 2*cBC13)*sB + cB*cB*fC[14]; - e[1]= fC[1] - cB*c6 + sB*fC[10] + mJC13*sB + mJC14*cB; - e[2]= fC[2] - cB*c7 + sB*fC[11] - mJC13*cB + mJC14*sB; - e[3]= fC[3] + t*fC[15] + mJC23*sB + mJC24*cB; - e[4]= fC[4] + t*fC[16] - mJC23*cB + mJC24*sB; - - e[15]= fC[15] + c18*sB + fC[19]*cB; - e[16]= fC[16] - c18*cB + fC[19]*sB; - e[17]= c17 + fC[20]*t; - e[18]= c18*c + fC[19]*s; - e[19]= -c18*s + fC[19]*c; - - e[5]= fC[5] + (c17 + e[17] )*t; - - e[6]= c*c6 + s*fC[10] + mJC33*sB + mJC34*cB; - e[7]= c*c7 + s*fC[11] - mJC33*cB + mJC34*sB; - e[8]= c*c8 + s*fC[12] + e[18]*t; - e[9]= mJC33*c + mJC34*s; - e[10]= -s*c6 + c*fC[10] + mJC43*sB + mJC44*cB; - - - e[11]= -s*c7 + c*fC[11] - mJC43*cB + mJC44*sB; - e[12]= -s*c8 + c*fC[12] + e[19]*t; - e[13]= mJC43*c + mJC44*s; - e[14]= -mJC43*s + mJC44*c; - e[20]= fC[20]; - e[21]= fC[21] + fC[25]*cB + c24*sB; - e[22]= fC[22] - c24*cB + fC[25]*sB; - e[23]= fC[23] + fC[26]*t; - e[24]= c*c24 + s*fC[25]; - e[25]= c*fC[25] - c24*s; - e[26]= fC[26]; - e[27]= fC[27]; - e[28]= fC[28] + fC[32]*cB + c31*sB; - e[29]= fC[29] - c31*cB + fC[32]*sB; - e[30]= fC[30] + fC[33]*t; - e[31]= c*c31 + s*fC[32]; - e[32]= c*fC[32] - s*c31; - e[33]= fC[33]; - e[34]= fC[34]; - e[35]= fC[35]; -} - - -Double_t KFParticleBase::GetDistanceFromVertex( const KFParticleBase &Vtx ) const -{ - //* Calculate distance from vertex [cm] - - return GetDistanceFromVertex( Vtx.fP ); -} - -Double_t KFParticleBase::GetDistanceFromVertex( const Double_t vtx[] ) const -{ - //* Calculate distance from vertex [cm] - - Double_t mP[8], mC[36]; - Transport( GetDStoPoint(vtx), mP, mC ); - Double_t d[3]={ vtx[0]-mP[0], vtx[1]-mP[1], vtx[2]-mP[2]}; - return TMath::Sqrt( d[0]*d[0]+d[1]*d[1]+d[2]*d[2] ); -} - -Double_t KFParticleBase::GetDistanceFromParticle( const KFParticleBase &p ) - const -{ - //* Calculate distance to other particle [cm] - - Double_t dS, dS1; - GetDStoParticle( p, dS, dS1 ); - Double_t mP[8], mC[36], mP1[8], mC1[36]; - Transport( dS, mP, mC ); - p.Transport( dS1, mP1, mC1 ); - Double_t dx = mP[0]-mP1[0]; - Double_t dy = mP[1]-mP1[1]; - Double_t dz = mP[2]-mP1[2]; - return TMath::Sqrt(dx*dx+dy*dy+dz*dz); -} - -Double_t KFParticleBase::GetDeviationFromVertex( const KFParticleBase &Vtx ) const -{ - //* Calculate sqrt(Chi2/ndf) deviation from vertex - - return GetDeviationFromVertex( Vtx.fP, Vtx.fC ); -} - - -Double_t KFParticleBase::GetDeviationFromVertex( const Double_t v[], const Double_t Cv[] ) const -{ - //* Calculate sqrt(Chi2/ndf) deviation from vertex - //* v = [xyz], Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix - - Double_t mP[8]; - Double_t mC[36]; - Double_t dS = GetDStoPoint(v); - Transport(dS , mP, mC ); - - Double_t d[3]={ v[0]-mP[0], v[1]-mP[1], v[2]-mP[2]}; - - Double_t sigmaS = .1+10.*TMath::Sqrt( (d[0]*d[0]+d[1]*d[1]+d[2]*d[2])/ - (mP[3]*mP[3]+mP[4]*mP[4]+mP[5]*mP[5]) ); - - - Double_t h[3] = { mP[3]*sigmaS, mP[4]*sigmaS, mP[5]*sigmaS }; - - Double_t mSi[6] = - { mC[0] +h[0]*h[0], - mC[1] +h[1]*h[0], mC[2] +h[1]*h[1], - mC[3] +h[2]*h[0], mC[4] +h[2]*h[1], mC[5] +h[2]*h[2] }; - - if( Cv ){ - mSi[0]+=Cv[0]; - mSi[1]+=Cv[1]; - mSi[2]+=Cv[2]; - mSi[3]+=Cv[3]; - mSi[4]+=Cv[4]; - mSi[5]+=Cv[5]; - } - - Double_t mS[6]; - - mS[0] = mSi[2]*mSi[5] - mSi[4]*mSi[4]; - mS[1] = mSi[3]*mSi[4] - mSi[1]*mSi[5]; - mS[2] = mSi[0]*mSi[5] - mSi[3]*mSi[3]; - mS[3] = mSi[1]*mSi[4] - mSi[2]*mSi[3]; - mS[4] = mSi[1]*mSi[3] - mSi[0]*mSi[4]; - mS[5] = mSi[0]*mSi[2] - mSi[1]*mSi[1]; - - Double_t s = ( mSi[0]*mS[0] + mSi[1]*mS[1] + mSi[3]*mS[3] ); - s = ( s > 1.E-20 ) ?1./s :0; - - return TMath::Sqrt( TMath::Abs(s*( ( mS[0]*d[0] + mS[1]*d[1] + mS[3]*d[2])*d[0] - +(mS[1]*d[0] + mS[2]*d[1] + mS[4]*d[2])*d[1] - +(mS[3]*d[0] + mS[4]*d[1] + mS[5]*d[2])*d[2] ))/2); -} - - -Double_t KFParticleBase::GetDeviationFromParticle( const KFParticleBase &p ) - const -{ - //* Calculate sqrt(Chi2/ndf) deviation from other particle - - Double_t dS, dS1; - GetDStoParticle( p, dS, dS1 ); - Double_t mP1[8], mC1[36]; - p.Transport( dS1, mP1, mC1 ); - - Double_t d[3]={ fP[0]-mP1[0], fP[1]-mP1[1], fP[2]-mP1[2]}; - - Double_t sigmaS = .1+10.*TMath::Sqrt( (d[0]*d[0]+d[1]*d[1]+d[2]*d[2])/ - (mP1[3]*mP1[3]+mP1[4]*mP1[4]+mP1[5]*mP1[5]) ); - - Double_t h[3] = { mP1[3]*sigmaS, mP1[4]*sigmaS, mP1[5]*sigmaS }; - - mC1[0] +=h[0]*h[0]; - mC1[1] +=h[1]*h[0]; - mC1[2] +=h[1]*h[1]; - mC1[3] +=h[2]*h[0]; - mC1[4] +=h[2]*h[1]; - mC1[5] +=h[2]*h[2]; - - return GetDeviationFromVertex( mP1, mC1 )*TMath::Sqrt(2./1.); -} - - - -void KFParticleBase::SubtractFromVertex( KFParticleBase &Vtx ) const -{ - //* Subtract the particle from the vertex - - Double_t fld[3]; - { - GetFieldValue( Vtx.fP, fld ); - const Double_t kCLight = 0.000299792458; - fld[0]*=kCLight; fld[1]*=kCLight; fld[2]*=kCLight; - } - - Double_t m[8]; - Double_t mCm[36]; - - if( Vtx.fIsLinearized ){ - GetMeasurement( Vtx.fVtxGuess, m, mCm ); - } else { - GetMeasurement( Vtx.fP, m, mCm ); - } - - Double_t mV[6]; - - mV[ 0] = mCm[ 0]; - mV[ 1] = mCm[ 1]; - mV[ 2] = mCm[ 2]; - mV[ 3] = mCm[ 3]; - mV[ 4] = mCm[ 4]; - mV[ 5] = mCm[ 5]; - - //* - - Double_t mS[6] = { mV[0]-Vtx.fC[0], - mV[1]-Vtx.fC[1], mV[2]-Vtx.fC[2], - mV[3]-Vtx.fC[3], mV[4]-Vtx.fC[4], mV[5]-Vtx.fC[5] }; - InvertCholetsky3(mS); - //* Residual (measured - estimated) - - Double_t zeta[3] = { m[0]-Vtx.fP[0], m[1]-Vtx.fP[1], m[2]-Vtx.fP[2] }; - - //* mCHt = mCH' - D' - - Double_t 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 - - Double_t 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 - - Double_t 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( Vtx.fChi2 - dChi2 < 0 ) return; - - 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 particle from the mother particle - - Double_t m[8]; - Double_t mV[36]; - - if( Vtx.fIsLinearized ){ - GetMeasurement( Vtx.fVtxGuess, m, mV ); - } else { - GetMeasurement( Vtx.fP, m, mV ); - } - - Double_t mS[6]= { mV[0] - Vtx.fC[0], - mV[1] - Vtx.fC[1], mV[2] - Vtx.fC[2], - mV[3] - Vtx.fC[3], mV[4] - Vtx.fC[4], mV[5] - Vtx.fC[5] }; - InvertCholetsky3(mS); - - //* Residual (measured - estimated) - - Double_t zeta[3] = { m[0]-Vtx.fP[0], m[1]-Vtx.fP[1], m[2]-Vtx.fP[2] }; - - //* CHt = CH' - D' - - Double_t 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 - - Double_t 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')' - - Double_t 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( Double_t dS, - Double_t P[], Double_t C[] ) const -{ - //* Transport the particle as a straight line - - 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]; - - Double_t c6 = fC[ 6] + dS*fC[ 9]; - Double_t c11 = fC[11] + dS*fC[14]; - Double_t c17 = fC[17] + dS*fC[20]; - Double_t sc13 = dS*fC[13]; - Double_t sc18 = dS*fC[18]; - Double_t sc19 = dS*fC[19]; - - C[ 0] = fC[ 0] + dS*( fC[ 6] + c6 ); - C[ 2] = fC[ 2] + dS*( fC[11] + c11 ); - C[ 5] = fC[ 5] + dS*( fC[17] + c17 ); - - C[ 7] = fC[ 7] + sc13; - C[ 8] = fC[ 8] + sc18; - C[ 9] = fC[ 9]; - - C[12] = fC[12] + sc19; - - C[ 1] = fC[ 1] + dS*( fC[10] + C[ 7] ); - C[ 3] = fC[ 3] + dS*( fC[15] + C[ 8] ); - C[ 4] = fC[ 4] + dS*( fC[16] + C[12] ); - C[ 6] = c6; - - C[10] = fC[10] + sc13; - C[11] = c11; - - C[13] = fC[13]; - C[14] = fC[14]; - C[15] = fC[15] + sc18; - C[16] = fC[16] + sc19; - C[17] = c17; - - C[18] = fC[18]; - C[19] = fC[19]; - C[20] = fC[20]; - C[21] = fC[21] + dS*fC[24]; - C[22] = fC[22] + dS*fC[25]; - C[23] = fC[23] + dS*fC[26]; - - C[24] = fC[24]; - C[25] = fC[25]; - C[26] = fC[26]; - C[27] = fC[27]; - C[28] = fC[28] + dS*fC[31]; - C[29] = fC[29] + dS*fC[32]; - C[30] = fC[30] + dS*fC[33]; - - C[31] = fC[31]; - C[32] = fC[32]; - C[33] = fC[33]; - C[34] = fC[34]; - C[35] = fC[35]; -} - - -void KFParticleBase::ConstructGammaBz( const KFParticleBase &daughter1, - const KFParticleBase &daughter2, Double_t Bz ) -{ - //* Create gamma - - const KFParticleBase *daughters[2] = { &daughter1, &daughter2}; - - Double_t v0[3]; - - if( !fIsLinearized ){ - Double_t ds, ds1; - Double_t m[8]; - Double_t mCd[36]; - daughter1.GetDStoParticle(daughter2, ds, ds1); - daughter1.Transport( ds, m, mCd ); - v0[0] = m[0]; - v0[1] = m[1]; - v0[2] = m[2]; - daughter2.Transport( ds1, m, mCd ); - v0[0] = .5*( v0[0] + m[0] ); - v0[1] = .5*( v0[1] + m[1] ); - v0[2] = .5*( v0[2] + m[2] ); - } else { - v0[0] = fVtxGuess[0]; - v0[1] = fVtxGuess[1]; - v0[2] = fVtxGuess[2]; - } - - fAtProductionVertex = 0; - fSFromDecay = 0; - fP[0] = v0[0]; - fP[1] = v0[1]; - fP[2] = v0[2]; - fP[3] = 0; - fP[4] = 0; - fP[5] = 0; - fP[6] = 0; - fP[7] = 0; - - - // fit daughters to the vertex guess - - Double_t daughterP[2][8], daughterC[2][36]; - Double_t vtxMom[2][3]; - - { - for( Int_t id=0; id<2; id++ ){ - - Double_t *p = daughterP[id]; - Double_t *mC = daughterC[id]; - - daughters[id]->GetMeasurement( v0, p, mC ); - - Double_t mAi[6]; - for(int i=0; i<6; i++) mAi[i] = mC[i]; - InvertCholetsky3(mAi); - //InvertSym3(mC, mAi ); - - Double_t mB[3][3]; - - mB[0][0] = mC[ 6]*mAi[0] + mC[ 7]*mAi[1] + mC[ 8]*mAi[3]; - mB[0][1] = mC[ 6]*mAi[1] + mC[ 7]*mAi[2] + mC[ 8]*mAi[4]; - mB[0][2] = mC[ 6]*mAi[3] + mC[ 7]*mAi[4] + mC[ 8]*mAi[5]; - - mB[1][0] = mC[10]*mAi[0] + mC[11]*mAi[1] + mC[12]*mAi[3]; - mB[1][1] = mC[10]*mAi[1] + mC[11]*mAi[2] + mC[12]*mAi[4]; - mB[1][2] = mC[10]*mAi[3] + mC[11]*mAi[4] + mC[12]*mAi[5]; - - mB[2][0] = mC[15]*mAi[0] + mC[16]*mAi[1] + mC[17]*mAi[3]; - mB[2][1] = mC[15]*mAi[1] + mC[16]*mAi[2] + mC[17]*mAi[4]; - mB[2][2] = mC[15]*mAi[3] + mC[16]*mAi[4] + mC[17]*mAi[5]; - - Double_t z[3] = { v0[0]-p[0], v0[1]-p[1], v0[2]-p[2] }; - - vtxMom[id][0] = p[3] + mB[0][0]*z[0] + mB[0][1]*z[1] + mB[0][2]*z[2]; - vtxMom[id][1] = p[4] + mB[1][0]*z[0] + mB[1][1]*z[1] + mB[1][2]*z[2]; - vtxMom[id][2] = p[5] + mB[2][0]*z[0] + mB[2][1]*z[1] + mB[2][2]*z[2]; - - daughters[id]->Transport( daughters[id]->GetDStoPoint(v0), p, mC ); - - } - - } // fit daughters to guess - - - // fit new vertex - { - - Double_t mpx0 = vtxMom[0][0]+vtxMom[1][0]; - Double_t mpy0 = vtxMom[0][1]+vtxMom[1][1]; - Double_t mpt0 = TMath::Sqrt(mpx0*mpx0 + mpy0*mpy0); - // Double_t a0 = TMath::ATan2(mpy0,mpx0); - - Double_t ca0 = mpx0/mpt0; - Double_t sa0 = mpy0/mpt0; - Double_t r[3] = { v0[0], v0[1], v0[2] }; - Double_t mC[3][3] = {{10000., 0 , 0 }, - {0, 10000., 0 }, - {0, 0, 10000. } }; - Double_t chi2=0; - - for( Int_t id=0; id<2; id++ ){ - const Double_t kCLight = 0.000299792458; - Double_t q = Bz*daughters[id]->GetQ()*kCLight; - Double_t px0 = vtxMom[id][0]; - Double_t py0 = vtxMom[id][1]; - Double_t pz0 = vtxMom[id][2]; - Double_t pt0 = TMath::Sqrt(px0*px0+py0*py0); - Double_t mG[3][6], mB[3], mH[3][3]; - // r = {vx,vy,vz}; - // m = {x,y,z,Px,Py,Pz}; - // V = daughter.C - // G*m + B = H*r; - // q*x + Py - q*vx - sin(a)*Pt = 0 - // q*y - Px - q*vy + cos(a)*Pt = 0 - // (Px*cos(a) + Py*sin(a) ) (vz -z) - Pz( cos(a)*(vx-x) + sin(a)*(vy-y)) = 0 - - mG[0][0] = q; - mG[0][1] = 0; - mG[0][2] = 0; - mG[0][3] = -sa0*px0/pt0; - mG[0][4] = 1 -sa0*py0/pt0; - mG[0][5] = 0; - mH[0][0] = q; - mH[0][1] = 0; - mH[0][2] = 0; - mB[0] = py0 - sa0*pt0 - mG[0][3]*px0 - mG[0][4]*py0 ; - - // q*y - Px - q*vy + cos(a)*Pt = 0 - - mG[1][0] = 0; - mG[1][1] = q; - mG[1][2] = 0; - mG[1][3] = -1 + ca0*px0/pt0; - mG[1][4] = + ca0*py0/pt0; - mG[1][5] = 0; - mH[1][0] = 0; - mH[1][1] = q; - mH[1][2] = 0; - mB[1] = -px0 + ca0*pt0 - mG[1][3]*px0 - mG[1][4]*py0 ; - - // (Px*cos(a) + Py*sin(a) ) (z -vz) - Pz( cos(a)*(x-vx) + sin(a)*(y-vy)) = 0 - - mG[2][0] = -pz0*ca0; - mG[2][1] = -pz0*sa0; - mG[2][2] = px0*ca0 + py0*sa0; - mG[2][3] = 0; - mG[2][4] = 0; - mG[2][5] = 0; - - mH[2][0] = mG[2][0]; - mH[2][1] = mG[2][1]; - mH[2][2] = mG[2][2]; - - mB[2] = 0; - - // fit the vertex - - // V = GVGt - - Double_t mGV[3][6]; - Double_t mV[6]; - Double_t m[3]; - for( Int_t i=0; i<3; i++ ){ - m[i] = mB[i]; - for( Int_t k=0; k<6; k++ ) m[i]+=mG[i][k]*daughterP[id][k]; - } - for( Int_t i=0; i<3; i++ ){ - for( Int_t j=0; j<6; j++ ){ - mGV[i][j] = 0; - for( Int_t k=0; k<6; k++ ) mGV[i][j]+=mG[i][k]*daughterC[id][ IJ(k,j) ]; - } - } - for( Int_t i=0, k=0; i<3; i++ ){ - for( Int_t j=0; j<=i; j++,k++ ){ - mV[k] = 0; - for( Int_t l=0; l<6; l++ ) mV[k]+=mGV[i][l]*mG[j][l]; - } - } - - - //* CHt - - Double_t mCHt[3][3]; - Double_t mHCHt[6]; - Double_t mHr[3]; - for( Int_t i=0; i<3; i++ ){ - mHr[i] = 0; - for( Int_t k=0; k<3; k++ ) mHr[i]+= mH[i][k]*r[k]; - } - - for( Int_t i=0; i<3; i++ ){ - for( Int_t j=0; j<3; j++){ - mCHt[i][j] = 0; - for( Int_t k=0; k<3; k++ ) mCHt[i][j]+= mC[i][k]*mH[j][k]; - } - } - - for( Int_t i=0, k=0; i<3; i++ ){ - for( Int_t j=0; j<=i; j++, k++ ){ - mHCHt[k] = 0; - for( Int_t l=0; l<3; l++ ) mHCHt[k]+= mH[i][l]*mCHt[l][j]; - } - } - - Double_t mS[6] = { mHCHt[0]+mV[0], - mHCHt[1]+mV[1], mHCHt[2]+mV[2], - mHCHt[3]+mV[3], mHCHt[4]+mV[4], mHCHt[5]+mV[5] }; - - - //InvertSym3(mS,mS); - InvertCholetsky3(mS); - - //* Residual (measured - estimated) - - Double_t zeta[3] = { m[0]-mHr[0], m[1]-mHr[1], m[2]-mHr[2] }; - - //* Kalman gain K = mCH'*S - - Double_t k[3][3]; - - for(Int_t i=0;i<3;++i){ - k[i][0] = mCHt[i][0]*mS[0] + mCHt[i][1]*mS[1] + mCHt[i][2]*mS[3]; - k[i][1] = mCHt[i][0]*mS[1] + mCHt[i][1]*mS[2] + mCHt[i][2]*mS[4]; - k[i][2] = mCHt[i][0]*mS[3] + mCHt[i][1]*mS[4] + mCHt[i][2]*mS[5]; - } - - //* New estimation of the vertex position r += K*zeta - - for(Int_t i=0;i<3;++i) - r[i] = r[i] + k[i][0]*zeta[0] + k[i][1]*zeta[1] + k[i][2]*zeta[2]; - - //* New covariance matrix C -= K*(mCH')' - - for(Int_t i=0;i<3;++i){ - for(Int_t j=0;j<=i;++j){ - mC[i][j] = mC[i][j] - (k[i][0]*mCHt[j][0] + k[i][1]*mCHt[j][1] + k[i][2]*mCHt[j][2]); - mC[j][i] = mC[i][j]; - } - } - - - //* Calculate Chi^2 - - chi2 += ( ( 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] ); - } - - // store vertex - - fNDF = 2; - fChi2 = chi2; - for( Int_t i=0; i<3; i++ ) fP[i] = r[i]; - for( Int_t i=0,k=0; i<3; i++ ){ - for( Int_t j=0; j<=i; j++,k++ ){ - fC[k] = mC[i][j]; - } - } - } - - // now fit daughters to the vertex - - fQ = 0; - fSFromDecay = 0; - - for(Int_t i=3;i<8;++i) fP[i]=0.; - for(Int_t i=6;i<36;++i) fC[i]=0.; - - - for( Int_t id=0; id<2; id++ ){ - - Double_t *p = daughterP[id]; - Double_t *mC = daughterC[id]; - daughters[id]->GetMeasurement( v0, p, mC ); - - const Double_t *m = fP, *mV = fC; - - Double_t mAi[6]; - for(int i=0; i<6; i++) mAi[i] = mC[i]; - InvertCholetsky3(mAi); - //InvertSym3(mC, mAi ); - - Double_t mB[4][3]; - - mB[0][0] = mC[ 6]*mAi[0] + mC[ 7]*mAi[1] + mC[ 8]*mAi[3]; - mB[0][1] = mC[ 6]*mAi[1] + mC[ 7]*mAi[2] + mC[ 8]*mAi[4]; - mB[0][2] = mC[ 6]*mAi[3] + mC[ 7]*mAi[4] + mC[ 8]*mAi[5]; - - mB[1][0] = mC[10]*mAi[0] + mC[11]*mAi[1] + mC[12]*mAi[3]; - mB[1][1] = mC[10]*mAi[1] + mC[11]*mAi[2] + mC[12]*mAi[4]; - mB[1][2] = mC[10]*mAi[3] + mC[11]*mAi[4] + mC[12]*mAi[5]; - - mB[2][0] = mC[15]*mAi[0] + mC[16]*mAi[1] + mC[17]*mAi[3]; - mB[2][1] = mC[15]*mAi[1] + mC[16]*mAi[2] + mC[17]*mAi[4]; - mB[2][2] = mC[15]*mAi[3] + mC[16]*mAi[4] + mC[17]*mAi[5]; - - mB[3][0] = mC[21]*mAi[0] + mC[22]*mAi[1] + mC[23]*mAi[3]; - mB[3][1] = mC[21]*mAi[1] + mC[22]*mAi[2] + mC[23]*mAi[4]; - mB[3][2] = mC[21]*mAi[3] + mC[22]*mAi[4] + mC[23]*mAi[5]; - - - Double_t z[3] = { m[0]-p[0], m[1]-p[1], m[2]-p[2] }; - - { - Double_t mAV[6] = { mC[0]-mV[0], mC[1]-mV[1], mC[2]-mV[2], - mC[3]-mV[3], mC[4]-mV[4], mC[5]-mV[5] }; - - Double_t mAVi[6]; - for(int i=0; i<6; i++) mAVi[i] = mAV[i]; - InvertCholetsky3(mAVi); -// if( !InvertSym3(mAV, mAVi) ){ - Double_t dChi2 = ( +(mAVi[0]*z[0] + mAVi[1]*z[1] + mAVi[3]*z[2])*z[0] - +(mAVi[1]*z[0] + mAVi[2]*z[1] + mAVi[4]*z[2])*z[1] - +(mAVi[3]*z[0] + mAVi[4]*z[1] + mAVi[5]*z[2])*z[2] ); - fChi2+= TMath::Abs( dChi2 ); - // } - fNDF += 2; - } - - //* Add the daughter momentum to the particle momentum - - fP[3]+= p[3] + mB[0][0]*z[0] + mB[0][1]*z[1] + mB[0][2]*z[2]; - fP[4]+= p[4] + mB[1][0]*z[0] + mB[1][1]*z[1] + mB[1][2]*z[2]; - fP[5]+= p[5] + mB[2][0]*z[0] + mB[2][1]*z[1] + mB[2][2]*z[2]; - fP[6]+= p[6] + mB[3][0]*z[0] + mB[3][1]*z[1] + mB[3][2]*z[2]; - - Double_t d0, d1, d2; - - d0= mB[0][0]*mV[0] + mB[0][1]*mV[1] + mB[0][2]*mV[3] - mC[ 6]; - d1= mB[0][0]*mV[1] + mB[0][1]*mV[2] + mB[0][2]*mV[4] - mC[ 7]; - d2= mB[0][0]*mV[3] + mB[0][1]*mV[4] + mB[0][2]*mV[5] - mC[ 8]; - - //fC[6]+= mC[ 6] + d0; - //fC[7]+= mC[ 7] + d1; - //fC[8]+= mC[ 8] + d2; - fC[9]+= mC[ 9] + d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - - d0= mB[1][0]*mV[0] + mB[1][1]*mV[1] + mB[1][2]*mV[3] - mC[10]; - d1= mB[1][0]*mV[1] + mB[1][1]*mV[2] + mB[1][2]*mV[4] - mC[11]; - d2= mB[1][0]*mV[3] + mB[1][1]*mV[4] + mB[1][2]*mV[5] - mC[12]; - - //fC[10]+= mC[10]+ d0; - //fC[11]+= mC[11]+ d1; - //fC[12]+= mC[12]+ d2; - fC[13]+= mC[13]+ d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - fC[14]+= mC[14]+ d0*mB[1][0] + d1*mB[1][1] + d2*mB[1][2]; - - d0= mB[2][0]*mV[0] + mB[2][1]*mV[1] + mB[2][2]*mV[3] - mC[15]; - d1= mB[2][0]*mV[1] + mB[2][1]*mV[2] + mB[2][2]*mV[4] - mC[16]; - d2= mB[2][0]*mV[3] + mB[2][1]*mV[4] + mB[2][2]*mV[5] - mC[17]; - - //fC[15]+= mC[15]+ d0; - //fC[16]+= mC[16]+ d1; - //fC[17]+= mC[17]+ d2; - fC[18]+= mC[18]+ d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - fC[19]+= mC[19]+ d0*mB[1][0] + d1*mB[1][1] + d2*mB[1][2]; - fC[20]+= mC[20]+ d0*mB[2][0] + d1*mB[2][1] + d2*mB[2][2]; - - d0= mB[3][0]*mV[0] + mB[3][1]*mV[1] + mB[3][2]*mV[3] - mC[21]; - d1= mB[3][0]*mV[1] + mB[3][1]*mV[2] + mB[3][2]*mV[4] - mC[22]; - d2= mB[3][0]*mV[3] + mB[3][1]*mV[4] + mB[3][2]*mV[5] - mC[23]; - - //fC[21]+= mC[21] + d0; - //fC[22]+= mC[22] + d1; - //fC[23]+= mC[23] + d2; - fC[24]+= mC[24] + d0*mB[0][0] + d1*mB[0][1] + d2*mB[0][2]; - fC[25]+= mC[25] + d0*mB[1][0] + d1*mB[1][1] + d2*mB[1][2]; - fC[26]+= mC[26] + d0*mB[2][0] + d1*mB[2][1] + d2*mB[2][2]; - fC[27]+= mC[27] + d0*mB[3][0] + d1*mB[3][1] + d2*mB[3][2]; - } - - SetMassConstraint(0,0); - -} - -Bool_t KFParticleBase::InvertSym3( const Double_t A[], Double_t Ai[] ) -{ - //* Invert symmetric matric stored in low-triagonal form - - Bool_t ret = 0; - Double_t a0 = A[0], a1 = A[1], a2 = A[2], a3 = A[3]; - - Ai[0] = a2*A[5] - A[4]*A[4]; - Ai[1] = a3*A[4] - a1*A[5]; - Ai[3] = a1*A[4] - a2*a3; - Double_t det = (a0*Ai[0] + a1*Ai[1] + a3*Ai[3]); - if( det>1.e-20 ) det = 1./det; - else{ - det = 0; - ret = 1; - } - Ai[0] *= det; - Ai[1] *= det; - Ai[3] *= det; - Ai[2] = ( a0*A[5] - a3*a3 )*det; - Ai[4] = ( a1*a3 - a0*A[4] )*det; - Ai[5] = ( a0*a2 - a1*a1 )*det; - return ret; -} - -void KFParticleBase::InvertCholetsky3(Double_t a[6]) -{ - Double_t 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 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)); - } - Double_t 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 << 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()); - return os; -} diff --git a/StRoot/StarRoot/KFParticleBase.h b/StRoot/StarRoot/KFParticleBase.h deleted file mode 100644 index a8dc59d82a7..00000000000 --- a/StRoot/StarRoot/KFParticleBase.h +++ /dev/null @@ -1,252 +0,0 @@ -//--------------------------------------------------------------------------------- -// The KFParticleBase 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 describes general mathematics which is used by KFParticle class -// -// -= Copyright © ALICE HLT Group =- -//_________________________________________________________________________________ -#ifndef KFParticleBASE_H -#define KFParticleBASE_H -#include "TObject.h" -class KFParticleBase : public TObject { - public: - // ABSTRACT METHODS HAVE TO BE DEFINED IN USER CLASS - // Virtual method to access the magnetic field - virtual void GetFieldValue(const Double_t xyz[], Double_t 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 Double_t GetDStoPoint( const Double_t xyz[] ) const = 0; - // Get dS to other particle p (dSp for particle p also returned) - virtual void GetDStoParticle( const KFParticleBase &p, - Double_t &DS, Double_t &DSp ) const = 0; - // Transport on dS value along trajectory, output to P,C - virtual void Transport( Double_t dS, Double_t P[], Double_t C[] ) const = 0; - KFParticleBase(); - virtual ~KFParticleBase() {} - // Initialisation from "cartesian" coordinates ( X Y Z Px Py Pz ) - // Parameters, covariance matrix, charge, and mass hypothesis should be provided - void Initialize( const Double_t Param[], const Double_t Cov[], Int_t Charge, Double_t Mass, Int_t PID = 0); - // Initialise covariance matrix and set current parameters to 0.0 - void Initialize(); - virtual void Clear(Option_t * /*option*/ =""); - // Set decay vertex parameters for linearisation - void SetVtxGuess( Double_t x, Double_t y, Double_t z ); - void SetID(Int_t id=0) {fID = id;} - void SetParentID(Int_t id=0) {fParentID = id;} - // ACCESSORS - Int_t GetID() const {return fID;} - Int_t GetParentID() const {return fParentID;} - Double_t GetX () const { return fP[0]; } - Double_t GetY () const { return fP[1]; } - Double_t GetZ () const { return fP[2]; } - Double_t GetPx () const { return fP[3]; } - Double_t GetPy () const { return fP[4]; } - Double_t GetPz () const { return fP[5]; } - Double_t GetE () const { return fP[6]; } - Double_t GetS () const { return fP[7]; } - Short_t GetQ () const { return fQ; } - Double_t GetChi2 () const { return fChi2; } - Short_t GetNDF () const { return fNDF; } - - const Double_t *GetParameter() const { return fP;} - Double_t GetParameter ( Int_t i ) const { return fP[i];} - const Double_t *GetCovariance() const { return fC;} - Double_t GetCovariance( Int_t i ) const { return fC[i]; } - Double_t GetCovariance( Int_t i, Int_t j ) const { return fC[IJ(i,j)]; } - - // Accessors with calculations( &value, &estimated sigma ) - // error flag returned (0 means no error during calculations) - - Int_t GetMomentum ( Double_t &P, Double_t &SigmaP ) const ; - Int_t GetPt ( Double_t &Pt, Double_t &SigmaPt ) const ; - Int_t GetEta ( Double_t &Eta, Double_t &SigmaEta ) const ; - Int_t GetPhi ( Double_t &Phi, Double_t &SigmaPhi ) const ; - Int_t GetMass ( Double_t &M, Double_t &SigmaM ) const ; - Int_t GetDecayLength ( Double_t &L, Double_t &SigmaL ) const ; - Int_t GetDecayLengthXY ( Double_t &L, Double_t &SigmaL ) const ; - Int_t GetLifeTime ( Double_t &T, Double_t &SigmaT ) const ; - Int_t GetR ( Double_t &R, Double_t &SigmaR ) const ; - - // - // MODIFIERS - // - - Double_t & X () { return fP[0]; } - Double_t & Y () { return fP[1]; } - Double_t & Z () { return fP[2]; } - Double_t & Px () { return fP[3]; } - Double_t & Py () { return fP[4]; } - Double_t & Pz () { return fP[5]; } - Double_t & E () { return fP[6]; } - Double_t & S () { return fP[7]; } - Short_t & Q () { return fQ; } - Double_t & Chi2 () { return fChi2; } - Short_t & NDF () { return fNDF; } - - Double_t & Parameter ( Int_t i ) { return fP[i]; } - Double_t & Covariance( Int_t i ) { return fC[i]; } - Double_t & Covariance( Int_t i, Int_t j ) { return fC[IJ(i,j)]; } - - - // - // 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 ); - - // Set production vertex - - void SetProductionVertex( const KFParticleBase &Vtx ); - - // Set mass constraint - - void SetMassConstraint( Double_t Mass, Double_t 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, Double_t Mass=-1, Bool_t IsConstrained=0 ); - - - // - // 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( Double_t dS ); - - // Particular extrapolators one can use - - Double_t GetDStoPointBz( Double_t Bz, const Double_t xyz[] ) const; - - void GetDStoParticleBz( Double_t Bz, const KFParticleBase &p, - Double_t &dS, Double_t &dS1 ) const ; - - // Double_t GetDStoPointCBM( const Double_t xyz[] ) const; - - void TransportBz( Double_t Bz, Double_t dS, Double_t P[], Double_t C[] ) const; - void TransportCBM( Double_t dS, Double_t P[], Double_t C[] ) const; - - - // - // OTHER UTILITIES - // - - // Calculate distance from another object [cm] - - Double_t GetDistanceFromVertex( const Double_t vtx[] ) const; - Double_t GetDistanceFromVertex( const KFParticleBase &Vtx ) const; - Double_t GetDistanceFromParticle( const KFParticleBase &p ) const; - - // Calculate sqrt(Chi2/ndf) deviation from vertex - // v = [xyz], Cv=[Cxx,Cxy,Cyy,Cxz,Cyz,Czz]-covariance matrix - - Double_t GetDeviationFromVertex( const Double_t v[], - const Double_t Cv[]=0 ) const; - Double_t GetDeviationFromVertex( const KFParticleBase &Vtx ) const; - Double_t GetDeviationFromParticle( const KFParticleBase &p ) const; - - // Subtract the particle from the vertex - - void SubtractFromVertex( KFParticleBase &Vtx ) const ; - void SubtractFromParticle( KFParticleBase &Vtx ) const; - - // Special method for creating gammas - - void ConstructGammaBz( const KFParticleBase &daughter1, - const KFParticleBase &daughter2, Double_t Bz ); - 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 SetIdTruth(Int_t idtru,Int_t qatru=0) {fIdTruth = (UShort_t) idtru; fQuality = (UShort_t) qatru;} - void SetIdParentMcVx(Int_t id) {fIdParentMcVx = id;} - void SetPDG ( Int_t pdg ) { fPDG = pdg; } - Int_t GetPDG () const { return fPDG; } - protected: - - static Int_t IJ( Int_t i, Int_t j ){ - return ( j<=i ) ? i*(i+1)/2+j :j*(j+1)/2+i; - } - - Double_t & Cij( Int_t i, Int_t j ){ return fC[IJ(i,j)]; } - - void Convert( Bool_t ToProduction ); - void TransportLine( Double_t S, Double_t P[], Double_t C[] ) const ; - Double_t GetDStoPointLine( const Double_t xyz[] ) const; - - static Bool_t InvertSym3( const Double_t A[], Double_t Ainv[] ); - static void InvertCholetsky3(Double_t a[6]); - - static void MultQSQt( const Double_t Q[], const Double_t S[], - Double_t SOut[] ); - - static Double_t GetSCorrection( const Double_t Part[], const Double_t XYZ[] ); - - void GetMeasurement( const Double_t XYZ[], Double_t m[], Double_t V[] ) const ; - - Char_t fBeg[1]; //! - Int_t fID; - Int_t fParentID; - Double32_t fP[8]; // Main particle parameters {X,Y,Z,Px,Py,Pz,E,S[=DecayLength/P]} - Double32_t fC[36]; // Low-triangle covariance matrix of fP - Short_t fQ; // Particle charge - Short_t fNDF; // Number of degrees of freedom - Double32_t fChi2; // Chi^2 - - Double32_t fSFromDecay; // Distance from decay vertex to current position - Bool_t fAtProductionVertex; //! Flag shows that the particle error along its trajectory is taken from production vertex - - Double32_t fVtxGuess[3]; //! Guess for the position of the decay vertex ( used for linearisation of equations ) - - Bool_t fIsLinearized; //! Flag shows that the guess is present - UShort_t fIdTruth; // MC track id - UShort_t fQuality; // quality of this information (percentage of hits coming from the above MC track) - UShort_t fIdParentMcVx; // for track and McTrack for vertex - Short_t fPDG; // pdg hypothesis - Char_t fEnd[1]; //! - ClassDef(KFParticleBase,4) -}; -std::ostream& operator<<(std::ostream& os, KFParticleBase const & particle); -#endif diff --git a/StRoot/StarRoot/KFVertex.cxx b/StRoot/StarRoot/KFVertex.cxx deleted file mode 100644 index d0f05c4a618..00000000000 --- a/StRoot/StarRoot/KFVertex.cxx +++ /dev/null @@ -1,129 +0,0 @@ -//---------------------------------------------------------------------------- -// Implementation of the KFVertex class -// . -// @author S.Gorbunov, I.Kisel -// @version 1.0 -// @since 13.05.07 -// -// Class to reconstruct and store primary and secondary vertices -// 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 Group =- -//____________________________________________________________________________ - - -#include "KFVertex.h" - -ClassImp(KFVertex) - - -KFVertex::KFVertex( const VVertex &vertex ): fIsConstrained(0) -{ - // Constructor from ALICE VVertex - - vertex.GetXYZ( fP ); - vertex.GetCovarianceMatrix( fC ); - fChi2 = vertex.GetChi2(); - fNDF = 2*vertex.GetNContributors() - 3; - fQ = 0; - fAtProductionVertex = 0; - fIsLinearized = 0; - fSFromDecay = 0; -} - -/* -void KFVertex::Print(Option_t* ) const -{ - cout<<"KFVertex position: "<2 ) - { - Double_t worstChi = 0.; - Int_t worstDaughter = 0; - for( Int_t it=0; it=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; iChiCut*ChiCut*GetNDF() ){ - for( int i=0; i StCloseFileOnTerminate *StCloseFileOnTerminate::fgCloseFileOnTerminate = 0; //_________________________________________________________ StCloseFileOnTerminate:: StCloseFileOnTerminate() : TSignalHandler(kSigTermination, kFALSE) @@ -18,6 +20,7 @@ StCloseFileOnTerminate &StCloseFileOnTerminate::Instantiate() if (! fgCloseFileOnTerminate ) { fgCloseFileOnTerminate = new StCloseFileOnTerminate; ::Warning("StCloseFileOnTerminate::Instantiate","Asynch signal handler has been created"); + std::set_terminate([](){ std::cout << "Unhandled exception\n"; fgCloseFileOnTerminate->Notify(); std::abort();}); } return *fgCloseFileOnTerminate; } @@ -32,13 +35,13 @@ Bool_t StCloseFileOnTerminate::Notify() { TIter next(files); while( TFile *f = (TFile *) next() ) { if ( f-> IsWritable() ) { - Error(__FUNCTION__, "file %s will be closed", f->GetName()); + // Error(__FUNCTION__, "file %s will be closed", f->GetName()); f->Write(); f->Close(); ++count; Error(__FUNCTION__, "file %s has been closed", f->GetName()); } } - files->Delete(); + // files->Delete(); } if (count) Error(__FUNCTION__, "%d files have been closed", count); else Print(" There was no open file to close"); diff --git a/StRoot/StarRoot/StCloseFileOnTerminate.h b/StRoot/StarRoot/StCloseFileOnTerminate.h index 60618acb295..5a584cbfd2d 100644 --- a/StRoot/StarRoot/StCloseFileOnTerminate.h +++ b/StRoot/StarRoot/StCloseFileOnTerminate.h @@ -39,8 +39,8 @@ class StCloseFileOnTerminate : public TSignalHandler { //! Create an instance of the signal handler (Should be called at once by code) public: static StCloseFileOnTerminate &Instantiate(); - protected: static bool Exists() {return fgCloseFileOnTerminate;} + protected: //! Close the open ROOT files upon SIGTERM sent by system to terminate the job virtual Bool_t Notify(); ClassDef(StCloseFileOnTerminate,0) diff --git a/StRoot/StarRoot/StMemStat.cxx b/StRoot/StarRoot/StMemStat.cxx index 90aadb35218..c3f6ac2424e 100644 --- a/StRoot/StarRoot/StMemStat.cxx +++ b/StRoot/StarRoot/StMemStat.cxx @@ -8,10 +8,13 @@ * *************************************************************************** **************************************************************************/ +#include #include #include #include +#ifndef __APPLE__ #include +#endif #include #include #include @@ -61,7 +64,7 @@ void StMemStat::Stop() Double_t dif = Used() - fLast; //printf("DEBUG >> time distance between two stops Used=%f Last=%f\n",Used(),fLast); - if ( fabs(dif) < LOWEST_VAL ) dif = 0.0; + if ( TMath::Abs(dif) < LOWEST_VAL ) dif = 0.0; if ( dif < fMin ) fMin = dif; if ( dif > fMax ) fMax = dif; @@ -74,10 +77,10 @@ void StMemStat::Print(const char *) const { if (!fTally) return; Double_t aver = fAver/fTally; - Double_t rms = ::sqrt(fabs(fRms/fTally - aver*aver)); + Double_t rms = ::sqrt(TMath::Abs(fRms/fTally - aver*aver)); //printf("DEBUG :: %.10f %d %.10f %.10f\n",fAver,fTally,fRms,aver); - if ( fabs(aver) < LOWEST_VAL ) aver = 0.0; + if ( TMath::Abs(aver) < LOWEST_VAL ) aver = 0.0; if ( rms < LOWEST_VAL ) rms = 0.0; printf("%40.40s(%d)%12.6f%12.6f%12.6f%12.6f\n", @@ -109,7 +112,7 @@ void StMemStat::Summary() if (m->fMax > dmax) dmax=m->fMax; dmp = m->fAver/m->fTally; daver += dmp; - drms += fabs(m->fRms/m->fTally-dmp*dmp); + drms += TMath::Abs(m->fRms/m->fTally-dmp*dmp); } if(!dtally) return; @@ -118,7 +121,7 @@ void StMemStat::Summary() printf("\n"); //VP daver /= dtally; - drms = ::sqrt(fabs(drms)); + drms = ::sqrt(TMath::Abs(drms)); printf("%40.40s(%d)%12.6f%12.6f%12.6f%12.6f\n", "Total", (int)dtally, dmin, daver, dmax, drms); @@ -141,16 +144,24 @@ void StMemStat::doPs(std::string who, std::string where) //______________________________________________________________________________ Double_t StMemStat::Used() { +#ifndef __APPLE__ struct mallinfo info; info = mallinfo(); return double(info.uordblks + info.usmblks)/1024/1024; +#else + return 0; +#endif } //______________________________________________________________________________ Double_t StMemStat::Free() { +#ifndef __APPLE__ struct mallinfo info; info = mallinfo(); return double(info.fordblks + info.fsmblks)/1024/1024; +#else + return 0; +#endif } //______________________________________________________________________________ diff --git a/StRoot/StarRoot/StarRootLinkDef.h b/StRoot/StarRoot/StarRootLinkDef.h index 9fddfc7578e..7d1cb683c70 100644 --- a/StRoot/StarRoot/StarRootLinkDef.h +++ b/StRoot/StarRoot/StarRootLinkDef.h @@ -1,4 +1,4 @@ -#ifdef __CINT__ +#if defined(__CINT__) || defined(__CLING__) #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; @@ -61,10 +61,6 @@ #pragma link C++ enum EDraw3DStyle; //IncFile=TPolynomial.h #pragma link C++ namespace TPolynomial; -#pragma link C++ class KFParticleBase+; -#pragma link C++ class KFParticle+; -#pragma link C++ class MTrack+; -#pragma link C++ class MVertex+; #pragma link C++ class TTreeIter-; #pragma link C++ class TTreeIterCast-; #endif diff --git a/StRoot/StarRoot/TAttr.cxx b/StRoot/StarRoot/TAttr.cxx index a565e09e3e8..988057c57d7 100644 --- a/StRoot/StarRoot/TAttr.cxx +++ b/StRoot/StarRoot/TAttr.cxx @@ -63,6 +63,11 @@ int TAttr::SetAttr(const TAttr *att) return add; } //_____________________________________________________________________________ +void TAttr::SetAttr(const char *key, Bool_t val) +{ + TString ts; ts+=(char)val; SetAttr(key, ts.Data()); +} +//_____________________________________________________________________________ void TAttr::SetAttr(const char *key, Long_t val) { TString ts; ts+=val; SetAttr(key, ts.Data()); @@ -87,7 +92,7 @@ const char *TAttr::SAttr(const char *key) const if (att) { // we found the attribut int n = att->GetUniqueID(); att->SetUniqueID(n+1); - if (n<13) Info("Found","%s = %s\n",att->GetName(),att->GetTitle()); + if (n<13) Info("Found","%s = %s",att->GetName(),att->GetTitle()); } return (att)? att->GetTitle():""; } diff --git a/StRoot/StarRoot/TAttr.h b/StRoot/StarRoot/TAttr.h index f757f4a0fa6..fa42e1cd719 100644 --- a/StRoot/StarRoot/TAttr.h +++ b/StRoot/StarRoot/TAttr.h @@ -20,6 +20,7 @@ class TAttr: public TList TAttr(const char *name=""); ~TAttr(); void SetAttr(const char *key,const char* val); +void SetAttr(const char *key,Bool_t val); void SetAttr(const char *key,Long_t val); void SetAttr(const char *key,ULong_t val); void SetAttr(const char *key,double val); diff --git a/StRoot/StarRoot/TDirIter.cxx b/StRoot/StarRoot/TDirIter.cxx index d7584b42fe1..1671bc0d712 100644 --- a/StRoot/StarRoot/TDirIter.cxx +++ b/StRoot/StarRoot/TDirIter.cxx @@ -133,6 +133,13 @@ void TDirIter::ResetQQ(const char *path) } //______________________________________________________________________________ const char *TDirIter::NextFile() +{ + const TNamed *d = TDirIter::NextFileName(); + if (! d) return 0; + return d->GetName(); +} +//______________________________________________________________________________ +const TNamed *TDirIter::NextFileName() { if (fIter == -1) { const char *name=0; @@ -141,7 +148,7 @@ const char *TDirIter::NextFile() } fIter++; if (fIter > fArr->GetLast()) return 0; - return fArr->At(fIter)->GetName(); + return (TNamed *) fArr->At(fIter); } //______________________________________________________________________________ @@ -212,7 +219,7 @@ TString TDirIter::MakeWild(const char *re) for (int i=0;re[i];i++) { if (i == 0) {ts+="^" ;} - if (re[i]=='*') {ts+="[a-zA-Z0-9_\\.,-= ]*"; continue;} + if (re[i]=='*') {ts+="[a-zA-Z0-9_\\.,-=+ ]*"; continue;} if (re[i]=='#') {ts+=".*"; continue;} if (re[i] == '.') {ts+="\\."; continue;} ts += re[i]; @@ -220,7 +227,10 @@ TString TDirIter::MakeWild(const char *re) ts += "$"; return ts; } - +//________________________________________________________________________________ +Int_t TDirIter::NoFiles() const { + return fArr ? fArr->GetLast() : 0; +} diff --git a/StRoot/StarRoot/TDirIter.h b/StRoot/StarRoot/TDirIter.h index deceead404f..8cae3cd2bd4 100644 --- a/StRoot/StarRoot/TDirIter.h +++ b/StRoot/StarRoot/TDirIter.h @@ -11,7 +11,7 @@ #include "TString.h" #include "TRegexp.h" -class TOBjArray; +class TObjArray; class TDirIter { public: @@ -19,7 +19,9 @@ class TDirIter ~TDirIter(); void Reset (const char *path, Int_t maxlev = 99); const char *NextFile(); - + const TNamed *NextFileName(); +Int_t NoFiles() const; + const TObjArray *Array() {return fArr;} private: TString MakeWild(const char *re); const char *NextFileQ(); diff --git a/StRoot/StarRoot/TNumDeriv.cxx b/StRoot/StarRoot/TNumDeriv.cxx index f763632481a..5c51c3c8106 100644 --- a/StRoot/StarRoot/TNumDeriv.cxx +++ b/StRoot/StarRoot/TNumDeriv.cxx @@ -4,7 +4,7 @@ #include "TNumDeriv.h" -#ifndef __CINT__ +#if !defined(__CINT__) && !defined(__CLING__) #include #include #include diff --git a/StRoot/StarRoot/TNumDeriv.h b/StRoot/StarRoot/TNumDeriv.h index 52de5dbd7ba..b248f2f9efd 100644 --- a/StRoot/StarRoot/TNumDeriv.h +++ b/StRoot/StarRoot/TNumDeriv.h @@ -57,7 +57,7 @@ ClassDef(TNumDeriv2Test,0) }; -#ifdef __CINT__ +#if defined(__CINT__) || defined(__CLING__) #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; diff --git a/StRoot/StarRoot/TRArray.h b/StRoot/StarRoot/TRArray.h index b37344f1421..26e24670e2f 100644 --- a/StRoot/StarRoot/TRArray.h +++ b/StRoot/StarRoot/TRArray.h @@ -13,7 +13,7 @@ #else #include "TCernLib.h" #endif -#ifndef __CINT__ +#if !defined(__CINT__) && !defined(__CLING__) #define __VA_LIST__(name) \ va_list args; \ va_start(args,va_(name)); \ @@ -35,11 +35,13 @@ class TRArray : public TArrayD { kAxBxAT, kATxBxA, kSxA, kAxS, kSxAT, kATxS, kAxAT, kATxA, - kAxSxAT, kATxSxA, kRxSxR + kAxSxAT, kATxSxA, kRxSxR, + kSCor, + kRxS }; TRArray(Int_t N=0): TArrayD(N), fValid(kTRUE), fIsNotOwn(kFALSE) {} // TRArray(Int_t N,Double_t scalar): TArrayD(N) {if (scalar != 0) Reset(scalar);} -#ifndef __CINT__ +#if !defined(__CINT__) && !defined(__CLING__) TRArray(Int_t N,Double_t a0, ...); #endif TRArray(Int_t N,const Double_t *Array): TArrayD(N,Array), fValid(kTRUE), fIsNotOwn(kFALSE) {} @@ -66,43 +68,43 @@ class TRArray : public TArrayD { virtual Double_t &operator()(Int_t i) {return operator[](i);} virtual Double_t operator()(Int_t i) const {return operator[](i);} friend TRArray &operator-=(TRArray &target, Double_t scalar) { - for (int i=0; i= fNcols) { ::Error("TRMatrix::operator()", "index j %d out of bounds (size: %d, this: %p)", - j, fNcols, this); + j, fNcols, (void *) this); j = 0; } if (i < 0 || i >= fNrows) { ::Error("TRMatrix::operator()", "index i %d out of bounds (size: %d, this: %p)", - i, fNrows, this); + i, fNrows, (void *) this); i = 0; } return TArrayD::operator[](j + i*fNcols); diff --git a/StRoot/StarRoot/TRSymMatrix.cxx b/StRoot/StarRoot/TRSymMatrix.cxx index 46794e3e46c..0a41cf1cbfd 100644 --- a/StRoot/StarRoot/TRSymMatrix.cxx +++ b/StRoot/StarRoot/TRSymMatrix.cxx @@ -19,7 +19,7 @@ TRSymMatrix::TRSymMatrix(Int_t nrows,const Double_t *Array) : TRArray() { Int_t ij; Int_t i = 0, j = 0; for (Int_t l = 0; l < fN; l++) { - ij = i*(i+1)/2 + j; + ij = IJ(i,j); fArray[ij] = Array[l]; if (i < fNrows - 1) i++; else { @@ -41,7 +41,7 @@ TRSymMatrix::TRSymMatrix(Int_t nrows,const Float_t *Array) : TRArray() { Int_t ij; Int_t i = 0, j = 0; for (Int_t l = 0; l < fN; l++) { - ij = i*(i+1)/2 + j; + ij = IJ(i,j); fArray[ij] = Array[l]; if (i < fNrows - 1) i++; else { @@ -60,7 +60,7 @@ TRSymMatrix::TRSymMatrix(ETRMatrixCreatorsOp kop,Int_t nrows) : case kZero: break; case kUnit: - for (int i=0; i 0 && fArray[jj] > 0) + fArray[ij] = S[ij]/(fArray[ii]*fArray[jj]); + else + fArray[ij] = 0; + } + } + break; default: Error("TRSymMatrix(ETRMatrixCreatorsOp)", "operation %d not yet implemented", kop); } @@ -121,12 +138,33 @@ TRSymMatrix::TRSymMatrix(const TRMatrix& A,ETRMatrixCreatorsOp kop,const TRSymMa } //________________________________________________________________________________ TRSymMatrix::TRSymMatrix(const TRSymMatrix& Q,ETRMatrixCreatorsOp kop,const TRSymMatrix& T){ - assert (kop == kRxSxR); - Int_t M = Q.GetNcols(); - assert(M == T.GetNcols()); - fNrows = M; - Set(fNrows*(fNrows+1)/2); - TCL::trqsq(Q.GetArray(),T.GetArray(),fArray,M); + Int_t M, i, j, k, ij; + switch (kop) { + case kRxSxR: + M = Q.GetNcols(); + assert(M == T.GetNcols()); + fNrows = M; + Set(fNrows*(fNrows+1)/2); + TCL::trqsq(Q.GetArray(),T.GetArray(),fArray,M); + break; + case kRxS: + M = Q.GetNcols(); + assert(M == T.GetNcols()); + fNrows = M; + Set(fNrows*(fNrows+1)/2); + for (i = 0; i < M; i++) + for (j = 0; j <= i; j++) { + ij = IJ(i,j); + fArray[ij] = 0; + for (k = 0; k < M; k++) { + fArray[ij] += Q(i,k) * T (k,j); + } + } + break; + default: + Error("TRSymMatrix(ETRMatrixCreatorsOp)", "operation %d not yet implemented", kop); + } + } //________________________________________________________________________________ TRSymMatrix::TRSymMatrix(const TRMatrix& A,ETRMatrixCreatorsOp kop) { @@ -168,14 +206,16 @@ ostream& operator<<(ostream& s,const TRSymMatrix &target) { Int_t Nrows = target.GetNrows(); const Double_t *Array = target.GetArray(); s << "Semi Positive DefinedSymMatrix Size \t[" - << Nrows << "," << Nrows << "]" << endl; + << Nrows << "," << Nrows << "]"; if (Array) { s.setf(std::ios::fixed,std::ios::scientific); s.setf(std::ios::showpos); - for (int i = 0; i< Nrows; i++) { - for (int j = 0; j <= i; j++) - s << std::setw(width) << std::setprecision(width-3) << Array[i*(i+1)/2 + j] << ":\t"; + Int_t i1 = 0; + Int_t i2 = Nrows; + for (int i = i1; i< i2; i++) { s << endl; + for (int j = i1; j <= i; j++) + s << std::setw(width) << std::setprecision(width-3) << target(i,j) << ":\t"; } s.unsetf(std::ios::showpos); } @@ -183,7 +223,35 @@ ostream& operator<<(ostream& s,const TRSymMatrix &target) { return s; } //________________________________________________________________________________ -void TRSymMatrix::Print(Option_t *opt) const {if (opt) {}; cout << *this << endl;} +void TRSymMatrix::Print(Option_t *opt) const {if (opt); cout << *this << endl;} +//________________________________________________________________________________ +void TRSymMatrix::Print(Int_t I, Int_t N) const { + static const int width = 10; + Int_t Nrows = GetNrows(); + const Double_t *Array = GetArray(); + cout << "Semi Positive DefinedSymMatrix Size \t[" + << Nrows << "," << Nrows << "]"; + if (I >= 0) cout << " subset with I = " << I; + if (N >= 0) cout << " subset with N = " << N; + cout << endl; + if (Array) { + cout.setf(std::ios::fixed,std::ios::scientific); + cout.setf(std::ios::showpos); + Int_t i1 = 0; + if (I >= 0 && I < Nrows) i1 = I; + Int_t i2 = Nrows; + if (i1 + N < Nrows) i2 = i1 + N; + for (int i = i1; i< i2; i++) { + for (int j = i1; j <= i; j++) + cout << std::setw(width) << std::setprecision(width-3) << Array[IJ(i,j)] << ":\t"; + cout << endl; + } + cout.unsetf(std::ios::showpos); + } + else cout << " Empty"; + cout << endl; + return; +} //________________________________________________________________________________ Int_t TRSymMatrix::SpmInv(const TRSymMatrix &S, TRVector *B) { if (&S != this) *this = S; @@ -361,10 +429,10 @@ Int_t TRSymMatrix::TrchLU(const double *a, double *b, int n) { if (j != i__) b[kpiv] = sum * r__; else { if (sum > 0) dc = TMath::Sqrt(sum); - else dc = 0; + else {dc = 0; if (sum < 0) fail++;} b[kpiv] = dc; if (r__ > 0. && dc > 0) r__ = (double)1. / dc; - else {r__ = 0; fail++;} + else r__ = 0; } kpiv += j; } @@ -376,24 +444,3 @@ Int_t TRSymMatrix::TrchLU(const double *a, double *b, int n) { Int_t TRSymMatrix::TrInv(const Double_t *g, Double_t *gi, Int_t n) {TCL::trinv(g, gi, n); return 0;} //________________________________________________________________________________ Int_t TRSymMatrix::TrsmUL(const Double_t *g, Double_t *gi, Int_t n) {TCL::trsmul(g, gi, n); return 0;} -#if 0 -//________________________________________________________________________________ -Double_t &TRSymMatrix::operator()(Int_t i,Int_t j){ - // assert(! (j < 0 || j >= fNrows)); - if (j < 0 || j >= fNrows) { - ::Error("TRSymMatrix::operator()", "index j %d out of bounds (size: %d, this: %p)", - j, fNrows, this); - j = 0; - } - // assert(! (i < 0 || i >= fNrows)); - if (i < 0 || i >= fNrows) { - ::Error("TRSymMatrix::operator()", "index i %d out of bounds (size: %d, this: %p)", - i, fNrows, this); - i = 0; - } - Int_t m = i; - Int_t l = j; - if (i > j) {m = j; l = i;} - return TArrayD::operator[](m + (l+1)*l/2); -} -#endif diff --git a/StRoot/StarRoot/TRSymMatrix.h b/StRoot/StarRoot/TRSymMatrix.h index 3d940a488e3..6c3fa01039f 100644 --- a/StRoot/StarRoot/TRSymMatrix.h +++ b/StRoot/StarRoot/TRSymMatrix.h @@ -17,7 +17,7 @@ class TRSymMatrix : public TRArray { TRSymMatrix(const TRMatrix& A,ETRMatrixCreatorsOp kop,const TRSymMatrix& S); TRSymMatrix(const TRSymMatrix& Q,ETRMatrixCreatorsOp kop,const TRSymMatrix& T); TRSymMatrix(const TRMatrix& A,ETRMatrixCreatorsOp kop); -#ifndef __CINT__ +#if !defined(__CINT__) && !defined(__CLING__) TRSymMatrix (Int_t nrows, Double_t a0, ...); #endif virtual ~TRSymMatrix() {} @@ -30,10 +30,12 @@ class TRSymMatrix : public TRArray { static Int_t spminv(Double_t *v, Double_t *b, Int_t n, Int_t &nrank, Double_t *diag, Bool_t *flag); virtual void Print(Option_t *opt="") const; + void Print(Int_t I, Int_t N = -1) const; Double_t &operator()(Int_t i) {return TRArray::operator[](i);} Double_t operator()(Int_t i) const {return TRArray::operator[](i);} - Double_t &operator()(Int_t i,Int_t j); - Double_t operator()(Int_t i,Int_t j) const; + static Int_t IJ(Int_t i, Int_t j) {return ( j<=i ) ? i*(i+1)/2+j :j*(j+1)/2+i;} + Double_t &operator()(Int_t i,Int_t j) {return TRArray::operator[](IJ(i,j));} + Double_t operator()(Int_t i,Int_t j) const {return TRArray::operator[](IJ(i,j));} void AddRow(const Double_t *row) { fNrows++; Set(fNrows*(fNrows+1)/2); memcpy(fArray+(fNrows-1)*fNrows/2, row, fNrows*sizeof(Double_t)); } @@ -50,45 +52,5 @@ class TRSymMatrix : public TRArray { ClassDef(TRSymMatrix,1) // TRSymMatrix class (double precision) }; std::ostream& operator<<(std::ostream& s,const TRSymMatrix &target); -inline Double_t &TRSymMatrix::operator()(Int_t i,Int_t j){ - // assert(! (j < 0 || j >= fNrows)); - if (j < 0 || j >= fNrows) { - ::Error("TRSymMatrix::operator()", "index j %d out of bounds (size: %d, this: %p)", - j, fNrows, this); - j = 0; - assert(0); - } - // assert(! (i < 0 || i >= fNrows)); - if (i < 0 || i >= fNrows) { - ::Error("TRSymMatrix::operator()", "index i %d out of bounds (size: %d, this: %p)", - i, fNrows, this); - i = 0; - assert(0); - } - Int_t m = i; - Int_t l = j; - if (i > j) {m = j; l = i;} - return TArrayD::operator[](m + (l+1)*l/2); -} -inline Double_t TRSymMatrix::operator()(Int_t i,Int_t j) const { - // assert(! (j < 0 || j >= fNrows)); - if (j < 0 || j >= fNrows) { - ::Error("TRSymMatrix::operator()", "index j %d out of bounds (size: %d, this: %p)", - j, fNrows, this); - j = 0; - assert(0); - } - // assert(! (i < 0 || i >= fNrows)); - if (i < 0 || i >= fNrows) { - ::Error("TRSymMatrix::operator()", "index i %d out of bounds (size: %d, this: %p)", - i, fNrows, this); - i = 0; - assert(0); - } - Int_t m = i; - Int_t l = j; - if (i > j) {m = j; l = i;} - return TArrayD::operator[](m + (l+1)*l/2); -} #endif diff --git a/StRoot/StarRoot/TRVector.h b/StRoot/StarRoot/TRVector.h index 4a16ed38623..c9921f58e56 100644 --- a/StRoot/StarRoot/TRVector.h +++ b/StRoot/StarRoot/TRVector.h @@ -28,7 +28,7 @@ class TRVector : public TRMatrix { friend TRVector operator+(Double_t scalar, const TRVector &source) {TRVector s(source); s += scalar; return s;} friend TRVector operator-(const TRVector &source, Double_t scalar) {TRVector s(source); s -= scalar; return s;} friend TRVector operator-(Double_t scalar, const TRVector &source) {TRVector s(source); s -= scalar; return s;} -#ifndef __CINT__ +#if !defined(__CINT__) && !defined(__CLING__) TRVector(Int_t nrows,Double_t a0, ...); #endif virtual ~TRVector(){} diff --git a/StRoot/StarRoot/TTreeIter.h b/StRoot/StarRoot/TTreeIter.h index 8f1285bb888..9cacb2ea27f 100644 --- a/StRoot/StarRoot/TTreeIter.h +++ b/StRoot/StarRoot/TTreeIter.h @@ -79,7 +79,7 @@ class TTreeIter : public TNamed{ TChain *Chain() {return fTree;} TTreeIterCast &operator() (const TString varname); void **Void(const TString varname); -#ifndef __CINT__ +#if !defined(__CINT__) && !defined(__CLING__) TTreeIterCast &operator() (const char *varname); void **Void(const char *varname); #endif diff --git a/StRoot/StarRoot/genFitDca.cxx b/StRoot/StarRoot/genFitDca.cxx index 879b2c9aa27..edd4674b7b3 100644 --- a/StRoot/StarRoot/genFitDca.cxx +++ b/StRoot/StarRoot/genFitDca.cxx @@ -25,6 +25,9 @@ #include "TCernLib.h" #include "TVector3.h" #include "TVectorD.h" +#if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0) +using namespace std; +#endif #include "TString.h" double *Arr(TVector3 &v) {return (double*)&v[0];} diff --git a/StRoot/StarRoot/thmu.C b/StRoot/StarRoot/thmu.C index f935253c100..a4bd531096d 100644 --- a/StRoot/StarRoot/thmu.C +++ b/StRoot/StarRoot/thmu.C @@ -1,4 +1,4 @@ -#ifndef __CINT__ +#if !defined(__CINT__) && !defined(__CLING__) #include #include "TSystem.h" #include "TBenchmark.h" diff --git a/StRoot/StiMaker/MuPrmVtx.C b/StRoot/StiMaker/MuPrmVtx.C deleted file mode 100644 index 81395ba8997..00000000000 --- a/StRoot/StiMaker/MuPrmVtx.C +++ /dev/null @@ -1,580 +0,0 @@ -/* - Reconstruction of primary vertices from MuDst. - In directory where you have *MuDst.root files run - root.exe lMuDstK.C MuPrmVtx.C+ - $Id: MuPrmVtx.C,v 2.3 2013/04/10 22:14:20 fisyak Exp $ - */ -#define DEBUG -#define __IDTRUTH__ - -#define DRAW_RECO_HISTOS // draw histos which are used for reconstruction -//#define EVENT_DISPLAY // show tracks and vertices in each event on the screen - -#if !defined(__CINT__) || defined(__MAKECINT__) -#include "Riostream.h" -#include -#include "TSystem.h" -#include "TMath.h" -#include "TH1.h" -#include "TH2.h" -#include "TProfile.h" -#include "TStyle.h" -#include "TF1.h" -#include "TTree.h" -#include "TChain.h" -#include "TFile.h" -#include "TCanvas.h" -#include "TVector3.h" -#include "TLorentzVector.h" -#include "TDirIter.h" -#include "TTreeIter.h" -#include "StDcaGeometry.h" -#include "KFVertex.h" -#include "MTrack.h" -#include "VVertex.h" -#include "TH1K.h" -#include "TSpectrum.h" -#include "TVirtualFitter.h" -#include "TPolyMarker.h" -#include "TRVector.h" -#include "TRSymMatrix.h" -#include "Math/Functor.h" -#include "Math/GSLMinimizer1D.h" -#include "TROOT.h" -#include "TVector3.h" -#include "TArrayF.h" -#include "TClonesArray.h" -#include "StKFVertex/StAnneling.h" -#include "StKFVertex/StKFEvent.h" -#include "StKFVertex/StKFTrack.h" -#include "StKFVertex/StKFVertex.h" -#include "StKFVertex/StKFVerticesCollection.h" -#include "StKFVertex/StMuDstVtxT.h" -#include "StKFVertex/StVertexP.h" -#include "StKFVertex/StVertexT.h" -#include "StKFVertex/StKFVertexFinder.h" -#ifdef EVENT_DISPLAY -#include "StDraw3D.h" -static StDraw3D *eventD = 0; -#endif -#endif -#if 0 -static Int_t beamLine = 0; -static KFParticle beam; -static Double_t pZ = 1000; -#endif -Bool_t Ask() { - static Bool_t fAsk = kTRUE; - char symbol; - if (fAsk){ - std::cout << "ask (enter - next, s - save, r - don't ask, q - quit) >"; - do{ - std::cin.get(symbol); - if (symbol == 'r') - fAsk = kFALSE; - if (symbol == 'q') - return kTRUE; - } while (symbol != '\n'); - std::cout << endl; - } - return kFALSE; -} -//________________________________________________________________________________ -void MuPrmVtx(Int_t first, Int_t last, const Char_t *files, const Char_t* Out="") { - TDirIter Dir(files); - TString Files(files); -#if 0 - // if (Files.Contains("pp500") && ! Files.Contains("sim")) beamLine = 1; - /* beam line - SELECT * FROM Calibrations_rhic.vertexSeed v where beginTime > "2009-03-01" and beginTime < "2009-04-01"; - | beginTime | x0 | dxdz | y0 | dydz | err_x0 | err_dxdz | err_y0 | err_dydz - +----------------------+------------+------------+------------+-------------+------------+------------+------------+------------ - | 2009-03-26 04:10:21 | 0.42600000 | 0.00118000 | 0.00800000 | 0.00024000 | 0.00900000 | 0.00003000 | 0.00900000 | 0.00003000 - | 2009-03-26 21:40:24 | 0.42600000 | 0.00136000 | 0.01600000 | -0.00005000 | 0.00900000 | 0.00003000 | 0.00900000 | 0.00003000 - | 2010-03-20 01:00:00 | 0.27000001 | 0.00000000 |-0.03000000 | 0.00000000 | 0.15000001 | 0.00000000 | 0.15000001 | 0.00000000 - | 2010-04-09 07:15:15 | 0.27664959 | 0.00127356 |-0.07965557 | -0.00001392 | 0.00289759 | 0.00007723 | 0.00288955 | 0.00008473 - */ - struct vertexSeed_t {Double_t x0, dxdz, y0, dydz, err_x0, err_dxdz, err_y0, err_dydz;}; - vertexSeed_t b = { 0.42600000, 0.00118000, 0.00800000, 0.00024000, 0.00900000, 0.00003000, 0.00900000, 0.00003000}; -#endif - Char_t *file = 0; - Int_t NFiles = 0; - TTreeIter iter; - while ((file = (Char_t *) Dir.NextFile())) {iter.AddFile(file); NFiles++;} - if (! NFiles) return; - TString output(Out); - if (output == "") { - if (! iter.Chain()) return; - if (! iter.Chain()->GetListOfFiles()) return; - const Char_t *file1 = iter.Chain()->GetListOfFiles()->At(0)->GetTitle(); - TString dir = gSystem->BaseName(file1); - dir.ReplaceAll(".MuDst",""); - output += dir; - } - TFile *fOut = new TFile(output,"recreate"); - TTree *ftree = new TTree("StVertexT","Vertex tree"); - ftree->SetAutoSave(1000000000); // autosave when 1 Gbyte written - Int_t bufsize = 64000; - Int_t split = 99; - if (split) bufsize /= 4; - StKFEvent *fStKFEvent = new StKFEvent(); - TTree::SetBranchStyle(1); //new style by default - TBranch *branch = ftree->Branch("StKFEvent", "StKFEvent", &fStKFEvent, bufsize,split); - branch->SetAutoDelete(kFALSE); - - const Int_t*& MuEvent_mEventInfo_mRunId = iter("MuEvent.mEventInfo.mRunId"); - const Int_t*& MuEvent_mEventInfo_mId = iter("MuEvent.mEventInfo.mId"); - const Int_t& NoPrimaryVertices = iter("PrimaryVertices"); - // const Float_t*& MuEvent_mRunInfo_mTpcDriftVelocity = iter("MuEvent.mRunInfo.mTpcDriftVelocity[2]"); - const Float_t*& PrimaryVertices_mPosition_mX1 = iter("PrimaryVertices.mPosition.mX1"); - const Float_t*& PrimaryVertices_mPosition_mX2 = iter("PrimaryVertices.mPosition.mX2"); - const Float_t*& PrimaryVertices_mPosition_mX3 = iter("PrimaryVertices.mPosition.mX3"); - const Float_t*& PrimaryVertices_mPosError_mX1 = iter("PrimaryVertices.mPosError.mX1"); - const Float_t*& PrimaryVertices_mPosError_mX2 = iter("PrimaryVertices.mPosError.mX2"); - const Float_t*& PrimaryVertices_mPosError_mX3 = iter("PrimaryVertices.mPosError.mX3"); - const Float_t*& PrimaryVertices_mRanking = iter("PrimaryVertices.mRanking"); - const UShort_t*& PrimaryVertices_mNTracksUsed = iter("PrimaryVertices.mNTracksUsed"); -#ifdef __IDTRUTH__ - const UShort_t*& PrimaryVertices_mIdTruth = iter("PrimaryVertices.mIdTruth"); - const UShort_t*& PrimaryVertices_mQuality = iter("PrimaryVertices.mQuality"); - const Int_t*& PrimaryVertices_mIdParent = iter("PrimaryVertices.mIdParent"); // >> -#endif - const Int_t*& PrimaryTracks_mVertexIndex = iter("PrimaryTracks.mVertexIndex"); - const Int_t& NoPrimaryTracks = iter("PrimaryTracks"); - const Int_t*& PrimaryTracks_mIndex2Global = iter("PrimaryTracks.mIndex2Global"); - const Float_t*& PrimaryTracks_mChiSqZ = iter("PrimaryTracks.mChiSqZ"); -#ifdef __IDTRUTH__0 - const UShort_t*& PrimaryTracks_mIdTruth = iter("PrimaryTracks.mIdTruth"); - const UShort_t*& PrimaryTracks_mQuality = iter("PrimaryTracks.mQuality"); - const Int_t*& PrimaryTracks_mIdParentVx = iter("PrimaryTracks.mIdParentVx"); -#endif - const Int_t& NoGlobalTracks = iter("GlobalTracks"); - const Short_t*& GlobalTracks_mFlag = iter("GlobalTracks.mFlag"); - const Float_t*& GlobalTracks_mEta = iter("GlobalTracks.mEta"); - const Float_t*& GlobalTracks_mFirstPoint_mX3 = iter("GlobalTracks.mFirstPoint.mX3"); -#ifdef __IDTRUTH__ - const UShort_t*& GlobalTracks_mIdTruth = iter("GlobalTracks.mIdTruth"); - const UShort_t*& GlobalTracks_mQuality = iter("GlobalTracks.mQuality"); - const Int_t*& GlobalTracks_mIdParentVx = iter("GlobalTracks.mIdParentVx"); -#endif - // const UChar_t*& GlobalTracks_mNHitsFit = iter("GlobalTracks.mNHitsFit"); - // const Float_t*& GlobalTracks_mChiSqXY = iter("GlobalTracks.mChiSqXY"); - const Int_t*& GlobalTracks_mIndex2Cov = iter("GlobalTracks.mIndex2Cov"); - const Int_t& NoCovGlobTrack = iter("CovGlobTrack"); - const Float_t*& CovGlobTrack_mImp = iter("CovGlobTrack.mImp"); - const Float_t*& CovGlobTrack_mZ = iter("CovGlobTrack.mZ"); - const Float_t*& CovGlobTrack_mPsi = iter("CovGlobTrack.mPsi"); - const Float_t*& CovGlobTrack_mPti = iter("CovGlobTrack.mPti"); - const Float_t*& CovGlobTrack_mTan = iter("CovGlobTrack.mTan"); - const Float_t*& CovGlobTrack_mCurv = iter("CovGlobTrack.mCurv"); - const Float_t*& CovGlobTrack_mImpImp = iter("CovGlobTrack.mImpImp"); - const Float_t*& CovGlobTrack_mZImp = iter("CovGlobTrack.mZImp"); - const Float_t*& CovGlobTrack_mZZ = iter("CovGlobTrack.mZZ"); - const Float_t*& CovGlobTrack_mPsiImp = iter("CovGlobTrack.mPsiImp"); - const Float_t*& CovGlobTrack_mPsiZ = iter("CovGlobTrack.mPsiZ"); - const Float_t*& CovGlobTrack_mPsiPsi = iter("CovGlobTrack.mPsiPsi"); - const Float_t*& CovGlobTrack_mPtiImp = iter("CovGlobTrack.mPtiImp"); - const Float_t*& CovGlobTrack_mPtiZ = iter("CovGlobTrack.mPtiZ"); - const Float_t*& CovGlobTrack_mPtiPsi = iter("CovGlobTrack.mPtiPsi"); - const Float_t*& CovGlobTrack_mPtiPti = iter("CovGlobTrack.mPtiPti"); - const Float_t*& CovGlobTrack_mTanImp = iter("CovGlobTrack.mTanImp"); - const Float_t*& CovGlobTrack_mTanZ = iter("CovGlobTrack.mTanZ"); - const Float_t*& CovGlobTrack_mTanPsi = iter("CovGlobTrack.mTanPsi"); - const Float_t*& CovGlobTrack_mTanPti = iter("CovGlobTrack.mTanPti"); - const Float_t*& CovGlobTrack_mTanTan = iter("CovGlobTrack.mTanTan"); - // const Float_t*& Event_mMagneticField = iter("Event.mMagneticField"); - const Double_t*& Event_mMagneticField = iter("MuEvent.mRunInfo.mMagneticFieldZ"); -#ifdef __IDTRUTH__ - const Int_t& NoMuMcVertex = iter("StMuMcVertex"); -#if 0 - const Int_t*& StMuMcVertex_Id = iter("StMuMcVertex.mId"); -#endif - const Int_t*& StMuMcVertex_NoDaughters = iter("StMuMcVertex.mNoDaughters"); - const Int_t*& StMuMcVertex_IdParTrk = iter("StMuMcVertex.mIdParTrk"); - const Float_t*& StMuMcVertex_time = iter("StMuMcVertex.mTime"); - const Float_t*& StMuMcVertex_xyzV_mX1 = iter("StMuMcVertex.mXyzV.mX1"); - const Float_t*& StMuMcVertex_xyzV_mX2 = iter("StMuMcVertex.mXyzV.mX2"); - const Float_t*& StMuMcVertex_xyzV_mX3 = iter("StMuMcVertex.mXyzV.mX3"); - const Int_t& NoMuMcTrack = iter("StMuMcTrack"); -#if 0 - const Int_t*& StMuMcTrack_Id = iter("StMuMcTrack.mId"); -#endif - const Int_t*& StMuMcTrack_gePid = iter("StMuMcTrack.mGePid"); -#if 0 - const Int_t*& StMuMcTrack_IdVx = iter("StMuMcTrack.mIdVx"); - const Int_t*& StMuMcTrack_IdVxEnd = iter("StMuMcTrack.mIdVxEnd"); - const Float_t*& StMuMcTrack_pxyz_mX1 = iter("StMuMcTrack.mPxyz.mX1"); - const Float_t*& StMuMcTrack_pxyz_mX2 = iter("StMuMcTrack.mPxyz.mX2"); - const Float_t*& StMuMcTrack_pxyz_mX3 = iter("StMuMcTrack.mPxyz.mX3"); -#endif -#endif - StKFVertexFinder fitter; -#ifdef DRAW_RECO_HISTOS - if (! gROOT->IsBatch()) {TCanvas *c1 = new TCanvas("c1z","c1z",1400,600); fitter.SetCanvas(c1);} -#endif // DRAW_RECO_HISTOS - - // Now iterations - Int_t nev = 0; - while (iter.Next()) { // events loop - nev++; - if (nev < first) continue; - if (nev > last) break; -#ifdef EVENT_DISPLAY - if (! eventD) eventD = new StDraw3D(); // + Geometry // StDraw3D *eventD = new StDraw3D(0);// View with no detector geometry decoration - else eventD->Clear(); -#endif // EVENT_DISPLAY - fStKFEvent->Clear(); - KFParticle::SetField(Event_mMagneticField[0]); -#ifdef DEBUG - cout << "#" << nev << "\tRun " << MuEvent_mEventInfo_mRunId[0] << "\tEvent " << MuEvent_mEventInfo_mId[0] << endl; - cout << "NoTracks\t" << (int) NoGlobalTracks << " global\t" << (int) NoPrimaryTracks << " primary" << endl; -#endif - fitter.Reset(); -#if 0 - TObjArray tracks; - tracks.SetOwner(kTRUE); - TObjArray particles; - particles.SetOwner(kTRUE); -#endif - // Add measured multiplicities - Double_t ymax = fitter.Vtx()->GetMaximum(); - for (Int_t l = 0; l < NoPrimaryVertices; l++) { - Int_t mult = 0; - Int_t multP = 0; - Int_t mWest = 0; - Int_t mEast = 0; - Int_t Q = 0; - for (Int_t k = 0; k = NoGlobalTracks) continue; - if (GlobalTracks_mFlag[kg] < 0) continue; // Bad fit - if (GlobalTracks_mFlag[kg] > 700) continue; // FTPC - if (GlobalTracks_mFlag[kg]%100 == 11) continue; // Short track pointing to EEMC - Int_t kgc = GlobalTracks_mIndex2Cov[kg]; - if (kgc < 0 || kgc > NoCovGlobTrack) continue; - mult++; - if (CovGlobTrack_mPti[kgc] < 0) Q -= 1; - else Q += 1; - if (PrimaryTracks_mChiSqZ[k] < StAnneling::Chi2Cut()) multP++; - if (GlobalTracks_mEta[kg] > 0 && GlobalTracks_mFirstPoint_mX3[kg] > 0) mWest++; - if (GlobalTracks_mEta[kg] < 0 && GlobalTracks_mFirstPoint_mX3[kg] < 0) mEast++; - } - StMuDstVtxT V(PrimaryVertices_mPosition_mX1[l],PrimaryVertices_mPosition_mX2[l],PrimaryVertices_mPosition_mX3[l], - PrimaryVertices_mPosError_mX1[l],PrimaryVertices_mPosError_mX2[l],PrimaryVertices_mPosError_mX3[l], - PrimaryVertices_mNTracksUsed[l],mult,multP,mWest,mEast,Q,PrimaryVertices_mRanking[l], - PrimaryVertices_mIdTruth[l],PrimaryVertices_mQuality[l],PrimaryVertices_mIdParent[l]); -#ifdef __IDTRUTH__ - if (V.QaTruth() > 0) { - V.SetMc(NoMuMcVertex,NoMuMcTrack,StMuMcVertex_time, - StMuMcVertex_xyzV_mX1,StMuMcVertex_xyzV_mX2,StMuMcVertex_xyzV_mX3, - StMuMcVertex_NoDaughters,StMuMcVertex_IdParTrk,StMuMcTrack_gePid); - } -#endif - cout << Form("MuDst Primary Vertex: %3i with ",l) << V << endl; - fStKFEvent->AddMuVtx(V); - Double_t X = PrimaryVertices_mPosition_mX3[l]; - Double_t Y = mult; - if (1.1*Y > ymax) ymax = 1.1*Y; - TPolyMarker * pm = new TPolyMarker(1, &X, &Y); - fitter.VtxM()->GetListOfFunctions()->Add(pm); - pm->SetMarkerStyle(20); - pm->SetMarkerColor(l+2); - pm->SetMarkerSize(2); - Y = multP; - pm = new TPolyMarker(1, &X, &Y); - fitter.VtxM()->GetListOfFunctions()->Add(pm); - pm->SetMarkerStyle(21); - pm->SetMarkerColor(l+2); - pm->SetMarkerSize(2); - }; - fitter.Vtx()->SetMaximum(ymax); - Int_t NGoodGlobals = 0; - for (Int_t kg = 0; kg < NoGlobalTracks; kg++) { -#if 0 - tracks.AddAtAndExpand (0,kg); - particles.AddAtAndExpand (0,kg); -#endif - if (GlobalTracks_mFlag[kg] < 0) continue; // Bad fit - if (GlobalTracks_mFlag[kg] > 700) continue; // FTPC - if (GlobalTracks_mFlag[kg]%100 == 11) continue; // Short track pointing to EEMC - // if (TMath::Abs(GlobalTracks_mEta[kg]) > 5) continue; - Int_t kgc = GlobalTracks_mIndex2Cov[kg]; - if (kgc < 0 || kgc > NoCovGlobTrack) continue; - // if (TMath::Abs(CovGlobTrack_mImp[kgc]) > 10) continue; - // if (TMath::Abs(CovGlobTrack_mZ[kgc]) > zmax) continue; - - Double_t parsT[6] = { - CovGlobTrack_mImp[kgc],CovGlobTrack_mZ[kgc],CovGlobTrack_mPsi[kgc], - CovGlobTrack_mPti[kgc],CovGlobTrack_mTan[kgc],CovGlobTrack_mCurv[kgc]}; - Double_t errsT[15] = { - CovGlobTrack_mImpImp[kgc], - CovGlobTrack_mZImp[kgc], CovGlobTrack_mZZ[kgc], - CovGlobTrack_mPsiImp[kgc],CovGlobTrack_mPsiZ[kgc],CovGlobTrack_mPsiPsi[kgc], - CovGlobTrack_mPtiImp[kgc],CovGlobTrack_mPtiZ[kgc],CovGlobTrack_mPtiPsi[kgc],CovGlobTrack_mPtiPti[kgc], - CovGlobTrack_mTanImp[kgc],CovGlobTrack_mTanZ[kgc],CovGlobTrack_mTanPsi[kgc],CovGlobTrack_mTanPti[kgc], - CovGlobTrack_mTanTan[kgc]}; - StDcaGeometry *dca = new StDcaGeometry(); - dca->set(parsT, errsT); - KFParticle *particle = fitter.AddTrackAt(dca,kg); - delete dca; - Int_t iWE = 0; - if (GlobalTracks_mEta[kg] > 0 && GlobalTracks_mFirstPoint_mX3[kg] > 0) iWE = 1; - if (GlobalTracks_mEta[kg] < 0 && GlobalTracks_mFirstPoint_mX3[kg] < 0) iWE = 2; - particle->SetID(10000*iWE + kg+1); - particle->SetIdTruth(GlobalTracks_mIdTruth[kg],GlobalTracks_mQuality[kg]); - particle->SetIdParentVx(GlobalTracks_mIdParentVx[kg]); -#ifdef DEBUG2 - cout << "particle: " << *particle << endl; -#endif - // tracks.AddAt(dca,kg); - NGoodGlobals++; - } - - if (NGoodGlobals < 2) continue; - fitter.Fit(); - if (! fitter.Vertices()) continue; - fitter.Vertices()->SetMc(NoMuMcVertex,NoMuMcTrack,StMuMcVertex_time, - StMuMcVertex_xyzV_mX1,StMuMcVertex_xyzV_mX2,StMuMcVertex_xyzV_mX3, - StMuMcVertex_NoDaughters,StMuMcVertex_IdParTrk,StMuMcTrack_gePid); - fitter.Vertices()->Print(); - - Int_t Nvtx = fitter.Vertices()->NoVertices(); - for (Int_t l = 0; l < Nvtx; l++) { - StKFVertex *V = fitter.Vertices()->Vertex(l); - if (V) { - fStKFEvent->AddKFVtx(*V); - } - } - - - // Matching Dst => KFVertex 3D chi2 - Int_t NoMuDstVtx = fStKFEvent->NoMuDstVtx(); - Int_t NoKFVtx = fStKFEvent->NoKFVtx(); - for (Int_t i = 0; i < NoMuDstVtx; i++) { - StVertexT *VI = (StVertexT *) (*(fStKFEvent->MuDstVtx()))[i]; - for (Int_t j = 0; j < NoKFVtx; j++) { - StVertexT *VJ = (StVertexT *) (*(fStKFEvent->KFVtx()))[j]; - TVector3 diff = VI->Xyz() - VJ->Xyz(); - Double_t chi2 = - diff.x()*diff.x()/(VI->SigmaXyz().x()*VI->SigmaXyz().x() + VJ->SigmaXyz().x()*VJ->SigmaXyz().x()) + - diff.y()*diff.y()/(VI->SigmaXyz().y()*VI->SigmaXyz().y() + VJ->SigmaXyz().y()*VJ->SigmaXyz().y()) + - diff.z()*diff.z()/(VI->SigmaXyz().z()*VI->SigmaXyz().z() + VJ->SigmaXyz().z()*VJ->SigmaXyz().z()); - if (chi2 < 1e3) { - fStKFEvent->AddDKFPair(i,j,*VI,*VJ,chi2); - } - } - } - for (Int_t i = 1; i < NoKFVtx; i++) { - StVertexT *VI = (StVertexT *) (*(fStKFEvent->KFVtx()))[i]; - for (Int_t j = 0; j < i; j++) { - StVertexT *VJ = (StVertexT *) (*(fStKFEvent->KFVtx()))[j]; - TVector3 diff = VI->Xyz() - VJ->Xyz(); - Double_t chi2 = - diff.x()*diff.x()/(VI->SigmaXyz().x()*VI->SigmaXyz().x() + VJ->SigmaXyz().x()*VJ->SigmaXyz().x()) + - diff.y()*diff.y()/(VI->SigmaXyz().y()*VI->SigmaXyz().y() + VJ->SigmaXyz().y()*VJ->SigmaXyz().y()); - if (chi2 < 1e3) { - fStKFEvent->AddKFKFPair(i,j,*VI,*VJ,chi2); - } - } - } - ftree->Fill(); -#ifdef EVENT_DISPLAY - // fill - TArrayF xyzMcVxT(3*NoMuMcVertex); // from trigger event - TArrayF xyzMcVxP(3*NoMuMcVertex); // from pile up - Int_t NT = 0; - Int_t NP = 0; - for( int i = 0; i < NoMuMcVertex; ++i ) { - if (TMath::Abs(StMuMcVertex_time[i]) < 100e-9) { - xyzMcVxT[3*NT ] = StMuMcVertex_xyzV_mX1[i]; - xyzMcVxT[3*NT+1] = StMuMcVertex_xyzV_mX2[i]; - xyzMcVxT[3*NT+2] = StMuMcVertex_xyzV_mX3[i]; - NT++; - } else { - xyzMcVxP[3*NP ] = StMuMcVertex_xyzV_mX1[i]; - xyzMcVxP[3*NP+1] = StMuMcVertex_xyzV_mX2[i]; - xyzMcVxP[3*NP+2] = StMuMcVertex_xyzV_mX3[i]; - NP++; - } - } - TArrayF xyzRcVx(3*Nvtx); - Int_t NR = 0; - for (Int_t l = 0; l < Nvtx; l++) { - StKFVertex *V = fitter.Vertices()->Vertex(l); - if (V) { - xyzRcVx[3*NR ] = V->Vertex().GetX(); - xyzRcVx[3*NR+1] = V->Vertex().GetY(); - xyzRcVx[3*NR+2] = V->Vertex().GetZ(); - NR++; - } - } - eventD->Points(NR, xyzRcVx.GetArray(), kVtx); eventD->SetComment("Rc Vtx and Geometry"); - eventD->Points(NT, xyzMcVxT.GetArray(),kUsedHit); eventD->SetComment("Mc Vtx triggered and Geometry"); - eventD->Points(NP, xyzMcVxP.GetArray(),kUnusedHit); eventD->SetComment("Mc Vtx pile-up and Geometry"); - eventD->UpdateModified(); - while(!gSystem->ProcessEvents()){}; -#endif // EVENT_DISPLAY -#if defined(DRAW_RECO_HISTOS) || defined(EVENT_DISPLAY) - if (! gROOT->IsBatch() && Ask()) break; -#endif - } // loop ove events - - fOut->Write(); -} -//________________________________________________________________________________ -void Analysis(const Char_t *files="./y*.root") { - TDirIter Dir(files); - Char_t *file = 0; - TFile *fOut = new TFile("MuDst_KFV.root","recreate"); - TH2D *multDK = new TH2D("multDK","log_{2} (Multiplicity_{MuDst}) versus log_{2} (Multiplicity_{KFVertex})", - 120,-1.0,11.0, 120,-1.0,11.0); - TH2D *multDKQ = new TH2D("multDKQ","log_{2} (MultiplicityQ_{MuDst}) versus log_{2} (MultiplicityQ_{KFVertex})", - 120,-1.0,11.0, 120,-1.0,11.0); - TH2D *dXD = new TH2D("dXD","dX MuDst - MC versus log_{2} (Multiplicity_{MuDst})",120,-1.0,11.0,100,-5,5); - TH2D *dYD = new TH2D("dYD","dY MuDst - MC versus log_{2} (Multiplicity_{MuDst})",120,-1.0,11.0,100,-5,5); - TH2D *dZD = new TH2D("dZD","dZ MuDst - MC versus log_{2} (Multiplicity_{MuDst})",120,-1.0,11.0,100,-5,5); - - TH2D *dXK = new TH2D("dXK","dX KFVertex - MC versus log_{2} (Multiplicity_{KFVertex})",120,-1.0,11.0,100,-5,5); - TH2D *dYK = new TH2D("dYK","dY KFVertex - MC versus log_{2} (Multiplicity_{KFVertex})",120,-1.0,11.0,100,-5,5); - TH2D *dZK = new TH2D("dZK","dZ KFVertex - MC versus log_{2} (Multiplicity_{KFVertex})",120,-1.0,11.0,100,-5,5); - cout << "|Simulation Production | Total no. | MuDst Efficiency | | KFVertex Efficiency | |" << endl; - while ((file = (Char_t *) Dir.NextFile())) { - TString File(file); - if (File.Contains("event") || File.Contains("geant") || - File.Contains("hist") || File.Contains("tags") || File.Contains("runco") || - File.Contains("minimc") || File.Contains("event") || - File.Contains("MuDst")) continue; - TFile *f = new TFile (File); - if (! f) continue; - TTree *tree = (TTree *) f->Get("StVertexT"); - if (! tree ) {delete f; continue;} - TString Name(gSystem->BaseName(f->GetName())); - Name.ReplaceAll(".root",""); - TString Title(Name); - Title.ReplaceAll("_"," "); - fOut->cd(); - - TH1D *DM = new TH1D(Form("DM%s",Name.Data()),Form("MuDst Multiplicity for %s",Title.Data()),3000,0,3000); - TH1D *DMQ = new TH1D(Form("DMQ%s",Name.Data()),Form("MuDst Multiplicity*QA for %s",Title.Data()),3000,0,3000); - TH1D *KM = new TH1D(Form("KM%s",Name.Data()),Form("KFVer Multiplicity for %s",Title.Data()),3000,0,3000); - TH1D *KMQ = new TH1D(Form("KMQ%s",Name.Data()),Form("KFVer Multiplicity*QA for %s",Title.Data()),3000,0,3000); - StKFEvent *fStKFEvent = new StKFEvent(); - TBranch *branch = tree->GetBranch("StKFEvent"); - if (! branch) continue; - // tree->SetMakeClass(1); - branch->SetAddress(&fStKFEvent); - Int_t nbytes = 0, nb = 0;// ierr = 0, nevt = 0; - Long64_t nentries = tree->GetEntries(); - for (Long64_t jentry=0; jentryLoadTree(jentry) < 0) break; - nb = tree->GetEntry(jentry); nbytes += nb; - Int_t NoMuDst = fStKFEvent->NoMuDstVtx(); - Int_t NoKFVtx = fStKFEvent->NoKFVtx(); - // cout << "Event. \t" << jentry << "\tNo Dst " << NoMuDst << "\tKFV " << NoKFVtx << endl; - // find IdTruth = 1 vertices and plot them - TClonesArray *MuDst = fStKFEvent->MuDstVtx(); - Int_t MultMx = -1; - Int_t kd = -1; - Double_t MultD = 0.5; - Double_t MultDQ = 0.5; - TVector3 dXyz; - for (Int_t l = 0; l < NoMuDst; l++) { - StMuDstVtxT *md = (StMuDstVtxT *) MuDst->UncheckedAt(l); - if (md->IdTruth() != 1) continue; - Int_t Mult = md->Mult(); - if (Mult > MultMx) {MultMx = Mult; kd = l;} - } - if (kd >= 0) { - StMuDstVtxT *md = (StMuDstVtxT *) MuDst->UncheckedAt(kd); - MultD = md->Mult(); - DM->Fill(MultD); - MultDQ = TMath::Nint(MultD*md->QaTruth()/100.); - DMQ->Fill(MultDQ); - dXyz = md->Xyz() - md->XyzMc(); - dXD->Fill(TMath::Log2(MultD),dXyz.x()); - dYD->Fill(TMath::Log2(MultD),dXyz.y()); - dZD->Fill(TMath::Log2(MultD),dXyz.z()); - } - TClonesArray *KF = fStKFEvent->KFVtx(); - MultMx = -1; - Int_t kf = -1; - for (Int_t l = 0; l < NoKFVtx; l++) { - StVertexT *mk = (StVertexT *) KF->UncheckedAt(l); - if (mk->IdTruth() != 1) continue; - Int_t Mult = mk->Mult(); - if (Mult > MultMx) {MultMx = Mult; kf = l;} - } - Double_t MultK = 0.5; - Double_t MultKQ = 0.5; - if (kf >= 0) { - StVertexT *mk = (StVertexT *) KF->UncheckedAt(kf); - MultK = mk->Mult(); - KM->Fill(MultK); - MultKQ = TMath::Nint(MultK*mk->QaTruth()/100.); - KMQ->Fill(MultKQ); - dXyz = mk->Xyz() - mk->XyzMc(); - dXK->Fill(TMath::Log2(MultK),dXyz.x()); - dYK->Fill(TMath::Log2(MultK),dXyz.y()); - dZK->Fill(TMath::Log2(MultK),dXyz.z()); - } - multDK->Fill(TMath::Log2(MultK), TMath::Log2(MultD)); - multDKQ->Fill(TMath::Log2(MultKQ), TMath::Log2(MultDQ)); - } - cout << "Process \t" << f->GetName() << "\tread " << nentries << " entries and " << nbytes << " Bytes" << endl; - delete f; - TH1D *hists[4] = {DM, DMQ, KM, KMQ}; - cout << "|" << DM->GetTitle() << "|\t" << nentries; - for (Int_t i = 0; i < 4; i++) { -#if 0 - cout << hists[i]->GetName() << "\t" << hists[i]->GetTitle() - << "\tEntries = " << hists[i]->GetEntries() - << "\tMean = " << hists[i]->GetMean() << endl; -#else - cout << "|\t" << 100*hists[i]->GetEntries()/nentries << "\t|\t" << hists[i]->GetMean(); -#endif - } - cout << "\t|" << endl; - // compress multiplicity histograms - TH1D *DMr = 0, *DMQr = 0, *KMr = 0, *KMQr = 0; - Int_t nx = DM->GetNbinsX(); - for (Int_t i = nx; i > 0; i--) { - if (! DMr) { - if (DM->GetBinContent(i) <= 0 && KM->GetBinContent(i) <= 0) continue; - DMr = new TH1D(Form("DMr%s",Name.Data()),Form("MuDst Multiplicity for %s",Title.Data()),100,0,DM->GetXaxis()->GetBinUpEdge(i)); - DMQr = new TH1D(Form("DMQr%s",Name.Data()),Form("MuDst Multiplicity*QA for %s",Title.Data()),100,0,DM->GetXaxis()->GetBinUpEdge(i)); - KMr = new TH1D(Form("KMr%s",Name.Data()),Form("KFVer Multiplicity for %s",Title.Data()),100,0,DM->GetXaxis()->GetBinUpEdge(i)); - KMQr = new TH1D(Form("KMQr%s",Name.Data()),Form("KFVer Multiplicity*QA for %s",Title.Data()),100,0,DM->GetXaxis()->GetBinUpEdge(i)); - } - DMr->Fill(DM->GetBinCenter(i),DM->GetBinContent(i)); - DMQr->Fill(DMQ->GetBinCenter(i),DMQ->GetBinContent(i)); - KMr->Fill(KM->GetBinCenter(i),KM->GetBinContent(i)); - KMQr->Fill(KMQ->GetBinCenter(i),KMQ->GetBinContent(i)); - } - delete DM; delete DMQ; delete KM; delete KMQ; - } - fOut->Write(); -} -//________________________________________________________________________________ -void MuPrmVtx(Int_t last, const Char_t *files = "./*MuDst.root", const Char_t *Out="") { - MuPrmVtx(0,last,files,Out); -} -//________________________________________________________________________________ -void MuPrmVtx(const Char_t *files = "./*MuDst.root", const Char_t *Out="") { - MuPrmVtx(0,99999,files,Out); -} -//________________________________________________________________________________ -// $Log: MuPrmVtx.C,v $ -// Revision 2.3 2013/04/10 22:14:20 fisyak -// Roll back to version 04/04/2013 -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.13 2012/02/18 23:20:52 fisyak -// Rename StKFVertexFitter => StKFVertexFinder -// -// Revision 1.12 2012/02/07 19:38:26 fisyak -// Repackage -// diff --git a/StRoot/StiMaker/StAnneling.cxx b/StRoot/StiMaker/StAnneling.cxx deleted file mode 100644 index 4366f1ceb0d..00000000000 --- a/StRoot/StiMaker/StAnneling.cxx +++ /dev/null @@ -1,24 +0,0 @@ -// $Id: StAnneling.cxx,v 2.2 2018/04/10 11:32:09 smirnovd Exp $ -#include "StAnneling.h" -Double_t StAnneling::fChi2Cut = 12.25; // 13.81551055; // Prob = 1e-3 -Double_t StAnneling::fTemperature = 1; -// $Log: StAnneling.cxx,v $ -// Revision 2.2 2018/04/10 11:32:09 smirnovd -// Minor corrections across multiple files -// -// - Remove ClassImp macro -// - Change white space -// - Correct windows newlines to unix -// - Remove unused debugging -// - Correct StTpcRTSHitMaker header guard -// - Remove unused preprocessor directives in StiCA -// - Minor changes in status and debug print out -// - Remove using std namespace from StiKalmanTrackFinder -// - Remove includes for unused headers -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.2 2012/02/07 19:38:26 fisyak -// Repackage -// diff --git a/StRoot/StiMaker/StAnneling.h b/StRoot/StiMaker/StAnneling.h deleted file mode 100644 index 76b57a3933e..00000000000 --- a/StRoot/StiMaker/StAnneling.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __StAnneling_h__ -#define __StAnneling_h__ -// $Id: StAnneling.h,v 2.1 2012/05/07 14:56:14 fisyak Exp $ -#include "TMath.h" -#include "TObject.h" -//________________________________________________________________________________ -class StAnneling : public TObject { -public: - static void SetTemperature(Double_t Temperature=1) {fTemperature = Temperature;} - static Double_t Temperature() {return fTemperature;} - static void SetChi2Cut (Double_t chi2Cut=12.25) {fChi2Cut = chi2Cut;} - static Double_t Chi2Cut() {return fChi2Cut;} - static Double_t Weight() { - return TMath::Exp(Chi2Cut()/(2*Temperature())) + - Temperature()*TMath::Log(1 + TMath::Exp(Chi2Cut()/(2*Temperature()))); - } -private: - static Double_t fTemperature; - static Double_t fChi2Cut; - ClassDef(StAnneling,1) -}; -// $Log: StAnneling.h,v $ -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.3 2012/02/07 19:38:26 fisyak -// Repackage -// -#endif diff --git a/StRoot/StiMaker/StKFEvent.cxx b/StRoot/StiMaker/StKFEvent.cxx deleted file mode 100644 index ea3c138d298..00000000000 --- a/StRoot/StiMaker/StKFEvent.cxx +++ /dev/null @@ -1,32 +0,0 @@ -// $Id: StKFEvent.cxx,v 2.6 2018/04/10 11:32:09 smirnovd Exp $ -#include "StKFEvent.h" -TClonesArray *StKFEvent::fgMuDstVtx = 0; -TClonesArray *StKFEvent::fgKFVtx = 0; -TClonesArray *StKFEvent::fgDKFPair = 0; -TClonesArray *StKFEvent::fgKFKFPair = 0; -// $Log: StKFEvent.cxx,v $ -// Revision 2.6 2018/04/10 11:32:09 smirnovd -// Minor corrections across multiple files -// -// - Remove ClassImp macro -// - Change white space -// - Correct windows newlines to unix -// - Remove unused debugging -// - Correct StTpcRTSHitMaker header guard -// - Remove unused preprocessor directives in StiCA -// - Minor changes in status and debug print out -// - Remove using std namespace from StiKalmanTrackFinder -// - Remove includes for unused headers -// -// Revision 2.5 2015/12/20 01:35:12 fisyak -// Move back commits done by mistate -// -// Revision 2.3 2013/04/10 22:14:20 fisyak -// Roll back to version 04/04/2013 -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.2 2012/02/07 19:38:26 fisyak -// Repackage -// diff --git a/StRoot/StiMaker/StKFEvent.h b/StRoot/StiMaker/StKFEvent.h deleted file mode 100644 index 7d05876fb24..00000000000 --- a/StRoot/StiMaker/StKFEvent.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __StKFEvent__ -#define __StKFEvent__ -#include "Riostream.h" -#include "TObject.h" -#include "TClonesArray.h" -#include "StMuDstVtxT.h" -#include "StKFVertex.h" -#include "StVertexT.h" -#include "StVertexP.h" - -class StKFEvent : public TObject { -public: - StKFEvent() { - if (!fgMuDstVtx) fgMuDstVtx = new TClonesArray("StVertexT", 100); - fMuDstVtx = fgMuDstVtx; fNMuDstVtx = 0; - if (!fgKFVtx) fgKFVtx = new TClonesArray("StVertexT", 100); - fKFVtx = fgKFVtx; fNKFVtx = 0; - if (!fgDKFPair) fgDKFPair = new TClonesArray("StVertexP", 100); - fDKFPair = fgDKFPair; fNDKFPair = 0; - if (!fgKFKFPair) fgKFKFPair = new TClonesArray("StVertexP", 100); - fKFKFPair = fgKFKFPair; fNKFKFPair = 0; - } - virtual ~StKFEvent() {Clear();} - void SetTemperature(Double_t T) {fTemperature = T;} - void AddMuVtx(StMuDstVtxT &muDstVtx) {TClonesArray &MuDstVtxs = *fMuDstVtx; new(MuDstVtxs[fNMuDstVtx++]) StVertexT(muDstVtx);} - void AddKFVtx(StKFVertex &kfVtx) {TClonesArray &KFVtxs = *fKFVtx; new(KFVtxs[fNKFVtx++]) StVertexT(kfVtx); } - void AddDKFPair(Int_t i, Int_t j, StVertexT &muDstVtx, StVertexT &kfVtx, Double_t chi2 = 0) { - TClonesArray &DKFPairs = *fDKFPair; new(DKFPairs[fNDKFPair++]) StVertexP(i,j,muDstVtx,kfVtx,chi2); - } - void AddKFKFPair(Int_t i, Int_t j, StVertexT &kfVtxI, StVertexT &kfVtxJ, Double_t chi2 = 0) { - TClonesArray &KFKFPairs = *fKFKFPair; new(KFKFPairs[fNKFKFPair++]) StVertexP(i,j,kfVtxI,kfVtxJ,chi2); - } - void Clear(Option_t *option = "") { - fTemperature = 0; - fNMuDstVtx = 0; fMuDstVtx->Clear(option); - fNKFVtx = 0; fKFVtx->Clear(option); - fNDKFPair = 0; fDKFPair->Clear(option); - fNKFKFPair = 0; fKFKFPair->Clear(option); - } - void Reset(Option_t */* option = "" */) {SafeDelete(fgMuDstVtx); SafeDelete(fgKFVtx); SafeDelete(fgDKFPair); SafeDelete(fgKFKFPair);} - Int_t NoMuDstVtx() {return fNMuDstVtx;} - TClonesArray *MuDstVtx() {return fMuDstVtx;} - Int_t NoKFVtx() {return fNKFVtx;} - TClonesArray *KFVtx() {return fKFVtx;} - Int_t NoDKFPair() {return fNDKFPair;} - TClonesArray *DKFPair() {return fDKFPair;} - Int_t NoKFKFPair() {return fNKFKFPair;} - TClonesArray *KFKFPair() {return fKFKFPair;} -private: - Double_t fTemperature; - Int_t fNMuDstVtx; - Int_t fNKFVtx; - Int_t fNDKFPair; - Int_t fNKFKFPair; - TClonesArray *fMuDstVtx; //-> - TClonesArray *fKFVtx; //-> - TClonesArray *fDKFPair; //-> - TClonesArray *fKFKFPair; //-> - static TClonesArray *fgMuDstVtx; - static TClonesArray *fgKFVtx; - static TClonesArray *fgDKFPair; - static TClonesArray *fgKFKFPair; - - ClassDef(StKFEvent,1) -}; -#endif diff --git a/StRoot/StiMaker/StKFTrack.cxx b/StRoot/StiMaker/StKFTrack.cxx deleted file mode 100644 index 274ee0d9760..00000000000 --- a/StRoot/StiMaker/StKFTrack.cxx +++ /dev/null @@ -1,77 +0,0 @@ -// $Id: StKFTrack.cxx,v 2.3 2018/04/10 11:32:09 smirnovd Exp $ -#include "StKFTrack.h" -//________________________________________________________________________________ -StKFTrack::StKFTrack(Int_t k, KFParticle *particle, Double_t chi2, Int_t iWE) : - fK(k), fWeight(-1), fW(-1), fOrigKFParticle(particle), fWestOrEast(iWE) { - if (particle) { - fParticle = KFParticle(*particle); - SetChi2(chi2); - } -} -//________________________________________________________________________________ -void StKFTrack::SetChi2(Double_t chi2) { - fChi2 = chi2; - if (fChi2 >= 0) { - fWeight = TMath::Exp(-fChi2/(2.*StAnneling::Temperature())); - } else { - fWeight = -1; - } -} -//________________________________________________________________________________ -Int_t StKFTrack::CorrectGePid(Int_t gePid) { - // By pass embedding particle redefinition - if (gePid == 99) gePid = 11151; - if (gePid == 207) gePid = 41; - if (gePid == 40001) gePid = 24; - if (gePid == 98) gePid = 18; - if (gePid == 40002) gePid = 32; - if (gePid == 97) gePid = 26; - if (gePid == 40003) gePid = 23; - if (gePid == 40004) gePid = 31; - if (gePid == 40005) gePid = 22; - if (gePid == 40006) gePid = 30; - if (gePid == 10150) gePid = 150; - if (gePid == 10151) gePid = 151; - if (gePid == 11151) gePid = 10151; - if (gePid == 10018) gePid = 98; - if (gePid == 10026) gePid = 97; - if (gePid == 10017) gePid = 17; - if (gePid == 10039) gePid = 39; - if (gePid == 10040) gePid = 40; - if (gePid == 98) gePid = 18; - if (gePid == 97) gePid = 26; - if (gePid < 0 || gePid > 50) { - std::cout << "Illegal gePid " << gePid << std::endl; - } - if (gePid < 0 || gePid > 50) gePid = 51; - return gePid; -} -//________________________________________________________________________________ -std::ostream& operator<<(std::ostream& os, const StKFTrack& p) { - os << Form("%5i %9.3f %9.3f %9.3f %9.3f", - p.K(),p.Weight(),p.W(),p.OrigParticle()->GetZ(),p.Chi2()); - return os; -} -// $Log: StKFTrack.cxx,v $ -// Revision 2.3 2018/04/10 11:32:09 smirnovd -// Minor corrections across multiple files -// -// - Remove ClassImp macro -// - Change white space -// - Correct windows newlines to unix -// - Remove unused debugging -// - Correct StTpcRTSHitMaker header guard -// - Remove unused preprocessor directives in StiCA -// - Minor changes in status and debug print out -// - Remove using std namespace from StiKalmanTrackFinder -// - Remove includes for unused headers -// -// Revision 2.2 2012/06/11 15:33:41 fisyak -// std namespace -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.2 2012/02/07 19:38:26 fisyak -// Repackage -// diff --git a/StRoot/StiMaker/StKFTrack.h b/StRoot/StiMaker/StKFTrack.h deleted file mode 100644 index 421101ad078..00000000000 --- a/StRoot/StiMaker/StKFTrack.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __StKFTrack_h__ -#define __StKFTrack_h__ -// $Id: StKFTrack.h,v 2.2 2012/06/11 15:33:41 fisyak Exp $ -#include "Riostream.h" -#include "TObject.h" -#include "KFParticle.h" -#include "TRSymMatrix.h" -#include "StAnneling.h" -#include "TString.h" -class StKFTrack; -std::ostream& operator<<(std::ostream& os, const StKFTrack& p); -class StKFTrack : public TObject { -public: - StKFTrack(Int_t k = -1, KFParticle *particle = 0, Double_t chi2=-1, Int_t iWE = 0); - virtual ~StKFTrack() {} - void SetChi2(Double_t chi2=-1); - void Reset() {fParticle = KFParticle(*fOrigKFParticle);} - Int_t K() const {return fK;} // index in particle array - Double_t Weight() const {return fWeight;} // adaptive weight - Double_t W() const {return fW;} // adaptive weigth for multi vertices - Double_t Chi2() const {return fChi2;} - KFParticle Particle()const {return fParticle;}// particle with modified covariance matrix accourdingly to weight - KFParticle &Particle(){return *&fParticle;}// particle with modified covariance matrix accourdingly to weight - - Double_t &Weight() {return *&fWeight;} // adaptive weight - Double_t &W() {return *&fW;} // adaptive weigth for multi vertices - Double_t &Chi2() {return *&fChi2;} - KFParticle *OrigParticle() const {return fOrigKFParticle;} // - Bool_t IsWest() {return fWestOrEast > 0;} - Bool_t IsEast() {return fWestOrEast < 0;} - void Print(Option_t *option="") const {if (option) {}; std::cout << *this << std::endl;} - static Int_t CorrectGePid(Int_t gePid); -private: - const Int_t fK; // index in particle array - Double_t fWeight; // adaptive weight - Double_t fW; // adaptive weigth for multi vertices - Double_t fChi2; - KFParticle fParticle;// particle with modified covariance matrix accourdingly to weight - KFParticle *fOrigKFParticle; // - Int_t fWestOrEast; - ClassDef(StKFTrack,0) -}; -// $Log: StKFTrack.h,v $ -// Revision 2.2 2012/06/11 15:33:41 fisyak -// std namespace -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.2 2012/02/07 19:38:26 fisyak -// Repackage -// -#endif diff --git a/StRoot/StiMaker/StKFVertex.cxx b/StRoot/StiMaker/StKFVertex.cxx deleted file mode 100644 index dc7f82c67c2..00000000000 --- a/StRoot/StiMaker/StKFVertex.cxx +++ /dev/null @@ -1,244 +0,0 @@ -// $Id: StKFVertex.cxx,v 2.5 2018/04/10 11:32:09 smirnovd Exp $ -#include "StKFVertex.h" -#include "StKFTrack.h" -#include "TArrayC.h" - -#define __DEBUG__ -#if defined(__DEBUG__) -#define PrPP(A,B) if (Debug()) {cout << "StKFVertex::" << (#A) << "\t" << (#B) << " = \t" << (B) << endl;} -#else -#define PrPP(A,B) -#endif -using namespace std; -Int_t StKFVertex::_debug = 0; -const Char_t *StKFVertex::GeNames[52] = { - // 1 2 3 4 5 6 7 8 9 10 - "", - "gamma" ,"e+" ,"e-" ,"nu" ,"mu+" ,"mu-" ,"pi0" ,"pi+" ,"pi-" ,"K0L", - "K+" ,"K-" ,"N" ,"P" ,"Pbar" ,"K0S" ,"eta" ,"Lambda","Sigma+" ,"Sigma0", - "S-" ,"Xi0" ,"Xi-" ,"Omega","Nbar" ,"LamBar","SBar-","SBar0" ,"SBar+" ,"XiBar0", - "XiBar+" ,"OmBar","tau+","tau-" ,"D+" ,"D-" ,"D0" ,"Dbar0" ,"Ds+" ,"Ds-" , - "LambC+" ,"W+" ,"W-" ,"Z0" ,"H2" ,"H3" ,"alpha","geanti","He3" ,"Cerenk", - "??????"}; -//________________________________________________________________________________ -ostream& operator<<(ostream& os, const StKFVertex& v) { - Int_t iWest = v.MultW(); - Int_t iEast = v.MultE(); - os << Form(" with %4i tracks Q:%3i W/E = %3i/%3i",v.NoTracks(),v.Charge(),iWest,iEast); - for (Int_t i = 0; i < 3; i++) { - os << Form("%9.3f +/- %5.3f",v.Vertex().GetParameter(i),TMath::Sqrt(v.Vertex().GetCovariance(i,i))); - } - Double_t prob = TMath::Prob(v.Vertex().GetChi2(),v.Vertex().GetNDF()); - os << Form("\tchi2/NDF = %8.2f/%4i",v.Vertex().GetChi2(),v.Vertex().GetNDF()) - << Form(" prob = %6.4f",prob); - Double_t M, dM; - if (! v.Vertex().GetMass(M,dM)) { - os << " M = " << Form("%7.3f +/- %5.3f",M,dM); - } - Int_t kv = v.IdTruth(); - if (kv > 0) { - os << Form(" Mc/QA/t:%4i/%3i/%6.0f xyz: %8.3f%8.3f%8.3f m:%4i %6s",kv, v.QaTruth(), - v.TimeMc(), v.XyzMc().X(), v.XyzMc().Y(), v.XyzMc().Z(), - v.NoDaughtersMc(),StKFVertex::StKFVertex::GeNames[v.gePidMc()]); - } - return os; -} -//________________________________________________________________________________ -void StKFVertex::Fit() { - Compress(); - Int_t N = NoTracks(); - if (! N) return; - KFParticle **particles = new KFParticle*[N]; - for (Int_t i = 0; i < N; i++) { - // Track(i)->Reset(); - particles[i] = &(Track(i)->Particle()); - } - TArrayC Flag(N); - Vertex().ConstructPrimaryVertex((const KFParticle **) particles, N, - (Bool_t*) Flag.GetArray(),TMath::Sqrt(StAnneling::Chi2Cut()/2)); - //Check Covariance Matrix - // Double_t prob = TMath::Prob(Vertex().GetChi2(),Vertex().GetNDF()); - TRSymMatrix CL(3,Vertex().CovarianceMatrix()); - if (CL[0] <= 0 || CL[2] <= 0 || CL[5] <= 0) { - for (Int_t i = N-1; i >= 0; i--) delete Remove(i); - } else { - for (Int_t i = N-1; i >= 0; i--) if (! Flag[i]) delete Remove(i); - } - delete [] particles; - Compress(); - N = NoTracks(); - // Assign MC and RC - struct vertexPing { - Int_t Id; - Int_t nPings; - }; - static vertexPing candidates[20]; - memset(candidates,0,sizeof(candidates)); - Int_t NC = 0; - for (Int_t i = 0; i < N; i++) { - const StKFTrack *pTrack = Track(i); - if (! pTrack) continue; - Int_t IdVx = pTrack->Particle().IdParentVx(); - if (IdVx <= 0) continue; - Int_t J = -1; - for (Int_t j = 0; j < NC; j++) if (candidates[j].Id == IdVx) {J = j; break;} - if (J < 0) {J = NC; if (NC < 18) NC++;} - candidates[J].Id = IdVx; - candidates[J].nPings++; - } - Int_t dominant = -1; - Int_t J = -1; - for (Int_t j = 0; j < NC; j++) if (candidates[j].nPings > dominant) {dominant = candidates[j].nPings; J = j;} - if (J > -1) { - Int_t Id = candidates[J].Id; - Int_t QA = (100*dominant)/N; - SetIdTruth(Id,QA); - } - for (Int_t i = 0; i < N; i++) { - Track(i)->Particle().SetProductionVertex(Vertex()); - } -} -//________________________________________________________________________________ -void StKFVertex::AddTrack(const StKFTrack *track) { - Int_t k2 = track->K()%100000; - Int_t N1 = NoTracks(); - for (Int_t j = 0; j < N1; j++) {// protect from multiple copies of beam track - StKFTrack* t1 = Track(j); - Int_t k1 = t1->K()%100000; - if (k1 == k2) { - PrintW("AddTrack"); - assert(0); - } - } - fKFTracks.AddLast((TObject *)track); -} -//________________________________________________________________________________ -Double_t StKFVertex::UpdateVertex2TrackChi2() { - Int_t Ntracks = NoTracks(); - Double_t chi2Vx = 0; - PrPP(UpdateVertex2TrackChi2,fVertex); - if (_debug) PrintW("old Weghts "); - for (Int_t k = Ntracks - 1; k >= 0; k--) { - KFVertex vTmp = fVertex; - // PrPP(UpdateVertex2TrackChi2,vTmp); - StKFTrack &track = *Track(k); - // PrPP(UpdateVertex2TrackChi2,track.Particle()); - vTmp -= track.Particle(); - // PrPP(UpdateVertex2TrackChi2,vTmp); - KFParticle *particle = track.OrigParticle(); - if (! particle) continue; - // PrPP(UpdateVertex2TrackChi2,*particle); - Double_t chi2il = particle->GetDeviationFromVertex(vTmp); - chi2il *= 2*chi2il; - if (chi2il > StAnneling::Chi2Cut()) { - Remove(k); - continue; - } - track.SetChi2(chi2il); - chi2Vx += track.Chi2()/2 + TMath::Log(track.Weight() + StAnneling::Weight()); - } - Compress(); - if (_debug) PrintW("new Weights "); - return chi2Vx; -} -//________________________________________________________________________________ -StKFTrack* StKFVertex::Remove(KFParticle *particle) { - Int_t N = NoTracks(); - for (Int_t k = 0; k < N; k++) if (particle == Track(k)->OrigParticle()) return Remove(k); - return 0; -} -//________________________________________________________________________________ -Int_t StKFVertex::MultWE(Int_t k) const { - Int_t N = NoTracks(); - Int_t iWE = 0; - for (Int_t i = 0; i < N; i++) { - const StKFTrack* t = Track(i); - if (t) { - Int_t id = (t->OrigParticle()->GetID()/100000)%10; - if (id == k) iWE++; - } - } - return iWE; -} -//________________________________________________________________________________ -Int_t StKFVertex::Q() const { - Int_t iQ = 0; - Int_t N = NoTracks(); - for (Int_t i = 0; i < N; i++) { - const StKFTrack* t = Track(i); - if (t) {iQ += t->OrigParticle()->GetQ();} - } - return iQ; -} -//________________________________________________________________________________ -void StKFVertex::operator +=(StKFVertex &vtx) { - if (_debug) { - PrintW("Before Merge 1"); - vtx.PrintW("Before Merge 2"); - } - Int_t N2 = vtx.NoTracks(); - for (Int_t i = N2-1; i >= 0; i--) { - StKFTrack* t2 = (StKFTrack* ) vtx.Remove(i); - Int_t k2 = t2->K()%100000; - Int_t N1 = NoTracks(); - for (Int_t j = 0; j < N1; j++) {// protect from multiple copies of beam track - StKFTrack* t1 = Track(j); - Int_t k1 = t1->K()%100000; - if (k1 == k2) {SafeDelete(t2); break;} - } - if (t2) fKFTracks.AddLast(t2); - } - vtx.Compress(); - if (_debug) { - PrintW("After Merge 1"); - vtx.PrintW("After Merge 2"); - } -} -//________________________________________________________________________________ -void StKFVertex::PrintW(Option_t *option) const { - Int_t N = NoTracks(); - cout << Form("Vertex %5i with %5i tracks\t",fID,N); - Print(option); - cout << Form(" i k Weight W Z chi2") << endl; - for (Int_t i = 0; i < N; i++) { - const StKFTrack* t = Track(i); - cout << Form("%6i",i) << *t << endl; - } -} -//________________________________________________________________________________ -void StKFVertex::SetMc(Float_t time, Float_t x, Float_t y, Float_t z, Int_t NoDaughters, Int_t gePid) { - fTimeMc = 1e9*time; - fXyzMc = TVector3(x,y,z); - fNoDaughtersMc = NoDaughters; - fgePidMc = StKFTrack::CorrectGePid(gePid); -} -#undef PrPP -// $Log: StKFVertex.cxx,v $ -// Revision 2.5 2018/04/10 11:32:09 smirnovd -// Minor corrections across multiple files -// -// - Remove ClassImp macro -// - Change white space -// - Correct windows newlines to unix -// - Remove unused debugging -// - Correct StTpcRTSHitMaker header guard -// - Remove unused preprocessor directives in StiCA -// - Minor changes in status and debug print out -// - Remove using std namespace from StiKalmanTrackFinder -// - Remove includes for unused headers -// -// Revision 2.4 2013/04/10 22:14:20 fisyak -// Roll back to version 04/04/2013 -// -// Revision 2.2 2012/06/11 15:33:41 fisyak -// std namespace -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.3 2012/03/29 23:35:47 fisyak -// Fix problem with multiple beam tracks -// -// Revision 1.2 2012/02/07 19:38:26 fisyak -// Repackage -// diff --git a/StRoot/StiMaker/StKFVertex.h b/StRoot/StiMaker/StKFVertex.h deleted file mode 100644 index e4c12aac4b1..00000000000 --- a/StRoot/StiMaker/StKFVertex.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef __StKFVertex_h__ -#define __StKFVertex_h__ -// $Id: StKFVertex.h,v 2.4 2013/04/10 22:14:20 fisyak Exp $ -#include "Riostream.h" -#include "TObject.h" -#include "StKFTrack.h" -#include "TObjArray.h" -#include "KFVertex.h" -#include "TVector3.h" - -class StKFVertex; -std::ostream& operator<<(std::ostream& os, const StKFVertex& v); -class StKFVertex : public TObject { -public: - StKFVertex(Int_t id = -1) : fID(id) , fIdTruth(0), fQuality(0), fIdParentTk(0), - fTimeMc(0), fNoDaughtersMc(0), fgePidMc(0) - {fKFTracks.SetOwner(kTRUE); Clear();} - virtual ~StKFVertex() {Clear();} - void AddTrack(const StKFTrack *track); - virtual void Clear(Option_t *opt="") {fKFTracks.Clear(opt);} - StKFTrack* Remove(Int_t k=0) {return (StKFTrack *) fKFTracks.RemoveAt(k);} - StKFTrack* Remove(StKFTrack *track) {return (StKFTrack *) fKFTracks.Remove(track);} - StKFTrack* Remove(KFParticle *particle); - Int_t ID() const {return fID;} - KFVertex &Vertex() {return *&fVertex;} - KFVertex Vertex() const {return fVertex;} - TObjArray &Tracks() {return *&fKFTracks;} - Int_t NoTracks() const {return fKFTracks.GetEntriesFast();} - Int_t Charge() const {return fVertex.GetQ();} - StKFTrack* Track(Int_t k = 0) {return (StKFTrack* ) fKFTracks[k];} - const StKFTrack* Track(Int_t k = 0) const {return (const StKFTrack* ) fKFTracks[k];} - Double_t UpdateVertex2TrackChi2(); - void Compress() {fKFTracks.Compress();} - void Fit(); - Int_t IdTruth() const { return fIdTruth;} - Int_t QaTruth() const { return fQuality; } - Int_t IdParentTk() const {return fIdParentTk;} - void SetIdTruth(Int_t idtru,Int_t qatru=0) {fIdTruth = (UShort_t) idtru; fQuality = (UShort_t) qatru;} - void SetIdParentTk(Int_t id) {fIdParentTk = id;} - Int_t MultW() const {return MultWE(1);} - Int_t MultE() const {return MultWE(2);} - Int_t MultWE(Int_t k = 1) const; - Int_t Q() const; - void operator +=(StKFVertex &vtx); - void Print(Option_t *option="") const {std::cout << option << *this << std::endl; } - void PrintW(Option_t *option="") const; - void SetMc(Float_t time, Float_t x, Float_t y, Float_t z, Int_t NoDaughters, Int_t gePid); - Float_t TimeMc() const {return fTimeMc;} - const TVector3 &XyzMc() const {return *&fXyzMc;} - Int_t NoDaughtersMc() const {return fNoDaughtersMc;} - Int_t gePidMc() const {return fgePidMc;} - static void SetDebug(Int_t k = 0) {_debug = k;} - static Int_t Debug() {return _debug;} -private: - Int_t fID; - KFVertex fVertex; - TObjArray fKFTracks; - UShort_t fIdTruth; // MC vertex id - UShort_t fQuality; // quality of this information (percentage of hits coming from the above MC track) - Int_t fIdParentTk; - Float_t fTimeMc; - TVector3 fXyzMc; - Int_t fNoDaughtersMc; - Int_t fgePidMc; - public: - static Int_t _debug; - static const Char_t *GeNames[52]; - ClassDef(StKFVertex,0) -}; -// $Log: StKFVertex.h,v $ -// Revision 2.4 2013/04/10 22:14:20 fisyak -// Roll back to version 04/04/2013 -// -// Revision 2.2 2012/06/11 15:33:41 fisyak -// std namespace -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.3 2012/03/29 23:35:47 fisyak -// Fix problem with multiple beam tracks -// -// Revision 1.2 2012/02/07 19:38:26 fisyak -// Repackage -// -#endif diff --git a/StRoot/StiMaker/StKFVertexMaker.cxx b/StRoot/StiMaker/StKFVertexMaker.cxx deleted file mode 100644 index 538907cbb38..00000000000 --- a/StRoot/StiMaker/StKFVertexMaker.cxx +++ /dev/null @@ -1,649 +0,0 @@ -// $Id: StKFVertexMaker.cxx,v 2.8 2018/04/10 11:32:09 smirnovd Exp $ -#include "RVersion.h" -#if ROOT_VERSION_CODE < 331013 -#include "TCL.h" -#else -#include "TCernLib.h" -#endif -#include -using std::map; -#include "TMath.h" -#include "TH1.h" -#include "TCanvas.h" -#include "StDcaGeometry.h" -#include "KFParticle.h" -#include "KFVertex.h" -#include "MTrack.h" -#include "VVertex.h" -#include "TH1K.h" -#include "StAnneling.h" -#include "StKFEvent.h" -#include "StKFTrack.h" -#include "StKFVertex.h" -#include "StKFVerticesCollection.h" -#include "StVertexP.h" -#include "StVertexT.h" -#include "TDirectory.h" -#include "StEventTypes.h" -#include "Stypes.h" -#include "SystemOfUnits.h" -#include "StKFVertexMaker.h" -#include "StDetectorDbMaker/St_vertexSeedC.h" -#include "Sti/StiHit.h" -#include "Sti/StiKalmanTrack.h" -#include "Sti/StiKalmanTrackNode.h" -#include "StiStEventFiller.h" -#include "TRMatrix.h" -#include "TRSymMatrix.h" -#include "Sti/StiToolkit.h" -#include "TArrayI.h" - -StKFVerticesCollection *StKFVertexMaker::fcVertices = 0; -//________________________________________________________________________________ -StKFVertexMaker::~StKFVertexMaker() { - SafeDelete(fVtxM); - for (Int_t pass = 0; pass < fNPasses; pass++) { - SafeDelete(fVtxKs[pass]); - SafeDelete(fVtxKs[pass]); - } - SafeDelete(fSpectrum); - SafeDelete(func); - SafeDelete(fminBrent); - delete [] fVerticesPass; fVerticesPass = 0; - SafeDelete(fParticles); -} -//________________________________________________________________________________ -void StKFVertexMaker::Clear(Option_t *option) { - for (Int_t pass = 0; pass < fNPasses; pass++) { - fVtxKs[pass]->Reset(); - fVtxKs[pass]->SetMaximum(); - fVtxs[pass]->Reset(); - fVtxs[pass]->SetMaximum(); - } - fVtx = fVtxs[0]; // << switch between types Vtx = fVtxKs[0]; - fVtxM->Reset(); - fcVertices = 0; - fParticles->Clear("C"); -} -//________________________________________________________________________________ -StKFVertexMaker::StKFVertexMaker(const char *name) : StMaker(name), - fNzBins(2500), fNPasses(2), fSpectrum(0), fzWindow(2), - fVtxM(0), fVerticesPass(0), fTempLog(2), fminBrent(0), func(0), - mBeamLine(kFALSE), fc1(0) -{ - Int_t npeaks = 100; - Double_t zmin = -250; - Double_t zmax = 250; - // StKFVertex::_debug = 1; - for (Int_t pass = 0; pass < fNPasses; pass++) { - fVtxs[pass] = new TH1F(Form("Vtx%1i",pass),Form("z-dca distribution for pass = %1i",pass),fNzBins,zmin,zmax); - fVtxs[pass]->SetDirectory(0); - if (pass) fVtxs[pass]->SetLineColor(5); - fVtxs[pass]->SetDefaultSumw2(); - fVtxs[pass]->SetStats(0); - fVtxKs[pass] = new TH1K(Form("VtxK%1i",pass),Form("z-dca distribution for pass = %1i",pass),fNzBins,zmin,zmax); - fVtxKs[pass]->SetDirectory(0); - fVtxKs[pass]->SetStats(0); - fVtxKs[pass]->SetLineColor(2); - } - fVtxM = new TH1F("VtxM","MuDst reconstructed multiplicities versus Z",fNzBins,zmin,zmax); - fVtxM->SetDirectory(0); - fSpectrum = new TSpectrum(2*npeaks); - func = new ROOT::Math::Functor1D(&StKFVertexMaker::AnnelingFcn); - fminBrent = new ROOT::Math::GSLMinimizer1D(); - fVerticesPass = new StKFVerticesCollection *[fNPasses+1]; - memset (fVerticesPass, 0, (fNPasses+1)*sizeof(StKFVerticesCollection *)); - fParticles = new TObjArray(); - fParticles->SetOwner(kTRUE); - mVertexOrderMethod = orderByRanking; // change ordering by ranking -} -//_____________________________________________________________________________ -Int_t StKFVertexMaker::Init(){ - mBeamLine = IAttr("beamLine"); - return StMaker::Init(); -} -//_____________________________________________________________________________ -Int_t StKFVertexMaker::InitRun(Int_t runumber){ - return StMaker::InitRun(runumber); -} -//________________________________________________________________________________ -Int_t StKFVertexMaker::Make() { - StEvent* pEvent = dynamic_cast (GetInputDS("StEvent")); - if (! pEvent) { - LOG_WARN << "StKFVertexMaker::fit: no StEvent " << endm; - return kStOK; // if no event, we're done - } - Double_t bField = 0; - if (pEvent->runInfo()) bField = pEvent->runInfo()->magneticField(); - KFParticle::SetField(bField); - if (mBeamLine) { - St_vertexSeedC* vSeed = St_vertexSeedC::instance(); - Double_t x0 = vSeed->x0() ; Double_t err_x0 = vSeed->err_x0(); - Double_t y0 = vSeed->y0() ; Double_t err_y0 = vSeed->err_y0(); - Double_t dxdz = vSeed->dxdz(); Double_t err_dxdz = vSeed->err_dxdz(); - Double_t dydz = vSeed->dydz(); Double_t err_dydz = vSeed->err_dydz(); - Double_t weight = vSeed->weight(); - if (err_x0 < 0.010) err_x0 = 0.010; - if (err_y0 < 0.010) err_y0 = 0.010; - static Bool_t firstTime = kTRUE; - if (firstTime) { - firstTime = kFALSE; - LOG_INFO << "BeamLine Constraint: weight = " << weight << endm; - LOG_INFO << "x(z) = (" << x0 << " +- " << err_x0 << ") + (" << dxdz << " +- " << err_dxdz << ") * z" << endm; - LOG_INFO << "y(z) = (" << y0 << " +- " << err_y0 << ") + (" << dydz << " +- " << err_dydz << ") * z" << endm; - } - static Double_t pZ = 1000; - static MTrack track; - Double_t xyzP[6] = { x0, y0, 0., - pZ*dxdz, pZ*dydz, pZ}; - Double_t CovXyzP[21] = { - err_x0*err_x0, - 0 ,err_y0*err_y0, - 0 ,0 , 0, - 0 ,0 , 0, (err_dxdz*pZ)*(err_dxdz*pZ), - 0 ,0 , 0, 0, (err_dydz*pZ)*(err_dydz*pZ) - }; - track.SetParameters(xyzP); - track.SetCovarianceMatrix(CovXyzP); - track.SetNDF(1); - track.SetID(0); - track.SetCharge(1); - KFParticle *beam = new KFParticle(track, 321); - fParticles->AddAt(beam, 0); - } - StSPtrVecTrackNode& trackNode = pEvent->trackNodes(); - UInt_t nTracks = trackNode.size(); - StTrackNode *node=0; - Int_t NGoodGlobals = 0; - map TrackNodeMap; - for (UInt_t i=0; i < nTracks; i++) { - node = trackNode[i]; - if (!node) continue; - StGlobalTrack *gTrack = static_cast(node->track(global)); - if (! gTrack) continue; - const StDcaGeometry* dca = gTrack->dcaGeometry(); - if (! dca) continue; - if (gTrack->flag() < 0) continue; // Bad fit - if (gTrack->flag() > 700) continue; // FTPC - if (gTrack->flag()%100 == 11) continue; // Short track pointing to EEMC - if ((gTrack->isWestTpcOnly() || gTrack->isEastTpcOnly()) && gTrack->isPostXTrack()) continue; // wrong TPC side track - Int_t kg = gTrack->key(); - TrackNodeMap[kg] = node; - KFParticle *particle = AddTrackAt(dca,kg); - if (Debug() > 1) { - if (Debug() > 2) {LOG_INFO << Form("particle: %4i/%4i ",NGoodGlobals,kg) << *particle << endm;} - LOG_INFO << "Add to map[" << kg << "] node = " << TrackNodeMap[kg] << endm; - } - NGoodGlobals++; - } - if (NGoodGlobals < 2) return 0; - Fit(); - if (! Vertices()) return 0; - // - // In case there are no tracks left we better quit - // - StSPtrVecTrackDetectorInfo& detInfoVec = pEvent->trackDetectorInfo(); - Int_t Nvtx = Vertices()->NoVertices(); - for (Int_t l = 0; l < Nvtx; l++) { - const StKFVertex *V = Vertices()->Vertex(l); - if (! V) continue; - if (Debug() > 2) V->PrintW(); - // Store vertex - StPrimaryVertex *primV = new StPrimaryVertex; - StThreeVectorF XVertex(&V->Vertex().X()); - primV->setPosition(XVertex); - primV->setChiSquared(V->Vertex().Chi2()/V->Vertex().GetNDF()); - primV->setProbChiSquared(TMath::Prob(V->Vertex().GetChi2(),V->Vertex().GetNDF())); - Float_t cov[6]; - TCL::ucopy(&V->Vertex().Covariance(0),cov,6); - primV->setCovariantMatrix(cov); - primV->setVertexFinderId(KFVertexFinder); - primV->setFlag(1); // was not set earlier by this vertex finder ?? Jan - primV->setRanking(333); - primV->setNumTracksUsedInFinder(V->NoTracks()); - Bool_t beam = kFALSE; - Double_t Pars[6]; - TCL::ucopy(&V->Vertex().X(), Pars, 6); - Double_t Cov[21]; - TCL::ucopy(&V->Vertex().Covariance(0), Cov, 21); - StiHit *Vertex = StiToolkit::instance()->getHitFactory()->getInstance(); - Vertex->setGlobal(0, 0, V->Vertex().X(), V->Vertex().Y(), V->Vertex().Z(), 0); - Vertex->setError(cov); - Int_t NoTracks = V->NoTracks(); - TArrayI indexT(NoTracks); Int_t *indexes = indexT.GetArray(); - TArrayI IdT(NoTracks); Int_t *Ids = IdT.GetArray(); - for (Int_t itk = 0; itk < NoTracks; itk++) { - Ids[itk] = 999999; - const StKFTrack* track = V->Track(itk); - if (! track) continue; - const KFParticle &P = track->Particle(); - Int_t kg = P.GetID()%100000; - Ids[itk] = kg; - } - TMath::Sort(NoTracks,Ids,indexes,0); - for (Int_t i = 0; i < NoTracks; i++) { - Int_t itk = indexes[i]; - const StKFTrack* track = V->Track(itk); - if (! track) continue; - const KFParticle &P = track->Particle(); - Int_t kg = P.GetID()%100000; - if (kg == 0) { - assert(!beam); - beam = kTRUE; - continue; - } - if (Debug() > 2) { - const KFParticle *PO = track->OrigParticle(); - const KFParticle *PS[2] = {PO, &P}; - for (Int_t m = 0; m < 2; m++) { - if (! m) cout << "Original"; - else cout << "Fitted "; - static const Char_t *names[6] = {"x","y","z","px","py","pz"}; - for (Int_t j = 0; j < 6; j++) { - cout << Form(" %2s: %8.3f +/- %8.3f",names[j], - PS[m]->GetParameter(j), - PS[m]->GetCovariance(j,j) > 0 ? TMath::Sqrt(PS[m]->GetCovariance(j,j)) : -13); - } - cout << endl; - } - } - node = TrackNodeMap[kg]; - if (! node) { - LOG_INFO << "Missing node in map[" << kg << "] node = " << TrackNodeMap[kg] << endm; - assert(node); - } - StiKalmanTrack* kTrack = (*StiStEventFiller::Node2TrackMap())[node]; - assert(kTrack); - StGlobalTrack *gTrack = static_cast(node->track(global)); - assert(gTrack); -#ifdef ADD_NEW_NODE - // Replace dca node by a primary vertex - StiKalmanTrackNode *tNode = kTrack->getInnerMostNode(); - if (! tNode->isDca()) continue; -#if 1 - // tNode->print("XYZEPIJK"); -#endif - tNode->rotate(-tNode->getAlpha()); - // StiHit localVertex = *Vertex; - // localVertex.rotate(tNode->getAlpha()); - // tNode->setHit(&localVertex); - tNode->setHit(Vertex); - tNode->setDetector(0); - Double_t Phi, dPhi; - P.GetPhi(Phi,dPhi); - Double_t pT, dpT; - P.GetPt(pT,dpT); - StiNodePars &FP = tNode->fitPars(); - FP.x() = P.GetX(); - FP.y() = P.GetY(); // local Y-coordinate of this track (reference plane) - FP.z() = P.GetZ(); // local Z-coordinate of this track (reference plane) - FP.eta() = Phi - tNode->getAlpha(); // (signed curvature)*(local Xc of helix axis - X current point on track) - FP.ptin() = - P.GetQ()/pT; // signed invert pt [sign = sign(-qB)] - FP.tanl() = P.GetPz()/pT; // tangent of the track momentum dip angle - // FP.curv() = FP.hz()/FP.ptin(); // signed curvature [sign = sign(-qB)] - FP.ready(); - // FP.hz() = 0; // Z component magnetic field in units Pt(Gev) = Hz * RCurv(cm) - Double_t pzpT3 = - P.GetPz()/(pT*pT*pT); - Double_t f[6*6] = { - /* x, y, z, pX, pY, pZ */ - /* x */ 1, 0, 0, 0, 0, 0, - /* y */ 0, 1, 0, 0, 0, 0, - /* z */ 0, 0, 1, 0, 0, 0, - /* eta */ 0, 0, 0, P.GetPy()/(pT*pT), -P.GetPx()/(pT*pT), 0, - /* q/pT */ 0, 0, 0, -FP.ptin()*P.GetPx()/(pT*pT), -FP.ptin()*P.GetPy()/(pT*pT), 0, - /* tanL */ 0, 0, 0, pzpT3*P.GetPx(), pzpT3*P.GetPy(), 1./pT}; - TRMatrix F(6,6,f); if (Debug()) {LOG_INFO << "F\t" << F << endm;} - TRSymMatrix CovP(6,&((KFParticle *)&P)->Covariance(0)); if (Debug()) {LOG_INFO << "CovP\t" << CovP << endm;} - TRSymMatrix Covi(F,TRArray::kAxSxAT,CovP); if (Debug()) {LOG_INFO << "Covi\t" << Covi << endm;} - StiNodeErrs &FE = tNode->fitErrs(); - TCL::ucopy(Covi.GetArray(), FE.A, 21); - tNode->setReady(); -#if 0 - // tNode->print("XYZEPIJK"); - StiKalmanTrackNode *test = kTrack->getInnerMostHitNode(); - assert(test == tNode); - // Int_t status = kTrack->refit(); // refit with primary vertex - Int_t status = kTrack->fit(kInsideOut); - if (status) continue; // failed to refit -#endif - kTrack->setPrimary(l+1); -#else /* ! ADD_NEW_NODE */ - StiKalmanTrackNode *extended = (StiKalmanTrackNode*) kTrack->extendToVertex(Vertex); - if (extended) { - kTrack->add(extended,kOutsideIn); - if (extended && !extended->isValid()) extended=0; - if (extended && extended->getChi2()>1000) extended=0; - } - kTrack->reduce(); - if (! extended) continue; - //? kTrack->add(extended,kOutsideIn); - kTrack->setPrimary(l+1); - extended->setUntouched(); - Int_t ifail = kTrack->refit(); - ifail |= (kTrack->getInnerMostHitNode(3)!=extended); - kTrack->reduce(); - // something is wrong. It is not a primary - if (ifail) { - kTrack->removeLastNode(); - kTrack->setPrimary(0); - continue; - } -#endif /* ADD_NEW_NODE */ - //________________________________________________________________________________ - StTrackDetectorInfo* detInfo = new StTrackDetectorInfo; - StiStEventFiller::instance()->fillDetectorInfo(detInfo,kTrack,kFALSE); //3d argument used to increase/not increase the refCount. MCBS oct 04. - // StiStEventFiller::instance()->fillPulls(kTrack,1); - StPrimaryTrack* pTrack = new StPrimaryTrack; - node->addTrack(pTrack); // StTrackNode::addTrack() calls track->setNode(this); - pTrack->setKey( gTrack->key()); - pTrack->setFlagExtension( gTrack->flagExtension()); - StiStEventFiller::instance()->fillTrack(pTrack,kTrack, detInfo); - // set up relationships between objects - detInfoVec.push_back(detInfo); - primV->addDaughter(pTrack); - //________________________________________________________________________________ - } - if (beam ) primV->setBeamConstrained(); - //..... add vertex to the list - if (primV->numberOfDaughters() < 1) { - delete primV; - } else { - primV->setTrackNumbers(); - calculateRank(primV); - pEvent->addPrimaryVertex(primV,orderByRanking); - } - } - return kStOK; -} -//________________________________________________________________________________ -void StKFVertexMaker::calculateRank(StPrimaryVertex *primV) { - // Calculation of veretx ranks to select 'best' (i.e. triggered) vertex - // Simpilfied version (w/o weighting) - Float_t rank = primV->probChiSquared(); - static Float_t Wveto = 1; - static Float_t Wmatch = 4; - if (primV->isBeamConstrained()) rank += Wmatch; - rank -= Wveto*primV->numPostXTracks(); - rank += Wmatch*primV->numTracksWithPromptHit(); - rank += Wmatch*primV->numTracksCrossingCentralMembrane(); - rank += Wmatch*primV->numMatchesWithCTB() - - Wveto*primV->numNotMatchesWithCTB(); - rank += Wmatch*primV->numMatchesWithBTOF() - - Wveto*primV->numNotMatchesWithBTOF(); - rank += Wmatch*(primV->numMatchesWithBEMC() + primV->numMatchesWithEEMC()); - // It is unclear why the next line was uncommented but apparently it is not - // used. So, either this line or the semicolumn at the end of the preceeding - // line should be removed - //- Wveto*(primV->numNotMatchesWithBEMC() + primV->numNotMatchesWithEEMC()); - if (primV->numTracksTpcWestOnly() > 0 && primV->numTracksTpcEastOnly() > 0) - rank += Wmatch*TMath::Min(primV->numTracksTpcWestOnly(),primV->numTracksTpcEastOnly()); - primV->setRanking(rank); - if (Debug()) primV->Print(); -} -//________________________________________________________________________________ -KFParticle *StKFVertexMaker::AddTrackAt(const StDcaGeometry *dca, Int_t kg) { - fParticles->AddAtAndExpand (0,kg); - if (! dca) return 0; - Double_t xyzp[6], CovXyzp[21]; - dca->GetXYZ(xyzp,CovXyzp); - static MTrack track; - track.SetParameters(xyzp); - track.SetCovarianceMatrix(CovXyzp); - track.SetNDF(1); - // track.SetChi2(GlobalTracks_mChiSqXY[k]); - track.SetID(kg); - Int_t q = 1; - Int_t pdg = 211; - if (dca->charge() < 0) { - q = -1; - pdg = -211; - } - track.SetCharge(q); - KFParticle *particle = new KFParticle(track, pdg); - particle->SetID(kg); - fParticles->AddAt(particle,kg); - return particle; -} -//________________________________________________________________________________ -void StKFVertexMaker::Fit() { - if (Debug() != 2) StKFVertex::SetDebug(Debug()); - fcVertices = 0; - for (Int_t i = 0; i < fNPasses+1; i++) { - SafeDelete(fVerticesPass[i]); - } - Int_t NGoodGlobals = Particles().GetLast(); - - Double_t TempLog = fTempLog; // default Temperature Log - for (Int_t pass = 0; pass < fNPasses; pass++) { - Int_t nAccepted = 0; - Double_t dZ = fVtxs[pass]->GetBinWidth(1); - for (Int_t k = 0; k < NGoodGlobals; k++) { - KFParticle *particle = (KFParticle *) Particles()[k]; - if (! particle) continue; - Double_t pT; - Double_t dpT; - particle->GetPt(pT,dpT); - Double_t offset = 0.5*particle->GetPz()/pT; - Double_t SigmaZ = TMath::Sqrt(particle->Covariance(2,2) + offset*offset); - SigmaZ += dZ; - Double_t Z = particle->GetZ(); - fVtxKs[pass]->Fill(Z); - Int_t bin1 = fVtxs[pass]->FindBin(Z - 5*SigmaZ); - if (bin1 < 1) bin1 = 1; - Int_t bin2 = fVtxs[pass]->FindBin(Z + 5*SigmaZ); - if (bin2 > fNzBins) bin2 = fNzBins; - Double_t z = fVtxs[pass]->GetBinCenter(bin1); - for (Int_t bin = bin1; bin <= bin2; bin++, z += dZ) { - fVtxs[pass]->Fill(z,(TMath::Erfc((z - Z - fzWindow)/SigmaZ) - TMath::Erfc((z - Z + fzWindow)/SigmaZ))/2.); - } - nAccepted++; - } - Double_t F = fVtxKs[pass]->GetEntries(); - if (F < 1) continue; - fVtxKs[pass]->SetNormFactor(F/dZ); - fVtx = fVtxs[0]; // << switch between types Vtx = fVtxKs[0]; - TString opt("new"); - if (! Canvas()) opt = "goff"; - Int_t nfound = fSpectrum->Search(fVtx,3,opt,TMath::Min(0.1,5./NGoodGlobals)); - if (! nfound) continue; - if (Canvas()) { - Canvas()->cd(); - fVtxs[0]->Draw(); fVtxKs[0]->Draw("same"); - fVtxM->Draw("same"); - if (pass) fVtx->Draw("same"); - Canvas()->Update(); - } - if (StKFVertex::Debug() > 1) { - LOG_INFO << "Found " << nfound - << " candidate peaks to fit with " << NGoodGlobals - << " good globals from with " << nAccepted << " accepted" << endm; - } - Double_t *zOfPeaks = new Double_t[nfound]; - Int_t npeaks = 0; -#if ROOT_VERSION_CODE > 336641 /* ROOT_VERSION(5,35,1) */ - Double_t *xpeaks = fSpectrum->GetPositionX(); -#else - Float_t *xpeaks = fSpectrum->GetPositionX(); -#endif - for (Int_t p = 0; p < nfound; p++) { -#if ROOT_VERSION_CODE > 336641 /* ROOT_VERSION(5,35,1) */ - Double_t xp = xpeaks[p]; -#else - Float_t xp = xpeaks[p]; -#endif - Int_t bin = fVtx->GetXaxis()->FindBin(xp); - Double_t yp = fVtx->GetBinContent(bin); - Double_t ep = fVtx->GetBinError(bin); - if (yp-1.25*ep < 0) continue; - zOfPeaks[npeaks] = xp; - npeaks++; - } - if (StKFVertex::Debug() > 1) { - LOG_INFO << "Found " << npeaks << " useful peaks to fit" << endm; - } - if (! npeaks) {delete [] zOfPeaks; break; } - if (fVerticesPass[pass]) {delete fVerticesPass[pass]; fVerticesPass[pass] = 0;} - fVerticesPass[pass] = new StKFVerticesCollection(npeaks, zOfPeaks); - delete [] zOfPeaks; - fcVertices = fVerticesPass[pass]; - fcVertices->DoTrack2VertexAssociation(Particles()); - if (! fcVertices->NoVertices()) continue; - if (AnnelingFcn(TMath::Exp(-TempLog)) <= 0) continue; - if (! fcVertices->NoVertices()) continue; - fcVertices->UniqueTracks2VertexAssociation(); // Make track associated with only vertex - // fcVertices->PrintV(NoMuMcVertex,NoMuMcTrack,StMuMcVertex_time, - // StMuMcVertex_xyzV_mX1,StMuMcVertex_xyzV_mX2,StMuMcVertex_xyzV_mX3, - // StMuMcVertex_NoDaughters,StMuMcVertex_IdParTrk,StMuMcTrack_gePid); - } - if (! fVerticesPass[0]) return; - if (fNPasses > 1 && Canvas()) { - Canvas()->cd(); - fVtxs[1]->Draw("same"); - Canvas()->Update(); - } - Int_t N1 = fVerticesPass[0]->NoVertices(); - if (! N1) return; - if (fVerticesPass[1]) { - *fVerticesPass[0] += *fVerticesPass[1]; - } - fcVertices = fVerticesPass[0]; - fcVertices->MergeDuplicatedVertices(); - if (! fcVertices->NoVertices()) return; - // Double_t Temperature = TMath::Exp(TempLog); - TempLog = 5; - Double_t Temperature = TMath::Exp(TempLog); -#if 1 - // secondary vertices - Int_t pass = fNPasses; - if (fVerticesPass[pass]) {delete fVerticesPass[pass]; fVerticesPass[pass] = 0;} - fVerticesPass[pass] = new StKFVerticesCollection(); - fcVertices = fVerticesPass[pass]; - StAnneling::SetTemperature(Temperature); - for (Int_t k = 1; k < NGoodGlobals; k++) { - KFParticle *particleK = (KFParticle *) Particles()[k]; - if (! particleK) continue; - if (particleK->GetID() > 100000) continue; - StKFVertex *vtx = 0; - for (Int_t l = k+1; l < NGoodGlobals; l++) { - KFParticle *particleL = (KFParticle *) Particles()[l]; - if (! particleL) continue; - if (particleL->GetID() > 100000) continue; - Double_t dist = particleK->GetDistanceFromParticle(*particleL); - if (dist > 5.0) continue; - if (! vtx) { - vtx = new StKFVertex(fcVertices->NoVertices() + 1); - vtx->AddTrack(new StKFTrack(k,particleK)); - } - vtx->AddTrack(new StKFTrack(l,particleL)); - } - if (! vtx) continue; - vtx->Fit(); - Int_t N = vtx->NoTracks(); - if (! N) {delete vtx; vtx = 0; continue;} - Double_t X = vtx->Vertex().X(); - Double_t Y = vtx->Vertex().Y(); - Double_t R = TMath::Sqrt(X*X + Y*Y); - if (R > 200 ) {delete vtx; vtx = 0; continue;} - Double_t prob = TMath::Prob(vtx->Vertex().GetChi2(),vtx->Vertex().GetNDF()); - if (N > 2 || prob > 1.e-3) {// Allow V2 to share tracks - for (Int_t i = 0; i < N; i++) { - KFParticle *particle = vtx->Track(i)->OrigParticle();; - Int_t ID = particle->GetID()%100000 + 100000*vtx->ID();; - particle->SetID(ID); - } - } - fcVertices->AddVertex(vtx); - } - if (StKFVertex::Debug() > 1) { - LOG_INFO << "Candidate for secondary vertices: " << fcVertices->NoVertices() << endm; - } - if ( fcVertices->NoVertices() ) { - // fcVertices->PrintV(NoMuMcVertex,NoMuMcTrack,StMuMcVertex_time, - // StMuMcVertex_xyzV_mX1,StMuMcVertex_xyzV_mX2,StMuMcVertex_xyzV_mX3, - // StMuMcVertex_NoDaughters,StMuMcVertex_IdParTrk,StMuMcTrack_gePid); - *fVerticesPass[0] += *fVerticesPass[fNPasses]; - } - // end of loop for secondary vertices -#endif - fcVertices = fVerticesPass[0]; - fcVertices->Compress(); - if (! fcVertices->NoVertices()) return; - fcVertices->MergeDuplicatedVertices(); - fminBrent->SetFunction(*func,TMath::Exp(-0.5*(TempLog)),TMath::Exp(-TempLog),1); - if (! fminBrent->Minimize(10,0.1,0.1)) { - LOG_WARN << "Temperature fit has failed" << endm; - Temperature = 1; - } else { - Temperature = 1./fminBrent->XMinimum(); - } - StAnneling::SetTemperature(Temperature); - fcVertices->UniqueTracks2VertexAssociation(); // Make track associated with only vertex - fcVertices->Fit(29,Canvas(),fVtx); - if (Canvas()) Canvas()->Update(); -} -//________________________________________________________________________________ -Double_t StKFVertexMaker::AnnelingFcn(Double_t TInv) { - if (! fcVertices) return 0; - Double_t Temperature = 1./TInv; - StAnneling::SetTemperature(Temperature); - Double_t Chi2 = fcVertices->Fit(); - if (StKFVertex::Debug()) - LOG_INFO << "StKFVertexMaker::AnnelingFcn\tTemperature = " << Temperature << " Chi2 = " << Chi2 << endm; - return Chi2; -} -//________________________________________________________________________________ -// $Log: StKFVertexMaker.cxx,v $ -// Revision 2.8 2018/04/10 11:32:09 smirnovd -// Minor corrections across multiple files -// -// - Remove ClassImp macro -// - Change white space -// - Correct windows newlines to unix -// - Remove unused debugging -// - Correct StTpcRTSHitMaker header guard -// - Remove unused preprocessor directives in StiCA -// - Minor changes in status and debug print out -// - Remove using std namespace from StiKalmanTrackFinder -// - Remove includes for unused headers -// -// Revision 2.7 2016/06/08 23:32:46 smirnovd -// Integration of StiCA -// -// This is a squashed commit with all changes combined. To see individual -// modifications check out the ds-StiCA_2016 branch in star-sti repository. -// Alternatively, one can explore the StiCA_2016 branch in the STAR's CVS -// repository. -// -// Revision 2.6 2013/04/10 22:14:20 fisyak -// Roll back to version 04/04/2013 -// -// Revision 2.4 2013/01/28 21:51:17 fisyak -// Correct ranking -// -// Revision 2.3 2013/01/17 15:57:25 fisyak -// Add handles for debugging -// -// Revision 2.2 2012/09/16 21:38:42 fisyak -// use of Tpc West Only and East Only tracks, clean up -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.5 2012/04/13 14:42:58 fisyak -// Freeze -// -// Revision 1.4 2012/03/29 23:35:47 fisyak -// Fix problem with multiple beam tracks -// -// Revision 1.3 2012/03/26 23:42:35 fisyak -// Add beam constrain -// -// Revision 1.2 2012/02/20 22:38:34 fisyak -// Freeze before go for ranking -// -// Revision 1.1 2012/02/18 23:20:52 fisyak -// Rename StKFVertexFitter => StKFVertexMaker -// -// Revision 1.3 2012/02/07 19:38:26 fisyak -// Repackage -// diff --git a/StRoot/StiMaker/StKFVertexMaker.h b/StRoot/StiMaker/StKFVertexMaker.h deleted file mode 100644 index 2b4a82396e5..00000000000 --- a/StRoot/StiMaker/StKFVertexMaker.h +++ /dev/null @@ -1,94 +0,0 @@ -// $Id: StKFVertexMaker.h,v 2.5 2018/01/03 21:23:36 smirnovd Exp $ - -#ifndef STAR_StKFVertexMaker -#define STAR_StKFVertexMaker - -/*! - * - * \class StKFVertexMaker - * \author fisyak - * \date 2012/04/18 - * \brief virtual base class for Maker - * - */ - -#ifndef StMaker_H -#include "StMaker.h" -#endif -#include "TObjArray.h" -#include "TSpectrum.h" -#include "Math/Functor.h" -#include "Math/GSLMinimizer1D.h" -#include "StEnumerations.h" -#include "TCanvas.h" -#include "TH1K.h" -class StPrimaryVertex; -class StEvent; -class StDcaGeometry; -class KFParticle; -class StKFVerticesCollection; - -class StKFVertexMaker : public StMaker { - public: - StKFVertexMaker(const char *name="KFVertex"); - virtual ~StKFVertexMaker(); - virtual Int_t Init(); - virtual Int_t Make(); - virtual Int_t InitRun (Int_t runumber); - // virtual Int_t FinishRun(Int_t runumber){return 0;}; // Overload empty StMaker::FinishRun - void Clear(Option_t *option=""); - void Fit(); - TH1F *VtxM() {return fVtxM;} - void SetZwindow(Double_t z = 2) {fzWindow = z;} - void SetDefaultTempLog(Double_t tLog = 2) {fTempLog = tLog;} - static Double_t AnnelingFcn(Double_t TInv=1); - TH1 *Vtx() {return fVtx;} - StKFVerticesCollection* Vertices() {return fcVertices;} - TObjArray &Particles() {return *fParticles;} - KFParticle *AddTrackAt(const StDcaGeometry *dca,Int_t kg); - void calculateRank(StPrimaryVertex *primV); - void SetCanvas(TCanvas *c1) {fc1 = c1;} - TCanvas *Canvas() {return fc1;} - TH1F *GetVtxs(Int_t pass = 0) {return fVtxs[pass];} - TH1K *GetVtxKs(Int_t pass = 0) {return fVtxKs[pass];} - TH1F *GetVtxM() {return fVtxM;} - private: - TObjArray *fParticles; // KF particles - Int_t fNzBins; - Int_t fNPasses; - TSpectrum *fSpectrum; - Double_t fzWindow; - TH1F *fVtxM; - StKFVerticesCollection **fVerticesPass; - static StKFVerticesCollection *fcVertices; // current vertex collection - Double_t fTempLog; - ROOT::Math::GSLMinimizer1D *fminBrent; - ROOT::Math::Functor1D *func; - TH1F *fVtxs[2]; - TH1 *fVtx; - TH1K *fVtxKs[2]; - Bool_t mBeamLine; - StPrimaryVertexOrder mVertexOrderMethod; // will default to 0 i.e. orderByNumberOfDaughters - TCanvas *fc1; - /// Displayed on session exit, leave it as-is please ... - virtual const char *GetCVS() const { - static const char cvs[]="Tag $Name: $ $Id: StKFVertexMaker.h,v 2.5 2018/01/03 21:23:36 smirnovd Exp $ built " __DATE__ " " __TIME__ ; - return cvs; - } - - ClassDef(StKFVertexMaker,0) //StAF chain virtual base class for Makers -}; -#endif -// $Log: StKFVertexMaker.h,v $ -// Revision 2.5 2018/01/03 21:23:36 smirnovd -// StKFVertexMaker: Added missing include -// -// Revision 2.4 2014/08/06 11:43:59 jeromel -// Suffix on literals need to be space (later gcc compiler makes it an error) - first wave of fixes -// -// Revision 2.3 2013/04/10 22:14:20 fisyak -// Roll back to version 04/04/2013 -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// diff --git a/StRoot/StiMaker/StKFVerticesCollection.cxx b/StRoot/StiMaker/StKFVerticesCollection.cxx deleted file mode 100644 index 8f151a7ca76..00000000000 --- a/StRoot/StiMaker/StKFVerticesCollection.cxx +++ /dev/null @@ -1,401 +0,0 @@ -// $Id: StKFVerticesCollection.cxx,v 2.5 2018/04/10 11:32:10 smirnovd Exp $ -#include "StKFVerticesCollection.h" -#include "TArrayI.h" -#include "TArrayD.h" -#include "TRSymMatrix.h" -#include "TRVector.h" -#include "TPolyMarker.h" -#include "TList.h" -using namespace std; -Double_t StKFVerticesCollection::fgVxPenaltyFactor = 1000; -//________________________________________________________________________________ -StKFVerticesCollection::StKFVerticesCollection(Int_t NoPeaks, Double_t *zOfPeaks, Double_t sigmaXY, Double_t sigmaZ) : - fVertices(NoPeaks,0) { - fVertices.SetOwner(kTRUE); - for (Int_t peak = 0; peak < NoPeaks; peak++) { - AddVertex(0.,0., zOfPeaks[peak], sigmaXY, sigmaZ); - } -} -//________________________________________________________________________________ -void StKFVerticesCollection::AddVertex(Double_t x, Double_t y, Double_t z, Double_t sigmaXY, Double_t sigmaZ) { - StKFVertex *vtx = new StKFVertex(fVertices.GetEntriesFast() + 1); - vtx->Vertex().SetBeamConstraint(x, y, z, sigmaXY, sigmaXY, sigmaZ); - fVertices.AddLast(vtx); -} -//________________________________________________________________________________ -void StKFVerticesCollection::operator +=(StKFVerticesCollection &col) { - Int_t N2 = col.NoVertices(); - for (Int_t i = N2-1; i >= 0; i--) { - fVertices.AddLast(col.Remove(i)); - } - col.Compress(); -} -//________________________________________________________________________________ -void StKFVerticesCollection::SetMc(Int_t NoMuMcVertex, Int_t NoMuMcTrack, const Float_t *time, - const Float_t *x,const Float_t *y,const Float_t *z, - const Int_t *NoDaughters,const Int_t *IdParTrk,const Int_t *gePid) { - Int_t Nvtx = NoVertices(); - for (Int_t l = 0; l < Nvtx; l++) { - StKFVertex *V = Vertex(l); - if (! V) continue; - Int_t kv = V->IdTruth(); - if (kv > 0 && kv <= NoMuMcVertex) { - if (time && x && y && z && NoDaughters && IdParTrk) { - Int_t kvp = IdParTrk[kv-1]; - Int_t ge = 0; - if (kvp > 0 && kvp <= NoMuMcTrack) ge = gePid[kvp-1]; - V->SetMc(time[kv-1],x[kv-1],y[kv-1],z[kv-1],NoDaughters[kv-1],ge); - } - } - } -} -//________________________________________________________________________________ -ostream& operator<<(ostream& os, const StKFVerticesCollection& vc) { - Int_t Nvtx = vc.NoVertices(); - for (Int_t l = 0; l < Nvtx; l++) { - const StKFVertex *V = vc.Vertex(l); - if (! V) continue; - os << Form("Vtx: %3i",l) << *V << endl; - } - return os; -} -//________________________________________________________________________________ -Double_t StKFVerticesCollection::DoTrack2VertexAssociation(const TObjArray &particles) { - Double_t chi2Total = 0; - Int_t NVtx = NoVertices(); - Int_t Ntracks = particles.GetEntriesFast(); - TArrayI Idx(Ntracks); - TArrayD Chi2s(Ntracks); - for (Int_t l = 0; l < NVtx; l++) { - StKFVertex *vtx = Vertex(l); - if (! vtx) continue; - // if (! vtx->Vertex()) continue; - // vtx->PrintW(); - KFParticle *particle = 0; - for (Int_t k = 0; k < Ntracks; k++) { - Chi2s[k] = 1e10; - particle = (KFParticle *) particles.UncheckedAt(k); - if (! particle) continue; - if (particle->GetID() > 100000) continue; - Double_t chi2il = particle->GetDeviationFromVertex(vtx->Vertex()); - chi2il *= 2*chi2il; - Chi2s[k] = chi2il; - } - vtx->Clear(); - TMath::Sort(Ntracks,Chi2s.GetArray(),Idx.GetArray(),0); - Double_t chi2Vx = 0; - for (Int_t j = 0; j < Ntracks; j++) { - Int_t k = Idx[j]; - particle = (KFParticle *) particles.UncheckedAt(k); - if (! particle) continue; - if (Chi2s[k] > StAnneling::Chi2Cut()) break; - StKFTrack *track = new StKFTrack(k,particle,Chi2s[k]); - chi2Vx += track->Chi2()/2 + TMath::Log(track->Weight() + StAnneling::Weight()); - vtx->AddTrack(track); - } - if (vtx->NoTracks() < 2) { - delete vtx; Vertex(l) = 0; - continue; - } - if (StKFVertex::Debug()) vtx->PrintW("DoTrack2VertexAssociation "); - chi2Total += chi2Vx; - // vtx->PrintW(); - } - fVertices.Compress(); - if (NoVertices()) UpdateWeights(); - return chi2Total; -} -//________________________________________________________________________________ -Double_t StKFVerticesCollection::UpdateStVertexTrackAssociation() { - Double_t chi2Total = 0; - Int_t NVtx = NoVertices(); - for (Int_t l = 0; l < NVtx; l++) { - StKFVertex *vtx = Vertex(l); - if (! vtx) continue; - chi2Total += vtx->UpdateVertex2TrackChi2(); - } - return chi2Total; -} -//________________________________________________________________________________ -void StKFVerticesCollection::CleanDuplicatedVertices() { - Int_t NVtx = NoVertices(); - // Check that vertices are the same - for (Int_t l = 1; l < NVtx; l++) { - StKFVertex *vtxl = Vertex(l); - if (! vtxl) continue; - Int_t NL = vtxl->NoTracks(); - TRVector vL(3,vtxl->Vertex().Parameters()); - TRSymMatrix CL(3,vtxl->Vertex().CovarianceMatrix()); - for (Int_t m = 0; m < l; m++) { - StKFVertex *vtxm = Vertex(m); - if (! vtxm) continue; - // compliete overlap by an other vertex - Int_t NM = vtxm->NoTracks(); - Int_t Nmatched = 0; - for (Int_t i = 0; i < NL; i++) - for (Int_t j = 0; j < NM; j++) - if (vtxl->Track(i)->OrigParticle() == vtxm->Track(j)->OrigParticle()) Nmatched++; - if (Nmatched == TMath::Min(NL,NM)) { - TRVector vM(3,vtxm->Vertex().Parameters()); - TRSymMatrix CM(3,vtxm->Vertex().CovarianceMatrix()); - vM -= vL; - CM += CL; - TRSymMatrix G(CM,TRArray::kInverted); - Double_t chi2 = G.Product(vM,TRArray::kATxSxA); - Double_t prob = TMath::Prob(chi2,3); - if (prob > 0.10) { - if ((NL > NM) || ((NL == NM) && (vtxl->Vertex().GetChi2() < vtxm->Vertex().GetChi2()))) { - if (StKFVertex::Debug()) { - vtxm->Print(Form("Cleaned Vertex prob %7.2f M %3i keep L %3i L(%3i/%7.2f) M (%3i/%7.2f)\t", - prob,m,l,NL,vtxl->Vertex().GetChi2(),NM,vtxm->Vertex().GetChi2())); - } - delete vtxm; Vertex(m) = 0; - continue; - } else { - if (StKFVertex::Debug()) { - vtxl->Print(Form("Cleaned Vertex prob %7.2f L %3i keep M %3i M(%3i/%7.2f) L (%3i/%7.2f)", - prob,l,m,NM,vtxm->Vertex().GetChi2(),NL,vtxl->Vertex().GetChi2())); - } - delete vtxl; Vertex(l) = 0; - break; - } - } - } - } - } - fVertices.Compress(); -} -//________________________________________________________________________________ -void StKFVerticesCollection::MergeDuplicatedVertices() { - // Check that vertices are the same - for (Int_t l = 1; l < NoVertices(); l++) { - StKFVertex *vtxl = Vertex(l); - if (! vtxl) continue; - if (! vtxl->NoTracks()) {delete vtxl; vtxl = Vertex(l) = 0; continue;} - TRVector vL(3,vtxl->Vertex().Parameters()); - TRSymMatrix CL(3,vtxl->Vertex().CovarianceMatrix()); - for (Int_t m = 0; m < l; m++) { - StKFVertex *vtxm = Vertex(m); - if (! vtxm) continue; - if (! vtxm->NoTracks()) {delete vtxm; vtxm = Vertex(m) = 0; continue;} - TRVector vM(3,vtxm->Vertex().Parameters()); - vM -= vL; - if (vM.Mag() > 5.) continue; - TRSymMatrix CM(3,vtxm->Vertex().CovarianceMatrix()); - CM += CL; - CM[0] += 0.0001; // 100 mkm tolerance - CM[2] += 0.0001; - CM[5] += 0.0001; - TRSymMatrix G(CM,TRArray::kInverted); - Double_t chi2 = G.Product(vM,TRArray::kATxSxA); - Double_t prob = TMath::Prob(chi2,3); - if (prob > 1e-4) { - *vtxm += *vtxl; - // if (vtxl->NoTracks()) vtxl->Clear("keep"); - delete vtxl; vtxl = Vertex(l) = 0; - vtxm->Fit(); - break; - } - } - } - fVertices.Compress(); -} -//________________________________________________________________________________ -void StKFVerticesCollection::UpdateWeights() { - Int_t NVtx = NoVertices(); - for (Int_t l = 0; l < NVtx; l++) { - StKFVertex *vtxl = Vertex(l); - if (! vtxl) continue; - // recalculate weights - if (StKFVertex::Debug()) vtxl->PrintW("Weights to Update "); - for (Int_t i = 0; i < vtxl->NoTracks(); i++) { - Double_t Dominator = TMath::Exp(-StAnneling::Chi2Cut()/(2*StAnneling::Temperature())) + vtxl->Track(i)->Weight(); - for (Int_t m = 0; m < NVtx; m++) { - if (l == m) continue; - StKFVertex *vtxm = Vertex(m); - if (! vtxm) continue; - for (Int_t j = 0; j < vtxm->NoTracks(); j++) { - if (vtxl->Track(i)->OrigParticle() == vtxm->Track(j)->OrigParticle()) { - Dominator += vtxm->Track(j)->Weight(); - break; - } - } - } - vtxl->Track(i)->W() = vtxl->Track(i)->Weight()/Dominator; - vtxl->Track(i)->Particle() = *(vtxl->Track(i)->OrigParticle()); - Double_t *CovXyz = vtxl->Track(i)->Particle().CovarianceMatrix(); - for (Int_t j = 0; j < 36; j++) CovXyz[j] = CovXyz[j]/vtxl->Track(i)->W(); - } - if (StKFVertex::Debug()) vtxl->PrintW("Updated Weights "); - } -} -//________________________________________________________________________________ -void StKFVerticesCollection::UniqueTracks2VertexAssociation(){ - // Make track associated with only vertex (by maximum weight to the vertex) - Int_t NVtx = NoVertices(); - for (Int_t l = 0; l < NVtx; l++) { - StKFVertex *vtxl = Vertex(l); - if (! vtxl) continue; - // recalculate weights - for (Int_t i = vtxl->NoTracks()-1; i >= 0; i--) { - if (! vtxl->Track(i)) continue; - Double_t WMax = vtxl->Track(i)->Weight(); - Int_t iMax = i; - Int_t lMax = l; - Int_t nPart = 1; - KFParticle *particleMax = vtxl->Track(i)->OrigParticle(); - for (Int_t m = 0; m < NVtx; m++) { - if (l == m) continue; - StKFVertex *vtxm = Vertex(m); - if (! vtxm) continue; - for (Int_t j = 0; j < vtxm->NoTracks(); j++) { - if (particleMax == vtxm->Track(j)->OrigParticle()) { - nPart++; - if (vtxm->Track(j)->Weight() > WMax) { - WMax = vtxm->Track(j)->Weight(); - iMax = j; - lMax = m; - particleMax = vtxm->Track(j)->OrigParticle(); - break; - } - } - } - } - if (WMax < 0.01) { // Particle weight is too small => remove the particle from all vertices - for (Int_t m = 0; m < NVtx; m++) { - StKFVertex *vtxm = Vertex(m); - if (! vtxm) continue; - delete vtxm->Remove(particleMax); - vtxm->Compress(); - } - if (! vtxl->NoTracks()) break; - continue; - } - if (nPart > 1) { - for (Int_t m = 0; m < NVtx; m++) { - StKFVertex *vtxm = Vertex(m); - if (! vtxm) continue; - if (m != lMax) { - if (particleMax->GetID()%100000) { // beam track is not in the game - delete vtxm->Remove(particleMax); - vtxm->Compress(); - if (vtxm->NoTracks() == 0) {delete vtxm; Vertex(m) = 0;} - } - } else vtxm->Track(iMax)->W() = vtxm->Track(iMax)->Weight(); - } - } - } - } - for (Int_t l = 0; l < NVtx; l++) { - StKFVertex *vtxl = Vertex(l); - if (! vtxl) continue; - if (vtxl->NoTracks() == 0) {delete vtxl; Vertex(l) = 0;} - } - fVertices.Compress(); - NVtx = NoVertices(); - // Set particle ID - for (Int_t l = 0; l < NVtx; l++) { - StKFVertex *vtxl = Vertex(l); - if (! vtxl) continue; - Int_t N = vtxl->NoTracks(); - for (Int_t i = 0; i < N; i++) { - KFParticle *particle = vtxl->Track(i)->OrigParticle();; - Int_t ID = particle->GetID()%100000 + 100000*vtxl->ID();; - particle->SetID(ID); - } - } -} -//________________________________________________________________________________ -Double_t StKFVerticesCollection::Fit(Int_t marker, TCanvas *c1, TH1 *Vtx) { - // Primary Vertex fit - Double_t chi2Total = 1e10; - fVertices.Compress(); - Int_t NVtx = NoVertices(); - if (! NVtx) return chi2Total; - for (Int_t l = 0; l < NVtx; l++) { - StKFVertex *vtx = Vertex(l); - if (! vtx) continue; - vtx->Vertex().SetBeamConstraintOff(); - vtx->Fit(); - if (vtx->Vertex().GetNDF() < 1 || vtx->NoTracks() < 2) { - delete vtx; - Vertex(l) = 0; - continue; - } else { - chi2Total += fgVxPenaltyFactor; - } - } - fVertices.Compress(); - CleanDuplicatedVertices(); - fVertices.Compress(); - chi2Total = UpdateStVertexTrackAssociation(); - UpdateWeights(); - // - if (StKFVertex::Debug()) { - cout << "chi2Total = " << chi2Total - << " at Temperature " << StAnneling::Temperature() - << " and Log(Temperature) " << TMath::Log(StAnneling::Temperature()) - << " no. vertices " << NoVertices() - << endl; - } - if (Vtx) { - Double_t ymax = Vtx->GetMaximum(); - for (Int_t i = 0; i < NVtx; i++) { - StKFVertex *vtx = Vertex(i); - if (! vtx) continue; - Double_t X = vtx->Vertex().GetParameter(2); - Double_t Y = vtx->NoTracks(); - if (Y > ymax) ymax = Y; - TPolyMarker * pm = new TPolyMarker(1, &X, &Y); - Vtx->GetListOfFunctions()->Add(pm); - pm->SetMarkerColor(TMath::Log(StAnneling::Temperature())+2); - Int_t m = 22; - if (marker) { - m = marker; - pm->SetMarkerColor(4); - if (StKFVertex::Debug()) vtx->PrintW(); - } - pm->SetMarkerStyle(m); - pm->SetMarkerSize(2); - // chi2NDF->Fill(TMath::Log10(vtx->NoTracks()),vtx->Vertex().GetChi2()/vtx->Vertex().GetNDF()); - } - if (c1) { - Vtx->SetMaximum(ymax); - Vtx->Draw("same"); - c1->Update(); - } - } - return chi2Total; -} -// $Log: StKFVerticesCollection.cxx,v $ -// Revision 2.5 2018/04/10 11:32:10 smirnovd -// Minor corrections across multiple files -// -// - Remove ClassImp macro -// - Change white space -// - Correct windows newlines to unix -// - Remove unused debugging -// - Correct StTpcRTSHitMaker header guard -// - Remove unused preprocessor directives in StiCA -// - Minor changes in status and debug print out -// - Remove using std namespace from StiKalmanTrackFinder -// - Remove includes for unused headers -// -// Revision 2.4 2013/04/10 22:14:20 fisyak -// Roll back to version 04/04/2013 -// -// Revision 2.2 2012/06/11 15:33:41 fisyak -// std namespace -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.5 2012/03/29 23:35:47 fisyak -// Fix problem with multiple beam tracks -// -// Revision 1.4 2012/03/26 23:42:35 fisyak -// Add beam constrain -// -// Revision 1.3 2012/02/07 19:38:26 fisyak -// Repackage -// diff --git a/StRoot/StiMaker/StKFVerticesCollection.h b/StRoot/StiMaker/StKFVerticesCollection.h deleted file mode 100644 index 8f9b30cc18b..00000000000 --- a/StRoot/StiMaker/StKFVerticesCollection.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __StKFVerticesCollection_h__ -// $Id: StKFVerticesCollection.h,v 2.2 2012/06/11 15:33:41 fisyak Exp $ -#define __StKFVerticesCollection_h__ -#include "TObject.h" -#include "TObjArray.h" -#include "StKFVertex.h" -#include "TCanvas.h" -#include "TH1.h" -#include "TH1K.h" -class StKFVerticesCollection; -std::ostream& operator<<(std::ostream& os, const StKFVerticesCollection& vc); -class StKFVerticesCollection : public TObject { -public: - StKFVerticesCollection(Int_t NoPeaks = 0, Double_t *zOfPeaks = 0, Double_t sigmaXY = 1.5, Double_t sigmaZ = 2); - void AddVertex(Double_t x, Double_t y, Double_t z, Double_t sigmaXY, Double_t sigmaZ); - void AddVertex(StKFVertex*vtx) {fVertices.AddLast(vtx);} - virtual ~StKFVerticesCollection() {} - Int_t NoVertices() const {return fVertices.GetEntriesFast();} - StKFVertex* Remove(Int_t k=0) {return (StKFVertex *) fVertices.RemoveAt(k);} - Double_t DoTrack2VertexAssociation(const TObjArray &particles); // associate tracks to vertex - Double_t UpdateStVertexTrackAssociation(); // reassociate tracks to vertex - void CleanDuplicatedVertices(); - void MergeDuplicatedVertices(); - void UpdateWeights(); - void UniqueTracks2VertexAssociation(); - void Compress() {fVertices.Compress();} - Double_t Fit(Int_t marker = 0, TCanvas *c1 = 0, TH1* Vtx = 0); - StKFVertex *&Vertex(Int_t l) {return (StKFVertex *&) fVertices[l];} - const StKFVertex *Vertex(Int_t l) const {return (const StKFVertex *) fVertices[l];} - void operator +=(StKFVerticesCollection &col); - void SetMc(Int_t NoMuMcVertex = 0, Int_t NoMuMcTrack = 0, const Float_t *time = 0, - const Float_t *x = 0,const Float_t *y = 0,const Float_t *z = 0, - const Int_t *NoDaughters = 0,const Int_t *IdParTrk = 0,const Int_t *gePid = 0); - virtual void Print(const Option_t* opt = "") const {if (opt) {}; std::cout << *this;} - static void SetVxPenaltyFactor(Double_t chi2 = 1000) {fgVxPenaltyFactor = chi2;} - private: - TObjArray fVertices; - static Double_t fgVxPenaltyFactor; - public: - ClassDef(StKFVerticesCollection,0) -}; -// $Log: StKFVerticesCollection.h,v $ -// Revision 2.2 2012/06/11 15:33:41 fisyak -// std namespace -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.3 2012/03/26 23:42:36 fisyak -// Add beam constrain -// -// Revision 1.2 2012/02/07 19:38:26 fisyak -// Repackage -// -#endif diff --git a/StRoot/StiMaker/StMuDstVtxT.cxx b/StRoot/StiMaker/StMuDstVtxT.cxx deleted file mode 100644 index 34c5e829daf..00000000000 --- a/StRoot/StiMaker/StMuDstVtxT.cxx +++ /dev/null @@ -1,44 +0,0 @@ -// $Id: StMuDstVtxT.cxx,v 2.7 2018/04/10 11:32:10 smirnovd Exp $ -#include "StMuDstVtxT.h" -#include "StKFVertex.h" - -std::ostream& operator<<(std::ostream& os, const StMuDstVtxT& v) { - os << Form("Q:%3i M:%3i/%3i/%3i W/E %3i/%3i tracks rank %5i xyz = %9.3f +/- %5.3f, %9.3f +/- %5.3f, %9.3f +/- %5.3f", - v.Q(),v.MultU(),v.Mult(),v.MultC(),v.MultW(),v.MultE(),v.Rank(), - v.Xyz().x(),v.SigmaXyz().x(), - v.Xyz().y(),v.SigmaXyz().x(), - v.Xyz().z(),v.SigmaXyz().x()) - << Form(" Mc/QA/t:%4i/%3i/%6.0f xyz: %8.3f%8.3f%8.3f m:%4i %6s",v.IdTruth(), v.QaTruth(), - v.TimeMc(), v.XyzMc().X(), v.XyzMc().Y(), v.XyzMc().Z(), - v.NoDaughtersMc(),StKFVertex::GeNames[v.gePidMc()]); - return os; -} -// $Log: StMuDstVtxT.cxx,v $ -// Revision 2.7 2018/04/10 11:32:10 smirnovd -// Minor corrections across multiple files -// -// - Remove ClassImp macro -// - Change white space -// - Correct windows newlines to unix -// - Remove unused debugging -// - Correct StTpcRTSHitMaker header guard -// - Remove unused preprocessor directives in StiCA -// - Minor changes in status and debug print out -// - Remove using std namespace from StiKalmanTrackFinder -// - Remove includes for unused headers -// -// Revision 2.6 2015/12/20 01:35:12 fisyak -// Move back commits done by mistate -// -// Revision 2.4 2013/04/10 22:14:20 fisyak -// Roll back to version 04/04/2013 -// -// Revision 2.2 2012/06/11 15:33:41 fisyak -// std namespace -// -// Revision 2.1 2012/05/07 14:56:14 fisyak -// Add StKFVertexMaker -// -// Revision 1.2 2012/02/07 19:38:26 fisyak -// Repackage -// diff --git a/StRoot/StiMaker/StMuDstVtxT.h b/StRoot/StiMaker/StMuDstVtxT.h deleted file mode 100644 index 57745b9c195..00000000000 --- a/StRoot/StiMaker/StMuDstVtxT.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __StMuDstVtxT_h__ -#define __StMuDstVtxT_h__ -#include "Riostream.h" -#include "TObject.h" -#include "TVector3.h" -#include "StKFTrack.h" -class StMuDstVtxT; -std::ostream& operator<<(std::ostream& os, const StMuDstVtxT& v); -class StMuDstVtxT : public TObject { -public: - StMuDstVtxT(Double_t x = 0, Double_t y = 0, Double_t z = 0, - Double_t sigma_x = 0, Double_t sigma_y = 0, Double_t sigma_z = 0, - Int_t multU = 0, Int_t mult = 0, Int_t multC = 0, Int_t multW = 0, - Int_t multE = 0, Int_t q = 0, Int_t r = 0, - Short_t idTruth = 0, Short_t Qual = 0, Int_t idParentTk = 0) : - fMultU(multU), fMult(mult), fMultC(multC), fMultW(multW), fMultE(multE), fQ(q), fRank(r), - fXyz(x,y,z), fSigmaXyz(sigma_x,sigma_y,sigma_z), - fIdTruth(idTruth), fQuality(Qual), fIdParentTk(idParentTk), fTimeMc(0), fNoDaughtersMc(0), fgePidMc(0) {} - virtual ~StMuDstVtxT() {} - TVector3 &Xyz() {return *&fXyz;} - TVector3 &SigmaXyz() {return *&fSigmaXyz;} - TVector3 Xyz() const {return fXyz;} - TVector3 SigmaXyz() const {return fSigmaXyz;} - TVector3 &XyzMc() {return *&fXyzMc;} - TVector3 XyzMc() const {return fXyzMc;} - Int_t Mult() const {return fMult;} - Int_t MultU() const {return fMultU;} - Int_t MultC() const {return fMultC;} - Int_t MultW() const {return fMultW;} - Int_t MultE() const {return fMultE;} - Int_t Q() const {return fQ;} - Int_t Rank() const {return fRank;} - Short_t IdTruth() const {return fIdTruth;} - Short_t QaTruth() const {return fQuality;} - Int_t IdParentTk() const {return fIdParentTk;} - Float_t TimeMc() const {return fTimeMc;} - Int_t NoDaughtersMc() const {return fNoDaughtersMc;} - Int_t gePidMc() const {return fgePidMc;} - void Print(Option_t *option="") const {if (option) {}; std::cout << *this << std::endl;} - void SetMc(Int_t NoMuMcVertex = 0, Int_t NoMuMcTrack = 0, const Float_t *time = 0, - const Float_t *x = 0,const Float_t *y = 0,const Float_t *z = 0, - const Int_t *NoDaughters = 0,const Int_t *IdParTrk = 0,const Int_t *gePid = 0) { - Int_t kv = IdTruth(); - if (kv > 0 && kv <= NoMuMcVertex) { - if (time && x && y && z && NoDaughters && IdParTrk) { - fTimeMc = 1e9*time[kv-1]; - fXyzMc = TVector3(x[kv-1],y[kv-1],z[kv-1]); - fNoDaughtersMc = NoDaughters[kv-1]; - Int_t kvp = IdParTrk[kv-1]; - if (kvp > 0 && kvp <= NoMuMcTrack) { - fgePidMc = StKFTrack::CorrectGePid(gePid[kvp-1]); - } - } - } - } -protected: - Int_t fMultU, fMult, fMultC, fMultW, fMultE; - Int_t fQ; // charge - Int_t fRank; // MC=>0 - TVector3 fXyz; - TVector3 fSigmaXyz; - Short_t fIdTruth; - Short_t fQuality; - Int_t fIdParentTk; - Float_t fTimeMc; - TVector3 fXyzMc; - Int_t fNoDaughtersMc; - Int_t fgePidMc; - ClassDef(StMuDstVtxT,1) -}; -#endif diff --git a/StRoot/StiMaker/StVertexP.h b/StRoot/StiMaker/StVertexP.h deleted file mode 100644 index c4ca505dddd..00000000000 --- a/StRoot/StiMaker/StVertexP.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __StVertexP_h__ -#define __StVertexP_h__ - -#include "TObject.h" -#include "StVertexT.h" -class StVertexP : public TObject { // Vertex pair -public: - StVertexP() : fI(0), fJ(0), fChi2(0) {} - StVertexP(Int_t i, Int_t j, StVertexT &VI, StVertexT &VJ, Double_t chi2) : fI(i), fJ(j), fChi2(chi2), fVI(VI), fVJ(VJ) {} - virtual ~StVertexP() {} -private: - Int_t fI; - Int_t fJ; - Double_t fChi2; - StVertexT fVI; - StVertexT fVJ; - ClassDef(StVertexP,1) -}; // for pair vertices -#endif diff --git a/StRoot/StiMaker/StVertexT.h b/StRoot/StiMaker/StVertexT.h deleted file mode 100644 index b1867426a67..00000000000 --- a/StRoot/StiMaker/StVertexT.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __StVertexT_h__ -#define __StVertexT_h__ -#include "StMuDstVtxT.h" -class StVertexT : public StMuDstVtxT { -public: - StVertexT(Double_t x = 0, Double_t y = 0, Double_t z = 0, - Double_t sigma_x = 0, Double_t sigma_y = 0, Double_t sigma_z = 0, - Int_t multU = 0, Int_t mult = 0, Int_t multW = 0, Int_t multE = 0, Int_t q = 0, Int_t r = 0, - Int_t ndf = 0, Double_t prob = 0, Double_t chi2 = 0, - Short_t idTruth = 0, Short_t Qual = 0, Int_t idParentTk = 0) : - StMuDstVtxT(x,y,z,sigma_x,sigma_y,sigma_z,multU,mult,multW,multE,q,r,idTruth,Qual,idParentTk), - fNDF(ndf), fProb(prob), fChi2(chi2), - fiMuDst(0), fChi2MuDst(0), fiKF(0), fChi2KF(0) {} - StVertexT(StMuDstVtxT &dst, Int_t ndf = 0, Double_t prob = 0, Double_t chi2 = 0) : - StMuDstVtxT(dst), fNDF(ndf), fProb(prob), fChi2(chi2), - fiMuDst(0), fChi2MuDst(0), fiKF(0), fChi2KF(0) {} - StVertexT(StKFVertex &v) : StMuDstVtxT(v.Vertex().GetX(), - v.Vertex().GetY(), - v.Vertex().GetZ(), - TMath::Sqrt(v.Vertex().GetCovariance(0,0)), - TMath::Sqrt(v.Vertex().GetCovariance(1,1)), - TMath::Sqrt(v.Vertex().GetCovariance(2,2)), - -1, v.NoTracks(), -1, v.MultW(), v.MultE(), v.Q(), 0, - v.IdTruth(), v.QaTruth(), v.IdParentTk()), - fNDF(v.Vertex().GetNDF()),fProb(TMath::Prob(v.Vertex().GetChi2(),v.Vertex().GetNDF())), - fChi2(v.Vertex().GetChi2()), - fiMuDst(0), fChi2MuDst(0), fiKF(0), fChi2KF(0) { - fTimeMc = v.TimeMc(); - fXyzMc = v.XyzMc(); - fNoDaughtersMc = v.NoDaughtersMc(); - fgePidMc = v.gePidMc(); - } - virtual ~StVertexT() {} - void SetMuDst(Int_t i, Double_t p) {fiMuDst = i; fChi2MuDst = p;} - void SetKF(Int_t i, Double_t p) {fiKF = i; fChi2KF = p;} -private: - Int_t fNDF; - Double_t fProb; - Double_t fChi2; - Int_t fiMuDst; // KFVertex best match with MuDst - Double_t fChi2MuDst; // chi2 for the above match - Int_t fiKF; // KFVertex best match with KFVertex in (x,y) - Double_t fChi2KF; // chi2 for the above match - ClassDef(StVertexT,1) -}; -#endif diff --git a/StRoot/StiMaker/StiMakerLinkDef.h b/StRoot/StiMaker/StiMakerLinkDef.h deleted file mode 100644 index 9b4990e7308..00000000000 --- a/StRoot/StiMaker/StiMakerLinkDef.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __CINT__ -#pragma link off all globals; -#pragma link off all classes; -#pragma link off all functions; -#endif diff --git a/mgr/ConsDefs.pm b/mgr/ConsDefs.pm index b48db30bef4..4797a42ecdb 100644 --- a/mgr/ConsDefs.pm +++ b/mgr/ConsDefs.pm @@ -801,6 +801,7 @@ # restore ($CFLAGS,$CXXFLAGS) = @ARGS; # <--- same order than above } + $CXXFLAGS .= " -fdiagnostics-color=always";# -Wno-pedantic -Wno-shadow -Wno-unused-parameter -Wno-extra -Wno-shadow"; diff --git a/mgr/Conscript-standard b/mgr/Conscript-standard index ab1f1a4a7b1..9e3c54d7cb9 100644 --- a/mgr/Conscript-standard +++ b/mgr/Conscript-standard @@ -916,7 +916,22 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) { if ( defined($ENV{Vc_LIB_DIR}) ) { die("Vc_LIB_DIR is not supported anymore. Please use Vc_DIR."); } $LIBS = "-lVc"; if ($extraCXXFLAGS =~ /USE_TBB/) {$LIBS .= " -lTBB";} - } + } elsif ( $pkg =~ m/KFParticle/ || $pkg =~ m/StMuMcAnalysisMaker/ || $pkg =~ m/^StKFParticleAnalysisMaker$/) { +# $CPPFLAGS .= " -DDO_TPCCATRACKER_EFF_PERFORMANCE"; +# $main::PATH_SEPARATOR . "#" . $Dir . $main::PATH_SEPARATOR . "#" . $Dir . "/../TPCCATracker" . +# $main::PATH_SEPARATOR . "#" . $Dir . "/../TPCCATrackerPerformance" . +# $main::PATH_SEPARATOR . "#" . $Dir . "/../KFParticlePerformance"; + $CPPPATH .= $main::PATH_SEPARATOR . "#" . $Dir . "/../KFParticle" . + $main::PATH_SEPARATOR . "#" . $Dir . "/../KFParticle/KFPSimd"; + my $extraCXXFLAGS = ""; +# " -DNVALGRIND -DSTAR_STANDALONE";# -W -Wall -Wswitch -Wformat -Wchar-subscripts"; + if ($STAR_SYS eq 'sl64_gcc447' or $STAR_SYS eq 'sl64_x8664_gcc447') {$extraCXXFLAGS .= " --param large-function-growth=500";} + $extraCXXFLAGS .= " -DNDEBUG"; + $CXXFLAGS .= $extraCXXFLAGS; +# $CXXFLAGS =~ s/mavx/msse4\.2/; + $CXXFLAGS .= " -msse4.2"; +# print "======================================== TH => $CPPPATH \tCPPFLAGS => $CPPFLAGS\n"; + } if ( $pkg =~ m/^Sti$/) { if ($DEBUG =~ /-O/ and $STAR_SYS =~ /gcc432/) { # hack for Sti with gcc432 $envNoDeb = $env->clone('DEBUG' => '-g'); @@ -975,7 +990,7 @@ if ( $pkg !~ /^sim$/ && $pkg !~ /^gen$/ ) { # print "pkg = $pkg FPPFLAGS = $FPPFLAGS\n"; my $libpath = $LIBPATH; if (! $LIBS) {$libpath = "";} -# print "CPPPATH => $CPPPATH \tCPPFLAGS => $CPPFLAGS\n"; +# print "======================================== TH => $CPPPATH \tCPPFLAGS => $CPPFLAGS\n"; #print "DEBUG Passing $ROOTCINT_CPPFLAGS\n"; $env2 = $env1->clone('Package' => $pkg, 'EXTRA_CPPFLAGS' => $EXTRA_CPPFLAGS,