diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0aef82debb458e44c3b9bfa1dceb4d2f79548bee..521e9b519646214a6154fc49f8195c60ed6806b2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,10 +16,11 @@ build_image: # description: triggers a build of the project as a Docker image, # each branch will have an individual Docker image that will be used # in the following stages of the pipeline for testing the code + image: + name: gitlab-registry.cern.ch/linuxsupport/cc7-base:latest stage: build tags: - - cvmfs - - docker + - k8s-cvmfs script: - yum -y install redhat-lsb redhat-lsb-core man uuid-devel libuuid libuuid-devel mesa-libGL-devel libXpm-devel - mkdir build @@ -33,12 +34,13 @@ build_image: - build/ test_unittest: + image: + name: gitlab-registry.cern.ch/linuxsupport/cc7-base:latest stage: test tags: - - cvmfs - - docker + - k8s-cvmfs script: - - yum -y install man + - yum -y install man git make cmake3 gcc-c++ gcc binutils libX11-devel libXpm-devel libXft-devel libXext-devel python openssl-devel - cd build - set +e && source ${ATLAS_LOCAL_ROOT_BASE}/user/atlasLocalSetup.sh; set -e - set +e && asetup --input=../../calypso/asetup.faser Athena,22.0.49; set -e @@ -46,3 +48,6 @@ test_unittest: - ctest -j3 dependencies: - build_image + artifacts: + paths: + - LastTest.log diff --git a/Control/CalypsoExample/TruthEventDumper/python/TruthEventDumperAlg.py b/Control/CalypsoExample/TruthEventDumper/python/TruthEventDumperAlg.py index 934433e2f375d6f0883a5a66e66dba70f1515427..8986c1165ece677bb37a42998bc2e0d05642cd8e 100644 --- a/Control/CalypsoExample/TruthEventDumper/python/TruthEventDumperAlg.py +++ b/Control/CalypsoExample/TruthEventDumper/python/TruthEventDumperAlg.py @@ -36,4 +36,4 @@ class TruthEventDumperAlg(PyAthena.Alg): # print("Mid part: ", self.maxMid, " out of ", 1000000 - 200000, " (",100*self.maxMid/(1000000-200000),"% of overflow") # print("Hi part: ", self.maxHi, " out of ", (1<<31)//1000000, " (", 100*self.maxHi/((1<<31)//1000000),"% of overflow") - return StatusCode.Success \ No newline at end of file + return StatusCode.Success diff --git a/Generators/TestBeamReader/CMakeLists.txt b/Generators/TestBeamReader/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..64e5ec13d29414fcbf2468e64170029a8cf6c44b --- /dev/null +++ b/Generators/TestBeamReader/CMakeLists.txt @@ -0,0 +1,11 @@ +################################################################################ +# Package: ReadTestBeam +################################################################################ + +# Declare the package name: +atlas_subdir( TestBeamReader ) + +# Install files from the package: +atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} ) + +atlas_install_joboptions( share/*.py ) \ No newline at end of file diff --git a/Generators/TestBeamReader/python/TestBeamReaderAlgH2_CMS.py b/Generators/TestBeamReader/python/TestBeamReaderAlgH2_CMS.py new file mode 100644 index 0000000000000000000000000000000000000000..959242ab0aaa0639c672ba669b9c16400f5f726d --- /dev/null +++ b/Generators/TestBeamReader/python/TestBeamReaderAlgH2_CMS.py @@ -0,0 +1,95 @@ +# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.AppMgr import ServiceMgr as svcMgr +from GeneratorModules.EvgenAlg import EvgenAlg +from AthenaPython.PyAthena import StatusCode, EventInfo, EventID, EventType +from AthenaCommon.SystemOfUnits import GeV, m +import ROOT +import math + + +class TestBeamReader(EvgenAlg): + def __init__(self, name="TestBeamReader", MCEventKey="BeamTruthEvent"): + super(TestBeamReader,self).__init__(name=name) + self.McEventKey = MCEventKey + return + + def fillEvent(self, evt): + try: + from AthenaPython.PyAthena import HepMC3 as HepMC + except ImportError: + from AthenaPython.PyAthena import HepMC as HepMC + evt.weights().push_back(1.0) + eventNumber = 0 + treeEventId = 0 + runNumber = 100 + mcEventType = EventType() + mcEventType.add_type(EventType.IS_SIMULATION) + + mcEventId = EventID(run_number = runNumber, event_number = eventNumber) + mcEventInfo = EventInfo(id = mcEventId, type = mcEventType) + self.evtStore.record(mcEventInfo, "McEventInfo", True, False) + ROOT.SetOwnership(mcEventType, False) + ROOT.SetOwnership(mcEventId, False) + ROOT.SetOwnership(mcEventInfo, False) + pos = HepMC.FourVector(13.8*0.001*m, 22.7*0.001*m, 0*m, 0) + gv = HepMC.GenVertex(pos) + ROOT.SetOwnership(gv, False) + evt.add_vertex(gv) + + nParticles = list(self.evtStore["N"]) + + pdgclol = list(self.evtStore["vecPDG"]) + px =list(self.evtStore["vecPx"]) + py = list(self.evtStore["vecPy"]) + pz = list(self.evtStore["vecPz"]) + + for i in range(nParticles[0]): + gp = HepMC.GenParticle() + pdgc = int() + + pdgc = math.floor(pdgclol[i]) + if (pdgc ==-11 or pdgc ==11): + M = (0.511*0.001) + elif (pdgc == 22): + M = 0.0 + else: + M = 0.0 + E = math.sqrt(((px[i])*(px[i]))+((py[i])*(py[i]))+((pz[i])*(pz[i]))+((M)*(M))) + mom = HepMC.FourVector(px[i]*0.001*GeV, py[i]*0.001*GeV, pz[i]*0.001*GeV, E*0.001*GeV) + gp.set_momentum(mom) + gp.set_generated_mass(M*GeV) + gp.set_pdg_id(pdgc) + + hepmc_status = 4 + gp.set_status(hepmc_status) + ROOT.SetOwnership(gp, False) + gv.add_particle_in(gp) + + + + for i in range(nParticles[0]): + gp = HepMC.GenParticle() + + pdgc = int() + pdgc = math.floor(pdgclol[i]) + if (pdgc ==-11 or pdgc ==11): + M = (0.511*0.001) + elif (pdgc == 22): + M = 0.0 + else: + M = 0.0 + E = math.sqrt(((px[i])*(px[i]))+((py[i])*(py[i]))+((pz[i])*(pz[i]))+((M)*(M))) + mom = HepMC.FourVector(px[i]*0.001*GeV, py[i]*0.001*GeV, pz[i]*0.001*GeV, E*0.001*GeV) + gp.set_momentum(mom) + gp.set_generated_mass(M*GeV) + gp.set_pdg_id(pdgc) + + hepmc_status = 1 + gp.set_status(hepmc_status) + ROOT.SetOwnership(gp, False) + + gv.add_particle_out(gp) + + + return StatusCode.Success diff --git a/Generators/TestBeamReader/python/__init__.py b/Generators/TestBeamReader/python/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d13ae164caa4e93bf2899cea4e67d0ec515784a2 --- /dev/null +++ b/Generators/TestBeamReader/python/__init__.py @@ -0,0 +1 @@ +# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration diff --git a/Generators/TestBeamReader/share/Numpy_H2.py b/Generators/TestBeamReader/share/Numpy_H2.py new file mode 100644 index 0000000000000000000000000000000000000000..9644c3d584d8157b8aa6b1acdcba8d1b7fad5b32 --- /dev/null +++ b/Generators/TestBeamReader/share/Numpy_H2.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +# Set up (Py)ROOT. +import ROOT +import datetime +from array import array +import math +import datetime +import pickle +import pandas +import uproot3 +import uproot +import numpy as np +import awkward as ak +t1 = uproot3.open("/eos/project/f/faser-preshower/simulations/H2_beamline/1M_events/FASER_e-_v46_80GeV.root")["NTuples/GoodParticle"] + + +FASERdf= t1.pandas.df(["FASER_Px", "FASER_Py","FASER_Pz" ,"FASER_PDGid", "FASER_EventID", "FASER_x", "FASER_y"] ) +pandas.set_option("display.max_rows", None, "display.max_columns", None) + + +FASERdf_new = FASERdf.groupby('FASER_EventID').agg(list) + + +FASERdf_new =FASERdf_new.drop(FASERdf_new.index[0]) + + +data = {key: FASERdf_new[key].values for key in [ "FASER_Px", "FASER_Py","FASER_Pz" ,"FASER_PDGid", "FASER_x", "FASER_y"]} + +a = ak.Array(data["FASER_Px"]) +print(a) +#ta =a +b = ak.Array(data["FASER_Py"]) +print(b) +c = ak.Array(data["FASER_Pz"]) +print(c) +d = ak.Array(data["FASER_PDGid"]) +print(d) +e = ak.Array(data["FASER_x"]) +print(e) +f = ak.Array(data["FASER_y"]) +print(f) + +with uproot.recreate("80GeV_first.root") as rootfile: + rootfile["tree1"] = ak.zip({"FASER_Px": a, "FASER_Py": b, "FASER_Pz": c, "FASER_PDGid":d, "FASER_x":e, "FASER_y": f}) + +f = ROOT.TFile.Open("80GeV_e-_calypso_H2input.root", "recreate") +t = ROOT.TTree("t","t") + +f1 = ROOT.TFile("80GeV_first.root") +tree1 = f1.Get("tree1") + + + + +vecPx = ROOT.std.vector(float)() +vecPy = ROOT.std.vector(float)() +vecPz = ROOT.std.vector(float)() +vecPDG = ROOT.std.vector(float)() +Num = ROOT.std.vector(int)() +t.Branch("vecPx", vecPx) +t.Branch("vecPy", vecPy) +t.Branch("vecPz", vecPz) +t.Branch("vecPDG", vecPDG) +t.Branch("N", Num) +print(tree1.GetEntries()) +for x in range(tree1.GetEntries()): + tree1.GetEntry(x) + px= list(tree1.FASER_Px) + py= list(tree1.FASER_Py) + pz=list(tree1.FASER_Pz) + pdg=list(tree1.FASER_PDGid) + n = (tree1.n) + j = 0 + vecPx.clear() + vecPy.clear() + vecPz.clear() + vecPDG.clear() + Num.clear() + for j in range(n): + vecPx.push_back(px[j]) + vecPy.push_back(py[j]) + vecPz.push_back(pz[j]) + vecPDG.push_back(pdg[j]) + Num.push_back(n) + t.Fill() + + +f.Write() +f.Close() diff --git a/Generators/TestBeamReader/share/TestBeamReader_jobOptionsH2_CMS.py b/Generators/TestBeamReader/share/TestBeamReader_jobOptionsH2_CMS.py new file mode 100644 index 0000000000000000000000000000000000000000..3656ceefec3cfa79d329341d492e2f9c7e0e0e29 --- /dev/null +++ b/Generators/TestBeamReader/share/TestBeamReader_jobOptionsH2_CMS.py @@ -0,0 +1,39 @@ +# +# Usage: athena.py -c'INPUT=["/eos/project/f/faser-preshower/simulations/H2_beamline/1M_events/FASER_e-_v46_100GeV.root"]; OUTPUT="100GeV.H2.EVNT.pool.root"' TestBeamReader/TestBeamReader_jobOptionsH2_CMS.py +# INPUT and OUTPUT are mandatory (INPUT can be a list, as shown above) +# EVTMAX can be omitted; then all input files are read to the end +# + +if not 'INPUT' in dir(): + print("Missing INPUT parameter") + exit() + +if not isinstance(INPUT, (list,tuple)): + INPUT = [INPUT] + pass + +if not 'OUTPUT' in dir(): + print("Missing OUTPUT parameter") + exit() + +import AthenaRootComps.ReadAthenaRoot + +svcMgr.EventSelector.InputCollections = INPUT +svcMgr.EventSelector.TupleName = "t" + +from TestBeamReader.TestBeamReaderAlgH2_CMS import TestBeamReader + +from AthenaCommon.AlgSequence import AlgSequence +job = AlgSequence() +job += TestBeamReader() + +from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream +ostream = AthenaPoolOutputStream( "StreamEVGEN" , OUTPUT, noTag=True ) +ostream.ItemList.remove("EventInfo#*") +ostream.ItemList += [ "EventInfo#McEventInfo", + "McEventCollection#*" ] +print(ostream.ItemList) +if not 'EVTMAX' in dir(): + EVTMAX = -1 + +theApp.EvtMax = EVTMAX diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx index 1fc059dc4de07df69f939839e78e3b7e2cea627e..0e88d1e46f6d84ed87bda1b669c9f4ca35aa3ea6 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx @@ -225,6 +225,9 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("longTracks", &m_longTracks, "longTracks/I"); m_tree->Branch("Track_Chi2", &m_Chi2); m_tree->Branch("Track_nDoF", &m_DoF); + m_tree->Branch("Track_module_eta0", &m_module_eta0); + m_tree->Branch("Track_module_phi0", &m_module_phi0); + m_tree->Branch("Track_hitSet", &m_hitSet); m_tree->Branch("Track_x0", &m_xup); m_tree->Branch("Track_y0", &m_yup); m_tree->Branch("Track_z0", &m_zup); @@ -912,16 +915,20 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const std::set<std::pair<int, int>> layerMap; std::set<int> stationMap; // Check for hit in the three downstream stations + HitSet hitSet {24}; for (auto measurement : *(track->measurementsOnTrack())) { const Tracker::FaserSCT_ClusterOnTrack* cluster = dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*>(measurement); if (cluster != nullptr) { Identifier id = cluster->identify(); int station = m_sctHelper->station(id); int layer = m_sctHelper->layer(id); + int side = m_sctHelper->side(id); stationMap.emplace(station); layerMap.emplace(station, layer); + hitSet.set(23 - (station * 6 + layer * 2 + side)); } } + m_hitSet.push_back(hitSet.to_ulong()); if (stationMap.count(1) == 0 || stationMap.count(2) == 0 || stationMap.count(3) == 0) continue; const Trk::TrackParameters* upstreamParameters = track->trackParameters()->front(); @@ -933,6 +940,12 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const m_Chi2.push_back(track->fitQuality()->chiSquared()); m_DoF.push_back(track->fitQuality()->numberDoF()); + const Trk::MeasurementBase *measurement = track->measurementsOnTrack()->front(); + const Tracker::FaserSCT_ClusterOnTrack* cluster = + dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack*>(measurement); + Identifier id = cluster->identify(); + m_module_eta0.push_back(m_sctHelper->eta_module(id)); + m_module_phi0.push_back(m_sctHelper->phi_module(id)); m_nHit0.push_back(stationMap.count(0)); m_nHit1.push_back(stationMap.count(1)); @@ -1418,6 +1431,9 @@ NtupleDumperAlg::clearTree() const m_Chi2.clear(); m_DoF.clear(); + m_module_eta0.clear(); + m_module_phi0.clear(); + m_hitSet.clear(); m_charge.clear(); m_nLayers.clear(); m_longTracks = 0; diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h index 475378c18625a5c359c4f8c8ef8d52e48ee96c87..a741bcbe55097ba754a256fe3804f0e6cc170db9 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h @@ -24,10 +24,13 @@ #include "xAODEventInfo/EventInfo.h" #include "StoreGate/ReadDecorHandle.h" #include "FaserActsVertexing/IVertexingTool.h" +#include <boost/dynamic_bitset.hpp> #include <vector> #include <nlohmann/json.hpp> +using HitSet = boost::dynamic_bitset<>; + class TTree; class TH1; class FaserSCT_ID; @@ -225,6 +228,9 @@ private: mutable int m_longTracks; mutable int m_propagationError; + mutable std::vector<int> m_module_eta0; + mutable std::vector<int> m_module_phi0; + mutable std::vector<unsigned long> m_hitSet; mutable std::vector<double> m_Chi2; mutable std::vector<double> m_DoF; mutable std::vector<double> m_xup; diff --git a/Tracking/Acts/FaserActsGeometry/CMakeLists.txt b/Tracking/Acts/FaserActsGeometry/CMakeLists.txt index e15adcec74c6efaee85c11e388517683262c6522..58c40ebec78ecb3ab4585b9dc744392c4aa19042 100755 --- a/Tracking/Acts/FaserActsGeometry/CMakeLists.txt +++ b/Tracking/Acts/FaserActsGeometry/CMakeLists.txt @@ -56,6 +56,8 @@ atlas_add_component( FaserActsGeometry src/FaserActsAlignmentCondAlg.cxx src/NominalAlignmentCondAlg.cxx src/FaserActsVolumeMappingTool.cxx + src/FaserActsGeometryBoundaryTestAlg.h + src/FaserActsGeometryBoundaryTestAlg.cxx src/components/*.cxx PUBLIC_HEADERS FaserActsGeometry INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS} @@ -84,3 +86,7 @@ atlas_install_headers( FaserActsGeometry ) atlas_install_python_modules( python/*.py ) atlas_install_scripts( test/*.py ) +atlas_add_test( FaserActsGeometryBoundary_test + SCRIPT python ${CMAKE_CURRENT_SOURCE_DIR}/test/FaserActsGeometryBoundary_test.py + PROPERTIES WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + PROPERTIES TIMEOUT 300 ) diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsGeometryBoundaryTestAlg.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsGeometryBoundaryTestAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..57c1e3a2fe68bea133d167ea00dd539edfc0f3fe --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsGeometryBoundaryTestAlg.cxx @@ -0,0 +1,97 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS and FASER collaborations +*/ + + +#include "FaserActsGeometryBoundaryTestAlg.h" +#include "FaserActsGeometry/FaserActsGeometryContext.h" +#include "Acts/Surfaces/Surface.hpp" +#include "Acts/Surfaces/PlaneSurface.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Geometry/DetectorElementBase.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" + + +FaserActsGeometryBoundaryTestAlg::FaserActsGeometryBoundaryTestAlg(const std::string &name, ISvcLocator *pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator) {} + + +StatusCode FaserActsGeometryBoundaryTestAlg::initialize() { + ATH_CHECK(m_trackingGeometryTool.retrieve()); + return StatusCode::SUCCESS; +} + + +StatusCode FaserActsGeometryBoundaryTestAlg::execute(const EventContext &ctx) const { + + std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry + = m_trackingGeometryTool->trackingGeometry(); + + const Acts::GeometryContext gctx = + m_trackingGeometryTool->getGeometryContext(ctx).context(); + + // loop over all tracking layer and check if contained detector elements are insie boundaries + // return StatusCode::Failure so that test fails, if the edge of any detector element is outside boundaries + const Acts::TrackingVolume *trackingVolume = trackingGeometry->highestTrackingVolume(); + for (auto volume : trackingVolume->confinedVolumes()->arrayObjects()) { + for (const auto& layer : volume->confinedLayers()->arrayObjects()) { + if (layer->layerType() == Acts::LayerType::active) { + // get inner and outer boundaries from approach descriptor: + // - innerBoundary is approach suface with minimum z position + // - outerBoundary is approach suface with maximum z position + Acts::SurfaceVector approachSurfaces = layer->approachDescriptor()->containedSurfaces(); + const Acts::Surface *innerApproachSurface = *std::min_element( + approachSurfaces.begin(), approachSurfaces.end(), + [&gctx](const auto &lhs, const auto &rhs) { + return lhs->center(gctx).z() < rhs->center(gctx).z(); + } + ); + const Acts::Surface *outerApproachSurface = *std::max_element( + approachSurfaces.begin(), approachSurfaces.end(), + [&gctx](const auto &lhs, const auto &rhs) { + return lhs->center(gctx).z() < rhs->center(gctx).z(); + } + ); + double zInnerBoundary = innerApproachSurface->center(gctx).z(); + double zOuterBoundary = outerApproachSurface->center(gctx).z(); + + // loop over surface array and check if all edges are between inner and outer boundary + for (const Acts::Surface *surface : layer->surfaceArray()->surfaces()) { + auto planeSurface = dynamic_cast<const Acts::PlaneSurface *>(surface); + // make sure surface has a associated detector element (there are other active detector elements + // e.g. containing material or at the tracking volume boundaries) + if (surface->associatedDetectorElement() != nullptr) { + auto bounds = dynamic_cast<const Acts::RectangleBounds*>(&surface->bounds()); + const Acts::Vector2 min = bounds->min(); + const Acts::Vector2 max = bounds->max(); + // create dummpy momentum vector: local to global transformation requires momentum vector, + // which is ignored for PlaneSurface + Acts::Vector3 dummyMomentum {1., 1., 1.}; + // get global position at all edges of the surface + std::vector<Acts::Vector3> edges {}; + edges.push_back(planeSurface->localToGlobal(gctx, {min.x(), min.y()}, dummyMomentum)); + edges.push_back(planeSurface->localToGlobal(gctx, {min.x(), max.y()}, dummyMomentum)); + edges.push_back(planeSurface->localToGlobal(gctx, {max.x(), min.y()}, dummyMomentum)); + edges.push_back(planeSurface->localToGlobal(gctx, {max.x(), max.y()}, dummyMomentum)); + for (const Acts::Vector3 &edgePosition : edges) { + if ((edgePosition.z() < zInnerBoundary) || (edgePosition.z() > zOuterBoundary)) { + std::cout << "?? surface outside boundaries\n"; + std::cout << "inner Boundary: " << zInnerBoundary << std::endl; + std::cout << "outer Boundary: " << zOuterBoundary << std::endl; + std::cout << "edge: " << edgePosition.x() << ", " << edgePosition.y() << ", " << edgePosition.z() << std::endl; + return StatusCode::FAILURE; + } + } + } + } + } + } + } + + return StatusCode::SUCCESS; +} + +StatusCode FaserActsGeometryBoundaryTestAlg::finalize() { + return StatusCode::SUCCESS; +} diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsGeometryBoundaryTestAlg.h b/Tracking/Acts/FaserActsGeometry/src/FaserActsGeometryBoundaryTestAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..b2c0bf3c73b35ac1d0b9857a8c0aae72cfb3c56c --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsGeometryBoundaryTestAlg.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS and FASER collaborations +*/ + +#ifndef FASERACTSGEOMETRY_FASERACTSGEOMETRYBOUNDARYTESTALG_H +#define FASERACTSGEOMETRY_FASERACTSGEOMETRYBOUNDARYTESTALG_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" + + +class FaserActsGeometryBoundaryTestAlg : public AthReentrantAlgorithm { +public: + FaserActsGeometryBoundaryTestAlg(const std::string &name, ISvcLocator *pSvcLocator); + virtual StatusCode initialize() override final; + virtual StatusCode execute(const EventContext &ctx) const override final; + virtual StatusCode finalize() override final; + +private: + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool { + this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; +}; + + +#endif // FASERACTSGEOMETRY_FASERACTSGEOMETRYBOUNDARYTESTALG_H \ No newline at end of file diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsLayerBuilder.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsLayerBuilder.cxx index c5f6a68ab01b8da95f3d62149d23bdf41684263d..649f2503cb69c93b96b8e454727998656898eccf 100644 --- a/Tracking/Acts/FaserActsGeometry/src/FaserActsLayerBuilder.cxx +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsLayerBuilder.cxx @@ -206,7 +206,8 @@ FaserActsLayerBuilder::buildLayers(const Acts::GeometryContext& gctx, std::shared_ptr<const Acts::ProtoSurfaceMaterial> materialProxy = nullptr; double layerZ = 0.5 * (pl.min(Acts::binZ) + pl.max(Acts::binZ)); - double layerThickness = (pl.max(Acts::binZ) - pl.min(Acts::binZ)); + // increase layerThickness by 4 mm so that after alignment shifts all modules are still within the boundaries + double layerThickness = (pl.max(Acts::binZ) - pl.min(Acts::binZ)) + 4_mm; double layerZInner = layerZ - layerThickness/2.; double layerZOuter = layerZ + layerThickness/2.; diff --git a/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx b/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx index e7b7fb2fe49208911b0d98c2ba4a6d6b960df89f..a103c7a9466eb66446036cc2978e82dba8889fee 100755 --- a/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx +++ b/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx @@ -16,6 +16,7 @@ #include "../FaserActsMaterialMapping.h" #include "../FaserActsSurfaceMappingTool.h" #include "../FaserActsMaterialTrackWriterSvc.h" +#include "../FaserActsGeometryBoundaryTestAlg.h" DECLARE_COMPONENT( FaserActsTrackingGeometrySvc ) DECLARE_COMPONENT( FaserActsTrackingGeometryTool ) @@ -30,3 +31,4 @@ DECLARE_COMPONENT( FaserActsMaterialJsonWriterTool ) DECLARE_COMPONENT( FaserActsMaterialTrackWriterSvc ) DECLARE_COMPONENT( FaserActsMaterialMapping ) DECLARE_COMPONENT( FaserActsSurfaceMappingTool ) +DECLARE_COMPONENT( FaserActsGeometryBoundaryTestAlg ) diff --git a/Tracking/Acts/FaserActsGeometry/test/FaserActsGeometryBoundary_test.py b/Tracking/Acts/FaserActsGeometry/test/FaserActsGeometryBoundary_test.py new file mode 100644 index 0000000000000000000000000000000000000000..b6a841642b17b6ecd412fc55ced498524ece9ca5 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/test/FaserActsGeometryBoundary_test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +""" +Copyright (C) 2002-2023 CERN for the benefit of the ATLAS and FASER collaboration +""" + + +def FaserActsGeometryBoundaryTestCfg(flags, name="FaserActsGeometryBoundaryTestAlg", **kwargs): + + from FaserSCT_GeoModel.FaserSCT_GeoModelConfig import FaserSCT_GeometryCfg + from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg + from FaserActsGeometry.ActsGeometryConfig import ActsTrackingGeometryToolCfg + from AthenaConfiguration.ComponentFactory import CompFactory + + acc = FaserSCT_GeometryCfg(flags) + acc.merge(MagneticFieldSvcCfg(flags)) + result, actsTrackingGeometryTool = ActsTrackingGeometryToolCfg(flags) + test_alg = CompFactory.FaserActsGeometryBoundaryTestAlg + test_alg.TrackingGeometryTool = actsTrackingGeometryTool + acc.merge(result) + acc.addEventAlgo(test_alg(name, **kwargs)) + return acc + + +if __name__ == "__main__": + + import sys + from AthenaCommon.Configurable import Configurable + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + from CalypsoConfiguration.MainServicesConfig import MainServicesCfg + from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg + + Configurable.configurableRun3Behavior = True + ConfigFlags.Input.isMC = False + ConfigFlags.GeoModel.Align.Dynamic = False + ConfigFlags.IOVDb.DatabaseInstance = "CONDBR3" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-04" + ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" + ConfigFlags.Detector.GeometryFaserSCT = True + ConfigFlags.lock() + + acc = MainServicesCfg(ConfigFlags) + acc.merge(FaserGeometryCfg(ConfigFlags)) + acc.merge(FaserActsGeometryBoundaryTestCfg(ConfigFlags)) + + replicaSvc = acc.getService("DBReplicaSvc") + replicaSvc.COOLSQLiteVetoPattern = "" + replicaSvc.UseCOOLSQLite = True + replicaSvc.UseCOOLFrontier = False + replicaSvc.UseGeomSQLite = True + + sys.exit(int(acc.run(maxEvents=1).isFailure()))