2121#include " DataFormatsCTP/TriggerOffsetsParam.h"
2222#include " Framework/CCDBParamSpec.h"
2323#include " DataFormatsCTP/Configuration.h"
24+ #include " CommonConstants/LHCConstants.h"
25+ #include < DataFormatsParameters/GRPLHCIFData.h>
2426
2527using namespace o2 ::ctp::reco_workflow;
2628
@@ -181,6 +183,9 @@ void RawDecoderSpec::run(framework::ProcessingContext& ctx)
181183 mErrorTCR += mDecoder .getErrorTCR ();
182184 mIRRejected += mDecoder .getIRRejected ();
183185 mTCRRejected += mDecoder .getTCRRejected ();
186+ // Luminosity per bunch crossing
187+ const auto [countsPerBC1, countsPerBC2] = computeLumiPerBC (mOutputDigits );
188+ integrateLumi (countsPerBC1, countsPerBC2);
184189 }
185190 if (mDoLumi ) {
186191 uint32_t tfCountsT = 0 ;
@@ -224,6 +229,89 @@ void RawDecoderSpec::run(framework::ProcessingContext& ctx)
224229 ctx.outputs ().snapshot (o2::framework::Output{" CTP" , " LUMI" , 0 }, mOutputLumiInfo );
225230 }
226231}
232+ // Function to compute luminosity per BC from the interaction counts from CTP digits
233+ std::pair<std::array<double , o2::constants::lhc::LHCMaxBunches>, std::array<double , o2::constants::lhc::LHCMaxBunches>> RawDecoderSpec::computeLumiPerBC (const o2::pmr::vector<CTPDigit>& ctpdigits)
234+ {
235+ int inp1 = mOutputLumiInfo .inp1 ;
236+ int inp2 = mOutputLumiInfo .inp2 ;
237+
238+ uint64_t inputMask1 = 1ull << (inp1 - 1 ); // TVX
239+ uint64_t inputMask2 = 1ull << (inp2 - 1 ); // VBA
240+
241+ double integratedRate = 0.0 ;
242+ std::cout << " Lumi called" << std::endl;
243+
244+ std::array<double , o2::constants::lhc::LHCMaxBunches> countsPerBC1{};
245+ std::array<double , o2::constants::lhc::LHCMaxBunches> countsPerBC2{};
246+
247+ for (const auto & digit : ctpdigits) {
248+ uint64_t mask = digit.CTPInputMask .to_ullong ();
249+ uint16_t bc = digit.intRecord .bc ;
250+
251+ if (bc < o2::constants::lhc::LHCMaxBunches) {
252+ if (mask & inputMask1) {
253+ countsPerBC1[bc] += 1.0 ;
254+ integratedRate += 1.0 ;
255+ // std::cout << "Orbit: " << std::dec << digit.intRecord.orbit << " Orbit: 0x" << std::hex << digit.intRecord.orbit << std::endl;
256+ }
257+
258+ if (mask & inputMask2) {
259+ countsPerBC2[bc] += 1.0 ;
260+ }
261+ }
262+ }
263+ totalTime += tfTime; // Accumulate total time for all processed time frames
264+ for (size_t bc = 0 ; bc < countsPerBC1.size (); ++bc) {
265+ if (countsPerBC1[bc] > 0 ) {
266+ // LOG(info) << " BC " << bc << ": " << lumiPerBC[bc]/totalTime;
267+ }
268+ }
269+ // std::cout << "Integrated luminosity over all BCs: " << integratedRate/totalTime << std::endl;
270+ return {countsPerBC1, countsPerBC2};
271+ }
272+ // Accumulate luminosity per BC over multiple time frames
273+ void RawDecoderSpec::integrateLumi (const std::array<double , o2::constants::lhc::LHCMaxBunches>& perTFInp1,
274+ const std::array<double , o2::constants::lhc::LHCMaxBunches>& perTFInp2)
275+ {
276+
277+ for (size_t bc = 0 ; bc < mCountsPerBC1 .size (); ++bc) {
278+ mCountsPerBC1 [bc] += perTFInp1[bc];
279+ }
280+
281+ for (size_t bc = 0 ; bc < mCountsPerBC2 .size (); ++bc) {
282+ mCountsPerBC2 [bc] += perTFInp2[bc];
283+ }
284+
285+ // Count number of filled BCs
286+ size_t filledBCs = mLHCBCs .count ();
287+
288+ for (size_t bc = 0 ; bc < mCountsPerBC1 .size (); ++bc) {
289+ if (mLHCBCs .test (bc)) { // Only print filled BCs
290+ LOG (info) << " Filled BC " << bc
291+ << " : Input1 Lumi: " << mCountsPerBC1 [bc] / (totalTime * filledBCs)
292+ << " , Input2 Lumi: " << mCountsPerBC2 [bc] / (totalTime * filledBCs)
293+ << " ; Accumulated Counts Input1: " << mCountsPerBC1 [bc]
294+ << " , Input2: " << mCountsPerBC2 [bc];
295+ } else if (mCountsPerBC1 [bc] > 0 ) { // Only print non-zero luminosity
296+ LOG (info) << " BC " << bc
297+ << " : Input1 Lumi: " << mCountsPerBC1 [bc] / (totalTime * filledBCs)
298+ << " , Input2 Lumi: " << mCountsPerBC2 [bc] / (totalTime * filledBCs)
299+ << " ; Accumulated Counts Input1: " << mCountsPerBC1 [bc]
300+ << " , Input2: " << mCountsPerBC2 [bc];
301+ }
302+ }
303+ // Calculate and print the total integrated luminosity
304+ int totalCountsInp1 = 0 ;
305+ int totalCountsInp2 = 0 ;
306+ for (const auto & count : mCountsPerBC1 ) {
307+ totalCountsInp1 += count;
308+ }
309+ LOG (info) << " Total Integrated Luminosity Input 1: " << totalCountsInp1 / totalTime;
310+ for (const auto & count : mCountsPerBC2 ) {
311+ totalCountsInp2 += count;
312+ }
313+ LOG (info) << " Total Integrated Luminosity Input 2: " << totalCountsInp2 / totalTime;
314+ }
227315o2::framework::DataProcessorSpec o2::ctp::reco_workflow::getRawDecoderSpec (bool askDISTSTF, bool digits, bool lumi)
228316{
229317 if (!digits && !lumi) {
@@ -237,6 +325,7 @@ o2::framework::DataProcessorSpec o2::ctp::reco_workflow::getRawDecoderSpec(bool
237325
238326 std::vector<o2::framework::OutputSpec> outputs;
239327 inputs.emplace_back (" ctpconfig" , " CTP" , " CTPCONFIG" , 0 , o2::framework::Lifetime::Condition, o2::framework::ccdbParamSpec (" CTP/Config/Config" , 1 ));
328+ inputs.emplace_back (" grplhcif" , " GLO" , " GRPLHCIF" , 0 , o2::framework::Lifetime::Condition, o2::framework::ccdbParamSpec (" GLO/Config/GRPLHCIF" ));
240329 inputs.emplace_back (" trigoffset" , " CTP" , " Trig_Offset" , 0 , o2::framework::Lifetime::Condition, o2::framework::ccdbParamSpec (" CTP/Config/TriggerOffsets" ));
241330 if (digits) {
242331 outputs.emplace_back (" CTP" , " DIGITS" , 0 , o2::framework::Lifetime::Timeframe);
@@ -245,7 +334,7 @@ o2::framework::DataProcessorSpec o2::ctp::reco_workflow::getRawDecoderSpec(bool
245334 outputs.emplace_back (" CTP" , " LUMI" , 0 , o2::framework::Lifetime::Timeframe);
246335 }
247336 return o2::framework::DataProcessorSpec{
248- " ctp-raw-decoder" ,
337+ " ctp-raw-decoder-lumi " ,
249338 inputs,
250339 outputs,
251340 o2::framework::AlgorithmSpec{o2::framework::adaptFromTask<o2::ctp::reco_workflow::RawDecoderSpec>(digits, lumi)},
@@ -271,5 +360,17 @@ void RawDecoderSpec::updateTimeDependentParams(framework::ProcessingContext& pc)
271360 mDecoder .setCTPConfig (*ctpcfg);
272361 LOG (info) << " ctpconfig for run done:" << mDecoder .getCTPConfig ().getRunNumber ();
273362 }
363+ const auto grplhcif = pc.inputs ().get <o2::parameters::GRPLHCIFData*>(" grplhcif" );
364+ if (grplhcif != nullptr ) {
365+ LOG (info) << " GRPLHCIF injection scheme: " << grplhcif->getInjectionScheme ();
366+
367+ // Get filled bunches
368+ auto bfilling = grplhcif->getBunchFilling ();
369+ std::vector<int > bcs = bfilling.getFilledBCs ();
370+ mLHCBCs .reset ();
371+ for (auto const & bc : bcs) {
372+ mLHCBCs .set (bc, 1 );
373+ }
374+ }
274375 }
275376}
0 commit comments