src/tools/ROOT.h

Set of ROOT utilities for framework integration. More…

Namespaces

Name
allpix
Helper class to hold support layers for a detector model.

Classes

Name
class allpix::ThreadedHistogram
A re-implementation of ROOT::TThreadedObject.

Types

Name
template <class T >
using std::unique_ptr< ThreadedHistogram< T > >
Histogram

Functions

Name
template <typename T >
ROOT::Math::DisplacementVector3D< T >
from_string_impl(std::string str, type_tag< ROOT::Math::DisplacementVector3D< T » )
Enable support to convert string directly to ROOT 3D displacement vector while fetching configuration parameter.
template <typename T >
std::string
to_string_impl(const ROOT::Math::DisplacementVector3D< T > & vec, empty_tag )
Enable support to convert ROOT 3D displacement vector to string for storage in the configuration.
template <typename T >
ROOT::Math::DisplacementVector2D< T >
from_string_impl(std::string str, type_tag< ROOT::Math::DisplacementVector2D< T » )
Enable support to convert string directly to ROOT 2D displacement vector while fetching configuration parameter.
template <typename T >
std::string
to_string_impl(const ROOT::Math::DisplacementVector2D< T > & vec, empty_tag )
Enable support to convert ROOT 2D displacement vector to string for storage in the configuration.
template <typename T >
ROOT::Math::PositionVector3D< T >
from_string_impl(std::string str, type_tag< ROOT::Math::PositionVector3D< T » )
Enable support to convert string directly to ROOT 3D position vector while fetching configuration parameter.
template <typename T >
std::string
to_string_impl(const ROOT::Math::PositionVector3D< T > & vec, empty_tag )
Enable support to convert ROOT 3D position vector to string for storage in the configuration.
template <typename T >
ROOT::Math::PositionVector2D< T >
from_string_impl(std::string str, type_tag< ROOT::Math::PositionVector2D< T » )
Enable support to convert string directly to ROOT 2D position vector while fetching configuration parameter.
template <typename T >
std::string
to_string_impl(const ROOT::Math::PositionVector2D< T > & vec, empty_tag )
Enable support to convert ROOT 2D position vector to string for storage in the configuration.
template <typename T ,typename U >
std::ostream &
operator«(std::ostream & os, const ROOT::Math::DisplacementVector3D< T, U > & vec)
Overload output stream operator to display ROOT 3D displacement vector.
template <typename T ,typename U >
std::ostream &
operator«(std::ostream & os, const ROOT::Math::DisplacementVector2D< T, U > & vec)
Overload output stream operator to display ROOT 2D displacement vector.
template <typename T ,typename U >
std::ostream &
operator«(std::ostream & os, const ROOT::Math::PositionVector3D< T, U > & vec)
Overload output stream operator to display ROOT 3D position vector.
template <typename T ,typename U >
std::ostream &
operator«(std::ostream & os, const ROOT::Math::PositionVector2D< T, U > & vec)
Overload output stream operator to display ROOT 2D position vector.
template <typename T ,class… ARGS>
std::unique_ptr< ThreadedHistogram< T > >
CreateHistogram(ARGS &&… args)
Helper method to instantiate new objects of the type ThreadedHistogram.
std::unique_lock< std::mutex > root_process_lock()
Lock for TProcessID simultaneous action.

Detailed Description

Set of ROOT utilities for framework integration.

Copyright: Copyright (c) 2017-2024 CERN and the Allpix Squared authors. This software is distributed under the terms of the MIT License, copied verbatim in the file “LICENSE.md”. 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. SPDX-License-Identifier: MIT

Types Documentation

using Histogram

template <class T >
using allpix::Histogram = typedef std::unique_ptr<ThreadedHistogram<T> >;

Functions Documentation

function from_string_impl

template <typename T >
inline ROOT::Math::DisplacementVector3D< T > from_string_impl(
    std::string str,
    type_tag< ROOT::Math::DisplacementVector3D< T >> 
)

