Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOF: Adding workflow for integrated TOF currents #10608

Merged
merged 5 commits into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Detectors/TOF/calibration/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ o2_add_library(TOFCalibration
src/TOFDCSProcessor.cxx
src/TOFFEElightReader.cxx
src/TOFFEElightConfig.cxx
src/TOFIntegratedClusterCalibrator.cxx
src/TOFDiagnosticCalibrator.cxx
PUBLIC_LINK_LIBRARIES O2::DataFormatsTOF O2::TOFBase
O2::CCDB
Expand All @@ -38,6 +39,7 @@ o2_target_root_dictionary(TOFCalibration
include/TOFCalibration/TOFDCSProcessor.h
include/TOFCalibration/TOFFEElightReader.h
include/TOFCalibration/TOFFEElightConfig.h
include/TOFCalibration/TOFIntegratedClusterCalibrator.h
include/TOFCalibration/TOFDiagnosticCalibrator.h)

if (OpenMP_CXX_FOUND)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// 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.

/// \file TOFIntegratedClusterCalibrator.h
/// \brief calibrator class for accumulating integrated clusters
/// \author Matthias Kleiner <[email protected]>
/// \date Jan 21, 2023

#ifndef TOF_INTEGRATEDCLUSTERCALIBRATOR_H_
#define TOF_INTEGRATEDCLUSTERCALIBRATOR_H_

#include "DetectorsCalibration/TimeSlotCalibration.h"
#include "DetectorsCalibration/TimeSlot.h"

namespace o2
{
namespace tof
{

/// struct containing the integrated TOF currents
struct ITOFC {
std::vector<float> mITOFCNCl; ///< integrated 1D TOF cluster currents
std::vector<float> mITOFCQ; ///< integrated 1D TOF qTot currents
ClassDefNV(ITOFC, 1);
};

/// class for accumulating integrated TOF currents
class TOFIntegratedClusters
{
public:
/// \constructor
/// \param tFirst first TF of the stored currents
/// \param tLast last TF of the stored currents
TOFIntegratedClusters(o2::calibration::TFType tFirst, o2::calibration::TFType tLast) : mTFFirst{tFirst}, mTFLast{tLast} {};

/// \default constructor for ROOT I/O
TOFIntegratedClusters() = default;

/// print summary informations
void print() const { LOGP(info, "TF Range from {} to {} with {} of remaining data", mTFFirst, mTFLast, mRemainingData); }

/// accumulate currents for given TF
/// \param tfID TF ID of incoming data
/// \param iTOFCNcl integrated TOF currents for one TF for number of clusters
/// \param iTOFCqTot integrated TOF currents for one TF for qTot
void fill(const o2::calibration::TFType tfID, const std::vector<float>& iTOFCNcl, const std::vector<float>& iTOFCqTot);

/// merging TOF currents with previous interval
void merge(const TOFIntegratedClusters* prev);

/// \return returns if already all expected TFs are received
bool hasEnoughData() const { return mRemainingData ? false : true; }

/// \return returns accumulated TOF currents
const auto& getITOFCCurrents() const { return mCurrents; }

/// dump object to disc
/// \param outFileName name of the output file
/// \param outName name of the object in the output file
void dumpToFile(const char* outFileName = "TOFIntegratedClusters.root", const char* outName = "ITOFC") const;

/// dump object to TTree for visualisation
/// \param outFileName name of the output file
void dumpToTree(const char* outFileName = "ITOFCTree.root");

private:
ITOFC mCurrents; ///< buffer for integrated currents
o2::calibration::TFType mTFFirst{}; ///< first TF of currents
o2::calibration::TFType mTFLast{}; ///< last TF of currents
o2::calibration::TFType mRemainingData{}; ///< counter for received data
unsigned int mNValuesPerTF{}; ///< number of expected currents per TF (estimated from first received data)
bool mInitialize{true}; ///< flag if this object will be initialized when fill method is called

/// init member when first data is received
/// \param vec received data which is used to estimate the expected data
void initData(const std::vector<float>& vec);

ClassDefNV(TOFIntegratedClusters, 1);
};

class TOFIntegratedClusterCalibrator : public o2::calibration::TimeSlotCalibration<o2::tof::TOFIntegratedClusters>
{
using TFType = o2::calibration::TFType;
using Slot = o2::calibration::TimeSlot<o2::tof::TOFIntegratedClusters>;
using CalibVector = std::vector<ITOFC>;
using TFinterval = std::vector<std::pair<TFType, TFType>>;
using TimeInterval = std::vector<std::pair<long, long>>;

public:
/// default constructor
TOFIntegratedClusterCalibrator() = default;

/// default destructor
~TOFIntegratedClusterCalibrator() final = default;

/// check if given slot has already enough data
bool hasEnoughData(const Slot& slot) const final { return slot.getContainer()->hasEnoughData(); }

/// clearing all calibration objects in the output buffer
void initOutput() final;

/// storing the integrated currents for given slot
void finalizeSlot(Slot& slot) final;

/// Creates new time slot
Slot& emplaceNewSlot(bool front, TFType tstart, TFType tend) final;

/// \return CCDB output informations
const TFinterval& getTFinterval() const { return mIntervals; }

/// \return Time frame time information
const TimeInterval& getTimeIntervals() const { return mTimeIntervals; }

/// \return returns calibration objects (pad-by-pad gain maps)
auto getCalibs() && { return std::move(mCalibs); }

/// check if calibration data is available
bool hasCalibrationData() const { return mCalibs.size() > 0; }

/// set if debug objects will be created
void setDebug(const bool debug) { mDebug = debug; }

private:
TFinterval mIntervals; ///< start and end time frames of each calibration time slots
TimeInterval mTimeIntervals; ///< start and end times of each calibration time slots
CalibVector mCalibs; ///< Calibration object containing for each pad a histogram with normalized charge
bool mDebug{false}; ///< write debug output objects

ClassDefOverride(TOFIntegratedClusterCalibrator, 1);
};

} // end namespace tof
} // end namespace o2

#endif /* TOF_CHANNEL_CALIBRATOR_H_ */
6 changes: 6 additions & 0 deletions Detectors/TOF/calibration/src/TOFCalibrationLinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,10 @@
#pragma link C++ class o2::calibration::TimeSlotCalibration < o2::tof::Diagnostic> + ;
#pragma link C++ class o2::tof::TOFDiagnosticCalibrator + ;

#pragma link C++ struct o2::tof::ITOFC + ;
#pragma link C++ class o2::tof::TOFIntegratedClusters + ;
#pragma link C++ class o2::tof::TOFIntegratedClusterCalibrator + ;
#pragma link C++ class o2::calibration::TimeSlot < o2::tof::TOFIntegratedClusters> + ;
#pragma link C++ class o2::calibration::TimeSlotCalibration < o2::tof::TOFIntegratedClusters> + ;

#endif
183 changes: 183 additions & 0 deletions Detectors/TOF/calibration/src/TOFIntegratedClusterCalibrator.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// 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.

/// \file TOFIntegratedClusterCalibrator.cxx
///
/// \author Matthias Kleiner <[email protected]>
/// \date Jan 21, 2023

#include "TOFCalibration/TOFIntegratedClusterCalibrator.h"
#include "CommonUtils/TreeStreamRedirector.h"

namespace o2
{
namespace tof
{
using Slot = o2::calibration::TimeSlot<o2::tof::TOFIntegratedClusters>;

void TOFIntegratedClusters::dumpToFile(const char* outFileName, const char* outName) const
{
TFile fOut(outFileName, "RECREATE");
fOut.WriteObject(this, outName);
fOut.Close();
}

void TOFIntegratedClusters::fill(const o2::calibration::TFType tfID, const std::vector<float>& iTOFCNcl, const std::vector<float>& iTOFCqTot)
{
// check if size is same
if (iTOFCNcl.size() != iTOFCqTot.size()) {
LOGP(warning, "Received data with different size. iTOFCNcl.size {} iTOFCqTot.size {}", iTOFCNcl.size(), iTOFCqTot.size());
return;
}

if (iTOFCNcl.empty()) {
LOGP(info, "Empty data received. Returning");
return;
}

// initialize when first data is received
if (mInitialize) {
initData(iTOFCqTot);
}

// check if all data is already received (this should never happen)
if (mRemainingData == 0) {
LOGP(warning, "All packages already received. Returning");
return;
}

if (iTOFCNcl.size() != mNValuesPerTF) {
LOGP(info, "Received data with size {} expected size {} (expected size can be ignored if merging was performed)", iTOFCNcl.size(), mNValuesPerTF);
}

const unsigned int posIndex = (tfID - mTFFirst) * mNValuesPerTF;
if (posIndex + iTOFCNcl.size() > mCurrents.mITOFCNCl.size()) {
LOGP(warning, "Index for TF {} is larger {} than expected max index {} with {} values per package", tfID, posIndex, mCurrents.mITOFCNCl.size(), mNValuesPerTF);
return;
}

// copy data to buffer
std::copy(iTOFCNcl.begin(), iTOFCNcl.end(), mCurrents.mITOFCNCl.begin() + posIndex);
std::copy(iTOFCqTot.begin(), iTOFCqTot.end(), mCurrents.mITOFCQ.begin() + posIndex);

mRemainingData -= iTOFCNcl.size();
LOGP(debug, "Processed TF {} at index {} with first TF {} and {} expected currents per TF. Remaining data {}", tfID, posIndex, mTFFirst, mNValuesPerTF, mRemainingData);
}

void TOFIntegratedClusters::merge(const TOFIntegratedClusters* prev)
{
LOGP(info, "Printing last object...");
prev->print();
LOGP(info, "Printing current object...");
print();

const auto tfMin = std::min(mTFFirst, prev->mTFFirst);
const auto tfMax = std::max(mTFLast, prev->mTFLast);

if (prev->mInitialize) {
// if last object was not initialized adjust tf range
mTFFirst = tfMin;
mTFLast = tfMax;
if (!mInitialize) {
// current buffer is already initialized just add empty values in front of buffer
LOGP(info, "Adding dummy data to front");
std::vector<float> vecTmp(mNValuesPerTF * ((prev->mTFLast - prev->mTFFirst) + 1), 0);
mCurrents.mITOFCNCl.insert(mCurrents.mITOFCNCl.begin(), vecTmp.begin(), vecTmp.end());
mCurrents.mITOFCQ.insert(mCurrents.mITOFCQ.begin(), vecTmp.begin(), vecTmp.end());
}
LOGP(info, "Do not merge last object since it was not initialized. Adjusting TF range:");
print();
return;
}

// check if current object needs to be initialized
if (mInitialize) {
// init with dummy vector
initData(std::vector<float>(prev->mNValuesPerTF));
}

// creating new temporary object with the range of current and last object
const unsigned int totalTFs = (tfMax - tfMin) + 1; // add 1 since first<= t <=last
const unsigned int nTotal = mNValuesPerTF * totalTFs;
TOFIntegratedClusters dataTmp(tfMin, tfMax);
dataTmp.mInitialize = false; // do no initialization as it is done manually
dataTmp.mNValuesPerTF = mNValuesPerTF;
dataTmp.mRemainingData = -1;
dataTmp.mCurrents.mITOFCNCl.resize(nTotal);
dataTmp.mCurrents.mITOFCQ.resize(nTotal);

// fill buffered values to tmp objects
dataTmp.fill(mTFFirst, mCurrents.mITOFCNCl, mCurrents.mITOFCQ);
dataTmp.fill(prev->mTFFirst, prev->mCurrents.mITOFCNCl, prev->mCurrents.mITOFCQ);

dataTmp.mRemainingData = mRemainingData;
*this = std::move(dataTmp);
LOGP(info, "Merging done", totalTFs);
print();
}

void TOFIntegratedClusters::initData(const std::vector<float>& vec)
{
mInitialize = false;
const unsigned int totalTFs = (mTFLast - mTFFirst) + 1; // add 1 since first<= t <=last
mNValuesPerTF = vec.size();
const unsigned int nTotal = mNValuesPerTF * totalTFs;
mCurrents.mITOFCNCl.resize(nTotal);
mCurrents.mITOFCQ.resize(nTotal);
mRemainingData = nTotal;
LOGP(info, "Init: Expecting {} packages with {} values per package with {} total values", mRemainingData, mNValuesPerTF, nTotal);
}

void TOFIntegratedClusters::dumpToTree(const char* outFileName)
{
o2::utils::TreeStreamRedirector pcstream(outFileName, "RECREATE");
pcstream << "tree"
<< "currents=" << mCurrents
<< "firstTF=" << mTFFirst
<< "lastTF=" << mTFLast
<< "remainingData=" << mRemainingData
<< "valuesPerTF=" << mNValuesPerTF
<< "\n";
}

void TOFIntegratedClusterCalibrator::initOutput()
{
mIntervals.clear();
mCalibs.clear();
mTimeIntervals.clear();
}

void TOFIntegratedClusterCalibrator::finalizeSlot(Slot& slot)
{
const TFType startTF = slot.getTFStart();
const TFType endTF = slot.getTFEnd();
LOGP(info, "Finalizing slot {} <= TF <= {}", startTF, endTF);

auto& TOFIntegratedClusters = *slot.getContainer();
if (mDebug) {
TOFIntegratedClusters.dumpToFile(fmt::format("TOFIntegratedClusters_TF_{}_{}_TS_{}_{}.root", startTF, endTF, slot.getStartTimeMS(), slot.getEndTimeMS()).data());
}
mCalibs.emplace_back(TOFIntegratedClusters.getITOFCCurrents());
mIntervals.emplace_back(startTF, endTF);
mTimeIntervals.emplace_back(slot.getStartTimeMS(), slot.getEndTimeMS());
}

/// Creates new time slot
Slot& TOFIntegratedClusterCalibrator::emplaceNewSlot(bool front, TFType tstart, TFType tend)
{
auto& cont = getSlots();
auto& slot = front ? cont.emplace_front(tstart, tend) : cont.emplace_back(tstart, tend);
slot.setContainer(std::make_unique<TOFIntegratedClusters>(tstart, tend));
return slot;
}

} // end namespace tof
} // end namespace o2
19 changes: 18 additions & 1 deletion Detectors/TOF/workflow/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ o2_add_library(TOFWorkflowUtils
src/CompressedAnalysisTask.cxx
src/EntropyEncoderSpec.cxx
src/EntropyDecoderSpec.cxx
PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction O2::TOFWorkflowIO O2::Steer)
src/TOFIntegrateClusterSpec.cxx
src/TOFMergeIntegrateClusterSpec.cxx
PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::TOFBase O2::DataFormatsTOF O2::TOFReconstruction O2::TOFWorkflowIO O2::Steer O2::TOFCalibration)

o2_add_executable(make-parameter-collection
SOURCES src/make-parameter-collection.cxx
Expand Down Expand Up @@ -52,3 +54,18 @@ o2_add_executable(file-proxy
SOURCES src/file-proxy.cxx
COMPONENT_NAME tof
PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils)

o2_add_executable(integrate-cluster-workflow
SOURCES src/cluster-integrator.cxx
COMPONENT_NAME tof
PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils)

o2_add_executable(integrate-cluster-reader-workflow
SOURCES src/cluster-integrator-reader.cxx
COMPONENT_NAME tof
PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils)

o2_add_executable(merge-integrate-cluster-workflow
SOURCES src/cluster-merge-integrator.cxx
COMPONENT_NAME tof
PUBLIC_LINK_LIBRARIES O2::TOFWorkflowUtils)
Loading