|
| 1 | +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. |
| 2 | +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. |
| 3 | +// All rights not expressly granted are reserved. |
| 4 | +// |
| 5 | +// This software is distributed under the terms of the GNU General Public |
| 6 | +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". |
| 7 | +// |
| 8 | +// In applying this license CERN does not waive the privileges and immunities |
| 9 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 10 | +// or submit itself to any jurisdiction. |
| 11 | + |
| 12 | +#include "Common/Core/CollisionTypeHelper.h" |
| 13 | +#include "Common/DataModel/EventSelection.h" |
| 14 | +#include "Common/DataModel/FT0Corrected.h" |
| 15 | + |
| 16 | +#include <CCDB/BasicCCDBManager.h> |
| 17 | +#include <CommonConstants/PhysicsConstants.h> |
| 18 | +#include <DataFormatsFT0/Digit.h> |
| 19 | +#include <DataFormatsParameters/GRPLHCIFData.h> |
| 20 | +#include <Framework/AnalysisDataModel.h> |
| 21 | +#include <Framework/AnalysisHelpers.h> |
| 22 | +#include <Framework/AnalysisTask.h> |
| 23 | +#include <Framework/Configurable.h> |
| 24 | +#include <Framework/HistogramRegistry.h> |
| 25 | +#include <Framework/HistogramSpec.h> |
| 26 | +#include <Framework/InitContext.h> |
| 27 | +#include <Framework/OutputObjHeader.h> |
| 28 | +#include <Framework/runDataProcessing.h> |
| 29 | + |
| 30 | +#include <TRandom3.h> |
| 31 | + |
| 32 | +#include <bitset> |
| 33 | +#include <chrono> |
| 34 | +#include <cstdint> |
| 35 | +#include <string> |
| 36 | + |
| 37 | +using namespace o2; |
| 38 | +using namespace o2::framework; |
| 39 | +using namespace o2::aod; |
| 40 | + |
| 41 | +struct ft0CorrectedTableMcOverride { |
| 42 | + // Configurables |
| 43 | + Configurable<float> resoFT0A{"resoFT0A", 20.f, "FT0A resolution in ps for the MC override"}; |
| 44 | + Configurable<float> resoFT0C{"resoFT0C", 20.f, "FT0C resolution in ps for the MC override"}; |
| 45 | + Configurable<bool> addHistograms{"addHistograms", false, "Add QA histograms"}; |
| 46 | + Configurable<int> cfgCollisionSystem{"collisionSystem", -2, "Collision system: -2 (use cfg values), -1 (autoset), 0 (pp), 1 (PbPb), 2 (XeXe), 3 (pPb)"}; |
| 47 | + Configurable<std::string> cfgUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; |
| 48 | + Configurable<std::string> cfgPathGrpLhcIf{"ccdb-path-grplhcif", "GLO/Config/GRPLHCIF", "Path on the CCDB for the GRPLHCIF object"}; |
| 49 | + Configurable<int64_t> cfgTimestamp{"ccdb-timestamp", -1, "timestamp of the object"}; |
| 50 | + Service<o2::ccdb::BasicCCDBManager> ccdb; |
| 51 | + |
| 52 | + // Producer |
| 53 | + Produces<o2::aod::FT0sCorrected> table; |
| 54 | + using BCsWithMatchings = soa::Join<aod::BCs, aod::Run3MatchedToBCSparse>; |
| 55 | + using CollisionEvSel = soa::Join<aod::Collisions, aod::EvSels>::iterator; |
| 56 | + static constexpr float invLightSpeedCm2NS = 1.f / o2::constants::physics::LightSpeedCm2NS; |
| 57 | + |
| 58 | + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; |
| 59 | + void init(o2::framework::InitContext&) |
| 60 | + { |
| 61 | + if (doprocessStandard && doprocessWithBypassFT0timeInMC) { |
| 62 | + LOG(fatal) << "Both processStandard and processWithBypassFT0timeInMC are enabled. Pick one of the two"; |
| 63 | + } |
| 64 | + if (!doprocessStandard && !doprocessWithBypassFT0timeInMC) { |
| 65 | + LOG(fatal) << "No process is enabled. Pick one"; |
| 66 | + } |
| 67 | + ccdb->setURL(cfgUrl); |
| 68 | + ccdb->setTimestamp(cfgTimestamp); |
| 69 | + ccdb->setCaching(true); |
| 70 | + ccdb->setLocalObjectValidityChecking(); |
| 71 | + // Not later than now objects |
| 72 | + ccdb->setCreatedNotAfter(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()); |
| 73 | + |
| 74 | + if (doprocessWithBypassFT0timeInMC) { |
| 75 | + // From ps to ns |
| 76 | + resoFT0A.value = resoFT0A.value / 1000.f; |
| 77 | + resoFT0C.value = resoFT0C.value / 1000.f; |
| 78 | + } |
| 79 | + if (!addHistograms) { |
| 80 | + return; |
| 81 | + } |
| 82 | + histos.add("t0A", "t0A", kTH1D, {{1000, -1, 1, "t0A (ns)"}}); |
| 83 | + histos.add("t0C", "t0C", kTH1D, {{1000, -1, 1, "t0C (ns)"}}); |
| 84 | + histos.add("t0AC", "t0AC", kTH1D, {{1000, -1000, 1000, "t0AC (ns)"}}); |
| 85 | + histos.add("deltat0AC", "deltat0AC", kTH1D, {{1000, -1, 1, "#Deltat0AC (ns)"}}); |
| 86 | + histos.add("deltat0ACps", "deltat0ACps", kTH1D, {{1000, -1000, 1000, "#Deltat0AC (ps)"}}); |
| 87 | + if (doprocessWithBypassFT0timeInMC) { |
| 88 | + histos.add("MC/deltat0A", "t0A", kTH1D, {{1000, -50, 50, "t0A (ps)"}}); |
| 89 | + histos.add("MC/deltat0C", "t0C", kTH1D, {{1000, -50, 50, "t0C (ps)"}}); |
| 90 | + histos.add("MC/deltat0AC", "t0AC", kTH1D, {{1000, -50, 50, "t0AC (ps)"}}); |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + void process(soa::Join<aod::Collisions, aod::EvSels, aod::McCollisionLabels> const& collisions, |
| 95 | + soa::Join<BCsWithMatchings, aod::Timestamps> const& bcs, |
| 96 | + aod::FT0s const&, |
| 97 | + aod::McCollisions const&) |
| 98 | + { |
| 99 | + if (cfgCollisionSystem.value == -1) { |
| 100 | + o2::parameters::GRPLHCIFData* grpo = ccdb->template getForTimeStamp<o2::parameters::GRPLHCIFData>(cfgPathGrpLhcIf, |
| 101 | + bcs.iteratorAt(0).timestamp()); |
| 102 | + cfgCollisionSystem.value = CollisionSystemType::getCollisionTypeFromGrp(grpo); |
| 103 | + switch (cfgCollisionSystem.value) { |
| 104 | + case CollisionSystemType::kCollSyspp: |
| 105 | + resoFT0A.value = 24.f; |
| 106 | + resoFT0C.value = 24.f; |
| 107 | + break; |
| 108 | + case CollisionSystemType::kCollSysPbPb: |
| 109 | + resoFT0A.value = 5.65f; |
| 110 | + resoFT0C.value = 5.65f; |
| 111 | + break; |
| 112 | + default: |
| 113 | + break; |
| 114 | + } |
| 115 | + // Resolution is given in ps |
| 116 | + resoFT0A.value = resoFT0A.value / 1000.f; |
| 117 | + resoFT0C.value = resoFT0C.value / 1000.f; |
| 118 | + } |
| 119 | + table.reserve(collisions.size()); |
| 120 | + float t0A = 1e10f; |
| 121 | + float t0C = 1e10f; |
| 122 | + float eventtimeMC = 1e10f; |
| 123 | + float posZMC = 0; |
| 124 | + bool hasMCcoll = false; |
| 125 | + |
| 126 | + for (const auto& collision : collisions) { |
| 127 | + hasMCcoll = false; |
| 128 | + eventtimeMC = 1e10f; |
| 129 | + t0A = 1e10f; |
| 130 | + t0C = 1e10f; |
| 131 | + posZMC = 0; |
| 132 | + const float vertexPV = collision.posZ(); |
| 133 | + const float vertex_corr = vertexPV * invLightSpeedCm2NS; |
| 134 | + constexpr float dummyTime = 30.; // Due to HW limitations time can be only within range (-25,25) ns, dummy time is around 32 ns |
| 135 | + if (collision.has_mcCollision()) { |
| 136 | + hasMCcoll = true; |
| 137 | + const auto& collisionMC = collision.mcCollision(); |
| 138 | + eventtimeMC = collisionMC.t(); |
| 139 | + posZMC = collisionMC.posZ(); |
| 140 | + } |
| 141 | + if (collision.has_foundFT0()) { |
| 142 | + const auto& ft0 = collision.foundFT0(); |
| 143 | + const std::bitset<8>& triggers = ft0.triggerMask(); |
| 144 | + const bool ora = triggers[o2::ft0::Triggers::bitA]; |
| 145 | + const bool orc = triggers[o2::ft0::Triggers::bitC]; |
| 146 | + |
| 147 | + if (ora && ft0.timeA() < dummyTime) { |
| 148 | + t0A = ft0.timeA(); |
| 149 | + if (hasMCcoll) { |
| 150 | + const float diff = eventtimeMC - posZMC * invLightSpeedCm2NS + gRandom->Gaus(0.f, resoFT0A); |
| 151 | + t0A = diff; |
| 152 | + } |
| 153 | + t0A += vertex_corr; |
| 154 | + } |
| 155 | + if (orc && ft0.timeC() < dummyTime) { |
| 156 | + t0C = ft0.timeC(); |
| 157 | + if (hasMCcoll) { |
| 158 | + const float diff = eventtimeMC + posZMC * invLightSpeedCm2NS + gRandom->Gaus(0.f, resoFT0C); |
| 159 | + t0C = diff; |
| 160 | + } |
| 161 | + t0C -= vertex_corr; |
| 162 | + } |
| 163 | + } |
| 164 | + LOGF(debug, " T0 collision time T0A = %f, T0C = %f", t0A, t0C); |
| 165 | + if (addHistograms) { |
| 166 | + histos.fill(HIST("t0A"), t0A); |
| 167 | + histos.fill(HIST("t0C"), t0C); |
| 168 | + histos.fill(HIST("t0AC"), (t0A + t0C) * 0.5f); |
| 169 | + histos.fill(HIST("deltat0AC"), t0A - t0C); |
| 170 | + if (hasMCcoll) { |
| 171 | + histos.fill(HIST("MC/deltat0A"), (t0A - eventtimeMC) * 1000.f); |
| 172 | + histos.fill(HIST("MC/deltat0C"), (t0C - eventtimeMC) * 1000.f); |
| 173 | + histos.fill(HIST("MC/deltat0AC"), ((t0A + t0C) * 0.5f - eventtimeMC) * 1000.f); |
| 174 | + } |
| 175 | + } |
| 176 | + table(t0A, t0C); |
| 177 | + } |
| 178 | + } |
| 179 | +}; |
| 180 | + |
| 181 | +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask<ft0CorrectedTableMcOverride>(cfgc)}; } |
0 commit comments