// Copyright 2019-2020 CERN and copyright holders of ALICE O2. // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. // All rights not expressly granted are reserved. // // This software is distributed under the terms of the GNU General Public // License v3 (GPL Version 3), copied verbatim in the file "COPYING". // // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include #include #include #include #include #include #include #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" #include "Framework/HistogramRegistry.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/PIDResponse.h" #include "EMCALBase/Geometry.h" #include "EMCALCalib/BadChannelMap.h" #include "PWGJE/DataModel/EMCALClusters.h" #include "DataFormatsEMCAL/Cell.h" #include "DataFormatsEMCAL/Constants.h" #include "DataFormatsEMCAL/AnalysisCluster.h" #include "CommonDataFormat/InteractionRecord.h" // \struct ClusterTutorial /// \brief Skeleton task for EMCal cluster tutorial /// \author Florian Jonas , Oak Ridge National Laoratory; Joshua König , Goethe-University Frankfurt; Marvin Hemmer , Goethe-University Frankfurt /// \since 09.04.2023 using namespace o2::framework; using namespace o2::framework::expressions; using collisionEvSelIt = o2::soa::Join::iterator; // we need to filter the emcal clusters, since we only want clusters from one specific clusterizer algorithm using selectedClusters = o2::soa::Filtered; struct ClusterTutorial { HistogramRegistry mHistManager{"ClusterMonitorHistograms"}; Preslice perCluster = o2::aod::emcalclustercell::emcalclusterId; // configurable parameters Configurable mDoEventSel{"doEventSel", 0, "demand kINT7"}; Configurable mVertexCut{"vertexCut", -1, "apply z-vertex cut with abs value in cm"}; Configurable mClusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default"}; // define cluster filter. It selects only those clusters which are of the type. Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == mClusterDefinition); /// \brief Create output histograms and initialize geometry void init(InitContext const&) { mHistManager.add("clusterE", "Energy of cluster;'it{E} (GeV)", HistType::kTH1F, {{200, 0., 40.}}); mHistManager.add("clusterAmpFractionLeadingCell", "Fraction of energy in leading cell", HistType::kTH1F, {{100, 0, 1}}); } /// \brief Process EMCAL clusters that are matched to a collisions void processCalo(collisionEvSelIt const& theCollision, selectedClusters const& clusters, o2::aod::EMCALClusterCells const& emccluscells, o2::aod::Calos const& allcalos) { // do event selection if mDoEventSel is specified // currently the event selection is hard coded to kINT7 // but other selections are possible that are defined in TriggerAliases.h bool isSelected = true; if (mDoEventSel) { if (theCollision.bc().runNumber() < 300000) { if (!theCollision.alias()[kINT7]) { isSelected = false; } } else { if (!theCollision.alias()[kTVXinEMC]) { isSelected = false; } } } if (!isSelected) { return; } if (mVertexCut > 0 && TMath::Abs(theCollision.posZ()) > mVertexCut) { return; } // loop over all clusters from accepted collision for (const auto& cluster : clusters) { mHistManager.fill(HIST("clusterE"), cluster.energy()); // example of loop over all cells of current cluster // cell.calo() allows to access the cell properties as defined in AnalysisDataModel // In this exammple, we loop over all cells and find the cell of maximum energy and plot the fraction // it carries of the whole cluster auto cellsofcluster = emccluscells.sliceBy(perCluster, cluster.globalIndex()); double maxamp = 0; double ampfraction = 0; for (const auto& cell : cellsofcluster) { // example how to get any information of the cell associated with cluster if (cell.calo().amplitude() > maxamp) { maxamp = cell.calo().amplitude(); } } ampfraction = maxamp / cluster.energy(); mHistManager.fill(HIST("clusterAmpFractionLeadingCell"), ampfraction); } } PROCESS_SWITCH(ClusterTutorial, processCalo, "process only reconstructed info", true); void processDummy(collisionEvSelIt const& collision) { // do nothing } PROCESS_SWITCH(ClusterTutorial, processDummy, "Dummy function", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc)}; }