Enable support to convert string directly to ROOT 3D displacement vector while fetching configuration parameter.

function to_string_impl

template <typename T >
inline std::string to_string_impl(
    const ROOT::Math::DisplacementVector3D< T > & vec,
    empty_tag 
)

Enable support to convert ROOT 3D displacement vector to string for storage in the configuration.

function from_string_impl

template <typename T >
inline ROOT::Math::DisplacementVector2D< T > from_string_impl(
    std::string str,
    type_tag< ROOT::Math::DisplacementVector2D< T >> 
)

Enable support to convert string directly to ROOT 2D displacement vector while fetching configuration parameter.

function to_string_impl

template <typename T >
inline std::string to_string_impl(
    const ROOT::Math::DisplacementVector2D< T > & vec,
    empty_tag 
)

Enable support to convert ROOT 2D displacement vector to string for storage in the configuration.

function from_string_impl

template <typename T >
inline ROOT::Math::PositionVector3D< T > from_string_impl(
    std::string str,
    type_tag< ROOT::Math::PositionVector3D< T >> 
)

Enable support to convert string directly to ROOT 3D position vector while fetching configuration parameter.

function to_string_impl

template <typename T >
inline std::string to_string_impl(
    const ROOT::Math::PositionVector3D< T > & vec,
    empty_tag 
)

Enable support to convert ROOT 3D position vector to string for storage in the configuration.

function from_string_impl

template <typename T >
inline ROOT::Math::PositionVector2D< T > from_string_impl(
    std::string str,
    type_tag< ROOT::Math::PositionVector2D< T >> 
)

Enable support to convert string directly to ROOT 2D position vector while fetching configuration parameter.

function to_string_impl

template <typename T >
inline std::string to_string_impl(
    const ROOT::Math::PositionVector2D< T > & vec,
    empty_tag 
)

Enable support to convert ROOT 2D position vector to string for storage in the configuration.

function operator«

template <typename T ,
typename U >
inline std::ostream & operator<<(
    std::ostream & os,
    const ROOT::Math::DisplacementVector3D< T, U > & vec
)

Overload output stream operator to display ROOT 3D displacement vector.

function operator«

template <typename T ,
typename U >
inline std::ostream & operator<<(
    std::ostream & os,
    const ROOT::Math::DisplacementVector2D< T, U > & vec
)

Overload output stream operator to display ROOT 2D displacement vector.

function operator«

template <typename T ,
typename U >
inline std::ostream & operator<<(
    std::ostream & os,
    const ROOT::Math::PositionVector3D< T, U > & vec
)

Overload output stream operator to display ROOT 3D position vector.

function operator«

template <typename T ,
typename U >
inline std::ostream & operator<<(
    std::ostream & os,
    const ROOT::Math::PositionVector2D< T, U > & vec
)

Overload output stream operator to display ROOT 2D position vector.

function CreateHistogram

template <typename T ,
class... ARGS>
std::unique_ptr< ThreadedHistogram< T > > CreateHistogram(
    ARGS &&... args
)

Helper method to instantiate new objects of the type ThreadedHistogram.

Parameters:

  • args Arguments passed to histogram class

Return: Unique pointer to newly created object

function root_process_lock

inline std::unique_lock< std::mutex > root_process_lock()

Lock for TProcessID simultaneous action.

Source code


#ifndef ALLPIX_ROOT_H
#define ALLPIX_ROOT_H

#include <ostream>
#include <stdexcept>
#include <string>
#include <utility>

#include <Math/DisplacementVector2D.h>
#include <Math/DisplacementVector3D.h>
#include <Math/EulerAngles.h>
#include <Math/PositionVector2D.h>
#include <Math/PositionVector3D.h>
#include <RVersion.h>
#include <TProcessID.h>
#include <TString.h>

#include <ROOT/TThreadedObject.hxx>
#include <TH1.h>

