diff --git a/Algorithms/Digitization/src/DigitizationAlgorithm.cpp b/Algorithms/Digitization/src/DigitizationAlgorithm.cpp index 73d0f404f7d7f5abb6b7cd07769b8dc83f6da651..d8713f6c88ba1bdcc966106ec1b02513f5172ba8 100644 --- a/Algorithms/Digitization/src/DigitizationAlgorithm.cpp +++ b/Algorithms/Digitization/src/DigitizationAlgorithm.cpp @@ -67,16 +67,18 @@ FW::DigitizationAlgorithm::execute(const AlgorithmContext& context) const // now digitise for (auto& vData : simHits) { auto volumeKey = vData.first; - ACTS_DEBUG("- Processing Volume Data collection for volume with ID " - << volumeKey); + ACTS_VERBOSE("- Processing Volume Data collection for volume with ID " + << volumeKey); for (auto& lData : vData.second) { auto layerKey = lData.first; - ACTS_DEBUG("-- Processing Layer Data collection for layer with ID " - << layerKey); + ACTS_VERBOSE("-- Processing Layer Data collection for layer with ID " + << layerKey); for (auto& sData : lData.second) { auto moduleKey = sData.first; - ACTS_DEBUG("-- Processing Module Data collection for module with ID " - << moduleKey); + ACTS_VERBOSE("-- Processing Module Data collection for module with ID " + << moduleKey); + ACTS_VERBOSE("-- Recieved " << sData.second.size() + << " input data objects."); // get the hit parameters for (auto& hit : sData.second) { // get the surface @@ -105,7 +107,7 @@ FW::DigitizationAlgorithm::execute(const AlgorithmContext& context) const Acts::Vector2D localIntersection(localIntersect3D.x(), localIntersect3D.y()); Acts::Vector3D localDirection(invTransfrom.linear() - * hit.direction); + * hit.direction.normalized()); // now calculate the steps through the silicon std::vector<Acts::DigitizationStep> dSteps = m_cfg.planarModuleStepper->cellSteps(context.geoContext, @@ -113,7 +115,10 @@ FW::DigitizationAlgorithm::execute(const AlgorithmContext& context) const localIntersection, localDirection); // everything under threshold or edge effects - if (!dSteps.size()) continue; + if (!dSteps.size()) { + ACTS_VERBOSE("No steps returned from stepper."); + continue; + } /// let' create a cluster - centroid method double localX = 0.; double localY = 0.; diff --git a/Detectors/GenericDetector/include/ACTFW/GenericDetector/ProtoLayerCreatorT.hpp b/Detectors/GenericDetector/include/ACTFW/GenericDetector/ProtoLayerCreatorT.hpp index 6bacfbf0716e86049e728372d8503260f15310b1..02a7971c2cf4ab0f771745697c7d3c34de1c33ac 100644 --- a/Detectors/GenericDetector/include/ACTFW/GenericDetector/ProtoLayerCreatorT.hpp +++ b/Detectors/GenericDetector/include/ACTFW/GenericDetector/ProtoLayerCreatorT.hpp @@ -282,7 +282,7 @@ namespace Generic { moduleDigitizationPtr = std::make_shared<const Acts::DigitizationModule>( moduleSegmentation, - m_cfg.centralModuleThickness.at(icl), + 0.5 * m_cfg.centralModuleThickness.at(icl), m_cfg.centralModuleReadoutSide.at(icl), m_cfg.centralModuleLorentzAngle.at(icl)); } @@ -524,7 +524,7 @@ namespace Generic { moduleDigitizationPtr = std::make_shared<const Acts::DigitizationModule>( moduleSegmentation, - moduleThickness, + 0.5 * moduleThickness, m_cfg.posnegModuleReadoutSide.at(ipnl).at(ipnR), m_cfg.posnegModuleLorentzAngle.at(ipnl).at(ipnR)); } @@ -572,7 +572,8 @@ namespace Generic { moduleTransform, moduleBounds, moduleThickness, - moduleMaterialPtr); + moduleMaterialPtr, + moduleDigitizationPtr); layerStore.push_back(module); // now deal with the potential backside @@ -605,7 +606,8 @@ namespace Generic { moduleTransform, moduleBounds, moduleThickness, - moduleMaterialPtr); + moduleMaterialPtr, + moduleDigitizationPtr); // Put into the detector store layerStore.push_back(std::move(bsmodule)); // register the backside of the binmembers @@ -630,9 +632,9 @@ namespace Generic { layerBinsR *= m_cfg.posnegLayerBinMultipliers.first; } size_t layerBinsPhi = 0; - // take the maximum phi bins in that layer + // take the minimum phi bins in that layer for (unsigned int phiBins : m_cfg.posnegModulePhiBins.at(ipnl)) { - layerBinsPhi = phiBins > layerBinsPhi ? phiBins : layerBinsPhi; + layerBinsPhi = phiBins < layerBinsPhi ? phiBins : layerBinsPhi; layerBinsPhi *= m_cfg.posnegLayerBinMultipliers.second; } // create the layers with the surface arrays diff --git a/Examples/MaterialMapping/src/GeantinoRecordingExample.cpp b/Examples/MaterialMapping/src/GeantinoRecordingExample.cpp index 556e816ccab736e25776004da0da71eccc0acc7c..bff12179e24f35bfe3e01f0254a92bcee2284f36 100644 --- a/Examples/MaterialMapping/src/GeantinoRecordingExample.cpp +++ b/Examples/MaterialMapping/src/GeantinoRecordingExample.cpp @@ -96,7 +96,7 @@ main(int argc, char* argv[]) // Output directory std::string outputDir = vm["output-dir"].template as<std::string>(); - std::stirng matCollection = g4rConfig.geantMaterialCollection; + std::string matCollection = g4rConfig.geantMaterialCollection; if (vm["output-root"].template as<bool>()) { // Write the propagation steps as ROOT TTree diff --git a/Plugins/Txt/CMakeLists.txt b/Plugins/Txt/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..41f6d1b0a49e3ed5ded355f91602a52616eda6c8 --- /dev/null +++ b/Plugins/Txt/CMakeLists.txt @@ -0,0 +1,9 @@ +file(GLOB_RECURSE src_files "src/*.cpp" "include/*.*pp") + +add_library(ACTFWTxtPlugin SHARED ${src_files}) +target_include_directories(ACTFWTxtPlugin PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/> $<INSTALL_INTERFACE:include>) +target_link_libraries(ACTFWTxtPlugin PRIVATE ACTFramework ActsCore ActsDigitizationPlugin IdentificationPlugin) +target_link_libraries(ACTFWTxtPlugin PRIVATE Threads::Threads) + +install(TARGETS ACTFWTxtPlugin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(DIRECTORY include/ACTFW DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtParticleWriter.hpp b/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtParticleWriter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2197b8b13ef5c219ac15958db5a0cbfbc643ffbe --- /dev/null +++ b/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtParticleWriter.hpp @@ -0,0 +1,76 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2017-2018 Acts project team +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include <vector> +#include "ACTFW/Barcode/BarcodeSvc.hpp" +#include "ACTFW/EventData/SimParticle.hpp" +#include "ACTFW/EventData/SimVertex.hpp" +#include "ACTFW/Framework/WriterT.hpp" +#include "Acts/Utilities/Logger.hpp" + +namespace FW { +namespace Txt { + + using SimVertex = Data::SimVertex<Data::SimParticle>; + using ParticleWriter = WriterT<std::vector<Data::SimVertex<>>>; + + /// Write out a the particles associated to a list of process vertices, + /// the particles are in comma-separated-value format. + /// + /// This writer is restricted to outgoing particles, it is designed for + /// generated particle information. + /// + /// This writes one file per event into the configured output directory. By + /// default it writes to the current working directory. + /// Files are named using the following schema + /// + /// event000000001-particles.csv + /// event000000002-particles.csv + /// + /// and each line in the file corresponds to one particle. + class TxtParticleWriter : public ParticleWriter + { + public: + struct Config + { + std::string collection; ///< which collection to write + std::string outputDir; ///< where to place output files + std::string outputTrkFileName; ///< output file name Tracks + std::string outputVtxFileName; ///< output file name Vertices + size_t outputPrecision = 6; ///< floating point precision + + /// the BarcodeSvc to decode + std::shared_ptr<BarcodeSvc> barcodeSvc = nullptr; + + /// try to get the hits per particle map + std::string hitsPerParticleCollection = ""; + }; + + /// constructor + /// @param cfg is the configuration object + /// @parm level is the output logging level + TxtParticleWriter(const Config& cfg, + Acts::Logging::Level level = Acts::Logging::INFO); + + protected: + /// @brief Write method called by the base class + /// @param [in] ctx is the algorithm context for consistency + /// @param [in] vertices is the process vertex collection for the + /// particles to be attached + ProcessCode + writeT(const FW::AlgorithmContext& ctx, + const std::vector<Data::SimVertex<>>& vertices) final override; + + private: + Config m_cfg; //!< Nested configuration struct + }; + +} // namespace Txt +} // namespace FW diff --git a/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtPlanarClusterWriter.hpp b/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtPlanarClusterWriter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f8a8f6bd075934cc707c8568daf203d386fbfb99 --- /dev/null +++ b/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtPlanarClusterWriter.hpp @@ -0,0 +1,63 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2017-2018 Acts project team +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include <Acts/Plugins/Digitization/PlanarModuleCluster.hpp> +#include "ACTFW/Barcode/BarcodeSvc.hpp" +#include "ACTFW/EventData/DataContainers.hpp" +#include "ACTFW/Framework/WriterT.hpp" + +namespace FW { +namespace Txt { + + /// Write out a planar cluster collection in comma-separated-value format. + /// + /// This writes one file per event into the configured output directory. By + /// default it writes to the current working directory. Files are named + /// using the following schema + /// + /// event000000001-hits.csv + /// event000000002-hits.csv + /// + /// and each line in the file corresponds to one hit/cluster. + class TxtPlanarClusterWriter + : public WriterT<DetectorData<geo_id_value, Acts::PlanarModuleCluster>> + { + public: + using Base = WriterT<DetectorData<geo_id_value, Acts::PlanarModuleCluster>>; + + struct Config + { + std::string collection; ///< which collection to write + std::string outputDir; ///< where to place output files + size_t outputPrecision = 6; ///< floating point precision + + /// the BarcodeSvc to decode + std::shared_ptr<BarcodeSvc> barcodeSvc = nullptr; + }; + + /// Constructor with + /// @param cfg configuration struct + /// @param output logging level + TxtPlanarClusterWriter(const Config& cfg, + Acts::Logging::Level level = Acts::Logging::INFO); + + protected: + /// This implementation holds the actual writing method + /// and is called by the WriterT<>::write interface + ProcessCode + writeT(const AlgorithmContext& ctx, + const DetectorData<geo_id_value, Acts::PlanarModuleCluster>& + clusters) final override; + + private: + Config m_cfg; + }; +} // namespace Txt +} // namespace FW diff --git a/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtWriterOptions.hpp b/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtWriterOptions.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c4049bb01c0706cf8de55f510010e1c9fe25f8a5 --- /dev/null +++ b/Plugins/Txt/include/ACTFW/Plugins/Txt/TxtWriterOptions.hpp @@ -0,0 +1,37 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2017 Acts project team +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include <iostream> +#include "ACTFW/Plugins/Txt/TxtSurfaceWriter.hpp" +#include "ACTFW/Plugins/Txt/TxtTrackingGeometryWriter.hpp" +#include "ACTFW/Utilities/Options.hpp" + +namespace po = boost::program_options; + +namespace FW { + +namespace Options { + + // Common Txt writer option + /// + /// @tparam aopt_t Type of the options object (from BOOST) + /// + /// @param opt The options object, where string based options are attached + template <typename aopt_t> + void + addTxtWriterOptions(aopt_t& opt) + { + opt.add_options()("txt-hit-outputPrecission", + po::value<int>()->default_value(6), + "Floating number output precission."); + } + +} // namespace Options +} // namespace FW diff --git a/Plugins/Txt/src/TxtParticleWriter.cpp b/Plugins/Txt/src/TxtParticleWriter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..992896250847e51f405047911ebb7c97ef57c662 --- /dev/null +++ b/Plugins/Txt/src/TxtParticleWriter.cpp @@ -0,0 +1,100 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2017 Acts project team +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "ACTFW/Plugins/Txt/TxtParticleWriter.hpp" +#include <fstream> +#include <ios> +#include <stdexcept> +#include "ACTFW/Barcode/Barcode.hpp" +#include "ACTFW/Framework/WhiteBoard.hpp" +#include "ACTFW/Utilities/Paths.hpp" + +FW::Txt::TxtParticleWriter::TxtParticleWriter( + const FW::Txt::TxtParticleWriter::Config& cfg, + Acts::Logging::Level level) + : ParticleWriter(cfg.collection, "TxtParticleWriter", level), m_cfg(cfg) +{ + if (m_cfg.collection.empty()) { + throw std::invalid_argument("Missing input collection"); + } +} + +FW::ProcessCode +FW::Txt::TxtParticleWriter::writeT( + const FW::AlgorithmContext& ctx, + const std::vector<Data::SimVertex<>>& vertices) +{ + std::string pathOsTrack = perEventFilepath( + m_cfg.outputDir, m_cfg.outputTrkFileName, ctx.eventNumber); + std::ofstream osTrack(pathOsTrack, std::ofstream::out | std::ofstream::trunc); + if (!osTrack) { + throw std::ios_base::failure("Could not open '" + pathOsTrack + + "' to write"); + } + + std::string pathOsVertex = perEventFilepath( + m_cfg.outputDir, m_cfg.outputVtxFileName, ctx.eventNumber); + std::ofstream osVertex(pathOsVertex, + std::ofstream::out | std::ofstream::trunc); + if (!osVertex) { + throw std::ios_base::failure("Could not open '" + pathOsVertex + + "' to write"); + } + + // write csv header + osTrack << std::setw(4) << "trk"; + osTrack << std::setw(4) << "v"; + osTrack << std::setw(9) << "phi"; + osTrack << std::setw(9) << "theta"; + osTrack << std::setw(9) << "pT"; + osTrack << std::setw(4) << "q"; + osTrack << '\n'; + + // write csv header + osVertex << std::setw(4) << "v"; + osVertex << std::setw(9) << "x"; + osVertex << std::setw(9) << "y"; + osVertex << std::setw(9) << "z"; + osVertex << '\n'; + + // write one line per particle + osTrack << std::setprecision(m_cfg.outputPrecision); + for (auto& vertex : vertices) { + bool writeVertex = true; + for (auto& particle : vertex.outgoing()) { + // particle barcode + auto particleBarcode = particle.barcode(); + auto vertexNr = m_cfg.barcodeSvc->vertex(particleBarcode); + if (writeVertex) { + if (abs(vertex.position.z()) < 500.) { + osVertex << std::setw(4) << vertexNr; + osVertex << std::setw(9) << std::setprecision(3) << std::fixed + << vertex.position.x(); + osVertex << std::setw(9) << std::setprecision(3) << std::fixed + << vertex.position.y(); + osVertex << std::setw(9) << std::setprecision(3) << std::fixed + << vertex.position.z(); + osVertex << '\n'; + } + writeVertex = false; + } + auto particleNr = m_cfg.barcodeSvc->primary(particleBarcode); + osTrack << std::setw(4) << particleNr; + osTrack << std::setw(4) << vertexNr; + osTrack << std::setw(9) << std::setprecision(3) << std::fixed + << Acts::VectorHelpers::phi(particle.momentum()); + osTrack << std::setw(9) << std::setprecision(3) << std::fixed + << Acts::VectorHelpers::theta(particle.momentum()); + osTrack << std::setw(9) << std::setprecision(3) << std::fixed + << particle.pT(); + osTrack << std::setw(4) << int(particle.q()); + osTrack << '\n'; + } + } + return ProcessCode::SUCCESS; +} diff --git a/Plugins/Txt/src/TxtPlanarClusterWriter.cpp b/Plugins/Txt/src/TxtPlanarClusterWriter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c05672a5337d403c13919fb5837b50a1bacef6ad --- /dev/null +++ b/Plugins/Txt/src/TxtPlanarClusterWriter.cpp @@ -0,0 +1,117 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2017 Acts project team +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <fstream> +#include <ios> +#include <stdexcept> + +#include <Acts/Plugins/Digitization/PlanarModuleCluster.hpp> +#include "ACTFW/EventData/DataContainers.hpp" +#include "ACTFW/EventData/SimIdentifier.hpp" +#include "ACTFW/EventData/SimParticle.hpp" +#include "ACTFW/EventData/SimVertex.hpp" +#include "ACTFW/Framework/WhiteBoard.hpp" +#include "ACTFW/Plugins/Txt/TxtPlanarClusterWriter.hpp" +#include "ACTFW/Utilities/Paths.hpp" + +FW::Txt::TxtPlanarClusterWriter::TxtPlanarClusterWriter( + const FW::Txt::TxtPlanarClusterWriter::Config& cfg, + Acts::Logging::Level level) + : Base(cfg.collection, "TxtPlanarClusterWriter", level), m_cfg(cfg) +{ + if (m_cfg.collection.empty()) { + throw std::invalid_argument("Missing input collection"); + } +} + +FW::ProcessCode +FW::Txt::TxtPlanarClusterWriter::writeT( + const AlgorithmContext& context, + const FW::DetectorData<geo_id_value, Acts::PlanarModuleCluster>& clusters) +{ + // open per-event hits file + std::string pathHits + = perEventFilepath(m_cfg.outputDir, "hits.txt", context.eventNumber); + std::ofstream osHits(pathHits, std::ofstream::out | std::ofstream::trunc); + if (!osHits) { + throw std::ios_base::failure("Could not open '" + pathHits + "' to write"); + } + + // open per-event truth file + std::string pathTruth + = perEventFilepath(m_cfg.outputDir, "truth.txt", context.eventNumber); + std::ofstream osTruth(pathTruth, std::ofstream::out | std::ofstream::trunc); + if (!osTruth) { + throw std::ios_base::failure("Could not open '" + pathTruth + "' to write"); + } + + auto geoContext = context.geoContext; + + osHits << std::setw(10) << "h"; + osHits << std::setw(10) << "x"; + osHits << std::setw(10) << "y"; + osHits << std::setw(10) << "z"; + osHits << std::setw(5) << "lay"; + osHits << std::setw(5) << "vol"; + osHits << std::setw(6) << "trk"; + osHits << std::setw(9) << "pT"; + osHits << std::setw(4) << "q"; + osHits << std::setw(4) << "v"; // number of hits per track to be added + osHits << '\n'; + + osHits << std::setprecision(3); + + std::map<int, std::map<int, bool>> layerVolumeMap; + + size_t hitId = 0; + for (auto& volumeData : clusters) { + for (auto& layerData : volumeData.second) { + for (auto& moduleData : layerData.second) { + for (auto& cluster : moduleData.second) { + // local cluster information + auto parameters = cluster.parameters(); + Acts::Vector2D local(parameters[Acts::ParDef::eLOC_0], + parameters[Acts::ParDef::eLOC_1]); + Acts::Vector3D pos(0, 0, 0); + Acts::Vector3D mom(1, 1, 1); + // transform local into global position information + cluster.referenceSurface().localToGlobal(geoContext, local, mom, pos); + + // write hit information + osHits << std::setw(10) << std::setprecision(3) << std::fixed + << hitId++; + osHits << std::setw(10) << std::setprecision(3) << std::fixed + << pos.x(); + osHits << std::setw(10) << std::setprecision(3) << std::fixed + << pos.y(); + osHits << std::setw(10) << std::setprecision(3) << std::fixed + << pos.z(); + osHits << std::setw(5) << layerData.first; + osHits << std::setw(5) << volumeData.first; + + /// Hit identifier + auto hitIdentifier = cluster.sourceLink(); + // write hit-particle truth association + // each hit can have multiple particles, e.g. in a dense environment + for (auto& sPartilce : hitIdentifier.truthParticles()) { + auto particleBarcode = sPartilce->barcode(); + osHits << std::setw(6) + << m_cfg.barcodeSvc->primary(particleBarcode); + osHits << std::setw(9) << std::setprecision(3) << std::fixed + << sPartilce->pT(); + osHits << std::setw(4) << int(sPartilce->q()); + osHits << std::setw(4) << m_cfg.barcodeSvc->vertex(particleBarcode); + } + osHits << '\n'; + } + } + } + } + + return FW::ProcessCode::SUCCESS; +}