@@ -310,8 +310,13 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int
310310 // FIXME cleanup almost duplicated code
311311 auto & validMcInputs = processAttributes->validMcInputs ;
312312 using CachedMCLabelContainer = decltype (std::declval<InputRecord>().get <MCLabelContainer*>(DataRef{nullptr , nullptr , nullptr }));
313- std::array<CachedMCLabelContainer, NSectors> mcInputs;
314- std::array<gsl::span<const char >, NSectors> inputs;
313+ std::vector<CachedMCLabelContainer> mcInputs;
314+ std::vector<gsl::span<const char >> inputs;
315+ struct InputRef {
316+ DataRef data;
317+ DataRef labels;
318+ };
319+ std::map<int , InputRef> inputrefs;
315320 o2::gpu::GPUTrackingInOutZS tpcZS;
316321 std::vector<const void *> tpcZSmetaPointers[GPUTrackingInOutZS::NSLICES ][GPUTrackingInOutZS::NENDPOINTS ];
317322 std::vector<unsigned int > tpcZSmetaSizes[GPUTrackingInOutZS::NSLICES ][GPUTrackingInOutZS::NENDPOINTS ];
@@ -339,28 +344,23 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int
339344 if (sector < 0 ) {
340345 continue ;
341346 }
342- // the TPCSectorHeader now allows to transport information for more than one sector,
343- // e.g. for transporting clusters in one single data block. For the moment, the
344- // implemenation here requires single sectors
345- if (sector >= TPCSectorHeader::NSectors) {
346- throw std::runtime_error (" Expecting data for single sectors" );
347- }
348- if (validMcInputs.test (sector)) {
347+ std::bitset<NSectors> sectorMask (sectorHeader->sectorBits );
348+ if ((validMcInputs & sectorMask).any ()) {
349349 // have already data for this sector, this should not happen in the current
350350 // sequential implementation, for parallel path merged at the tracker stage
351351 // multiple buffers need to be handled
352352 throw std::runtime_error (" can only have one MC data set per sector" );
353353 }
354+ inputrefs[sector].labels = ref;
354355 if (caClusterer) {
355356 inputDigitsMC[sector] = std::move (pc.inputs ().get <const MCLabelContainer*>(ref));
356357 } else {
357- mcInputs[sector] = std::move (pc.inputs ().get <const MCLabelContainer*>(ref));
358358 }
359- validMcInputs. set (sector) ;
359+ validMcInputs |= sectorMask ;
360360 activeSectors |= sectorHeader->activeSectors ;
361361 if (verbosity > 1 ) {
362362 LOG (INFO ) << " received " << *(ref.spec ) << " MC label containers"
363- << " for sector " << sector //
363+ << " for sectors " << sectorMask //
364364 << std::endl //
365365 << " mc input status: " << validMcInputs //
366366 << std::endl //
@@ -371,7 +371,6 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int
371371
372372 auto & validInputs = processAttributes->validInputs ;
373373 int operation = 0 ;
374- std::map<int , DataRef> datarefs;
375374 std::vector<InputSpec> filter = {
376375 {" check" , ConcreteDataTypeMatcher{gDataOriginTPC , " DIGITS" }, Lifetime::Timeframe},
377376 {" check" , ConcreteDataTypeMatcher{gDataOriginTPC , " CLUSTERNATIVE" }, Lifetime::Timeframe},
@@ -384,24 +383,18 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int
384383 }
385384 const int sector = sectorHeader->sector ();
386385 if (sector < 0 ) {
387- // throw std::runtime_error("lagacy input, custom eos is not expected anymore")
388386 continue ;
389387 }
390- // the TPCSectorHeader now allows to transport information for more than one sector,
391- // e.g. for transporting clusters in one single data block. For the moment, the
392- // implemenation here requires single sectors
393- if (sector >= TPCSectorHeader::NSectors) {
394- throw std::runtime_error (" Expecting data for single sectors" );
395- }
396- if (validInputs.test (sector)) {
388+ std::bitset<NSectors> sectorMask (sectorHeader->sectorBits );
389+ if ((validInputs & sectorMask).any ()) {
397390 // have already data for this sector, this should not happen in the current
398391 // sequential implementation, for parallel path merged at the tracker stage
399392 // multiple buffers need to be handled
400393 throw std::runtime_error (" can only have one cluster data set per sector" );
401394 }
402395 activeSectors |= sectorHeader->activeSectors ;
403- validInputs. set (sector) ;
404- datarefs [sector] = ref;
396+ validInputs |= sectorMask ;
397+ inputrefs [sector]. data = ref;
405398 if (caClusterer && !zsOnTheFly) {
406399 inputDigits[sector] = pc.inputs ().get <gsl::span<o2::tpc::Digit>>(ref);
407400 LOG (INFO ) << " GOT SPAN FOR SECTOR " << sector << " -> " << inputDigits[sector].size ();
@@ -538,12 +531,20 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int
538531 throw std::runtime_error (" Incomplete mc label input, expecting complete data set, buffering has been removed" );
539532 }
540533 assert (processMC == false || validMcInputs == validInputs);
541- for (auto const & refentry : datarefs ) {
534+ for (auto const & refentry : inputrefs ) {
542535 auto & sector = refentry.first ;
543- auto & ref = refentry.second ;
544- inputs[sector] = gsl::span (ref.payload , DataRefUtils::getPayloadSize (ref));
536+ auto & ref = refentry.second .data ;
537+ if (ref.payload == nullptr ) {
538+ // skip zero-length message
539+ continue ;
540+ }
541+ if (refentry.second .labels .header != nullptr && refentry.second .labels .payload != nullptr ) {
542+ mcInputs.emplace_back (std::move (pc.inputs ().get <const MCLabelContainer*>(refentry.second .labels )));
543+ }
544+ inputs.emplace_back (gsl::span (ref.payload , DataRefUtils::getPayloadSize (ref)));
545545 printInputLog (ref, " received" , sector);
546546 }
547+ assert (mcInputs.size () == 0 || mcInputs.size () == inputs.size ());
547548 if (verbosity > 0 ) {
548549 // make human readable information from the bitfield
549550 std::string bitInfo;
@@ -680,15 +681,27 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int
680681 activeSectors |= 0x1 << sector;
681682 }
682683 }
683- for (auto const & sector : processAttributes->clusterOutputIds ) {
684- o2::tpc::TPCSectorHeader header{sector};
685- o2::header::DataHeader::SubSpecificationType subspec = sector;
684+ // previously, clusters have been published individually for the enabled sectors
685+ // clusters are now published as one block, subspec is NSectors
686+ if (processAttributes->clusterOutputIds .size () > 0 ) {
687+ o2::tpc::TPCSectorHeader header{0 };
688+ header.sectorBits = activeSectors;
689+ // subspecs [0, NSectors - 1] are used to identify sector data, we use NSectors
690+ // to indicate the full TPC
691+ o2::header::DataHeader::SubSpecificationType subspec = NSectors;
686692 header.activeSectors = activeSectors;
693+ // doing a copy for now, in the future the tracker uses the output buffer directly
687694 auto & target = pc.outputs ().make <std::vector<char >>({gDataOriginTPC , " CLUSTERNATIVE" , subspec, Lifetime::Timeframe, {header}});
688- std::vector<MCLabelContainer> labels;
689- ClusterNativeHelper::copySectorData (*ptrs.clusters , sector, target, labels);
690- if (pc.outputs ().isAllowed ({gDataOriginTPC , " CLNATIVEMCLBL" , subspec})) {
691- pc.outputs ().snapshot ({gDataOriginTPC , " CLNATIVEMCLBL" , subspec, Lifetime::Timeframe, {header}}, labels);
695+ ClusterNativeAccess const & accessIndex = *ptrs.clusters ;
696+ size_t outputSize = accessIndex.nClustersTotal * sizeof (ClusterNative) + sizeof (ClusterCountIndex);
697+ target.resize (outputSize);
698+ ClusterCountIndex* outIndex = reinterpret_cast <ClusterCountIndex*>(target.data ());
699+ ClusterNative* outClusters = reinterpret_cast <ClusterNative*>(target.data () + sizeof (ClusterCountIndex));
700+ static_assert (sizeof (ClusterCountIndex) == sizeof (accessIndex.nClusters ));
701+ memcpy (outIndex, &accessIndex.nClusters [0 ][0 ], sizeof (ClusterCountIndex));
702+ memcpy (outClusters, accessIndex.clustersLinear , accessIndex.nClustersTotal * sizeof (ClusterNative));
703+ if (pc.outputs ().isAllowed ({gDataOriginTPC , " CLNATIVEMCLBL" , subspec}) && accessIndex.clustersMCTruth ) {
704+ pc.outputs ().snapshot ({gDataOriginTPC , " CLNATIVEMCLBL" , subspec, Lifetime::Timeframe, {header}}, *accessIndex.clustersMCTruth );
692705 }
693706 }
694707
@@ -763,12 +776,11 @@ DataProcessorSpec getCATrackerSpec(ca::Config const& specconfig, std::vector<int
763776 }
764777 if (specconfig.outputCAClusters ) {
765778 for (auto const & sector : tpcsectors) {
766- o2::header::DataHeader::SubSpecificationType id = sector;
767- outputSpecs.emplace_back (gDataOriginTPC , " CLUSTERNATIVE" , id, Lifetime::Timeframe);
768779 processAttributes->clusterOutputIds .emplace_back (sector);
769- if (specconfig.processMC ) {
770- outputSpecs.emplace_back (OutputSpec{gDataOriginTPC , " CLNATIVEMCLBL" , id, Lifetime::Timeframe});
771- }
780+ }
781+ outputSpecs.emplace_back (gDataOriginTPC , " CLUSTERNATIVE" , NSectors, Lifetime::Timeframe);
782+ if (specconfig.processMC ) {
783+ outputSpecs.emplace_back (OutputSpec{gDataOriginTPC , " CLNATIVEMCLBL" , NSectors, Lifetime::Timeframe});
772784 }
773785 }
774786 return std::move (outputSpecs);
0 commit comments