#include "core/module/ThreadPool.hpp"
#include "core/utils/text.h"
#include "core/utils/type.h"

#include "core/utils/log.h"

namespace allpix {
    template <typename T>
    inline ROOT::Math::DisplacementVector3D<T> from_string_impl(std::string str,
                                                                type_tag<ROOT::Math::DisplacementVector3D<T>>) {
        std::vector<typename T::Scalar> vec_split = allpix::split<typename T::Scalar>(std::move(str));
        if(vec_split.size() != 3) {
            throw std::invalid_argument("array should contain exactly three elements");
        }
        return ROOT::Math::DisplacementVector3D<T>(vec_split[0], vec_split[1], vec_split[2]);
    }
    template <typename T> inline std::string to_string_impl(const ROOT::Math::DisplacementVector3D<T>& vec, empty_tag) {
        std::string res;
        res += std::to_string(vec.x());
        res += ",";
        res += std::to_string(vec.y());
        res += ",";
        res += std::to_string(vec.z());
        return res;
    }

    template <typename T>
    inline ROOT::Math::DisplacementVector2D<T> from_string_impl(std::string str,
                                                                type_tag<ROOT::Math::DisplacementVector2D<T>>) {
        std::vector<typename T::Scalar> vec_split = allpix::split<typename T::Scalar>(std::move(str));
        if(vec_split.size() != 2) {
            throw std::invalid_argument("array should contain exactly two elements");
        }
        return ROOT::Math::DisplacementVector2D<T>(vec_split[0], vec_split[1]);
    }
    template <typename T> inline std::string to_string_impl(const ROOT::Math::DisplacementVector2D<T>& vec, empty_tag) {
        std::string res;
        res += std::to_string(vec.x());
        res += ",";
        res += std::to_string(vec.y());
        return res;
    }

    template <typename T>
    inline ROOT::Math::PositionVector3D<T> from_string_impl(std::string str, type_tag<ROOT::Math::PositionVector3D<T>>) {
        std::vector<typename T::Scalar> vec_split = allpix::split<typename T::Scalar>(std::move(str));
        if(vec_split.size() != 3) {
            throw std::invalid_argument("array should contain exactly three elements");
        }
        return ROOT::Math::PositionVector3D<T>(vec_split[0], vec_split[1], vec_split[2]);
    }
    template <typename T> inline std::string to_string_impl(const ROOT::Math::PositionVector3D<T>& vec, empty_tag) {
        return to_string_impl(static_cast<ROOT::Math::DisplacementVector3D<T>>(vec), empty_tag());
    }

    template <typename T>
    inline ROOT::Math::PositionVector2D<T> from_string_impl(std::string str, type_tag<ROOT::Math::PositionVector2D<T>>) {
        std::vector<typename T::Scalar> vec_split = allpix::split<typename T::Scalar>(std::move(str));
        if(vec_split.size() != 2) {
            throw std::invalid_argument("array should contain exactly two elements");
        }
        return ROOT::Math::PositionVector2D<T>(vec_split[0], vec_split[1]);
    }
    template <typename T> inline std::string to_string_impl(const ROOT::Math::PositionVector2D<T>& vec, empty_tag) {
        return to_string_impl(static_cast<ROOT::Math::DisplacementVector2D<T>>(vec), empty_tag());
    }

    template <typename T, typename U>
    inline std::ostream& operator<<(std::ostream& os, const ROOT::Math::DisplacementVector3D<T, U>& vec) {
        return os << "(" << vec.x() << "," << vec.y() << "," << vec.z() << ")";
    }
    template <typename T, typename U>
    inline std::ostream& operator<<(std::ostream& os, const ROOT::Math::DisplacementVector2D<T, U>& vec) {
        return os << "(" << vec.x() << "," << vec.y() << ")";
    }
    template <typename T, typename U>
    inline std::ostream& operator<<(std::ostream& os, const ROOT::Math::PositionVector3D<T, U>& vec) {
        return os << "(" << vec.x() << "," << vec.y() << "," << vec.z() << ")";
    }
    template <typename T, typename U>
    inline std::ostream& operator<<(std::ostream& os, const ROOT::Math::PositionVector2D<T, U>& vec) {
        return os << "(" << vec.x() << "," << vec.y() << ")";
    }

