// @(#)$Id: hpidcandidate.cc,v 1.12 2006-11-24 16:00:29 christ Exp $ //*-- Author : Marcin Jaskula 27/07/2002 // Modified : Marcin Jaskula 06/09/2002 // Modified : Marcin Jaskula 16/09/2002 // - now this is an abstract class // Modified : Marcin Jaskula 31/10/2002 // - buildPidCandidateCategory moved from global to static function // Modified : Marcin Jaskula 01/12/2002 // - new method getPidCandidate() // - getCandidate() rewritten // Modified : Marcin Jaskula 18/04/2003 // - functions for calculation of the merged PDF and Bayes added // Redesigned by Tassilo Christ to reduce number of classes to one by managing // size of values array dynamically (HCategory has now the possibility to set // a flag "hasDynamicObjects" which allows to stream objects of a size which // isn't known at compile-time. // //_HADES_CLASS_DESCRIPTION //////////////////////////////////////////////////////////////////////////////// // // HPidCandidate // // // The container consists of all values returend by PidAlgorithms // for a specific HPidTrackCand // The idea of this container was to make it as flexible as possible and do not // fix the number and type of algorithms and reconstructed partices for which // the values are stored. The organization of the data in the container looks // like: // // ...... pAlogrithms ...... // . ------------------------- // . | | // p | | // P | | // a | | // r | | // t | pValues | // i | | // c | | // l | | // e | | // s | | // . | | // . | | // . ------------------------- // // Ids of used algorithms are stored in aAlogrithms vector constisting of // values from EnumPidAlgorithm_t (piddef.h). Ids larger then 100 mean // values for CL for algorihm (id - 100) // Ids of particles are stored in aParticles vector (from Geant). // // // The values returned from the algorithms are stored in 2D array // aValues[PID_ALG][PARTICLE] - where indices corresponds to values in // aAlogrithms and aParticles vectors. // //////////////////////////////////////////////////////////////////////////////// #pragma implementation #include "hpidcandidate.h" #include "hpidtrackcand.h" #include "hpidfl.h" #include "hades.h" #include "hevent.h" #include "hlinearcategory.h" #include #include #include using namespace std; // ----------------------------------------------------------------------------- ClassImp(HPidCandidate) // ----------------------------------------------------------------------------- HPidCandidate::HPidCandidate(void) { //default constructor to satisfy root! } HPidCandidate::HPidCandidate(Short_t numpart, Int_t numalgs, Int_t candIndex, Int_t momAlgIndex) { NUM_PARTICLES=numpart; NUM_ALGORITHMS=numalgs; NUM_VALUES=numpart*numalgs; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Here the "dynamic" part of memory allocation occurs. At compile time the number of algorithms and // particles isn't known - so we need to build the array at runtime. // As we overload the Clear-Function (see below) and set "DynamicObjects" to kTRUE the HLinearCategory // does the cleanup for us in HLinearCategory::Clear(Option_t). When the flag is set kTRUE it calls the // Clear Function of HPidCandidate which frees the memory again. // (See implementation of HLinearCategory::Clear(Otion_t) // ////////////////////////////////////////////////////////////////////////////////////////////////////////// aAlgorithms.Set(NUM_ALGORITHMS); aParticles.Set(NUM_PARTICLES); aValues.Set(NUM_PARTICLES*NUM_ALGORITHMS); iTrackCandIndex = candIndex; nMomAlgIndex = momAlgIndex; Reset(); } // ----------------------------------------------------------------------------- HPidCandidate::~HPidCandidate(void) { // Default destructor. Do not do anything } // ----------------------------------------------------------------------------- //This function frees the memory occupied by objects of type HPidCandidate in //the TClonesArray. void HPidCandidate::Clear(Option_t* opt) { aAlgorithms.Set(0); aParticles.Set(0); aValues.Set(0); } // Clears the arrays setting them to the default values void HPidCandidate::Reset(void) { Int_t i, iMax; if((iMax = getNAlgorithms()) > 0 && aAlgorithms.GetSize()== iMax) { for(i = 0; i < iMax; i++) { aAlgorithms[i] = algNotSet; } } else Error("HPidCandidate::Reset","There was a mismatch in the number of algorithms and the size of the array"); if(((iMax = getNParticles()) > 0) && (aParticles.GetSize() ==iMax)) { for(i = 0; i < iMax; i++) aParticles[i] = -99; } else Error("HPidCandidate::Reset","There was a mismatch in the number of particles and the size of the array"); iMax = getNParticles() * getNAlgorithms(); if(iMax == aValues.GetSize()) { for(i = 0; i < iMax; i++) { aValues[i] = nUNKNOWN; } } else Error("HPidCandidate::Reset","There was a mismatch in the number of values and the size of the array"); } // ----------------------------------------------------------------------------- Int_t HPidCandidate::print(void) const { UInt_t iAlg; UInt_t iPart; Bool_t arraysOK=kTRUE; printf(" P \\ A |"); if(aAlgorithms.GetSize() != (Int_t)getNAlgorithms()) { arraysOK=kFALSE; printf("Mismatch in size of algorithms array"); } if(aParticles.GetSize() != (Int_t)getNParticles()) { arraysOK=kFALSE; printf("Mismatch in size of particles array"); } if((aValues.GetSize() != (Int_t)getNValues())) { arraysOK=kFALSE; printf("Mismatch in size of values array"); } if(arraysOK) { for(iAlg = 0; iAlg < getNAlgorithms(); iAlg++) printf(" %6d |", aAlgorithms[iAlg]); printf("\n-------+"); for(iAlg = 0; iAlg < getNAlgorithms(); iAlg++) printf("---------+"); printf("\n"); for(iPart = 0; iPart < getNParticles(); iPart++) { printf("%6d |", aParticles[iPart]); for(iAlg = 0; iAlg < getNAlgorithms(); iAlg++) printf("%8.4f |", aValues[getValuePositionByIndex(iAlg, iPart)]); printf("\n"); } } printf("\n"); return 0; // allow to use in T.Draw(...) } // ----------------------------------------------------------------------------- //Return the HPidTrackCandidate object that was the origin of the HPidCandidate HPidTrackCand* HPidCandidate::getTrackCandidate(HCategory *pCat) const { // Returns HPidTrackCand object corresponding to iTrackCandIndex (if it exists) // Works when pCat is set or gHades->getCurrentEvent() is accessible if(iTrackCandIndex < 0) return NULL; return HPidFL::getTrackCand(iTrackCandIndex, pCat); } // ----------------------------------------------------------------------------- // Set algorithm Id eAlg at uiPos. Arrays bounds are checked void HPidCandidate::setAlgorithmIdByIndex(UInt_t uiPos, Short_t eAlg) { if((aAlgorithms.GetSize()<(Int_t)NUM_ALGORITHMS) || (uiPos >=NUM_ALGORITHMS)) { Error("setAlgorithmIdByIndex", "out of bound: [0, %d)", NUM_ALGORITHMS); return; } aAlgorithms[uiPos] = eAlg; } // ----------------------------------------------------------------------------- // Set whole vector of algoritms. The input array must have getNAlgorithms() members void HPidCandidate::setAlgorithmIds(Short_t aeAlgs[]) { if(sizeof(aeAlgs)/sizeof(Short_t)!=NUM_ALGORITHMS) { ::Error("HPidCandidate::setAlgorithms","Number of algorithms not matching selection!"); return; } if(aAlgorithms.GetSize() != (Int_t)NUM_ALGORITHMS) { Error("setAlgorithms", "Mismatch in size of algorithms array"); return; } aAlgorithms.Set(NUM_ALGORITHMS,aeAlgs); } // ----------------------------------------------------------------------------- // Get algorithm Id from the array of algorithms at position uiPos. // algNotSet is return if uiPos is out of bounds. Int_t HPidCandidate::getAlgorithmIdByIndex(UInt_t uiPos) const { if((aAlgorithms.GetSize()<=(Int_t)uiPos) || (uiPos >= NUM_ALGORITHMS)) { Error("getAlgorithmIdByIndex", "out of bound: [0, %d)", NUM_ALGORITHMS); return algNotSet; } return aAlgorithms[uiPos]; } // ----------------------------------------------------------------------------- Int_t HPidCandidate::getAlgorithmIndexById(Int_t eAlg) const { // Find the position of the eAlg algorithm in the array of algorithms. // Returns -1 if algorithm not set. // Existing of the proper algorithms array is checked Int_t i, iMax; iMax = getNAlgorithms(); for(i = 0; i < iMax; i++) { if(aAlgorithms[i] == eAlg) return i; } return -1; } // ----------------------------------------------------------------------------- void HPidCandidate::setParticleIdByIndex(UInt_t uiPos, Short_t nPart) { // Sets particle id nPart in the array of particle ids at position uiPos. Array bounds are checked. if((aParticles.GetSize() <= (Int_t)uiPos) || (uiPos >= getNParticles())) { Error("setParticleIdByIndex", "out of bound: [0, %d)", getNParticles()); return; } aParticles[uiPos] = nPart; } // ----------------------------------------------------------------------------- // Set whole vector of particle Ids. The input array must have getNParticles() members void HPidCandidate::setParticleIds(Short_t anPart[], Int_t nrOfParticles) { if( nrOfParticles != (Int_t)NUM_PARTICLES ) { ::Error("HPidCandidate::setParticleIds","Number of particles does not match"); return; } if(aParticles.GetSize() != nrOfParticles) { Error("setParticleIds", "Mismatch in size of particles array"); return; } aParticles.Set(NUM_PARTICLES,anPart); } // ----------------------------------------------------------------------------- Short_t HPidCandidate::getParticleIdByIndex(UInt_t uiPos) const { // Gets particle id nPart at position uiPos in the array of particle ids used. // Array bounds are checked and -10 returned in case of out of bounds. if((aParticles.GetSize()<=(Int_t)uiPos) || (uiPos >= getNParticles())) { Error("getParticleIdByIndex", "out of bound: [0, %d)", getNParticles()); return -10; } return aParticles[uiPos]; } // ----------------------------------------------------------------------------- Int_t HPidCandidate::getParticleIndexById(Short_t nPartId) const { // Find the position of the particle with PID nPartId in the array of involved species. // Returns -1 if particle id not set. // Existing of a propper particlesId array is checked. Int_t i, iMax; iMax = getNParticles(); for(i = 0; i < iMax; i++) { if(aParticles[i] == nPartId) return i; } return -1; } // ----------------------------------------------------------------------------- void HPidCandidate::setValueById(Int_t eAlg, Short_t nPartId, Float_t fVal) { // Set value in the array of pdf-values for the specified algorithm and particle Id Int_t iPart, iAlg; if(aValues.GetSize()!=(Int_t)(getNParticles())*(Int_t)(getNAlgorithms())) { Error("setValueById", "Mismatch in size of values array"); return; } if(((iAlg = getAlgorithmIndexById(eAlg)) < 0) || ((iPart = getParticleIndexById(nPartId)) < 0)) { return; } aValues[getValuePositionByIndex(iAlg, iPart)] = fVal; } // ----------------------------------------------------------------------------- void HPidCandidate::setValueByIndex(UInt_t uiAlgIdx, UInt_t uiPartIdx, Float_t fVal) { // Set value fVal for known position in the values array Int_t i; if((i = getValuePositionByIndex(uiAlgIdx, uiPartIdx)) < 0) Error("setValueByIndex", "Out of bounds"); else aValues[i] = fVal; } // ----------------------------------------------------------------------------- Float_t HPidCandidate::getValueById(Int_t eAlg, Short_t nPartId) const { // Returns value computed by algorithm eAlg for the particle nPartId // or 0.0 if algorithm or particle not in the arrays #warning This implementation has to be extended to strict checking Int_t iPart, iAlg; if(((iAlg = getAlgorithmIndexById(eAlg)) < 0) || ((iPart = getParticleIndexById(nPartId)) < 0)) { return 0.0f; } return aValues[getValuePositionByIndex(iAlg, iPart)]; } // ----------------------------------------------------------------------------- Float_t HPidCandidate::getValueByIndex(UInt_t uiAlgIdx, UInt_t uiPartIdx) const { // Returns pdf-value for a specific particle and algorithm index in the values array or 0.0 if out of bound #warning This implementation has to be extended to strict checking Int_t i = getValuePositionByIndex(uiAlgIdx, uiPartIdx); return (i < 0 ? -1.0f : aValues[i]); } // ----------------------------------------------------------------------------- HCategory* HPidCandidate::buildPidCandidateCategory() { // Static function for making the category for the specified class name. HCategory *pCat; static char* sCatName="HPidCandidate"; HEvent *pEvent; if((gHades == NULL) || ((pEvent = gHades->getCurrentEvent()) == NULL)) { ::Error("buildPidCandidateCategory", "Cannot access current event"); return NULL; } if((pCat = pEvent->getCategory(catPidCandidate)) != NULL) { ((HLinearCategory*)pCat)->setDynamicObjects(kTRUE); return pCat; } if((pCat = new HLinearCategory(sCatName, 1000)) == NULL) { ::Error("HPidCandidate::buildPidCandidateCategory", "Cannot create new category"); return NULL; } ((HLinearCategory*)pCat)->setDynamicObjects(kTRUE); //This category stores a variable amount of data. Within one DST the size of the //array is fixed (nAlgs times nParticles) but it is NOT known at compiletime! //Therefor we declare this category to be dynamic in size. This implies that the //Clear() function of the category is called with option "C" which calls the Clear() //function of all HPidCandidates in the TClonesArray pEvent->addCategory(catPidCandidate, pCat, "Pid"); return pCat; } // ----------------------------------------------------------------------------- Int_t HPidCandidate::calcBayesVector(Float_t fOut[],const Int_t aAlgs[], Int_t iAlgs) { // Calculate Bayes values for the all particles and the algorithms // with ids from array aAlgs of size iAlgs. If iAlgs==0 all available algorithms // are used - in this case aAlgs may be NULL. The output values are stored // in fOut array, which size should be suitable to contain all values. // fOut must not be NULL. The function returns the number of filled elements // in fOut array if(fOut == NULL) { Error("calcBayesVector", "fOut == NULL"); return 0; } Int_t iRelInt; if((iRelInt = getAlgorithmIndexById(algRelInt)) < 0) { Error("calcBayesVector", "no algRelInt in the container"); return 0; } //Float_t *fRelInt = getValuesVectorByIndex(iRelInt); Int_t i; Int_t iMax = getNParticles(); if((i = calcMergedPDFVector(fOut, aAlgs, iAlgs)) <= 0) return i; Float_t fSum = 0.0f; // calc products of joined PDFs with relative intensities for(i = 0; i < iMax; i++) { if(fOut[i] < 0.0) continue; if(getValueByIndex(iRelInt,i) < 0.0) { setValueByIndex(iRelInt,i,0.0); Error("HPidCandidate::calcBayesVector()","Negatiev relint value detected and resetted!"); } fOut[i] *= getValueByIndex(iRelInt,i) ; fSum += fOut[i]; } // renormalize if((fSum > 0.0f) && (fSum != 1.0f)) { fSum = 1.0f / fSum; for(i = 0; i < iMax; i++) { if(fOut[i] <= 0.0f) continue; fOut[i] *= fSum; } } return iMax; } // ----------------------------------------------------------------------------- #define FILL_ARRAY() \ if(iAlg0 > 0) aAlg[i++] = iAlg0; \ if(iAlg1 > 0) aAlg[i++] = iAlg1; \ if(iAlg2 > 0) aAlg[i++] = iAlg2; \ if(iAlg3 > 0) aAlg[i++] = iAlg3; \ if(iAlg4 > 0) aAlg[i++] = iAlg4; \ if(iAlg5 > 0) aAlg[i++] = iAlg5; \ if(iAlg6 > 0) aAlg[i++] = iAlg6; \ if(iAlg7 > 0) aAlg[i++] = iAlg7; \ if(iAlg8 > 0) aAlg[i++] = iAlg8; \ if(iAlg9 > 0) aAlg[i++] = iAlg9 // ----------------------------------------------------------------------------- Int_t HPidCandidate::calcBayesVectorFromAlgSelection(Float_t fOut[], Int_t iAlg0, Int_t iAlg1, Int_t iAlg2, Int_t iAlg3, Int_t iAlg4, Int_t iAlg5, Int_t iAlg6, Int_t iAlg7, Int_t iAlg8, Int_t iAlg9) { // Calculate Bayes values for the all particles and the algorithms // given as the arguments. If all iAlg? == 0 all available algorithms // are used. For more info see the descr. of the previous method, which // is called internally. Int_t aAlg[10]; Int_t i = 0; FILL_ARRAY(); return calcBayesVector(fOut, aAlg, i); } // ----------------------------------------------------------------------------- Float_t HPidCandidate::getBayesValue(Short_t nPID, const Int_t aAlgs[], Int_t iAlgs) { // Return the Bayes value for the give particle species nType. // For commends to the eAlgs and iAlgs see calcBayesVect descr. // In case of any error -1 is returned Int_t iIdx; if((iIdx = getParticleIndexById(nPID)) < 0) { Error("getBayesVect", "Particle %d not in the container", nPID); return -1.0f; } Float_t *fArr; if((fArr = new Float_t[getNParticles()]) == NULL) { Error("getBayesVect", "Cannot create temp array"); return -1.0f; } Float_t fVal; if(calcBayesVector(fArr, aAlgs, iAlgs) <= 0) fVal = -1.0f; else fVal = fArr[iIdx]; delete [] fArr; return fVal; } // ----------------------------------------------------------------------------- Float_t HPidCandidate::getBayesValueFromAlgSelection(Short_t nPID, Int_t iAlg0, Int_t iAlg1, Int_t iAlg2, Int_t iAlg3, Int_t iAlg4, Int_t iAlg5, Int_t iAlg6, Int_t iAlg7, Int_t iAlg8, Int_t iAlg9) { // Return the Bayes value for the give particle species nPID and the given // set of algorithms. For more info see descr. of getBayesVect and calcBayesVect // methods. Int_t aAlg[10]; Int_t i = 0; FILL_ARRAY(); return getBayesValue(nPID, aAlg, i); } // ----------------------------------------------------------------------------- Int_t HPidCandidate::calcMergedPDFVector(Float_t fOut[], const Int_t aAlgs[], Int_t iAlgs) const { // Calculate merged propability density for the all particles and the algorithms // with ids from array aAlgs of size iAlgs. If iAlgs==0 all available algorithms // are used - in this case aAlgs may be NULL. The output values are stored // in fOut array, which size should be suitable to contain all values. // fOut must not be NULL. The function returns the number of filled elements // in fOut array if(fOut == NULL) { Error("calcMergedPDFVector", "fOut == NULL"); return 0; } UInt_t iMax = getNParticles(); UInt_t i; Int_t a, c, k; Float_t pdf_factor=0.0; // clear the output for(i = 0; i < iMax; i++) fOut[i] = -1.0f; if(iAlgs <= 0) { c = 0; // loop over all algorithms and choose the PDF vectors for(k = 0; k < (Int_t)getNAlgorithms(); k++) { if(((a = getAlgorithmIdByIndex(k)) <= LAST_COMMON_ALG) || (a >= CL_ALOGRITHM_OFFSET)) { continue; } #warning This takes long and can be done much more efficiently //cout << "Algor ID is: " << a << endl; // calc the products - changed by Tassilo - check this later! /* af = getValuesVectorByIndex(k); for(i = 0; i < iMax; i++) { if(af[i] >= 0.0f) { if(fOut[i] < 0.0f) fOut[i] = af[i]; else fOut[i] *= af[i]; } } */ for(i = 0; i < iMax; i++) { pdf_factor=getValueByIndex(k,i); if(pdf_factor >= 0.0f) // do not consider negative probability densities!! They indicate void statements { if(fOut[i] < 0.0f) fOut[i] = pdf_factor; else fOut[i] *= pdf_factor; } } c++; } if(c <= 0) { Error("calcMergedPDFVector", "No PDF vector found"); goto lab_Error; } } else { for(c = 0; c < iAlgs; c++) { if((k = getAlgorithmIndexById(aAlgs[c])) < 0) { Error("calcMergedPDFVector", "No values for algorithm %d", aAlgs[c]); goto lab_Error; } // calc the products - changed by Tassilo check this! /* af = getValuesVectorByIndex(k); for(i = 0; i < iMax; i++) { if(af[i] >= 0.0f) { if(fOut[i] < 0.0f) fOut[i] = af[i]; else fOut[i] *= af[i]; } } */ for(i = 0; i < iMax; i++) { pdf_factor=getValueByIndex(k,i); if(pdf_factor >= 0.0f) // do not consider negative probability densities!! They indicate void statements { if(fOut[i] < 0.0f) fOut[i] = pdf_factor; else fOut[i] *= pdf_factor; } } } } return iMax; lab_Error: for(i = 0; i < iMax; i++) fOut[i] = -1.0f; return 0; } // ----------------------------------------------------------------------------- Int_t HPidCandidate::calcMergedPDFVectorFromAlgSelection(Float_t fOut[], Int_t iAlg0, Int_t iAlg1, Int_t iAlg2, Int_t iAlg3, Int_t iAlg4, Int_t iAlg5, Int_t iAlg6, Int_t iAlg7, Int_t iAlg8, Int_t iAlg9) const { // Calculate merged propability for the all particles and the algorithms // given as the arguments. If all iAlg? == 0 all available algorithms // are used. For more info see the descr. of the previous method, which // is called internally. Int_t aAlg[10]; Int_t i = 0; FILL_ARRAY(); return calcMergedPDFVector(fOut, aAlg, i); } // ----------------------------------------------------------------------------- Float_t HPidCandidate::getMergedPDFValue(Short_t nPID, const Int_t aAlgs[], Int_t iAlgs) const { // Return the merged propability value for the give particle species nPID. // For commends to the eAlgs and iAlgs see calcMergedVect descr. // In case of any error -1 is returned Int_t iIdx; if((iIdx = getParticleIndexById(nPID)) < 0) { Error("getMergedPDFValue", "Particle %d not in the container", nPID); return -1.0f; } Float_t *fArr; if((fArr = new Float_t[getNParticles()]) == NULL) { Error("getMergedPDFValue", "Cannot create temp array"); return -1.0f; } Float_t fVal; if(calcMergedPDFVector(fArr, aAlgs, iAlgs) <= 0) fVal = -1.0f; else fVal = fArr[iIdx]; delete [] fArr; return fVal; } // ----------------------------------------------------------------------------- Float_t HPidCandidate::getMergedPDFValueFromAlgSelection(Short_t nPID, Int_t iAlg0, Int_t iAlg1, Int_t iAlg2, Int_t iAlg3, Int_t iAlg4, Int_t iAlg5, Int_t iAlg6, Int_t iAlg7, Int_t iAlg8, Int_t iAlg9) const { // Return the merged propability value for the give particle species nPID. // and the set of algorithms. For more info see descr. of getMergedPDFValue // and calcMergedVect methods. Int_t aAlg[10]; Int_t i = 0; FILL_ARRAY(); cout << "Calling fobidden function!" <