/************************************************************************** * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ // This class derives from AliEMCALClustrerizer but also keeps the API of AliEMCALClusterizerv1 // Algorithm: // 1. peek the most energetic cell // 2. assign it as a center of the cluster and add cells surrounding it: 3x3, 5x5... // 3. remove the cells contributing to the cluster // 4. start from 1 for the remaining clusters // 5. cluster splitting (not implemented yet) - use the shape analysis to resolve the energy sharing // - for high energy clusters check the surrounding of the 3x3 clusters for extra energy // (merge 3x3 clusters and resolve the internal energy sharing - case for 2 clusters merged) // Use Case: // root [0] AliEMCALClusterizerFixedWindow * cl = new AliEMCALClusterizerFixedWindow("galice.root") // Warning in : object already instantiated // //reads gAlice from header file "..." // root [1] cl->ExecuteTask() // //finds RecPoints in all events stored in galice.root // root [2] cl->SetDigitsBranch("digits2") // //sets another title for Digitis (input) branch // root [3] cl->SetRecPointsBranch("recp2") // //sets another title four output branches // root [4] cl->SetTowerLocalMaxCut(0.03) // //set clusterization parameters // root [5] cl->ExecuteTask("deb all time") // //once more finds RecPoints options are // // deb - print number of found rec points // // deb all - print number of found RecPoints and some their characteristics // // time - print benchmarking results #include "AliEMCALClusterizerFixedWindow.h" // --- ROOT system --- #include #include #include #include #include #include #include #include // --- Standard library --- #include //#include //#include // --- AliRoot header files --- #include "AliLog.h" #include "AliEMCALRecPoint.h" #include "AliEMCALDigit.h" #include "AliEMCALGeometry.h" #include "AliCaloCalibPedestal.h" #include "AliEMCALCalibData.h" #include "AliESDCaloCluster.h" #include "AliEMCALUnfolding.h" #include "AliEMCALFixedWindowClusterInfo.h" ClassImp(AliEMCALClusterizerFixedWindow) //____________________________________________________________________________ AliEMCALClusterizerFixedWindow::AliEMCALClusterizerFixedWindow() : AliEMCALClusterizer(), nPhi(4), nEta(4), shiftPhi(2), shiftEta(2), fTRUshift(0), clusters_array(0), fClustersInfo(new AliEMCALFixedWindowClusterInfo("clustersInfo")) { // ctor with the indication of the file where header Tree and digits Tree are stored } //____________________________________________________________________________ AliEMCALClusterizerFixedWindow::AliEMCALClusterizerFixedWindow(AliEMCALGeometry* geometry) : AliEMCALClusterizer(geometry), nPhi(4), nEta(4), shiftPhi(2), shiftEta(2), fTRUshift(0), clusters_array(0), fClustersInfo(new AliEMCALFixedWindowClusterInfo("clustersInfo")) { // ctor with the indication of the file where header Tree and digits Tree are stored // use this contructor to avoid usage of Init() which uses runloader // change needed by HLT - MP } //____________________________________________________________________________ AliEMCALClusterizerFixedWindow::AliEMCALClusterizerFixedWindow(AliEMCALGeometry* geometry, AliEMCALCalibData * calib, AliCaloCalibPedestal * caloped) : AliEMCALClusterizer(geometry, calib, caloped), nPhi(4), nEta(4), shiftPhi(2), shiftEta(2), fTRUshift(0), clusters_array(0), fClustersInfo(new AliEMCALFixedWindowClusterInfo("clustersInfo")) { // ctor, geometry and calibration are initialized elsewhere. } //____________________________________________________________________________ AliEMCALClusterizerFixedWindow::~AliEMCALClusterizerFixedWindow() { // dtor delete fClustersInfo; } //____________________________________________________________________________ void AliEMCALClusterizerFixedWindow::Digits2Clusters(Option_t * option) { // Steering method to perform clusterization for the current event // in AliEMCALLoader if (strstr(option,"tim")) gBenchmark->Start("EMCALClusterizer"); if (strstr(option,"print")) Print(""); //Get calibration parameters from file or digitizer default values. GetCalibrationParameters(); //Get dead channel map from file or digitizer default values. GetCaloCalibPedestal(); MakeClusters(); //only the real clusters if (fToUnfold) { fClusterUnfolding->SetInput(fNumberOfECAClusters,fRecPoints,fDigitsArr); fClusterUnfolding->MakeUnfolding(); } //Evaluate position, dispersion and other RecPoint properties for EC section for (Int_t index = 0; index < fRecPoints->GetEntries(); index++) { AliEMCALRecPoint * rp = dynamic_cast(fRecPoints->At(index)); if (rp) { rp->EvalAll(fECAW0,fDigitsArr,fJustClusters); AliDebug(5, Form("MAX INDEX %d ", rp->GetMaximalEnergyIndex())); //For each rec.point set the distance to the nearest bad crystal if (fCaloPed) rp->EvalDistanceToBadChannels(fCaloPed); } } //fRecPoints->Sort(); for (Int_t index = 0; index < fRecPoints->GetEntries(); index++) { AliEMCALRecPoint *rp = dynamic_cast(fRecPoints->At(index)); if (rp) { rp->SetIndexInList(index); } else AliFatal("RecPoint NULL!!"); } if (fTreeR) fTreeR->Fill(); if (strstr(option,"deb") || strstr(option,"all")) PrintRecPoints(option); AliDebug(1,Form("EMCAL Clusterizer found %d Rec Points",fRecPoints->GetEntriesFast())); if (strstr(option,"tim")) { gBenchmark->Stop("EMCALClusterizer"); printf("Exec took %f seconds for Clusterizing", gBenchmark->GetCpuTime("EMCALClusterizer")); } } //____________________________________________________________________________ void AliEMCALClusterizerFixedWindow::MakeClusters() { // Make clusters if (fGeom == 0) AliFatal("Did not get geometry from EMCALLoader"); fNumberOfECAClusters = 0; fRecPoints->Delete(); if (fClustersInfo->GetLastElementId() > 0) fClustersInfo->Clear(); Int_t nSupMod=0, nModule=0, nIphi=0, nIeta=0, iphi=0, ieta=0; // Defining geometry and clusterization parameter Int_t nEtaDigitsSupMod = fGeom->GetNEta() * fGeom->GetNETAdiv(); // always 48?; Int_t nPhiDigitsSupMod = fGeom->GetNPhi() * fGeom->GetNPHIdiv(); // always 24?; Int_t nTRUPhi = 1; Int_t nTRUEta = 1; Int_t nEtaDigits = nEtaDigitsSupMod * fGeom->GetNumberOfSuperModules() / fGeom->GetNPhiSuperModule(); Int_t nPhiDigits = nPhiDigitsSupMod * fGeom->GetNPhiSuperModule(); if (fTRUshift) { nTRUPhi = fGeom->GetNPhiSuperModule() * 3; nTRUEta = fGeom->GetNumberOfSuperModules() / fGeom->GetNPhiSuperModule(); nEtaDigits /= nTRUEta; nPhiDigits /= nTRUPhi; } // Check if clusterizer parameter are compatible with calorimeter geometry if (nEtaDigits < nEta) { AliFatal(Form("Error: nEta = %d is greater than nEtaDigits = %d.",nEta,nEtaDigits)); return; } if (nPhiDigits < nPhi) { AliFatal(Form("Error: nPhi = %d is greater than nPhiDigits = %d.",nPhi,nPhiDigits)); return; } if (nEtaDigits % shiftEta != 0) { AliFatal(Form("Error: shiftEta = %d is such that clusters cannot slide the whole calorimeter (nEtaDigits = %d).",shiftEta,nEtaDigits)); return; } if (nPhiDigits % shiftPhi != 0) { AliFatal(Form("Error: shiftPhi = %d is such that clusters cannot slide the whole calorimeter (nPhiDigits = %d).",shiftPhi,nPhiDigits)); return; } if (nEta % shiftEta != 0) { AliFatal(Form("Error: shiftEta = %d is not divisor of nEta = %d.",shiftEta,nEta)); return; } if (nPhi % shiftPhi != 0) { AliFatal(Form("Error: shiftPhi = %d is not divisor of nPhi = %d).",shiftPhi,nPhi)); return; } Int_t maxiShiftPhi = nPhi / shiftPhi; Int_t maxiShiftEta = nEta / shiftEta; Int_t nDigitsCluster = nPhi * nEta; Int_t nClusEtaNoShift = nEtaDigits / nEta; Int_t nClusPhiNoShift = nPhiDigits / nPhi; Int_t nClusters = nClusEtaNoShift * nClusPhiNoShift * nTRUEta * nTRUPhi; Int_t nTotalClus = nClusters * maxiShiftEta * maxiShiftPhi; if (!clusters_array) { clusters_array = new AliEMCALDigit**[nTotalClus]; for (Int_t i = 0; i < nTotalClus; i++) { clusters_array[i] = NULL; } } AliEMCALDigit *digit = 0; for (Int_t ishiftPhi = 0; ishiftPhi < maxiShiftPhi; ishiftPhi++) { Int_t nClusPhi = (nPhiDigits - shiftPhi * ishiftPhi) / nPhi; for (Int_t ishiftEta = 0; ishiftEta < maxiShiftEta; ishiftEta++) { Int_t nClusEta = (nEtaDigits - shiftEta * ishiftEta) / nEta; Int_t iTotalClus = nClusters * (ishiftPhi * maxiShiftEta + ishiftEta); TIter nextdigit(fDigitsArr); nextdigit.Reset(); while (digit = static_cast(nextdigit())) { fGeom->GetCellIndex (digit->GetId(), nSupMod, nModule, nIphi, nIeta); fGeom->GetCellPhiEtaIndexInSModule (nSupMod, nModule, nIphi, nIeta, iphi, ieta); Int_t iphi_eff = iphi - shiftPhi * ishiftPhi + nPhiDigitsSupMod * (nSupMod / 2); // N supermodules along phi Int_t iTRUphi = iphi_eff / nPhiDigits; iphi_eff -= iTRUphi * nPhiDigits; Int_t iClusPhi = iphi_eff / nPhi; if (iphi_eff < 0 || iClusPhi >= nClusPhi) continue; Int_t ieta_eff = ieta - shiftEta * ishiftEta + nEtaDigitsSupMod * (nSupMod % 2); // 2 supermodules along eta Int_t iTRUeta = ieta_eff / nEtaDigits; ieta_eff -= iTRUeta * nEtaDigits; Int_t iClusEta = ieta_eff / nEta; if (ieta_eff < 0 || iClusEta >= nClusEta) continue; iphi_eff += iTRUphi * nPhiDigits; iClusPhi = iphi_eff / nPhi; ieta_eff += iTRUeta * nEtaDigits; iClusEta = ieta_eff / nEta; Int_t iCluster = iClusPhi + iClusEta * nClusPhiNoShift * nTRUPhi; Int_t iDigit = iphi_eff % nPhi + (ieta_eff % nEta) * nPhi; if (iCluster >= nClusters) { AliFatal(Form("ERROR: iCluster out of range! iCluster = %d, nClusters = %d", iCluster, nClusters)); return; } iCluster += iTotalClus; if (clusters_array[iCluster] == NULL) { fNumberOfECAClusters++; clusters_array[iCluster] = new AliEMCALDigit*[nDigitsCluster]; for (Int_t i = 0; i < nDigitsCluster; i++) { clusters_array[iCluster][i] = NULL; } fClustersInfo->Add(iCluster, -1, iClusEta, iClusPhi); } if (clusters_array[iCluster][iDigit] != NULL) { AliFatal("ERROR: digit already added!"); return; } clusters_array[iCluster][iDigit] = digit; } // loop on digit } // loop on eta shift } // loop on phi shift Int_t iRecPoint = 0; for (Int_t iCluster = 0; iCluster < nTotalClus; iCluster++) { if (clusters_array[iCluster] == NULL) continue; (*fRecPoints)[iRecPoint] = new AliEMCALRecPoint(""); AliEMCALRecPoint *recPoint = dynamic_cast (fRecPoints->At(iRecPoint)); if (recPoint) { if (fClustersInfo->ContainsIndex(iRecPoint)) AliFatal(Form("ERROR: index present already, %d", iRecPoint)); fClustersInfo->SetIndexFromId(iCluster, iRecPoint); iRecPoint++; recPoint->SetClusterType(AliVCluster::kEMCALClusterv1); // note: this way the sharing info is lost! for (Int_t iDigit = 0; iDigit < nDigitsCluster; iDigit++) { if (clusters_array[iCluster][iDigit] == NULL) continue; digit = clusters_array[iCluster][iDigit]; Float_t dEnergyCalibrated = digit->GetAmplitude(); Float_t time = digit->GetTime(); Calibrate(dEnergyCalibrated,time,digit->GetId()); digit->SetCalibAmp(dEnergyCalibrated); recPoint->AddDigit(*digit, dEnergyCalibrated, kFALSE); //Time or TimeR? clusters_array[iCluster][iDigit] = NULL; } } delete[] clusters_array[iCluster]; clusters_array[iCluster] = NULL; } AliDebug(1,Form("MakeClusters: Number of digits %d -> (e %f)\n", fDigitsArr->GetEntries(),fMinECut)); AliDebug(1,Form("total no of clusters %d from %d digits",fNumberOfECAClusters,fDigitsArr->GetEntriesFast())); }