    template <typename T, typename std::enable_if<std::is_base_of<TH1, T>::value>::type* = nullptr> class ThreadedHistogram {
    public:
        template <class... ARGS> explicit ThreadedHistogram(ARGS&&... args) { this->init(std::forward<ARGS>(args)...); }

        template <class... ARGS> Int_t Fill(ARGS&&... args) { // NOLINT
            return this->Get()->Fill(std::forward<ARGS>(args)...);
        }

        template <class... ARGS> void SetBinContent(ARGS&&... args) { // NOLINT
            this->Get()->SetBinContent(std::forward<ARGS>(args)...);
        }

        void Write() { this->Merge()->Write(); } // NOLINT

        std::shared_ptr<T> Get() { // NOLINT
            auto idx = ThreadPool::threadNum();
            auto& object = objects_[idx];
            if(!object) {
                object.reset(ROOT::Internal::TThreadedObjectUtils::Cloner<T>::Clone(model_.get(), directories_[idx]));
            }
            return object;
        }

        std::shared_ptr<T> Merge() { // NOLINT
            ROOT::TThreadedObjectUtils::MergeFunctionType<T> mergeFunction = ROOT::TThreadedObjectUtils::MergeTObjects<T>;
            if(is_merged_) {
                return objects_[0];
            }
            mergeFunction(objects_[0], objects_);
            is_merged_ = true;
            return objects_[0];
        }

    private:
        template <class... ARGS> void init(ARGS&&... args) {
            const auto num_slots = ThreadPool::threadCount();
            objects_.resize(num_slots);

#if ROOT_VERSION_CODE < ROOT_VERSION(6, 22, 0)
            directories_ = ROOT::Internal::TThreadedObjectUtils::DirCreator<T>::Create(num_slots);
#else
            // create at least one directory (we need it for the model), plus others as needed by the size of objects
            directories_.emplace_back(ROOT::Internal::TThreadedObjectUtils::DirCreator<T>::Create());
            for(auto i = 1u; i < num_slots; ++i) {
                directories_.emplace_back(ROOT::Internal::TThreadedObjectUtils::DirCreator<T>::Create());
            }
#endif

            TDirectory::TContext ctxt(directories_[0]);
            model_.reset(ROOT::Internal::TThreadedObjectUtils::Detacher<T>::Detach(new T(std::forward<ARGS>(args)...)));

            // initialize at least the base object
            objects_[0].reset(ROOT::Internal::TThreadedObjectUtils::Cloner<T>::Clone(model_.get(), directories_[0]));
        }

        std::unique_ptr<T> model_;
        std::vector<std::shared_ptr<T>> objects_;
        std::vector<TDirectory*> directories_;
        bool is_merged_{false};
    };

    template <typename T, class... ARGS> std::unique_ptr<ThreadedHistogram<T>> CreateHistogram(ARGS&&... args) {
        return std::make_unique<ThreadedHistogram<T>>(std::forward<ARGS>(args)...);
    }

    template <class T> using Histogram = std::unique_ptr<ThreadedHistogram<T>>;

    inline std::unique_lock<std::mutex> root_process_lock() {
        static std::mutex process_id_mutex;
        std::unique_lock<std::mutex> lock(process_id_mutex);

        auto* pids = TProcessID::GetPIDs();
        for(int i = 0; i < pids->GetEntries(); ++i) {
            auto* pid_ptr = static_cast<TProcessID*>((*pids)[i]);
            pid_ptr->Clear();
        }

        return lock;
    }
} // namespace allpix

#endif /* ALLPIX_ROOT_H */

Updated on 2024-12-13 at 08:31:37 +0000