diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..99a3531c48cdaaf7512ffab7b543a15ecad8181f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,60 @@ + + +dist: bionic + +services: + - docker + +language: cpp + +env: + matrix: + - COMPILER=gcc; LCG_RELEASE=LCG_96c_LS; STANDARD=17; COMPILER_VERSION=gcc8; + +before_install: + - wget --no-check-certificate https://ecsft.cern.ch/dist/cvmfs/cvmfs-release/cvmfs-release-latest_all.deb + - sudo dpkg -i cvmfs-release-latest_all.deb + - sudo apt-get update + - sudo apt-get install cvmfs cvmfs-config-default + - rm -f cvmfs-release-latest_all.deb + - sudo mkdir -p /etc/cvmfs + - echo "CVMFS_QUOTA_LIMIT='32140'" | sudo tee /etc/cvmfs/default.local > /dev/null + - echo "CVMFS_HTTP_PROXY=DIRECT" | sudo tee -a /etc/cvmfs/default.local > /dev/null + - echo "CVMFS_CACHE_BASE='/var/lib/cvmfs'" | sudo tee -a /etc/cvmfs/default.local > /dev/null + - echo "CVMFS_FORCE_SIGNING='yes'" | sudo tee -a /etc/cvmfs/default.local > /dev/null + - echo "CVMFS_REPOSITORIES='sft.cern.ch,sw-nightlies.hsf.org'" | sudo tee -a /etc/cvmfs/default.local > /dev/null + - echo "CVMFS_SEND_INFO_HEADER=no" | sudo tee -a /etc/cvmfs/default.local > /dev/null + - cat /etc/cvmfs/default.local + - # change wrt dd4hep setup: don't manually mount cvmfs folders + - #sudo /etc/init.d/autofs stop + - sudo cvmfs_config setup + - sudo cvmfs_config probe + - sudo mkdir -p /cvmfs/sft.cern.ch + - sudo mkdir -p /cvmfs/sft-nightlies.cern.ch + - sudo mkdir -p /cvmfs/geant4.cern.ch + - sudo mkdir -p /cvmfs/sw-nightlies.hsf.org + - ls /cvmfs/sft.cern.ch + - ls /cvmfs/geant4.cern.ch + - ls /cvmfs/sw-nightlies.hsf.org + - export CVMFS_REPOS="-v /cvmfs/sft.cern.ch:/cvmfs/sft.cern.ch" + - export CVMFS_REPOS="${CVMFS_REPOS} -v /cvmfs/sw-nightlies.hsf.org:/cvmfs/sw-nightlies.hsf.org" + - export CVMFS_REPOS="${CVMFS_REPOS} -v /cvmfs/geant4.cern.ch:/cvmfs/geant4.cern.ch" + + +# command to install dependencies +install: + - shopt -s extglob dotglob + - mkdir package + - mv !(package) package + - shopt -u dotglob + - export PKGDIR=${PWD}/package + +# command to run tests +script: + - docker run -ti --name CI_CONTAINER -v $PKGDIR:/workspace -e COMPILER_TYPE=$COMPILER -e LCG_RELEASE=${LCG_RELEASE} -e STANDARD=${STANDARD} -e COMPILER_VERSION=${COMPILER_VERSION} ${CVMFS_REPOS} -d clicdp/cc7-lcg bash + - docker exec -ti CI_CONTAINER /bin/bash -c "cd /workspace; ln -s /usr/lib64/liblzma.so.5.2.2 /usr/lib64/liblzma.so; echo 'hello world'" + + +# Don't send e-mail notifications +notifications: + email: false diff --git a/CMakeLists.txt b/CMakeLists.txt index afa6f8d043bc91b34583734d4c4eabcccf7b0ae2..f5534af8ba553e8f2c4d65f38a203c53bc5bbc00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,19 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0) +find_package(ROOT COMPONENTS RIO Tree) + find_package(GaudiProject) -gaudi_project(CEPCSW HEAD - USE Gaudi v29r2 ) \ No newline at end of file +# Set up C++ Standard +# ``-DCMAKE_CXX_STANDARD=<standard>`` when invoking CMake +set(CMAKE_CXX_STANDARD 17 CACHE STRING "") + +if(NOT CMAKE_CXX_STANDARD MATCHES "14|17") + message(FATAL_ERROR "Unsupported C++ standard: ${CMAKE_CXX_STANDARD}") +endif() + + +gaudi_project(CEPCSW v0r1 + USE Gaudi v33r1 + USE K4FWCore v0r1 +) \ No newline at end of file diff --git a/Detector/DetCEPCv4/CMakeLists.txt b/Detector/DetCEPCv4/CMakeLists.txt index 8d245fbd7245610a0bbb8648822399085c06105c..ff3a8a705aaac03ca036e80d14e4a045fed91286 100644 --- a/Detector/DetCEPCv4/CMakeLists.txt +++ b/Detector/DetCEPCv4/CMakeLists.txt @@ -9,6 +9,7 @@ gaudi_depends_on_subdirs(GaudiKernel) find_package(DD4hep COMPONENTS DDRec DDG4 DDParsers REQUIRED) +# find_package(DD4hep) find_package(Geant4) include(${Geant4_USE_FILE}) @@ -25,14 +26,28 @@ set(DetCEPCv4_src src/tracker/SIT_Simple_Pixel_geo.cpp src/tracker/TPC10_geo.cpp src/tracker/SET_Simple_Planar_geo.cpp + src/calorimeter/SEcal05_Helpers.cpp + src/calorimeter/SEcal05_Barrel.cpp + src/calorimeter/SEcal05_Endcaps.cpp + src/calorimeter/SEcal05_ECRing.cpp src/other/BoxSupport_o1_v01_geo.cpp src/other/TubeSupport_o1_v01_geo.cpp ) gaudi_add_module(DetCEPCv4 ${DetCEPCv4_src} - INCLUDE_DIRS DD4hep ROOT Geant4 src/include - LINK_LIBRARIES GaudiKernel DD4hep ${DD4hep_COMPONENT_LIBRARIES} ROOT Geant4) + INCLUDE_DIRS + # DD4hep + # ROOT + # Geant4 + src/include + LINK_LIBRARIES + # GaudiKernel + DD4hep + ${DD4hep_COMPONENT_LIBRARIES} + # ROOT + # Geant4 +) set(LIBRARY_OUTPUT_PATH ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) message(STATUS "LIBRARY_OUTPUT_PATH -> ${LIBRARY_OUTPUT_PATH}") diff --git a/Detector/DetCEPCv4/compact/CepC_v4-onlyECAL.xml b/Detector/DetCEPCv4/compact/CepC_v4-onlyECAL.xml new file mode 100644 index 0000000000000000000000000000000000000000..c24218a84234c2c90d31759f166de1845c82f49a --- /dev/null +++ b/Detector/DetCEPCv4/compact/CepC_v4-onlyECAL.xml @@ -0,0 +1,77 @@ +<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> + <info name="CepC_v04" + title="CepC detctor used for the optimisation" + author="C.D.Fu" + url="http://cepc.ihep.ac.cn" + status="experimental" + version="v04"> + <comment>CepC detector simulation models used for detector optimisation </comment> + </info> + <includes> + <gdmlFile ref="elements.xml"/> + <gdmlFile ref="materials.xml"/> + </includes> + <define> + <include ref="top_defs_CepC_v04.xml"/> + <include ref="top_defs.xml"/> + <include ref="basic_defs.xml"/> + <include ref="envelope_defs.xml"/> + <include ref="tube_defs.xml"/> + <include ref="misc_defs.xml"/> + <include ref="tracker_defs.xml"/> + <include ref="fcal_defs.xml"/> + <include ref="ecal_defs.xml"/> + <include ref="hcal_defs.xml"/> + <include ref="yoke_defs.xml"/> + <include ref="services_defs.xml"/> + <include ref="${DD4hepINSTALL}/DDDetectors/compact/detector_types.xml"/> + <include ref="limits.xml"/> + <!-- Readout slice in ecal for reconstruction --> + <constant name="Ecal_readout_segmentation_slice0" value="4"/> + <constant name="Ecal_readout_segmentation_slice1" value="10"/> + <!-- Readout slice in hcal for reconstruction --> + <constant name="Hcal_readout_segmentation_slice" value="3"/> + </define> + <limits> + <limitset name="cal_limits"> + <limit name="step_length_max" particles="*" value="cal_steplimit_val" unit="cal_steplimit_unit" /> + </limitset> + <limitset name="TPC_limits"> + <limit name="step_length_max" particles="*" value="tpc_steplimit_val" unit="tpc_steplimit_unit" /> + </limitset> + <limitset name="Tracker_limits"> + <limit name="step_length_max" particles="*" value="tracker_steplimit_val" unit="tracker_steplimit_unit" /> + </limitset> + </limits> + <include ref="display.xml"/> + <!-- <include ref="Beampipe_o1_v01_01.xml"/> --> + <!-- <include ref="vxd07.xml"/> --> + <!-- <include ref="ftd_simple_staggered_02.xml"/> --> + <!-- <include ref="sit_simple_pixel_sensors_01.xml"/> --> + <!-- <include ref="tpc10_01.xml"/> --> + <!-- <include ref="set_simple_planar_sensors_01.xml"/> --> + <include ref="SEcal05_siw_Barrel.xml"/> + <include ref="SEcal05_siw_Endcaps.xml"/> + <include ref="SEcal05_siw_ECRing.xml"/> + <!-- <include ref="Hcal_Barrel_SD_v01.xml"/> --> + <!-- <include ref="Hcal_Endcaps_SD_v01.xml"/> --> + <!-- <include ref="Hcal_EndcapRing_SD_v01.xml"/> --> + <!-- <include ref="Yoke05_Barrel.xml"/> --> + <!-- <include ref="Yoke05_Endcaps.xml"/> --> + <!-- <include ref="LumiCal.xml"/> --> + + <!--include ref="LHCal01.xml"/> + <include ref="BeamCal08.xml"/--> + + <!--include ref="coil03.xml"/--> + <!--include ref="SServices00.xml"/--> + <plugins> + <plugin name="DD4hepVolumeManager"/> + <plugin name="InstallSurfaceManager"/> + </plugins> + <!--include ref="Field_Solenoid_Map_s_4.0T.xml"/> + <include ref="Field_AntiDID_Map_s.xml"/> + <include ref="Field_FwdMagnets_Ideal_1000GeV.xml"/--> +</lccdd> diff --git a/Detector/DetCEPCv4/compact/FullDetGear.xml b/Detector/DetCEPCv4/compact/FullDetGear.xml new file mode 100644 index 0000000000000000000000000000000000000000..00f51646ab7d08a72ee1f1d42d53d4f5dee70557 --- /dev/null +++ b/Detector/DetCEPCv4/compact/FullDetGear.xml @@ -0,0 +1,330 @@ +<gear> + <global detectorName="CEPC_v4" /> + <!--Gear XML file automatically created with GearXML::createXMLFile ....--> + <BField type="ConstantBField" x="0.000000000e+00" y="0.000000000e+00" z="3.000000000e+00" /> + <detectors> + <detector geartype="TPCParameters" name="TPC"> + <maxDriftLength value="2.225000000e+03" /> + <driftVelocity value="0.000000000e+00" /> + <coordinateType value="polar" /> + <modules> + <module> + <moduleID value="0" /> + <readoutFrequency value="0.000000000e+00" /> + <PadRowLayout2D type="FixedPadSizeDiskLayout" rMin="3.840000000e+02" rMax="1.716000000e+03" padHeight="6.000000000e+00" padWidth="1.000000000e+00" maxRow="222" padGap="0.000000000e+00" phiMax="6.283185307e+00" /> + <offset x_r="0.000000000e+00" y_phi="0.000000000e+00" /> + <angle value="0.000000000e+00" /> + <enlargeActiveAreaBy value="0.000000000e+00" /> + </module> + </modules> + <parameter name="TPCGasProperties_RadLen" type="double" value="1.155205461e+05" /> + <parameter name="TPCGasProperties_dEdx" type="double" value="2.668179899e-07" /> + <parameter name="TPCInnerWallProperties_RadLen" type="double" value="2.740688665e+03" /> + <parameter name="TPCInnerWallProperties_dEdx" type="double" value="1.241647394e-05" /> + <parameter name="TPCOuterWallProperties_RadLen" type="double" value="6.495646008e+03" /> + <parameter name="TPCOuterWallProperties_dEdx" type="double" value="5.300932694e-06" /> + <parameter name="TPCWallProperties_RadLen" type="double" value="2.740688665e+03" /> + <parameter name="TPCWallProperties_dEdx" type="double" value="1.241647394e-05" /> + <parameter name="tpcInnerRadius" type="double" value="3.290000000e+02" /> + <parameter name="tpcInnerWallThickness" type="double" value="2.500000000e+01" /> + <parameter name="tpcOuterRadius" type="double" value="1.808000000e+03" /> + <parameter name="tpcOuterWallThickness" type="double" value="6.000000000e+01" /> + <parameter name="tpcZAnode" type="double" value="4.600000000e+03" /> + </detector> + <detector name="EcalBarrel" geartype="CalorimeterParameters"> + <layout type="Barrel" symmetry="8" phi0="0.000000000e+00" /> + <dimensions inner_r="1.847415655e+03" outer_z="2.350000000e+03" /> + <layer repeat="19" thickness="5.250000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + <layer repeat="1" thickness="6.300000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + <layer repeat="9" thickness="7.350000000e+00" absorberThickness="4.200000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + </detector> + <detector name="EcalEndcap" geartype="CalorimeterParameters"> + <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" /> + <dimensions inner_r="4.000000000e+02" outer_r="2.088800000e+03" inner_z="2.450000000e+03" /> + <layer repeat="19" thickness="5.250000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + <layer repeat="1" thickness="6.300000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + <layer repeat="9" thickness="7.350000000e+00" absorberThickness="4.200000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + </detector> + <detector name="EcalPlug" geartype="CalorimeterParameters"> + <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" /> + <dimensions inner_r="2.400000000e+02" outer_r="4.000000000e+02" inner_z="2.450000000e+03" /> + <layer repeat="19" thickness="5.250000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + <layer repeat="1" thickness="6.300000000e+00" absorberThickness="2.100000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + <layer repeat="9" thickness="7.350000000e+00" absorberThickness="4.200000000e+00" cellSize0="1.016666667e+01" cellSize1="1.016666667e+01" /> + </detector> + <detector name="YokeBarrel" geartype="CalorimeterParameters"> + <layout type="Barrel" symmetry="12" phi0="0.000000000e+00" /> + <dimensions inner_r="4.173929932e+03" outer_z="4.072000000e+03" /> + <layer repeat="1" thickness="4.000000000e+01" absorberThickness="0.000000000e+00" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" /> + <layer repeat="10" thickness="1.400000000e+02" absorberThickness="1.000000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" /> + <layer repeat="3" thickness="6.000000000e+02" absorberThickness="5.600000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" /> + </detector> + <detector name="YokeEndcap" geartype="CalorimeterParameters"> + <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" /> + <dimensions inner_r="3.200000000e+02" outer_r="7.414929932e+03" inner_z="4.072000000e+03" /> + <layer repeat="10" thickness="1.400000000e+02" absorberThickness="1.000000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" /> + <layer repeat="2" thickness="6.000000000e+02" absorberThickness="5.600000000e+02" cellSize0="3.000000000e+01" cellSize1="3.000000000e+01" /> + </detector> + <detector name="YokePlug" geartype="CalorimeterParameters"> + <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" /> + <dimensions inner_r="3.200000000e+02" outer_r="2.849254326e+03" inner_z="3.781430000e+03" /> + <parameter name="YokePlugThickness" type="double" value="2.905700000e+02" /> + </detector> + <detector name="HcalBarrel" geartype="CalorimeterParameters"> + <layout type="Barrel" symmetry="8" phi0="1.570796327e+00" /> + <dimensions inner_r="2.058000000e+03" outer_z="2.350000000e+03" /> + <layer repeat="40" thickness="2.673000000e+01" absorberThickness="2.000000000e+01" cellSize0="1.000000000e+01" cellSize1="1.000000000e+01" /> + <parameter name="Hcal_barrel_number_modules" type="int" value="5" /> + <parameter name="N_cells_z" type="int" value="91" /> + <parameter name="FrameWidth" type="double" value="1.000000000e+00" /> + <parameter name="Hcal_lateral_structure_thickness" type="double" value="1.000000000e+01" /> + <parameter name="Hcal_modules_gap" type="double" value="2.000000000e+00" /> + <parameter name="Hcal_outer_radius" type="double" value="3.144432447e+03" /> + <parameter name="Hcal_virtual_cell_size" type="double" value="1.000000000e+01" /> + <parameter name="InnerOctoSize" type="double" value="1.704903012e+03" /> + <parameter name="RPC_PadSeparation" type="double" value="0.000000000e+00" /> + <parameter name="TPC_Ecal_Hcal_barrel_halfZ" type="double" value="2.350000000e+03" /> + </detector> + <detector name="HcalEndcap" geartype="CalorimeterParameters"> + <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" /> + <dimensions inner_r="3.500000000e+02" outer_r="3.144432447e+03" inner_z="2.650000000e+03" /> + <layer repeat="40" thickness="2.673000000e+01" absorberThickness="2.000000000e+01" cellSize0="1.000000000e+01" cellSize1="1.000000000e+01" /> + <parameter name="FrameWidth" type="double" value="0.000000000e+00" /> + <parameter name="Hcal_virtual_cell_size" type="double" value="1.000000000e+01" /> + </detector> + <detector name="HcalRing" geartype="CalorimeterParameters"> + <layout type="Endcap" symmetry="2" phi0="0.000000000e+00" /> + <dimensions inner_r="2.138800000e+03" outer_r="3.144432447e+03" inner_z="2.450000000e+03" /> + <layer repeat="6" thickness="2.673000000e+01" absorberThickness="2.000000000e+01" cellSize0="1.000000000e+01" cellSize1="1.000000000e+01" /> + <parameter name="FrameWidth" type="double" value="0.000000000e+00" /> + <parameter name="Hcal_virtual_cell_size" type="double" value="1.000000000e+01" /> + </detector> + <detector name="Lcal" geartype="CalorimeterParameters"> + <layout type="Endcap" symmetry="1" phi0="0.000000000e+00" /> + <dimensions inner_r="3.225828541e+01" outer_r="9.880000000e+01" inner_z="9.519000000e+02" /> + <layer repeat="30" thickness="4.290000000e+00" absorberThickness="3.500000000e+00" cellSize0="1.039714290e+00" cellSize1="1.308996939e-01" /> + <parameter name="beam_crossing_angle" type="double" value="0.000000000e+00" /> + </detector> + <detector name="VXD" geartype="ZPlanarParameters"> + <type technology="HYBRID" /> + <shell halfLength="1.450000000e+02" gap="0.000000000e+00" innerRadius="6.500000000e+01" outerRadius="6.549392000e+01" radLength="3.527597571e+02" /> + <layers> + <layer nLadders="10" phi0="-1.570796327e+00"> + <ladder distance="1.600000000e+01" thickness="1.000000000e+00" width="1.150000000e+01" length="6.250000000e+01" offset="-1.874869853e+00" radLength="1.014262421e+03" /> + <sensitive distance="1.595000000e+01" thickness="5.000000000e-02" width="1.100000000e+01" length="6.250000000e+01" offset="-1.624869853e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="10" phi0="-1.570796327e+00"> + <ladder distance="1.700000000e+01" thickness="1.000000000e+00" width="1.150000000e+01" length="6.250000000e+01" offset="-1.874869853e+00" radLength="1.014262421e+03" /> + <sensitive distance="1.800000000e+01" thickness="5.000000000e-02" width="1.100000000e+01" length="6.250000000e+01" offset="-1.624869853e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="11" phi0="-1.570796327e+00"> + <ladder distance="3.700000000e+01" thickness="1.000000000e+00" width="2.250000000e+01" length="1.250000000e+02" offset="-1.837940563e+00" radLength="1.014262421e+03" /> + <sensitive distance="3.695000000e+01" thickness="5.000000000e-02" width="2.200000000e+01" length="1.250000000e+02" offset="-1.587940563e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="11" phi0="-1.570796327e+00"> + <ladder distance="3.800000000e+01" thickness="1.000000000e+00" width="2.250000000e+01" length="1.250000000e+02" offset="-1.837940563e+00" radLength="1.014262421e+03" /> + <sensitive distance="3.900000000e+01" thickness="5.000000000e-02" width="2.200000000e+01" length="1.250000000e+02" offset="-1.587940563e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="17" phi0="-1.570796327e+00"> + <ladder distance="5.800000000e+01" thickness="1.000000000e+00" width="2.250000000e+01" length="1.250000000e+02" offset="-2.636744400e+00" radLength="1.014262421e+03" /> + <sensitive distance="5.795000000e+01" thickness="5.000000000e-02" width="2.200000000e+01" length="1.250000000e+02" offset="-2.386744400e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="17" phi0="-1.570796327e+00"> + <ladder distance="5.900000000e+01" thickness="1.000000000e+00" width="2.250000000e+01" length="1.250000000e+02" offset="-2.636744400e+00" radLength="1.014262421e+03" /> + <sensitive distance="6.000000000e+01" thickness="5.000000000e-02" width="2.200000000e+01" length="1.250000000e+02" offset="-2.386744400e+00" radLength="9.366070445e+01" /> + </layer> + </layers> + </detector> + <detector name="FTD" geartype="FTDParameters"> + <layers> + <layer nPetals="16" nSensors="1" isDoubleSided="0" sensorType="PIXEL" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="1.500000000e+00" zsign0="-1.000000000e+00" zposition="2.200000000e+02"> + <support thickness="1.000000000e+00" width="1.180723890e+02" lengthMin="2.502788316e+01" lengthMax="7.200000000e+01" rInner="2.950000000e+01" radLength="2.860837413e+02" /> + <sensitive thickness="2.000000000e-02" width="1.180723890e+02" lengthMin="2.502788316e+01" lengthMax="7.200000000e+01" rInner="2.950000000e+01" radLength="9.366070445e+01" /> + </layer> + <layer nPetals="16" nSensors="1" isDoubleSided="0" sensorType="PIXEL" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="1.500000000e+00" zsign0="-1.000000000e+00" zposition="3.713094000e+02"> + <support thickness="1.000000000e+00" width="1.170317258e+02" lengthMin="2.544188474e+01" lengthMax="7.200000000e+01" rInner="3.054066325e+01" radLength="2.860837413e+02" /> + <sensitive thickness="2.000000000e-02" width="1.170317258e+02" lengthMin="2.544188474e+01" lengthMax="7.200000000e+01" rInner="3.054066325e+01" radLength="9.366070445e+01" /> + </layer> + <layer nPetals="16" nSensors="2" isDoubleSided="1" sensorType="STRIP" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="1.500000000e+00" zsign0="-1.000000000e+00" zposition="6.429059500e+02"> + <support thickness="2.000000000e+00" width="2.600401444e+02" lengthMin="1.903959852e+01" lengthMax="1.224900000e+02" rInner="3.251798652e+01" radLength="2.860837413e+02" /> + <sensitive thickness="2.000000000e-01" width="2.600401444e+02" lengthMin="1.903959852e+01" lengthMax="1.224900000e+02" rInner="3.251798652e+01" radLength="9.366070445e+01" /> + </layer> + <layer nPetals="16" nSensors="2" isDoubleSided="1" sensorType="STRIP" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="1.500000000e+00" zsign0="-1.000000000e+00" zposition="8.440001500e+02"> + <support thickness="2.000000000e+00" width="2.688914284e+02" lengthMin="1.551833880e+01" lengthMax="1.224900000e+02" rInner="3.397826298e+01" radLength="2.860837413e+02" /> + <sensitive thickness="2.000000000e-01" width="2.688914284e+02" lengthMin="1.551833880e+01" lengthMax="1.224900000e+02" rInner="3.397826298e+01" radLength="9.366070445e+01" /> + </layer> + <layer nPetals="16" nSensors="2" isDoubleSided="1" sensorType="STRIP" petalOpenningAngle="1.963495408e-01" phi0="0.000000000e+00" alpha="0.000000000e+00" zoffset="1.500000000e+00" zsign0="-1.000000000e+00" zposition="9.249600000e+02"> + <support thickness="2.000000000e+00" width="2.683035260e+02" lengthMin="1.575222092e+01" lengthMax="1.224900000e+02" rInner="3.456616538e+01" radLength="2.860837413e+02" /> + <sensitive thickness="2.000000000e-01" width="2.683035260e+02" lengthMin="1.575222092e+01" lengthMax="1.224900000e+02" rInner="3.456616538e+01" radLength="9.366070445e+01" /> + </layer> + </layers> + <parameter name="strip_angle_deg" type="double" value="5.000000000e+00" /> + <parameter name="strip_length_mm" type="double" value="2.500000000e+02" /> + <parameter name="strip_pitch_mm" type="double" value="1.000000000e-02" /> + <parameter name="strip_width_mm" type="double" value="1.000000000e-03" /> + </detector> + <detector name="SIT" geartype="ZPlanarParameters"> + <type technology="CCD" /> + <shell halfLength="0.000000000e+00" gap="0.000000000e+00" innerRadius="0.000000000e+00" outerRadius="0.000000000e+00" radLength="0.000000000e+00" /> + <layers> + <layer nLadders="10" phi0="0.000000000e+00"> + <ladder distance="1.531000000e+02" thickness="1.000000000e+00" width="9.916044311e+01" length="3.680000000e+02" offset="0.000000000e+00" radLength="2.134851878e+02" /> + <sensitive distance="1.529000000e+02" thickness="2.000000000e-01" width="9.916044311e+01" length="3.680000000e+02" offset="0.000000000e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="10" phi0="0.000000000e+00"> + <ladder distance="1.544000000e+02" thickness="1.000000000e+00" width="1.001352022e+02" length="3.680000000e+02" offset="0.000000000e+00" radLength="2.134851878e+02" /> + <sensitive distance="1.554000000e+02" thickness="2.000000000e-01" width="1.001352022e+02" length="3.680000000e+02" offset="0.000000000e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="19" phi0="0.000000000e+00"> + <ladder distance="3.001000000e+02" thickness="1.000000000e+00" width="9.988891763e+01" length="6.440000000e+02" offset="0.000000000e+00" radLength="2.134851878e+02" /> + <sensitive distance="2.999000000e+02" thickness="2.000000000e-01" width="9.988891763e+01" length="6.440000000e+02" offset="0.000000000e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="19" phi0="0.000000000e+00"> + <ladder distance="3.014000000e+02" thickness="1.000000000e+00" width="1.003895291e+02" length="6.440000000e+02" offset="0.000000000e+00" radLength="2.134851878e+02" /> + <sensitive distance="3.024000000e+02" thickness="2.000000000e-01" width="1.003895291e+02" length="6.440000000e+02" offset="0.000000000e+00" radLength="9.366070445e+01" /> + </layer> + </layers> + <parameter name="sensor_length_mm" type="double" value="9.200000000e+01" /> + <parameter name="strip_angle_deg" type="double" value="7.000000000e+00" /> + <parameter name="strip_length_mm" type="double" value="9.200000000e+01" /> + <parameter name="strip_pitch_mm" type="double" value="5.000000000e-02" /> + <parameter name="strip_width_mm" type="double" value="1.250000000e-02" /> + <parameter name="n_sensors_per_ladder" type="IntVec" value="8 8 14 14" /> + </detector> + <detector name="SET" geartype="ZPlanarParameters"> + <type technology="CCD" /> + <shell halfLength="0.000000000e+00" gap="0.000000000e+00" innerRadius="0.000000000e+00" outerRadius="0.000000000e+00" radLength="0.000000000e+00" /> + <layers> + <layer nLadders="24" phi0="0.000000000e+00"> + <ladder distance="1.811100000e+03" thickness="1.000000000e+00" width="4.766190158e+02" length="2.300000000e+03" offset="0.000000000e+00" radLength="2.134851878e+02" /> + <sensitive distance="1.810900000e+03" thickness="2.000000000e-01" width="4.766190158e+02" length="2.300000000e+03" offset="0.000000000e+00" radLength="9.366070445e+01" /> + </layer> + <layer nLadders="24" phi0="0.000000000e+00"> + <ladder distance="1.812400000e+03" thickness="1.000000000e+00" width="4.770139733e+02" length="2.300000000e+03" offset="0.000000000e+00" radLength="2.134851878e+02" /> + <sensitive distance="1.813400000e+03" thickness="2.000000000e-01" width="4.770139733e+02" length="2.300000000e+03" offset="0.000000000e+00" radLength="9.366070445e+01" /> + </layer> + </layers> + <parameter name="sensor_length_mm" type="double" value="9.200000000e+01" /> + <parameter name="strip_angle_deg" type="double" value="7.000000000e+00" /> + <parameter name="strip_length_mm" type="double" value="9.200000000e+01" /> + <parameter name="strip_pitch_mm" type="double" value="5.000000000e-02" /> + <parameter name="strip_width_mm" type="double" value="1.250000000e-02" /> + <parameter name="n_sensors_per_ladder" type="IntVec" value="50 50" /> + </detector> + <detector name="BeamPipe" geartype="GearParameters"> + <parameter name="BeamPipeHalfZ" type="double" value="7.300000000e+02" /> + <parameter name="BeamPipeProperties_RadLen" type="double" value="3.527597571e+02" /> + <parameter name="BeamPipeProperties_dEdx" type="double" value="2.941795296e-04" /> + <parameter name="BeamPipeRadius" type="double" value="1.400000000e+01" /> + <parameter name="BeamPipeThickness" type="double" value="5.000000000e-01" /> + <parameter name="RInner" type="DoubleVec" value="1.400000000e+01 1.400000000e+01 2.500000000e+00 1.300000000e+01 1.300000000e+01 1.300000000e+01 1.550000000e+01 1.550000000e+01 1.900000000e+01 1.900000000e+01 2.500000000e+01 2.500000000e+01 1.300000000e+01 1.300000000e+01 2.050000000e+01 2.050000000e+01 2.300000000e+01 2.300000000e+01 2.600000000e+01 2.600000000e+01 3.200000000e+01 3.200000000e+01" /> + <parameter name="ROuter" type="DoubleVec" value="1.450000000e+01 1.450000000e+01 1.800000000e+01 1.800000000e+01 1.550000000e+01 1.550000000e+01 1.900000000e+01 1.900000000e+01 2.500000000e+01 2.500000000e+01 3.300000000e+01 3.300000000e+01 1.550000000e+01 1.550000000e+01 2.300000000e+01 2.300000000e+01 2.600000000e+01 2.600000000e+01 3.200000000e+01 3.200000000e+01 4.000000000e+01 4.000000000e+01" /> + <parameter name="Z" type="DoubleVec" value="0.000000000e+00 5.000000000e+02 7.000000000e+02 7.010000000e+02 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 2.200000000e+03 3.950000000e+03 3.950000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03 4.450000000e+03" /> + </detector> + <detector name="CoilParameters" geartype="GearParameters"> + <parameter name="Coil_cryostat_c_modules_half_z" type="double" value="1.224000000e+03" /> + <parameter name="Coil_cryostat_c_modules_inner_radius" type="double" value="3.348930000e+03" /> + <parameter name="Coil_cryostat_c_modules_outer_radius" type="double" value="3.733930000e+03" /> + <parameter name="Coil_cryostat_half_z" type="double" value="3.872000000e+03" /> + <parameter name="Coil_cryostat_inner_cyl_half_z" type="double" value="3.872000000e+03" /> + <parameter name="Coil_cryostat_inner_cyl_inner_radius" type="double" value="3.173930000e+03" /> + <parameter name="Coil_cryostat_inner_cyl_outer_radius" type="double" value="3.963930000e+03" /> + <parameter name="Coil_cryostat_inner_radius" type="double" value="3.173930000e+03" /> + <parameter name="Coil_cryostat_mandrel_half_z" type="double" value="3.675000000e+03" /> + <parameter name="Coil_cryostat_mandrel_inner_radius" type="double" value="3.733930000e+03" /> + <parameter name="Coil_cryostat_mandrel_outer_radius" type="double" value="3.808930000e+03" /> + <parameter name="Coil_cryostat_modules_half_z" type="double" value="7.960000000e+02" /> + <parameter name="Coil_cryostat_modules_inner_radius" type="double" value="3.348930000e+03" /> + <parameter name="Coil_cryostat_modules_outer_radius" type="double" value="3.733930000e+03" /> + <parameter name="Coil_cryostat_outer_cyl_half_z" type="double" value="3.872000000e+03" /> + <parameter name="Coil_cryostat_outer_cyl_inner_radius" type="double" value="3.893930000e+03" /> + <parameter name="Coil_cryostat_outer_cyl_outer_radius" type="double" value="3.923930000e+03" /> + <parameter name="Coil_cryostat_outer_radius" type="double" value="3.923930000e+03" /> + <parameter name="Coil_cryostat_scint1_inner_radius" type="double" value="3.263930000e+03" /> + <parameter name="Coil_cryostat_scint1_outer_radius" type="double" value="3.273930000e+03" /> + <parameter name="Coil_cryostat_scint1_zposend" type="double" value="3.972000000e+03" /> + <parameter name="Coil_cryostat_scint1_zposin" type="double" value="3.772000000e+03" /> + <parameter name="Coil_cryostat_scint2_inner_radius" type="double" value="3.278930000e+03" /> + <parameter name="Coil_cryostat_scint2_outer_radius" type="double" value="3.288930000e+03" /> + <parameter name="Coil_cryostat_scint2_zposend" type="double" value="3.972000000e+03" /> + <parameter name="Coil_cryostat_scint2_zposin" type="double" value="3.772000000e+03" /> + <parameter name="Coil_cryostat_scint3_inner_radius" type="double" value="3.833930000e+03" /> + <parameter name="Coil_cryostat_scint3_outer_radius" type="double" value="3.843930000e+03" /> + <parameter name="Coil_cryostat_scint3_zposend" type="double" value="3.972000000e+03" /> + <parameter name="Coil_cryostat_scint3_zposin" type="double" value="3.772000000e+03" /> + <parameter name="Coil_cryostat_scint4_inner_radius" type="double" value="3.818930000e+03" /> + <parameter name="Coil_cryostat_scint4_outer_radius" type="double" value="3.828930000e+03" /> + <parameter name="Coil_cryostat_scint4_zposend" type="double" value="3.972000000e+03" /> + <parameter name="Coil_cryostat_scint4_zposin" type="double" value="3.772000000e+03" /> + <parameter name="Coil_cryostat_side_l_half_z" type="double" value="2.500000000e+01" /> + <parameter name="Coil_cryostat_side_l_inner_radius" type="double" value="3.213930000e+03" /> + <parameter name="Coil_cryostat_side_l_outer_radius" type="double" value="3.893930000e+03" /> + <parameter name="Coil_cryostat_side_r_half_z" type="double" value="2.500000000e+01" /> + <parameter name="Coil_cryostat_side_r_inner_radius" type="double" value="3.213930000e+03" /> + <parameter name="Coil_cryostat_side_r_outer_radius" type="double" value="3.893930000e+03" /> + <parameter name="Coil_material_c_modules" type="string" value="aluminium" /> + <parameter name="Coil_material_inner_cyl" type="string" value="aluminium" /> + <parameter name="Coil_material_mandrel" type="string" value="aluminium" /> + <parameter name="Coil_material_modules" type="string" value="aluminium" /> + <parameter name="Coil_material_outer_cyl" type="string" value="aluminium" /> + <parameter name="Coil_material_scint1" type="string" value="polystyrene" /> + <parameter name="Coil_material_scint2" type="string" value="polystyrene" /> + <parameter name="Coil_material_scint3" type="string" value="polystyrene" /> + <parameter name="Coil_material_scint4" type="string" value="polystyrene" /> + <parameter name="Coil_material_side_l" type="string" value="aluminium" /> + <parameter name="Coil_material_side_r" type="string" value="aluminium" /> + </detector> + <detector name="MokkaParameters" geartype="GearParameters"> + <parameter name="Ecal_endcap_outer_radius" type="string" value="2088.8" /> + <parameter name="Ecal_endcap_plug_rmin" type="string" value="240" /> + <parameter name="Ecal_endcap_zmax" type="string" value="2635" /> + <parameter name="Ecal_endcap_zmin" type="string" value="2450" /> + <parameter name="Ecal_outer_radius" type="string" value="2028" /> + <parameter name="Hcal_R_max" type="string" value="3144.43" /> + <parameter name="Hcal_endcap_zmin" type="string" value="2650" /> + <parameter name="Lcal_z_begin" type="string" value="951.9" /> + <parameter name="Lcal_z_thickness" type="string" value="128.1" /> + <parameter name="MokkaModel" type="string" value="CEPC_v4" /> + <parameter name="MokkaVersion" type="string" value="void" /> + <parameter name="SIT1_Half_Length_Z" type="string" value="368" /> + <parameter name="SIT1_Radius" type="string" value="152.9" /> + <parameter name="SIT2_Half_Length_Z" type="string" value="644" /> + <parameter name="SIT2_Radius" type="string" value="299.9" /> + <parameter name="TPC_Ecal_Hcal_barrel_halfZ" type="string" value="2350" /> + <parameter name="Yoke_Z_start_endcaps" type="string" value="4072" /> + <parameter name="Yoke_barrel_inner_radius" type="string" value="4173.92993164062" /> + <parameter name="calorimeter_region_rmax" type="string" value="3144.43" /> + <parameter name="calorimeter_region_zmax" type="string" value="3736.43" /> + <parameter name="tracker_region_rmax" type="string" value="1842.9" /> + <parameter name="tracker_region_zmax" type="string" value="2350" /> + <parameter name="world_box_hx" type="string" value="" /> + <parameter name="world_box_hy" type="string" value="" /> + <parameter name="world_box_hz" type="string" value="" /> + </detector> + <detector name="VXDInfra" geartype="GearParameters"> + <parameter name="ActiveLayerProperties_dEdx" type="double" value="3.870163611e-04" /> + <parameter name="BeSupportEndplateThickness" type="double" value="2.000000000e+00" /> + <parameter name="BeSupport_dEdx" type="double" value="2.941795296e-04" /> + <parameter name="CryostatAlHalfZ" type="double" value="1.766000000e+02" /> + <parameter name="CryostatAlInnerR" type="double" value="2.420000000e+01" /> + <parameter name="CryostatAlRadius" type="double" value="1.000000000e+02" /> + <parameter name="CryostatAlThickness" type="double" value="5.000000000e-01" /> + <parameter name="CryostatAlZEndCap" type="double" value="1.768500000e+02" /> + <parameter name="CryostatFoamRadius" type="double" value="9.000000000e+01" /> + <parameter name="CryostatFoamThickness" type="double" value="1.000000000e+01" /> + <parameter name="Cryostat_RadLen" type="double" value="8.896317758e+01" /> + <parameter name="Cryostat_dEdx" type="double" value="4.350185478e-04" /> + <parameter name="ElectronicEndLength" type="double" value="1.000000000e+01" /> + <parameter name="ElectronicEndThickness" type="double" value="1.000000000e-01" /> + <parameter name="StripLineBeamPipeRadius" type="double" value="2.430000000e+01" /> + <parameter name="VXDEndPlateInnerRadius" type="double" value="3.000000000e+01" /> + <parameter name="VXDSupport_dEdx" type="double" value="5.431907412e-05" /> + <parameter name="LadderGaps" type="DoubleVec" value="0.000000000e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00 0.000000000e+00" /> + <parameter name="StripLineFinalZ" type="DoubleVec" value="1.500000000e+02 1.500000000e+02 1.500000000e+02 1.500000000e+02 1.500000000e+02 1.500000000e+02" /> + </detector> + </detectors> + <materials> + <material name="VXDFoamShellMaterial" A="1.043890843e+01" Z="5.612886646e+00" density="2.500000000e+01" radLength="1.751650267e+04" intLength="6.594366018e+01" /> + <material name="VXDSupportMaterial" A="2.075865162e+01" Z="1.039383117e+01" density="2.765900000e+02" radLength="1.014262421e+03" intLength="1.206635688e+02" /> + </materials> +</gear> diff --git a/Detector/DetCEPCv4/src/calorimeter/SEcal05_Barrel.cpp b/Detector/DetCEPCv4/src/calorimeter/SEcal05_Barrel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a0329b4e2e351969fa8e0f5b4e2ceed47a1f5f8e --- /dev/null +++ b/Detector/DetCEPCv4/src/calorimeter/SEcal05_Barrel.cpp @@ -0,0 +1,444 @@ +//==================================================================== +// lcgeo - LC detector models in DD4hep +//-------------------------------------------------------------------- +// DD4hep Geometry driver for SiWEcalBarrel +// Ported from Mokka +//-------------------------------------------------------------------- +// S.Lu, DESY +// D.Jeans, Tokyo <-- to 05: add possibility to remove preshower layer +//==================================================================== + +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/DetType.h" + +#include "XML/Layering.h" +#include "TGeoTrd2.h" + +#include "XML/Utilities.h" +#include "DDRec/DetectorData.h" + +#include "DDSegmentation/MegatileLayerGridXY.h" +#include "DDSegmentation/WaferGridXY.h" + +#include "SEcal05_Helpers.h" + +#include <sstream> + +#undef NDEBUG +#include <assert.h> + +using namespace std; + +using dd4hep::BUILD_ENVELOPE; +using dd4hep::DetElement; +using dd4hep::Detector; +using dd4hep::Layering; +using dd4hep::Material; +using dd4hep::PlacedVolume; +using dd4hep::Position; +using dd4hep::Readout; +using dd4hep::Ref_t; +using dd4hep::RotationZYX; +using dd4hep::Segmentation; +using dd4hep::SensitiveDetector; +using dd4hep::Transform3D; +using dd4hep::Translation3D; +using dd4hep::Trapezoid; +using dd4hep::Volume; +using dd4hep::_toString; + +using dd4hep::rec::LayeredCalorimeterData; + +#define VERBOSE 1 + +// workaround for DD4hep v00-14 (and older) +#ifndef DD4HEP_VERSION_GE +#define DD4HEP_VERSION_GE(a,b) 0 +#endif + +/** SEcal05.cc + * + * new SEcal05 barrel driver: allows removal of preshower layer. DJeans UTokyo, sep/2016 + * based on SEcal04 + * + * @author: Shaojun Lu, DESY + * @version $Id: SEcal04_Barrel.cpp 1060 2016-09-05 07:48:41Z /C=JP/O=KEK/OU=CRC/CN=JEANS Daniel Thomelin Dietrich $ + * Ported from Mokka SEcal04 Barrel part. Read the constants from XML + * instead of the DB. Then build the Barrel in the same way with DD4hep + * construct. + * + * @history: F.Gaede, CERN/DESY, Nov. 10, 2014 + * added information for reconstruction: LayeringExtension and surfaces (experimental) + * removed DetElement for slices (not needed) increased multiplicity for layer DetElement + * along tower index + * F.Gaede: 03/2015: + * create the envelope volume with create_placed_envelope() using the xml + * + * D. Jeans: 03/2015: + * generalise to non-octagonal barrel shape + * allow dead region between end of each slab and the module edge (e.g. for the slab fastening system) + */ + +/* + + + + + y + ^ + | z is perpendicular to page (along beamline) + | + -----> x + + original coord system was very mixed up. + Daniel tried to rationalise it to make it more understandable (hopefully) + + absorber layers are wrapped in a number of layers of carbon fibre composite (CF) + + structure of slab (which is inserted into the structure) is defined in the compact description + + general structure (from +ve y) + ------------------------------- + + if preshower, front face (CF) \\\\\\\\\\\\\\\\\\ + + if no preshower, wrapped absorber ================== + + __________________ + alveolus, containing the slab |__________________| + + wrapped absorber =================== + __________________ + alveolus, containing the slab |__________________| + + . + repeat as required + . + + wrapped absorber =================== + __________________ + alveolus, containing the slab |__________________| + + back support plate (CF) \\\\\\\\\\\\\\\\\\\\ + //////////////////// + + */ + + + +static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDetector sens) { + + cout << "-----------------------" << endl; + cout << "creating SEcal05_Barrel" << endl; + cout << "-----------------------" << endl; + + xml_det_t x_det = element; + string det_name = x_det.nameStr(); + Layering layering (element); + + Material carbon_fibre = theDetector.material("CarbonFiber"); + + int det_id = x_det.id(); + DetElement sdet (det_name,det_id); + + xml_comp_t x_dim = x_det.dimensions(); + int nsides = x_dim.numsides(); + + double dphi = (2*M_PI/nsides); + double hphi = dphi/2; + + // --- create an envelope volume and position it into the world --------------------- + + Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector, element , sdet ) ; + + dd4hep::xml::setDetectorTypeFlag( element, sdet ) ; + + if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ; + + //----------------------------------------------------------------------------------- + + sens.setType("calorimeter"); + + DetElement stave_det("module1stave1",det_id); + + //==================================================================== + // + // Read all the constant from ILD_o1_v05.xml + // Use them to build HcalBarrel + // + //==================================================================== + + // some hardcoded values! + // const int N_FIBERS_W_STRUCTURE = 2; // number of CF layers around absorber layers in the structure + // const int N_FIBERS_ALVEOLUS = 3; // number of CF layers used to make alveolus + + // read other parameters from compact.xml file + + // overall size + double Ecal_inner_radius = theDetector.constant<double>("Ecal_inner_radius"); + + double Ecal_Barrel_halfZ = theDetector.constant<double>("Ecal_Barrel_halfZ"); + int Ecal_barrel_z_modules = theDetector.constant<int>("Ecal_barrel_z_modules"); + int Ecal_barrel_number_of_towers = theDetector.constant<int>("Ecal_barrel_number_of_towers"); + + double Ecal_barrel_thickness = theDetector.constant<double>("Ecal_barrel_thickness"); // what's assumed in the compact description + + // absorber layers + int Ecal_nlayers1 = theDetector.constant<int>("Ecal_nlayers1"); + int Ecal_nlayers2 = theDetector.constant<int>("Ecal_nlayers2"); + int Ecal_nlayers3 = theDetector.constant<int>("Ecal_nlayers3"); + + double Ecal_radiator_thickness1 = theDetector.constant<double>("Ecal_radiator_layers_set1_thickness"); + double Ecal_radiator_thickness2 = theDetector.constant<double>("Ecal_radiator_layers_set2_thickness"); + double Ecal_radiator_thickness3 = theDetector.constant<double>("Ecal_radiator_layers_set3_thickness"); + + // CF support dimensions + double Ecal_support_thickness = theDetector.constant<double>("Ecal_support_thickness"); + double Ecal_front_face_thickness = theDetector.constant<double>("Ecal_front_face_thickness"); + double Ecal_lateral_face_thickness = theDetector.constant<double>("Ecal_lateral_face_thickness"); + double Ecal_Slab_H_fiber_thickness = theDetector.constant<double>("Ecal_Slab_H_fiber_thickness"); + + + // double Ecal_fiber_thickness = theDetector.constant<double>("Ecal_fiber_thickness"); + // some hardcoded values! + // const int N_FIBERS_W_STRUCTURE = 2; // number of CF layers around absorber layers in the structure + // const int N_FIBERS_ALVEOLUS = 3; // number of CF layers used to make alveolus + double Ecal_fiber_thickness_structure = theDetector.constant<double>("Ecal_fiber_thickness_structure"); // absorber wrapping thickness + double Ecal_fiber_thickness_alveolus = theDetector.constant<double>("Ecal_fiber_thickness_alveolus"); // alveolar wall thickness + + double Ecal_Slab_shielding = theDetector.constant<double>("Ecal_Slab_shielding"); + + // first layer is preshower? + bool Ecal_Barrel_PreshowerLayer = theDetector.constant<int>("Ecal_Barrel_Preshower") > 0; + + // internal dimensions of slab + double Ecal_guard_ring_size = theDetector.constant<double>("Ecal_guard_ring_size"); + int Ecal_n_wafers_per_tower = theDetector.constant<int>("Ecal_n_wafers_per_tower"); + + std::string Ecal_layerConfig = theDetector.constant<string>("Ecal_layer_pattern"); + + int Ecal_end_of_slab_strategy = theDetector.constant<int>("Ecal_end_of_slab_strategy"); + + int Ecal_cells_across_megatile = theDetector.constant <int> ("Ecal_cells_across_megatile" ); + int Ecal_strips_across_megatile = theDetector.constant <int> ("Ecal_strips_across_megatile"); + int Ecal_strips_along_megatile = theDetector.constant <int> ("Ecal_strips_along_megatile" ); + + float Ecal_plugLength = 0.; + try { + Ecal_plugLength = theDetector.constant<double>("Ecal_Slab_Plug_length"); + } catch (std::runtime_error&e) { + cout << "SEcal05_Barrel: Ecal_plugLength not found, using " << Ecal_plugLength << endl; + } + + //--------------------------------- + + // set up the helper, which will make a module for us + + SEcal05_Helpers helper; + helper.setDet( & x_det ); + + // absorber layer structure + helper.setPreshower( Ecal_Barrel_PreshowerLayer ); + + cout << "SEcal05_Barrel: Preshower ? " << Ecal_Barrel_PreshowerLayer << endl; + + helper.setAbsLayers( Ecal_nlayers1, Ecal_radiator_thickness1, + Ecal_nlayers2, Ecal_radiator_thickness2, + Ecal_nlayers3, Ecal_radiator_thickness3 ); + + cout << "SEcal05_Barrel: absorber layers " << + Ecal_nlayers1 << "*" << Ecal_radiator_thickness1/dd4hep::mm << " mm + " << + Ecal_nlayers2 << "*" << Ecal_radiator_thickness2/dd4hep::mm << " mm + " << + Ecal_nlayers3 << "*" << Ecal_radiator_thickness3/dd4hep::mm << " mm " << endl; + + helper.checkLayerConsistency(); + + // structural CF thicknesses + helper.setCFthickness( Ecal_fiber_thickness_structure, // was N_FIBERS_W_STRUCTURE*Ecal_fiber_thickness, : updated DJ + Ecal_fiber_thickness_alveolus, // N_FIBERS_ALVEOLUS*Ecal_fiber_thickness, + Ecal_front_face_thickness, + Ecal_support_thickness); + + helper.setPlugLength( Ecal_plugLength ); + + // check resulting thickness is consistent with what's in compact description + float module_thickness = helper.getTotalThickness(); + if ( fabs( Ecal_barrel_thickness - module_thickness ) > 0.01 ) { + cout << "ERROR SEcal05_Barrel : ECAL barrel thickness in comapct decription not consistent with what I calculate!" << endl; + cout << " calculated = " << module_thickness << " compact description: " << Ecal_barrel_thickness << endl; + assert( 0 ); // exit + } + + cout << "SEcal05_Barrel : module thickness = " << module_thickness << endl; + + // set up the sensitive layer segmentation + + Readout readout = sens.readout(); + Segmentation seg = readout.segmentation(); + helper.setSegmentation( &seg ); + + helper.setNCells( Ecal_cells_across_megatile, Ecal_strips_across_megatile, Ecal_strips_along_megatile); + helper.setMagicMegatileStrategy ( Ecal_end_of_slab_strategy ); + + // layer configuration + int ntemp; + stringstream stream(Ecal_layerConfig); + std::vector < int > layerConfig; + while ( stream >> ntemp ) { + assert (ntemp>=0 ); + layerConfig.push_back( ntemp ); + } + cout << "SEcal05_Barrel : layer config: "; + for (size_t i=0; i<layerConfig.size(); i++) cout << layerConfig[i] << " "; + cout << endl; + + helper.setLayerConfig( layerConfig ); + + + // set the alveolar structure + + // get width of alveolus + double Ecal_Barrel_module_dim_z = 2 * Ecal_Barrel_halfZ / Ecal_barrel_z_modules ; + double alv_width = ( Ecal_Barrel_module_dim_z - 2.*Ecal_lateral_face_thickness ) / Ecal_barrel_number_of_towers; + + cout << "SEcal05_Barrel : width of module, alveolus = " << Ecal_Barrel_module_dim_z << " " << alv_width << endl; + + std::vector < int > ntowers; ntowers.push_back(Ecal_barrel_number_of_towers); + + helper.setTowersUnits( ntowers, + alv_width, + Ecal_n_wafers_per_tower, + Ecal_lateral_face_thickness, + Ecal_fiber_thickness_alveolus + Ecal_Slab_H_fiber_thickness + Ecal_Slab_shielding, + Ecal_guard_ring_size ); + + // shape of barrel module + // to get alignment as in ECAL interface design doc fig10 + double module_thickness_noSupport = module_thickness - Ecal_support_thickness; + + // double max_dim_x = 2. * tan(M_PI/8.) * Ecal_inner_radius + module_thickness_noSupport/sin(M_PI/4.); // longest side assumes oct + // double min_dim_x = max_dim_x - 2*module_thickness; // shorter one (assumes octagon) + + // double max_dim_x = 2. * tan(M_PI/nsides) * Ecal_inner_radius + module_thickness_noSupport / tan( 2*M_PI/nsides ); // longest side + double max_dim_x = 2. * tan(M_PI/nsides) * Ecal_inner_radius + module_thickness_noSupport / sin( 2*M_PI/nsides ); // longest side : fix DJeans 03/2017 + double min_dim_x = max_dim_x - 2*module_thickness/tan( 2*M_PI/nsides ) ; // shorter one + + if ( min_dim_x<0 || max_dim_x<0 ) { + std::cout << "SEcal05_Barrel ERROR : requesting too many sides! barrel modules have max/min extent " << max_dim_x << " " << min_dim_x << std::endl; + std::cout << "exiting" << std::endl; + assert(0); // exit gracefully + } + + Trapezoid trd(max_dim_x / 2, + min_dim_x / 2, + Ecal_Barrel_module_dim_z / 2, + Ecal_Barrel_module_dim_z / 2, + module_thickness/2); + + Volume mod_vol(det_name+"_module", trd, carbon_fibre); // DJeans 5-sep-2016 + + //========== fill data for reconstruction ============================ + LayeredCalorimeterData* caloData = new LayeredCalorimeterData ; + + helper.setModuleDimensions( 0, // int XYtype, // module shape in XY + 1, // int XZtype, // module shape in XZ + max_dim_x, // double dX_max, // maximum extent in X + -999, // dummy + 2.*M_PI/nsides + ); + + // traslation to get layers within the envelope + helper.setTranslation ( Position ( -max_dim_x/2. , -Ecal_Barrel_module_dim_z/2., -module_thickness/2. ) ); + + // make the module + + helper.makeModule( mod_vol, stave_det, + *caloData, + theDetector, sens ); + + for (size_t i=0; i<caloData->layers.size(); i++) { + caloData->layers[i].distance += Ecal_inner_radius; // add IP->front face distance + } + + // cout << "SEcal05_Barrel : cell sizes: " << endl; + // for (size_t i=0; i<caloData->layers.size(); i++) { + // cout << "sensitive layer " << i << " : x,y = " << caloData->layers[i].cellSize0 << " " << caloData->layers[i].cellSize1 << endl; + // } + + // ------------- create extension objects for reconstruction ----------------- + + caloData->layoutType = LayeredCalorimeterData::BarrelLayout ; + caloData->inner_symmetry = nsides ; + caloData->outer_symmetry = nsides ; + caloData->phi0 = 0 ; // hardcoded + + // extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in mm. + caloData->extent[0] = Ecal_inner_radius ; + caloData->extent[1] = ( Ecal_inner_radius + module_thickness ); + caloData->extent[2] = 0. ; + caloData->extent[3] = Ecal_Barrel_halfZ ; + //------------------------------------------------------- + + //==================================================================== + // Place ECAL Barrel stave module into the envelope volume + //==================================================================== + + double X = Ecal_inner_radius + module_thickness / 2.; + + // altered to get alignment as in ECAL interface design doc fig10 + // end of slabs aligned to inner face of support plate in next stave (not the outer surface) + // double Y = (module_thickness/2.) / sin(M_PI/4.); + double Y = (module_thickness_noSupport/2.) / sin(2.*M_PI/nsides); + + // stave numbering from 1->8 + // stave = 1 is in +ve x direction + // stave = 3 is in +ve y direction (ie at top of barrel) + // module index from 1->5 + // module = 1 is at -ve z + + for (int istave = 0; istave < nsides ; istave++) { + //for (int istave = 0; istave < 1 ; istave++) { + int stave_id = istave+1; + + // dstave is the change in stave index from the top module to the one with smallest positive phi (which has istave=0) + int dstave = int( nsides/4. ); + + + // rotations around the center to get the modules in the correct orientation + // top module (dstave) shits by hphi + pi/4 + double phirot = hphi + M_PI/2.; // + phirot += (istave - dstave)*dphi; + + + // this angle is used to get the stave in the right position wrt the origin + double phirot2 = (istave - dstave ) * dphi + hphi; + + for (int imodule = 0; imodule < Ecal_barrel_z_modules; imodule++) { + int module_id = imodule+1; + Transform3D tr( RotationZYX( 0 , phirot, M_PI/2.), // magic rotation! + Translation3D( + ( X*cos(phirot2)-Y*sin(phirot2) ) , + ( X*sin(phirot2)+Y*cos(phirot2) ) , + ( imodule+0.5 )*Ecal_Barrel_module_dim_z - Ecal_Barrel_halfZ ) + ); + PlacedVolume pv = envelope.placeVolume(mod_vol,tr); + pv.addPhysVolID("module",module_id); + pv.addPhysVolID("stave",stave_id); + + DetElement sd = (imodule==0 && istave==0) ? stave_det : stave_det.clone(_toString(module_id,"module%d")+_toString(stave_id,"stave%d")); + sd.setPlacement(pv); + sdet.add(sd); + } + } + + // Set envelope volume attributes. + envelope.setAttributes(theDetector,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + + sdet.addExtension< LayeredCalorimeterData >( caloData ) ; + + // cout << "finished SEcal05_Barrel" << endl; + + return sdet; +} + +DECLARE_DETELEMENT(SEcal05_Barrel,create_detector) diff --git a/Detector/DetCEPCv4/src/calorimeter/SEcal05_ECRing.cpp b/Detector/DetCEPCv4/src/calorimeter/SEcal05_ECRing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9499c1facf20346c61a4a6058ad21b28316f2e13 --- /dev/null +++ b/Detector/DetCEPCv4/src/calorimeter/SEcal05_ECRing.cpp @@ -0,0 +1,689 @@ +//==================================================================== +// lcgeo - LC detector models in DD4hep +//-------------------------------------------------------------------- +// DD4hep Geometry driver for SiWEcalEndcaps +// Ported from Mokka +//-------------------------------------------------------------------- +// S.Lu, DESY +// $Id$ +//==================================================================== + +/* History: + +// ******************************************************* +// * * +// * Mokka * +// * - the detailed geant4 simulation for ILC - * +// * * +// * For more information about Mokka, visit the * +// * * +// * Mokka.in2p3.fr Mokka home page. * +// * * +// ******************************************************* +// +// $Id$ +// $Name: mokka-07-00 $ +// +// +// +// SEcal04.cc +// +Shaojun Lu: Ported from Mokka SEcal04 Endcaps part. Read the constants from XML +instead of the DB. Then build the Endcap in the same way with DD4hep +construct. +Inside SEcal04, some parameters, which used by Ecal Endcaps, come from +Ecal Barrel. They can be seen here again. +Start ECRing ... +*/ + + +/* + + ============== + SEcal05_ECRing + =============== + SEcal04_ECRing driver originally assumend 2 identical modules in +/- z + this is not true, because lumical (and therefore hole in EC plug) is not centred, but offset in +z position + + SEcal05_ECRing driver corrects this (applies offset according to the crossing algle, to center it on the outgoing beampipe). + it also deals with the presence or not of a preshower layer + + this is a hack of the 04 version, not a clean rewrite as was done for barrel and endcap, so it's not very clean & tidy....but I think it works + + DJeans jan 2017 + + ======== + + + - fixed dd4hep::rec::LayeredCalorimeterData for case with no preshower + - small fixes to layer thicknesses (now take from compact description) to get exactly same structure as main endcaps + + DJeans July 2017 + + + ====== + + - fixes to LayeredCalorimeterData: "distance" defined to start of layer, some other issues + - fix to use correct absorber thickness at transition between stacks + - LayeredCalorimeterData material describtion: overall structure made in CF (previously air) + + DJeans Sep 2017 + +*/ + + +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/DetType.h" +#include "XML/Layering.h" +#include "XML/Utilities.h" +#include "DDRec/DetectorData.h" + +using namespace std; + +using dd4hep::BUILD_ENVELOPE; +using dd4hep::Box; +using dd4hep::DetElement; +using dd4hep::Detector; +using dd4hep::Layering; +using dd4hep::Material; +using dd4hep::PlacedVolume; +using dd4hep::Position; +using dd4hep::Readout; +using dd4hep::Ref_t; +using dd4hep::Rotation3D; +using dd4hep::RotationZYX; +using dd4hep::Segmentation; +using dd4hep::SensitiveDetector; +using dd4hep::SubtractionSolid; +using dd4hep::Transform3D; +using dd4hep::Tube; +using dd4hep::Volume; +using dd4hep::_toString; + +using dd4hep::rec::LayeredCalorimeterData; + +//#define VERBOSE 1 + +// workaround for DD4hep v00-14 (and older) +#ifndef DD4HEP_VERSION_GE +#define DD4HEP_VERSION_GE(a,b) 0 +#endif + +static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDetector sens) { + static double tolerance = 0e0; + + cout << "---------------------------------" << endl; + cout << " creating Ecal ECRing ( SEcal05_ECRing ) " << endl; + cout << "---------------------------------" << endl; + + xml_det_t x_det = element; + string det_name = x_det.nameStr(); + Layering layering (element); + + Material air = theDetector.air(); + Material CF = theDetector.material("CarbonFiber"); + + int det_id = x_det.id(); + xml_comp_t x_staves = x_det.staves(); + DetElement sdet (det_name,det_id); + + // --- create an envelope volume and position it into the world --------------------- + + Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector, element , sdet ) ; + + dd4hep::xml::setDetectorTypeFlag( element, sdet ) ; + + if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ; + + //----------------------------------------------------------------------------------- + + sens.setType("calorimeter"); + + Material stave_material = theDetector.material(x_staves.materialStr()); + + Readout readout = sens.readout(); + Segmentation seg = readout.segmentation(); + + std::vector<double> cellSizeVector = seg.segmentation()->cellDimensions(0); //Assume uniform cell sizes, provide dummy cellID + double cell_sizeX = cellSizeVector[0]; + double cell_sizeY = cellSizeVector[1]; + + //==================================================================== + // + // Read all the constant from ILD_o1_v05.xml + // Use them to build Ecal ECRing + // + //==================================================================== + + // read parametere from compact.xml file + double Ecal_fiber_thickness_alveolus = theDetector.constant<double>("Ecal_fiber_thickness_alveolus"); + double Ecal_fiber_thickness_structure = theDetector.constant<double>("Ecal_fiber_thickness_structure"); + + double Ecal_radiator_thickness1 = theDetector.constant<double>("Ecal_radiator_layers_set1_thickness"); + double Ecal_radiator_thickness2 = theDetector.constant<double>("Ecal_radiator_layers_set2_thickness"); + double Ecal_radiator_thickness3 = theDetector.constant<double>("Ecal_radiator_layers_set3_thickness"); + double Ecal_Barrel_halfZ = theDetector.constant<double>("Ecal_Barrel_halfZ"); + + double Ecal_support_thickness = theDetector.constant<double>("Ecal_support_thickness"); + double Ecal_front_face_thickness = theDetector.constant<double>("Ecal_front_face_thickness"); + double Ecal_lateral_face_thickness = theDetector.constant<double>("Ecal_lateral_face_thickness"); + + double Ecal_EC_Ring_gap = theDetector.constant<double>("Ecal_EC_Ring_gap"); + + double Ecal_cables_gap = theDetector.constant<double>("Ecal_cables_gap"); + double Lcal_outer_radius = theDetector.constant<double>("Lcal_outer_radius"); + double Ecal_Lcal_ring_gap = theDetector.constant<double>("Ecal_Lcal_ring_gap"); + double Ecal_endcap_center_box_size = theDetector.constant<double>("Ecal_endcap_center_box_size"); + + int Ecal_nlayers1 = theDetector.constant<int>("Ecal_nlayers1"); + int Ecal_nlayers2 = theDetector.constant<int>("Ecal_nlayers2"); + int Ecal_nlayers3 = theDetector.constant<int>("Ecal_nlayers3"); + + double EcalEndcapRing_inner_radius = theDetector.constant<double>("EcalEndcapRing_inner_radius"); + double EcalEndcapRing_outer_radius = theDetector.constant<double>("EcalEndcapRing_outer_radius"); + double EcalEndcapRing_min_z = theDetector.constant<double>("EcalEndcapRing_min_z"); + double EcalEndcapRing_max_z = theDetector.constant<double>("EcalEndcapRing_max_z"); + + + double crossing_angle = theDetector.constant<double>("CepC_Main_Crossing_Angle"); + bool Ecal_Barrel_PreshowerLayer = theDetector.constant<int>("Ecal_Barrel_Preshower") > 0; + + double Ecal_barrel_thickness = theDetector.constant<double>("Ecal_barrel_thickness"); + + //========== fill data for reconstruction ============================ + dd4hep::rec::LayeredCalorimeterData* caloData = new dd4hep::rec::LayeredCalorimeterData ; + caloData->layoutType = dd4hep::rec::LayeredCalorimeterData::EndcapLayout ; + caloData->inner_symmetry = 0 ; // hard code cernter pipe hole + caloData->outer_symmetry = 4 ; // outer box + caloData->phi0 = 0 ; + + /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in mm. + caloData->extent[0] = EcalEndcapRing_inner_radius ; + caloData->extent[1] = EcalEndcapRing_outer_radius ; + caloData->extent[2] = EcalEndcapRing_min_z ; + caloData->extent[3] = EcalEndcapRing_max_z ; + + + //==================================================================== + // + // general calculated parameters + // + //==================================================================== + + int Number_of_Si_Layers_in_Barrel = 0; + +#ifdef VERBOSE + std::cout << " Ecal total number of Silicon layers = " << Number_of_Si_Layers_in_Barrel << std::endl; +#endif + + int n_total_layers = Ecal_nlayers1 + Ecal_nlayers2 + Ecal_nlayers3; + Number_of_Si_Layers_in_Barrel = n_total_layers; // take account of preshower on/off (djeans) + if ( Ecal_Barrel_PreshowerLayer ) Number_of_Si_Layers_in_Barrel++; + + // calculate total thickness of ECAL + // updated to take info from xml description - djeans: 12 July 2017 + double module_thickness = Ecal_support_thickness + Ecal_front_face_thickness;// front and back supports + + // the absorber in the structure + for (int i=0; i<Ecal_nlayers1+Ecal_nlayers2+Ecal_nlayers3; i++) { + bool inStructure = Ecal_Barrel_PreshowerLayer==1 ? i%2==1 : i%2==0 ; + if ( inStructure ) { + double thickness (Ecal_radiator_thickness1); + if ( i>=Ecal_nlayers1 ) thickness = Ecal_radiator_thickness2; + if ( i>=Ecal_nlayers1+Ecal_nlayers2 ) thickness = Ecal_radiator_thickness3; + module_thickness += thickness + 2*Ecal_fiber_thickness_structure; // the absorber and its wrapping + } + } + + // the slabs + int l_num2(0); + for(xml_coll_t li(x_det,_U(layer)); li; ++li) { // types of layers (i.e. thin/thick absorber) or "stack" + xml_comp_t x_layer = li; + // Loop over number of repeats for this layer. + for (int j=0; j< x_layer.repeat(); j++) { // layers within this type (or "stack") + float thisthick = layering.layer(l_num2)->thickness(); + module_thickness+=thisthick + 2*Ecal_fiber_thickness_alveolus; // slab thickness, and the alveolar wall around it + l_num2++; + } + } + + + if ( fabs( Ecal_barrel_thickness - module_thickness) > 0.1 ) { + cout << "ERROR EC ecal thickness inconsistency: calculated, nominal = " << module_thickness << " " << Ecal_barrel_thickness << endl; + assert(0); + } + +#ifdef VERBOSE + std::cout << " module_thickness = " << module_thickness << std::endl; +#endif + + + double ECRingSiplateSize = Ecal_endcap_center_box_size + - 2 * Ecal_EC_Ring_gap + - 2 * Ecal_lateral_face_thickness; + + + // central hole is not centred on detector axis, but on outgoing beampipe (as is the lumical) + double hole_x_offset = tan(crossing_angle/2.) * (EcalEndcapRing_min_z + EcalEndcapRing_max_z)/2.; + + + // ========= Create Ecal end cap ring ==================================== + // It will be the volume for palcing the Ecal endcaps alveolus(i.e. Layers). + // And the structure W plate. + // Itself will be placed into the world volume. + // ========================================================================== + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //~ EndcapRing ~ + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + for(int module_num=0;module_num<2;module_num++) { // move module loop to here (modules not identical) + + DetElement module_det(_toString(module_num,"module%d"),det_id); + + double thismodule_hole_dx = hole_x_offset; + if ( module_num==0 ) thismodule_hole_dx*=-1; + Position hole_position(thismodule_hole_dx, 0, 0); + + double Ecal_endcap_Tube_rmax = Lcal_outer_radius + Ecal_Lcal_ring_gap; + + Tube CenterECTub(0., Ecal_endcap_Tube_rmax, module_thickness); + Box CenterECBox((Ecal_endcap_center_box_size/2. - Ecal_EC_Ring_gap), + (Ecal_endcap_center_box_size/2. - Ecal_EC_Ring_gap), + module_thickness/2.); + + SubtractionSolid ECRingSolid( CenterECBox, CenterECTub, hole_position); + + // Volume EnvLogECRing("ECRing",ECRingSolid,theDetector.material("g10")); + Volume EnvLogECRing("ECRing",ECRingSolid,theDetector.material("CarbonFiber")); // DJeans 5-sep-2016 + + //============================================================== + // build the layer and place into the ECRing + //============================================================== + + + //------------------------------------------------------- + // Radiator and towers placements inside the ECRing module + //------------------------------------------------------- + + // We count the layers starting from IP and from 1, + // so odd layers should be inside slabs and + // even ones on the structure. + // + + + double distance_ip_to_front_face = Ecal_Barrel_halfZ + Ecal_cables_gap; + double dist_from_front_face_tally(0); + + double z_floor = - module_thickness/2; + + double l_pos_z = z_floor; + + dd4hep::rec::LayeredCalorimeterData::Layer caloLayer ; + caloLayer.cellSize0 = cell_sizeX; + caloLayer.cellSize1 = cell_sizeY; + + //-------------------- start loop over ECAL layers ---------------------- + // Loop over the sets of layer elements in the detector. + double radiator_dim_y = Ecal_radiator_thickness1; //to be updated with slice radiator thickness + + double nRadiationLengths=0.; + double nInteractionLengths=0.; + double thickness_sum=0; + + int l_num = 1; + bool isFirstSens = true; + int myLayerNum = 0 ; + bool isFrontFace=true; + int absorber_index(0); + + for(xml_coll_t li(x_det,_U(layer)); li; ++li) { // types of layer + xml_comp_t x_layer = li; + int repeat = x_layer.repeat(); + + // Loop over number of repeats for this layer. + for (int j=0; j<repeat; j++) { + + // move structural layer to before the slabs - djeans + + // deal with preshower or lack thereof ------------------ + double radiator_dim_Z(0); + //double rad_pos_Z(0); + double this_struct_CFthick_beforeAbs(0); + double this_struct_CFthick_afterAbs(0); + double _CF_absWrap = Ecal_fiber_thickness_structure; + double _CF_alvWall = Ecal_fiber_thickness_alveolus; + if ( isFrontFace ) { // the first part of the module depends on whether we have preshwer or not + if ( Ecal_Barrel_PreshowerLayer==1 ) { // don't include W+CF wrapping; only one side of alveolus + this_struct_CFthick_beforeAbs = 0; + this_struct_CFthick_afterAbs = Ecal_front_face_thickness + _CF_alvWall; + radiator_dim_Z = 0; + } else { // include W+CF wrapping; only one side of alveolus + this_struct_CFthick_beforeAbs = Ecal_front_face_thickness + _CF_absWrap; + this_struct_CFthick_afterAbs = _CF_absWrap + _CF_alvWall; + radiator_dim_Z = Ecal_radiator_thickness1; // this line implicitly assumes Ecal_nlayers1>0... + //rad_pos_Z = radiator_dim_Z/2. + this_struct_CFthick_beforeAbs; // distance from top surface of structure to centre of radiator + absorber_index++; + } + + thickness_sum += radiator_dim_Z; + nRadiationLengths += radiator_dim_Z/stave_material.radLength(); + nInteractionLengths += radiator_dim_Z/stave_material.intLength(); + + thickness_sum += ( this_struct_CFthick_beforeAbs + this_struct_CFthick_afterAbs ); + nRadiationLengths += ( this_struct_CFthick_beforeAbs + this_struct_CFthick_afterAbs ) / CF.radLength(); + nInteractionLengths += ( this_struct_CFthick_beforeAbs + this_struct_CFthick_afterAbs ) / CF.intLength(); + + isFrontFace=false; + } else { // internal layer: include W+CF wrapping; both sides of alveolus + this_struct_CFthick_beforeAbs = _CF_alvWall+_CF_absWrap; + this_struct_CFthick_afterAbs = _CF_alvWall+_CF_absWrap; + + if ( absorber_index<Ecal_nlayers1 ) radiator_dim_Z=Ecal_radiator_thickness1; + else if ( absorber_index<Ecal_nlayers1+Ecal_nlayers2 ) radiator_dim_Z=Ecal_radiator_thickness2; + else if ( absorber_index<Ecal_nlayers1+Ecal_nlayers2+Ecal_nlayers3 ) radiator_dim_Z=Ecal_radiator_thickness3; + else { + assert(0 && "ERROR cannot determine absorber thickness for layer "); + } + + absorber_index++; + + assert( radiator_dim_Z>0 && "no radiator!" ); + } + //------------------------------- + + radiator_dim_y = radiator_dim_Z; // ahh different axis conventions.... + + l_pos_z += this_struct_CFthick_beforeAbs + radiator_dim_y/2; + + // ######################### + // BuildECRingStructureLayer + // ######################### + + Tube CenterECTubForSi(0., + Lcal_outer_radius + Ecal_Lcal_ring_gap + 0.001, // + tolerance, + module_thickness, + 0., + 2 * M_PI); + + + string l_name = _toString(l_num,"layer%d"); + RotationZYX rot(0,0,0); // a null rotation + + if ( radiator_dim_y>0 ) { + + string bs_name="bs"; + Box EndcapStructureLayer_box(ECRingSiplateSize/ 2. - tolerance, ECRingSiplateSize/ 2. - tolerance, radiator_dim_y/2.); + SubtractionSolid EndcapStructureLayerSolid( EndcapStructureLayer_box, CenterECTubForSi, hole_position); + Volume EndcapStructureLayer_vol(det_name+"_"+l_name+"_"+bs_name,EndcapStructureLayerSolid,theDetector.material(x_staves.materialStr())); + EndcapStructureLayer_vol.setVisAttributes(theDetector.visAttributes( x_staves.visStr())); + + // this is where we place the tungsten into the envelope + double bsl_pos_z = l_pos_z; + Position bsl_pos(0,0,bsl_pos_z); + Transform3D bsl_tran3D(rot,bsl_pos); + EnvLogECRing.placeVolume(EndcapStructureLayer_vol,bsl_tran3D); + } + + // Increment to next layer Z position. + l_pos_z += radiator_dim_y/2 + this_struct_CFthick_afterAbs; + + // now move to the alveolus and what's inside + double l_thickness = layering.layer(l_num-1)->thickness(); // Layer's thickness. this is the internal thickness of the alveolus + + l_pos_z += l_thickness/2.; // add in half the alveolus thickness + + int EC_Number_of_towers = 0; + + // We use the same method able to create the Barrel + // Slabs, so we have to rotate it later when placing + // into the EC modules. + // + // We use the same method able to create the Barrel + // radiator plates between slabs, but with the good + // dimensions to avoid to rotate it later when placing + // into the EC modules. + + // While the towers have the same shape use the same + // logical volumes and parameters. + + string tower_name = _toString(EC_Number_of_towers,"tower%d"); + + // build the ECRing layer, a box with hole in the middle + Box ECRingSiBox( ECRingSiplateSize/ 2. - tolerance, ECRingSiplateSize/ 2. - tolerance, l_thickness/2.0-tolerance); + + SubtractionSolid ECRingSiSolid( ECRingSiBox, CenterECTubForSi, hole_position); + + Volume l_vol(det_name+"_"+l_name+"_"+tower_name,ECRingSiSolid,air); + DetElement layer(module_det, l_name+tower_name, det_id); + + l_vol.setVisAttributes(theDetector.visAttributes( x_layer.visStr() )); + + // Loop over the sublayers or slices for this layer. + int s_num = 1; + double s_pos_z = -(l_thickness / 2); + + //-------------------------------------------------------------------------------- + // BuildECRing keep the Alveolus structure, the same as the Barrel and Endcap + //-------------------------------------------------------------------------------- + + for(xml_coll_t si(x_layer,_U(slice)); si; ++si) { + xml_comp_t x_slice = si; + string s_name = _toString(s_num,"slice%d"); + double s_thick = x_slice.thickness(); + Material slice_material = theDetector.material(x_slice.materialStr()); + + double slab_dim_x = ECRingSiplateSize/2.-tolerance; + double slab_dim_y = s_thick/2.-tolerance; + double slab_dim_z = ECRingSiplateSize/2.-tolerance; + + Box s_box(slab_dim_x,slab_dim_z,slab_dim_y); + + SubtractionSolid ECRingSiSliceSolid( s_box, CenterECTubForSi, hole_position); + + Volume s_vol(det_name+"_"+l_name+"_"+s_name,ECRingSiSliceSolid,slice_material); + DetElement slice(layer,s_name,det_id); + + s_vol.setVisAttributes(theDetector.visAttributes(x_slice.visStr())); + +#ifdef VERBOSE + std::cout<<"x_slice.materialStr(): "<< x_slice.materialStr() <<std::endl; +#endif + if (x_slice.materialStr().compare(x_staves.materialStr()) == 0){ + radiator_dim_y = s_thick; + + absorber_index++; + +#if DD4HEP_VERSION_GE( 0, 15 ) + caloLayer.outer_nRadiationLengths = nRadiationLengths; + caloLayer.outer_nInteractionLengths = nInteractionLengths; + caloLayer.outer_thickness = thickness_sum; + caloLayer.distance = distance_ip_to_front_face + dist_from_front_face_tally; +#endif + if (Ecal_Barrel_PreshowerLayer==0 || !isFirstSens ){ // add this layer to the caloData (unless its the first absorber layer of a no-preshower calo) + if ( module_num==0 ) { + caloData->layers.push_back( caloLayer ) ; +#ifdef VERBOSE +#if DD4HEP_VERSION_GE( 0, 15 ) + std::cout<<" caloLayer.distance: "<< caloLayer.distance <<std::endl; + std::cout<<" caloLayer.inner_nRadiationLengths: "<< caloLayer.inner_nRadiationLengths <<std::endl; + std::cout<<" caloLayer.inner_nInteractionLengths: "<< caloLayer.inner_nInteractionLengths <<std::endl; + std::cout<<" caloLayer.inner_thickness: "<< caloLayer.inner_thickness <<std::endl; + std::cout<<" caloLayer.sensitive_thickness: "<< caloLayer.sensitive_thickness <<std::endl; + std::cout<<" caloLayer.cellSize0, 1: " << caloLayer.cellSize0 << " " << caloLayer.cellSize1 << std::endl; + std::cout<<" caloLayer.outer_nRadiationLengths: "<< caloLayer.outer_nRadiationLengths <<std::endl; + std::cout<<" caloLayer.outer_nInteractionLengths: "<< caloLayer.outer_nInteractionLengths <<std::endl; + std::cout<<" caloLayer.outer_thickness: "<< caloLayer.outer_thickness <<std::endl; + std::cout<<" EcalECRing[1]==>caloLayer.inner_thickness + caloLayer.outer_thickness: " + << caloLayer.inner_thickness + caloLayer.outer_thickness <<std::endl; +#endif +#endif + dist_from_front_face_tally += caloLayer.inner_thickness+caloLayer.outer_thickness; + } + } + + nRadiationLengths = 0. ; + nInteractionLengths = 0. ; + thickness_sum = 0. ; + isFirstSens = false; + } // if radiator + + nRadiationLengths += s_thick/(2.*slice_material.radLength()); + nInteractionLengths += s_thick/(2.*slice_material.intLength()); + thickness_sum += s_thick/2; + + if ( x_slice.isSensitive() ) { + s_vol.setSensitiveDetector(sens); + +#if DD4HEP_VERSION_GE( 0, 15 ) + //Store "inner" quantities + caloLayer.inner_nRadiationLengths = nRadiationLengths; + caloLayer.inner_nInteractionLengths = nInteractionLengths; + caloLayer.inner_thickness = thickness_sum; + //Store sensitive slice thickness + caloLayer.sensitive_thickness = s_thick; +#ifdef VERBOSE + std::cout<<" l_num: "<<l_num <<std::endl; + std::cout<<" s_num: "<<s_num <<std::endl; + std::cout<<" module_thickness: "<< module_thickness <<std::endl; + std::cout<<" l_pos_z: "<< l_pos_z <<std::endl; + std::cout<<" l_thickness: "<< l_thickness <<std::endl; + std::cout<<" s_pos_z: "<< s_pos_z <<std::endl; + std::cout<<" s_thick: "<< s_thick <<std::endl; + std::cout<<" radiator_dim_y: "<< radiator_dim_y <<std::endl; +#endif + caloLayer.absorberThickness = radiator_dim_y ; +#endif + nRadiationLengths = 0. ; + nInteractionLengths = 0. ; + thickness_sum = 0. ; + } // if sensitive + + nRadiationLengths += s_thick/(2.*slice_material.radLength()); + nInteractionLengths += s_thick/(2.*slice_material.intLength()); + thickness_sum += s_thick/2; + + slice.setAttributes(theDetector,s_vol,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr()); + + // Slice placement. + PlacedVolume slice_phv = l_vol.placeVolume(s_vol,Position(0,0,s_pos_z+s_thick/2)); + + if ( x_slice.isSensitive() ) { + slice_phv.addPhysVolID("layer", myLayerNum++); + } + + slice.setPlacement(slice_phv); + // Increment Z position of slice. + s_pos_z += s_thick; + + // Increment slice number. + ++s_num; + } + + // add material between the "slabs" + + // we need to use correct thickness here! especially at the interface between stacks. + if ( absorber_index < Ecal_nlayers1 ) radiator_dim_y=Ecal_radiator_thickness1; + else if ( absorber_index < Ecal_nlayers1+Ecal_nlayers2 ) radiator_dim_y=Ecal_radiator_thickness2; + else if ( absorber_index < Ecal_nlayers1+Ecal_nlayers2+Ecal_nlayers3 ) radiator_dim_y=Ecal_radiator_thickness3; + else { + radiator_dim_y=0; + } + + // deal with final support plate + float cf_thick = Ecal_fiber_thickness_alveolus; + if ( absorber_index<Ecal_nlayers1+Ecal_nlayers2+Ecal_nlayers3 ) { + cf_thick += Ecal_fiber_thickness_structure; + } else { + cf_thick += Ecal_support_thickness; + } + + if ( module_num==0 ) { +#if DD4HEP_VERSION_GE( 0, 15 ) + caloLayer.distance = distance_ip_to_front_face + dist_from_front_face_tally; + caloLayer.outer_nRadiationLengths = nRadiationLengths + cf_thick/CF.radLength(); + caloLayer.outer_nInteractionLengths = nInteractionLengths + cf_thick/CF.intLength(); + caloLayer.outer_thickness = thickness_sum + cf_thick; +#endif + caloData->layers.push_back( caloLayer ) ; + +#ifdef VERBOSE +#if DD4HEP_VERSION_GE( 0, 15 ) + std::cout<<" caloLayer.distance: "<< caloLayer.distance <<std::endl; + std::cout<<" caloLayer.inner_nRadiationLengths: "<< caloLayer.inner_nRadiationLengths <<std::endl; + std::cout<<" caloLayer.inner_nInteractionLengths: "<< caloLayer.inner_nInteractionLengths <<std::endl; + std::cout<<" caloLayer.inner_thickness: "<< caloLayer.inner_thickness <<std::endl; + std::cout<<" caloLayer.sensitive_thickness: "<< caloLayer.sensitive_thickness <<std::endl; + std::cout<<" caloLayer.cellSize0, 1: " << caloLayer.cellSize0 << " " << caloLayer.cellSize1 << std::endl; + std::cout<<" caloLayer.outer_nRadiationLengths: "<< caloLayer.outer_nRadiationLengths <<std::endl; + std::cout<<" caloLayer.outer_nInteractionLengths: "<< caloLayer.outer_nInteractionLengths <<std::endl; + std::cout<<" caloLayer.outer_thickness: "<< caloLayer.outer_thickness <<std::endl; + + std::cout<<" EcalECRing[2]==>caloLayer.inner_thickness + caloLayer.outer_thickness: " + << caloLayer.inner_thickness + caloLayer.outer_thickness <<std::endl; +#endif +#endif + dist_from_front_face_tally += caloLayer.inner_thickness+caloLayer.outer_thickness; + } + + nRadiationLengths = radiator_dim_y/stave_material.radLength() + cf_thick/CF.radLength(); + nInteractionLengths = radiator_dim_y/stave_material.intLength() + cf_thick/CF.intLength(); + thickness_sum = radiator_dim_y + cf_thick; + + // this is where we place the slab (l_vol) into the envelope + int i_stave = 1; + int i_tower = 1; + Position l_pos(0,0,l_pos_z); + Transform3D tran3D(rot,l_pos); + PlacedVolume layer_phv = EnvLogECRing.placeVolume(l_vol,tran3D); + layer_phv.addPhysVolID("tower", i_tower); + layer_phv.addPhysVolID("stave", i_stave); + layer.setPlacement(layer_phv); + + l_pos_z += l_thickness/2.; // add in the other half of the alveolus + + ++l_num; + + } + } + + + // Set stave visualization. + if (x_staves) { + EnvLogECRing.setVisAttributes(theDetector.visAttributes(x_staves.visStr())); + } + + + //==================================================================== + // Place Ecal Endcap module into the assembly envelope volume + //==================================================================== + + double EC_module_z_offset = (EcalEndcapRing_min_z + EcalEndcapRing_max_z)/2.; + + int module_id = ( module_num == 0 ) ? 0:6; + double this_module_z_offset = ( module_id == 0 ) ? - EC_module_z_offset : EC_module_z_offset; + double this_module_rotY = ( module_id == 0 ) ? M_PI:0; + + Position xyzVec(0,0,this_module_z_offset); + RotationZYX rot(0,this_module_rotY,0); + Rotation3D rot3D(rot); + Transform3D tran3D(rot3D,xyzVec); + + PlacedVolume pv = envelope.placeVolume(EnvLogECRing,tran3D); + pv.addPhysVolID("module",module_id); // z: -/+ 0/6 + + DetElement sd = module_det; + sd.setPlacement(pv); + + } + + sdet.addExtension< dd4hep::rec::LayeredCalorimeterData >( caloData ) ; + + return sdet; + +} + + + +DECLARE_DETELEMENT(SEcal05_ECRing, create_detector) + diff --git a/Detector/DetCEPCv4/src/calorimeter/SEcal05_Endcaps.cpp b/Detector/DetCEPCv4/src/calorimeter/SEcal05_Endcaps.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a0f4c69ab8d19f05f2380a693f4549bbcf8dc8f5 --- /dev/null +++ b/Detector/DetCEPCv4/src/calorimeter/SEcal05_Endcaps.cpp @@ -0,0 +1,390 @@ +//==================================================================== +// lcgeo - LC detector models in DD4hep +//-------------------------------------------------------------------- +// DD4hep Geometry driver for SiWEcalEndcaps +// Ported from Mokka +//-------------------------------------------------------------------- +// S.Lu, DESY +// $Id: SEcal04_Endcaps.cpp 1060 2016-09-05 07:48:41Z /C=JP/O=KEK/OU=CRC/CN=JEANS Daniel Thomelin Dietrich $ +//==================================================================== + + /* History: + +// ******************************************************* +// * * +// * Mokka * +// * - the detailed geant4 simulation for ILC - * +// * * +// * For more information about Mokka, visit the * +// * * +// * Mokka.in2p3.fr Mokka home page. * +// * * +// ******************************************************* +// +// $Id: SEcal04_Endcaps.cpp 1060 2016-09-05 07:48:41Z /C=JP/O=KEK/OU=CRC/CN=JEANS Daniel Thomelin Dietrich $ +// $Name: mokka-07-00 $ +// +// +// +// SEcal04.cc +// + Shaojun Lu: Ported from Mokka SEcal04 Endcaps part. Read the constants from XML + instead of the DB. Then build the Endcap in the same way with DD4hep + construct. + Inside SEcal04, some parameters, which used by Ecal Endcaps, come from + Ecal Barrel. They can be ssen here again. + */ + +#include "DD4hep/DetFactoryHelper.h" +#include "XML/Layering.h" +#include "DD4hep/Shapes.h" +#include "XML/Utilities.h" +#include "DDRec/DetectorData.h" +#include "DDSegmentation/WaferGridXY.h" +#include <sstream> + +using namespace std; + +using dd4hep::BUILD_ENVELOPE; +using dd4hep::Box; +using dd4hep::DetElement; +using dd4hep::Detector; +using dd4hep::IntersectionSolid; +using dd4hep::Layering; +using dd4hep::Material; +using dd4hep::PlacedVolume; +using dd4hep::PolyhedraRegular; +using dd4hep::Position; +using dd4hep::Readout; +using dd4hep::Ref_t; +using dd4hep::Rotation3D; +using dd4hep::RotationZYX; +using dd4hep::Segmentation; +using dd4hep::SensitiveDetector; +using dd4hep::Transform3D; +using dd4hep::Volume; +using dd4hep::_toString; + +using dd4hep::rec::LayeredCalorimeterData; + +#include "SEcal05_Helpers.h" + +#undef NDEBUG +#include <assert.h> + + +//#define VERBOSE 1 + +// workaround for DD4hep v00-14 (and older) +#ifndef DD4HEP_VERSION_GE +#define DD4HEP_VERSION_GE(a,b) 0 +#endif + +static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDetector sens) { + + cout << "------------------------" << endl; + cout << "creating SEcal05_Endcaps" << endl; + cout << "------------------------" << endl; + + xml_det_t x_det = element; + string det_name = x_det.nameStr(); + Layering layering (element); + + int det_id = x_det.id(); + // xml_comp_t x_staves = x_det.staves(); + DetElement sdet (det_name,det_id); + // Volume motherVol = theDetector.pickMotherVolume(sdet); + + // --- create an envelope volume and position it into the world --------------------- + + Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector, element , sdet ) ; + + dd4hep::xml::setDetectorTypeFlag( element, sdet ) ; + + if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ; + //----------------------------------------------------------------------------------- + + sens.setType("calorimeter"); + + Readout readout = sens.readout(); + Segmentation seg = readout.segmentation(); + + //==================================================================== + // + // Read all the constant from ILD_o1_v05.xml + // Use them to build Ecal endcaps + // + //==================================================================== + + // read parameters from compact.xml file + double Ecal_Slab_shielding = theDetector.constant<double>("Ecal_Slab_shielding"); + double Ecal_fiber_thickness_structure = theDetector.constant<double>("Ecal_fiber_thickness_structure"); // absorber wrapping thickness + double Ecal_fiber_thickness_alveolus = theDetector.constant<double>("Ecal_fiber_thickness_alveolus"); // alveolar wall thickness + + double EcalBarrel_inner_radius = theDetector.constant<double>("TPC_outer_radius") +theDetector.constant<double>("Ecal_Tpc_gap"); + int Ecal_barrel_z_modules = theDetector.constant<int>("Ecal_barrel_z_modules"); + + double Ecal_radiator_thickness1 = theDetector.constant<double>("Ecal_radiator_layers_set1_thickness"); + double Ecal_radiator_thickness2 = theDetector.constant<double>("Ecal_radiator_layers_set2_thickness"); + double Ecal_radiator_thickness3 = theDetector.constant<double>("Ecal_radiator_layers_set3_thickness"); + double Ecal_Barrel_halfZ = theDetector.constant<double>("Ecal_Barrel_halfZ"); + + int Ecal_barrel_number_of_towers = theDetector.constant<int>("Ecal_barrel_number_of_towers"); + + double Ecal_support_thickness = theDetector.constant<double>("Ecal_support_thickness"); + double Ecal_front_face_thickness = theDetector.constant<double>("Ecal_front_face_thickness"); + double Ecal_lateral_face_thickness = theDetector.constant<double>("Ecal_lateral_face_thickness"); + double Ecal_Slab_H_fiber_thickness = theDetector.constant<double>("Ecal_Slab_H_fiber_thickness"); + + double Ecal_endcap_extra_size = theDetector.constant<double>("Ecal_endcap_extra_size"); + double Ecal_cables_gap = theDetector.constant<double>("Ecal_cables_gap"); + + int Ecal_nlayers1 = theDetector.constant<int>("Ecal_nlayers1"); + int Ecal_nlayers2 = theDetector.constant<int>("Ecal_nlayers2"); + int Ecal_nlayers3 = theDetector.constant<int>("Ecal_nlayers3"); + + // first layer is preshower? + bool Ecal_Endcap_PreshowerLayer = theDetector.constant<int>("Ecal_Endcap_Preshower") > 0; + + std::string Ecal_endcap_number_of_towers = theDetector.constant<string>("Ecal_endcap_number_of_towers"); + + int Ecal_end_of_slab_strategy = theDetector.constant<int>("Ecal_end_of_slab_strategy"); + + + int Ecal_n_wafers_per_tower = theDetector.constant<int>("Ecal_n_wafers_per_tower"); + + double Ecal_guard_ring_size = theDetector.constant<double>("Ecal_guard_ring_size"); + + double EcalEndcap_inner_radius = theDetector.constant<double>("EcalEndcap_inner_radius"); + double EcalEndcap_outer_radius = theDetector.constant<double>("EcalEndcap_outer_radius"); + double EcalEndcap_min_z = theDetector.constant<double>("EcalEndcap_min_z"); + double EcalEndcap_max_z = theDetector.constant<double>("EcalEndcap_max_z"); + + std::string Ecal_layerConfig = theDetector.constant<string>("Ecal_layer_pattern"); + + int Ecal_cells_across_megatile = theDetector.constant <int> ("Ecal_cells_across_megatile" ); + int Ecal_strips_across_megatile= theDetector.constant <int> ("Ecal_strips_across_megatile"); + int Ecal_strips_along_megatile = theDetector.constant <int> ("Ecal_strips_along_megatile" ); + + double Ecal_barrel_thickness = theDetector.constant<double>("Ecal_barrel_thickness"); // what's assumed in the compact description + + + //==================================================================== + // + // set up the helper + // + //==================================================================== + + SEcal05_Helpers helper; + + helper.setDet( & x_det ); + + // layer configuration + helper.setPreshower( Ecal_Endcap_PreshowerLayer ); + + cout << "Preshower ? " << Ecal_Endcap_PreshowerLayer << endl; + + helper.setAbsLayers( Ecal_nlayers1, Ecal_radiator_thickness1, + Ecal_nlayers2, Ecal_radiator_thickness2, + Ecal_nlayers3, Ecal_radiator_thickness3 ); + + cout << "absorber layers " << + Ecal_nlayers1 << "*" << Ecal_radiator_thickness1 << "mm + " << + Ecal_nlayers2 << "*" << Ecal_radiator_thickness2 << "mm + " << + Ecal_nlayers3 << "*" << Ecal_radiator_thickness3 << "mm " << endl; + + // check this setup is self-consistent + helper.checkLayerConsistency(); + + // set structural CF thicknesses + helper.setCFthickness( Ecal_fiber_thickness_structure, + Ecal_fiber_thickness_alveolus, + Ecal_front_face_thickness, + Ecal_support_thickness); + + // check that resulting total thickness is consistent with what's in the compact file + // n.b. this assumes same thickness in barrel and endcap! + float module_thickness = helper.getTotalThickness(); + if ( fabs( Ecal_barrel_thickness - module_thickness ) > 0.1*dd4hep::mm ) { + cout << "ERROR : thickness in comapct decription not consistent with what I calculate!" << endl; + cout << " calculated = " << module_thickness << " compact description: " << Ecal_barrel_thickness << endl; + assert( 0 ); // exit + } + + cout << "module thickness = " << module_thickness << endl; + + // set up the sensitive layer segmentation + helper.setSegmentation( &seg ); + + helper.setNCells( Ecal_cells_across_megatile, Ecal_strips_across_megatile, Ecal_strips_along_megatile); + helper.setMagicMegatileStrategy ( Ecal_end_of_slab_strategy ); + + + int ntemp; + std::stringstream stream(Ecal_layerConfig); + std::vector < int > layerConfig; + while ( stream >> ntemp ) { + assert( ntemp>=0 ); + layerConfig.push_back( ntemp ); + } + cout << "layer config: "; + for (size_t i=0; i<layerConfig.size(); i++) cout << layerConfig[i] << " "; + cout << endl; + + helper.setLayerConfig( layerConfig ); + + // set the number of towers/modules + std::vector < int > ntowers; + std::stringstream stream2( Ecal_endcap_number_of_towers ); + while ( stream2 >> ntemp ) { + ntowers.push_back( ntemp ); + } + + cout << "ECAL endcap tower configuration " << Ecal_endcap_number_of_towers << " : "; + for (size_t i=0; i<ntowers.size(); i++) + cout << ntowers[i] << " "; + cout << endl; + + // check that resulting quadrant size is consistent with compact description + // here we assume that the width of an alveolus in the endcaps is the same as that in the barrel. + double barrel_alv_width = ( Ecal_Barrel_halfZ*2./Ecal_barrel_z_modules - 2.*Ecal_lateral_face_thickness ) / Ecal_barrel_number_of_towers; + double calc_endcap_rout(EcalEndcap_inner_radius); + for (size_t i=0; i<ntowers.size(); i++) { + calc_endcap_rout+=ntowers[i]*barrel_alv_width + 2.*Ecal_lateral_face_thickness; + } + + cout << "alveolus width = " << barrel_alv_width << endl; + + // compare calculated size vs that in compact description + if ( fabs( calc_endcap_rout - EcalEndcap_outer_radius ) > 0.1*dd4hep::mm ) { + cout << "WARNING, inconsistent ECAL endcap radial extent! calculated: " << calc_endcap_rout << + " cm , nominal (from compact descrition): " << EcalEndcap_outer_radius << endl; + cout << "consider changing Ecal_endcap_extra_size from " << Ecal_endcap_extra_size << + " to " << calc_endcap_rout - EcalBarrel_inner_radius - Ecal_barrel_thickness << endl; + assert(0); + } + + + helper.setTowersUnits( ntowers, + barrel_alv_width, + Ecal_n_wafers_per_tower, + Ecal_lateral_face_thickness, + Ecal_fiber_thickness_alveolus + Ecal_Slab_H_fiber_thickness + Ecal_Slab_shielding, + Ecal_guard_ring_size ); + + + + // ========= Create Ecal endcaps ==================================== + // It will be the volume for palcing the Ecal endcaps alveolus(i.e. Layers). + // And the structure W plate. + // Itself will be placed into the world volume. + // ========================================================================== + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //~ EndcapStandardModule ~ + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // octagon + PolyhedraRegular ECPolyHedra(8, M_PI/8., 0., calc_endcap_rout, module_thickness); + + // take just one quadrant of the octagon, and remove the centre box + double quadr = calc_endcap_rout; // anything which is big enough + Box quadrant( quadr, quadr , module_thickness); + IntersectionSolid EndCapSolid( ECPolyHedra, + quadrant, + Position( quadr - EcalEndcap_inner_radius, + quadr + EcalEndcap_inner_radius, 0 ) ); + + Volume EnvLogEndCap("EcalEndcapQuadrant",EndCapSolid,theDetector.material("CarbonFiber")); + + // kink position wrt bottom of quadrant (inside the lateral support) + // Y==0 is defined as outer edge of lateral face of inner module of quadrant + double kink_y = calc_endcap_rout*tan(M_PI/8.) - EcalEndcap_inner_radius; + + helper.setModuleDimensions(1, // xytype + 0, // xztype + calc_endcap_rout + EcalEndcap_inner_radius, // dxMax + kink_y + ); + + helper.setTranslation ( Position ( -EcalEndcap_inner_radius , EcalEndcap_inner_radius, -module_thickness/2. ) ); + + // make the module + + LayeredCalorimeterData* caloData = new LayeredCalorimeterData ; + caloData->layoutType = LayeredCalorimeterData::EndcapLayout ; + + DetElement mod_det ("quad0",det_id); + + helper.makeModule( EnvLogEndCap, + mod_det, + *caloData, + theDetector, + sens ); + + for (size_t i=0; i<caloData->layers.size(); i++) { + caloData->layers[i].distance += Ecal_Barrel_halfZ + Ecal_cables_gap; // add IP->front face distance + } + + // cout << "cell sizes: " << endl; + // for (size_t i=0; i<caloData->layers.size(); i++) { + // cout << "sensitive layer " << i << " : x,y = " << caloData->layers[i].cellSize0 << " " << caloData->layers[i].cellSize1 << endl; + // } + + caloData->layoutType = LayeredCalorimeterData::EndcapLayout ; + caloData->inner_symmetry = 4 ; // hard code cernter box hole + caloData->outer_symmetry = 8 ; // outer Octagun + caloData->phi0 = 0 ; + + /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in mm. + caloData->extent[0] = EcalEndcap_inner_radius ; + caloData->extent[1] = EcalEndcap_outer_radius ; + caloData->extent[2] = EcalEndcap_min_z ; + caloData->extent[3] = EcalEndcap_max_z ; + + + + //==================================================================== + // Place Ecal Endcap modules into the assembly envelope volume + //==================================================================== + + for (int iend=0; iend<2; iend++) { // the 2 endcaps + int module_id = ( iend == 0 ) ? 0:6; + + double this_module_z_offset = (EcalEndcap_min_z + EcalEndcap_max_z)/2.; + if ( iend == 0 ) this_module_z_offset*=-1; + + double this_module_rotY = iend==0 ? M_PI : 0; + double rotZ_offset = iend==0 ? M_PI/8. - M_PI/2. : M_PI/8. + 3.*M_PI/4.; // magic rotation to get modules in right place + for (int iquad=0; iquad<4; iquad++) { // the 4 quadrants per endcap + int stave_id=iquad+1; + double this_module_rotZ(0); + if ( iend==0 ) { + this_module_rotZ = rotZ_offset - (iquad-2) * M_PI/2.; + } else { + this_module_rotZ = rotZ_offset + (iquad+1) * M_PI/2.; + } + Position xyzVec(0,0,this_module_z_offset); + RotationZYX rot( this_module_rotZ ,this_module_rotY, 0); + Rotation3D rot3D(rot); + Transform3D tran3D(rot3D,xyzVec); + PlacedVolume pv = envelope.placeVolume(EnvLogEndCap,tran3D); + pv.addPhysVolID("module",module_id); // z: -/+ 0/6 + pv.addPhysVolID("stave",stave_id); + DetElement sd = (iend==0 && iquad==0) ? mod_det : mod_det.clone(_toString(module_id,"module%d")+_toString(stave_id,"stave%d")); + sd.setPlacement(pv); + } + } + + sdet.addExtension< LayeredCalorimeterData >( caloData ) ; + + // cout << "finished SEcal05_Endcaps" << endl; + + return sdet; + +} + + + +DECLARE_DETELEMENT(SEcal05_Endcaps, create_detector) + diff --git a/Detector/DetCEPCv4/src/calorimeter/SEcal05_Helpers.cpp b/Detector/DetCEPCv4/src/calorimeter/SEcal05_Helpers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5b57dcf0a37225ae152b788954ac4664967712a --- /dev/null +++ b/Detector/DetCEPCv4/src/calorimeter/SEcal05_Helpers.cpp @@ -0,0 +1,729 @@ +#include "SEcal05_Helpers.h" + +SEcal05_Helpers::SEcal05_Helpers() { + // constructor, initialise internal variables + _x_det=NULL; + _layering=NULL; + _preshower=-1; + + _CF_absWrap=-1; + _CF_alvWall=-1; + _CF_front=-1; + _CF_back=-1; + + _ntowers.clear(); + _towerGap=-999; + _unitsPerTower=0; + _unitDeadEdge=-999; + + _cells_across_megatile=0; + _strips_across_megatile=0; + _strips_along_megatile=0; + + _constantSlabXYDimensions.clear(); + + _caloLayer.absorberThickness = -999; + _caloLayer.sensitive_thickness = -999; + _caloLayer.distance = 0; + + _totThick=0; + + _plugLength=0; + + _magicMegatileStrategy=-1; +} + + +void SEcal05_Helpers::setAbsLayers( int nl1, double th1, int nl2, double th2, int nl3, double th3 ) { + // set the number and thicknesses of absorber layers + _nlayers1=nl1; + _nlayers2=nl2; + _nlayers3=nl3; + _radiator_thickness1=th1; + _radiator_thickness2=th2; + _radiator_thickness3=th3; + return; +} + +void SEcal05_Helpers::checkLayerConsistency() { + // check requested number of absorber layers is cinsistent with preshower status + // we are constrained to have an even number of sensitive layers [ 2 sens. layers / slab ] + assert( (_preshower==0 || _preshower==1) && "_preshower not set" ); + int n_total_abs_layers = _nlayers1 + _nlayers2 + _nlayers3; // total number of Absorber layers + // check that number of requested absober layers is consistent + // if we want a preshower layer, total number of Absorber layers should be odd; otherwise even + if ( _preshower==1 && n_total_abs_layers%2==0 ) { + std::cout << "SEcal05_Helpers ERROR: inconsistent ECAL model !! if you request a preshower layer, the number of absorber layers = _nlayers1 + _nlayers2 + _nlayers3 must be odd" << std::endl; + std::cout << " Ecal_PreshowerLayer = " << _preshower << " ; _nlayers1/2/3 = " << _nlayers1 << " " << _nlayers2 << " " << _nlayers3 << std::endl; + assert(0); + } else if ( _preshower==0 && n_total_abs_layers%2==1 ) { + std::cout << "SEcal05_Helpers ERROR: inconsistent ECAL model !! if you request no preshower layer, the number of absorber layers = _nlayers1 + _nlayers2 + _nlayers3 must be even" << std::endl; + std::cout << " Ecal_PreshowerLayer = " << _preshower << " ; _nlayers1/2/3 = " << _nlayers1 << " " << _nlayers2 << " " << _nlayers3 << std::endl; + assert(0); + } + return; +} + +float SEcal05_Helpers::getTotalThickness() { + // calculate total thickness of ECAL + checkLayerConsistency(); + assert( _x_det && _layering && "_x_det or _layering not set" ); + assert( (_preshower==0 || _preshower==1) && "_preshower not set" ); + assert( _CF_absWrap>=0. && _CF_alvWall>=0. && _CF_front>=0. && _CF_back>=0. && "CF thicknesses not set" ); + float totalThickness = _CF_front+_CF_back;// front and back supports + + // the absorber in the structure + for (unsigned int i=0; i<_nlayers1+_nlayers2+_nlayers3; i++) { + bool inStructure = _preshower ? i%2==1 : i%2==0 ; + if ( inStructure ) { + double thickness (_radiator_thickness1); + if ( i>=_nlayers1 ) thickness = _radiator_thickness2; + if ( i>=_nlayers1+_nlayers2 ) thickness = _radiator_thickness3; + totalThickness += thickness + 2*_CF_absWrap; // the absorber and its wrapping + } + } + // the slabs + int l_num(0); + for(xml_coll_t li(*_x_det,_U(layer)); li; ++li) { // types of layers (i.e. thin/thick absorber) or "stack" + xml_comp_t x_layer = li; + // Loop over number of repeats for this layer. + for (int j=0; j< x_layer.repeat(); j++) { // layers within this type (or "stack") + float thisthick = _layering->layer(l_num)->thickness(); + totalThickness+=thisthick + 2*_CF_alvWall; // slab thickness, and the alveolar wall around it + l_num++; + } + } + return totalThickness; +} + +void SEcal05_Helpers::printSEcal05LayerInfo( dd4hep::rec::LayeredCalorimeterData::Layer & caloLayer) { + std::cout<<"SEcal05_Helpers === CALOLAYER printout: " << std::endl; + std::cout<<" caloLayer.distance: " << caloLayer.distance <<std::endl; + std::cout<<" caloLayer.inner_nRadiationLengths: " << caloLayer.inner_nRadiationLengths <<std::endl; + std::cout<<" caloLayer.inner_nInteractionLengths: "<< caloLayer.inner_nInteractionLengths <<std::endl; + std::cout<<" caloLayer.inner_thickness: " << caloLayer.inner_thickness <<std::endl; + std::cout<<" caloLayer.sensitive_thickness: " << caloLayer.sensitive_thickness <<std::endl; + std::cout<<" caloLayer.cellSize0, 1: " << caloLayer.cellSize0 << " " << caloLayer.cellSize1 << std::endl; + std::cout<<" caloLayer.outer_nRadiationLengths: " << caloLayer.outer_nRadiationLengths <<std::endl; + std::cout<<" caloLayer.outer_nInteractionLengths: "<< caloLayer.outer_nInteractionLengths <<std::endl; + std::cout<<" caloLayer.outer_thickness: " << caloLayer.outer_thickness <<std::endl; + return; +} + +double SEcal05_Helpers::getAbsThickness( unsigned int iAbsLay ) { //, int n1, int n2, int n3, double t1, double t2, double t3) { + // get the thickness of a given absorber layer + if ( iAbsLay < _nlayers1 ) return _radiator_thickness1; + else if ( iAbsLay - _nlayers1 < _nlayers2 ) return _radiator_thickness2; + else if ( iAbsLay - _nlayers1 - _nlayers2 < _nlayers3 ) return _radiator_thickness3; + assert(0 && "impossible layer number"); // should never get here + return -999.; +} + + + +std::vector <SEcal05_Helpers::dimposXYStruct> SEcal05_Helpers::getAbsPlateXYDimensions( double ztop ) { + // get the dimensions of absorber plates + // for trapeziodal case, this depends on the Z position + // CF wrap not taken into account, so this width constains both absorber and its wrapping + + if ( _module_XZtype==1 ) assert( ztop>=0 && "getAbsPlateXYDimensions: ztop not specified" ); // must specify Z position for case with non-uniform layers + + std::vector <dimposXYStruct> absorbersheets; + + if ( _module_XYtype == 1 ) { // each slab is different: calculate slab-by-slab (eg in endcap) + absorbersheets = getSlabXYDimensions( ztop ); + } else { // single sheet over all slabs (eg in barrel) + dimposXYStruct ss; + if ( _module_XZtype==0 ) { // no taper + ss.sizeX = _module_dX_max; + ss.posX = ss.sizeX/2.; + } else { // size varies by laer + + // ss.sizeX = _module_dX_max - 2.*ztop; // this assumes octagon + + ss.sizeX = _module_dX_max - 2.*ztop/tan(_module_angle); // for general shape + + ss.posX = _module_dX_max/2.; // keep it centered + } + ss.sizeY = _module_dY_total; + ss.posY = _module_dY_total/2.; + absorbersheets.push_back(ss); + } + return absorbersheets; +} + +std::vector <SEcal05_Helpers::dimposXYStruct> SEcal05_Helpers::getSlabXYDimensions( double ztop ) { + // calculate size and position of slab volumes + // size includes slab and dead area around it + + // ztop is Z of upper face of this slab (the face shortest in X) + if ( _module_XZtype==1 ) assert( ztop>=0 && "getSlabXYDimensions: ztop not specified" ); // must specify Z position for case with non-uniform layers + + std::vector <dimposXYStruct> layerslabdims; + if ( _module_XZtype == 0 && _constantSlabXYDimensions.size()>0 ) { // every layer is the same, and has already been calculated + layerslabdims = _constantSlabXYDimensions; + } else { + dimposXYStruct ss; + int totTow(0); + for (size_t imod=0; imod<_ntowers.size(); imod++) { // loop over "modules" [nb, for barrel, we only make a single module; for endcaps, typically have 3 per quadrant] + for (int itow = 0; itow<_ntowers[imod]; itow++) { // towers within the module + // each slab has same width + ss.sizeY = _alveolus_total_dim_Y; // this size include edge-of-tower dead space + ss.posY = + _moduleGap * ( 1 + 2*imod ) + // edge-of-module gaps from Y=0 to this slab + _alveolus_total_dim_Y * (totTow+0.5); // position of slab centre w.r.t (X,Y) = (0,0) + + if ( _module_XYtype==0 ) { // all slabs in a layer have same length + + if ( _module_XZtype == 0 ) { // all layers have same length + ss.sizeX = _module_dX_max; + ss.posX = ss.sizeX/2.; + } else { // layers vary in length : barrel module + + // ss.sizeX = _module_dX_max - 2.*ztop; // assumes octagon + + ss.sizeX = _module_dX_max - 2.*ztop/tan(_module_angle); // for general shape + + ss.posX = _module_dX_max/2.; // slabs all centred + } + + ss.sizeX -= _plugLength; // DANIELHACK + ss.posX += _plugLength/2.; // DANIELHACK + + + + } else if ( _module_XYtype==1 ) { // slabs within layer have different lengths : this is for endcap + // placing in Y + double upperY = ss.posY + 0.5*_alveolus_total_dim_Y; // Y position of upper edge + + if ( upperY<=_module_dY_kink ) { // straight edge part under kink + ss.sizeX = _module_dX_max; + } else { // sloping edge: take length at upperY, which is the shortest one + ss.sizeX = _module_dX_max - ( upperY - _module_dY_kink ); + } + + ss.posX = ss.sizeX/2.; // this aligns the -X end of slab + + ss.sizeX -= _plugLength; // DANIELHACK + ss.posX += _plugLength/2.; // DANIELHACK + + } else { + cout << " SEcal05_Helpers ERROR _module_XYtype = " << _module_XYtype << "!!!" << endl; + assert(0); + } + layerslabdims.push_back(ss); + totTow++; + } // towers + } // modules + + // if slab dimensions do not change layer-by-layer, memorise for next time + if ( _module_XZtype == 0 ) _constantSlabXYDimensions = layerslabdims; + } + return layerslabdims; +} + + +void SEcal05_Helpers::updateCaloLayers(double thickness, + dd4hep::Material mat, + bool isAbsorber, + bool isSensitive, + double cell_size_x, double cell_size_y, + bool isFinal + ) { + + if ( isFinal ) { // add material before saving layer + _layer_thickness += (thickness); + _layer_nRadiationLengths += (thickness)/mat.radLength() ; + _layer_nInteractionLengths += (thickness)/mat.intLength() ; + } + + // should we finish off the current layer? + if ( isFinal || // last slice of calo + (isAbsorber && _caloLayer.sensitive_thickness > 0 ) // end of a caloLayer + ) { + + // finalise caloLayer entry, add to caloData + _caloLayer.outer_thickness = _layer_thickness; + _caloLayer.outer_nRadiationLengths = _layer_nRadiationLengths; + _caloLayer.outer_nInteractionLengths = _layer_nInteractionLengths; + //_caloLayer.thickness = _caloLayer.inner_thickness + _caloLayer.outer_thickness ; + + // push it back + _caloData->layers.push_back( _caloLayer ) ; + // printSEcal05LayerInfo( _caloLayer ); + + // reset layer thicknesses + _layer_thickness=0; + _layer_nRadiationLengths=0; + _layer_nInteractionLengths=0; + + // update the calolayer.distance ( DJeans 12 sep 2017) + // here this is distance from ECAL start to the layer start; the Barrel and Endcap drivers add the distance from IP + _caloLayer.distance += _caloLayer.inner_thickness+_caloLayer.outer_thickness; + + + } + + if (!isFinal) { + + // first add half the material + _layer_thickness += (thickness/2.); + _layer_nRadiationLengths += (thickness/2.)/mat.radLength() ; + _layer_nInteractionLengths += (thickness/2.)/mat.intLength() ; + + // then we store material before and after centre of this layer + if ( isSensitive ) { + _caloLayer.cellSize0 = cell_size_x; + _caloLayer.cellSize1 = cell_size_y; + _caloLayer.sensitive_thickness = thickness ; + _caloLayer.inner_nRadiationLengths = _layer_nRadiationLengths ; + _caloLayer.inner_nInteractionLengths = _layer_nInteractionLengths ; + _caloLayer.inner_thickness = _layer_thickness ; + + // reset layer thicknesses + _layer_thickness=0; + _layer_nRadiationLengths=0; + _layer_nInteractionLengths=0; + } + + // add in remaining half of layer + _layer_thickness += (thickness/2.); + _layer_nRadiationLengths += (thickness/2.)/mat.radLength() ; + _layer_nInteractionLengths += (thickness/2.)/mat.intLength() ; + } + + _totThick+=thickness; + + return; +} + + +SEcal05_Helpers::dxinfo SEcal05_Helpers::getNormalMagicUnitsInX( double dx_total, double dx_unit, double dx_cell, double dx_dead , + int magicStrategy ) { + + dxinfo dxInf; + dxInf.normal_nX=-1; + dxInf.magic1_unitDX=-1; + dxInf.magic1_ncellsX=-1; + dxInf.magic2_unitDX=-1; + + int nNormalUnit = int( floor( dx_total / dx_unit ) ); + + if ( magicStrategy==0 ) { // just integer number of standard units (wafers/megatiles) + dxInf.normal_nX = nNormalUnit; + } else { + + double extraSpace = dx_total - nNormalUnit*dx_unit; + double extraSensitiveSpace = extraSpace - 2.*dx_dead; + double extraNCells = extraSensitiveSpace / dx_cell; + + if ( magicStrategy==1 ) { // last magic megatile has integer number of standard-sized cells + dxInf.normal_nX = nNormalUnit; + if ( extraNCells > 1.0 ) { + int iext = int( floor( extraNCells ) ); + dxInf.magic1_unitDX = iext*dx_cell + 2.*dx_dead; + dxInf.magic1_ncellsX = iext; + } + } else if ( magicStrategy==2 ) { + + // one magic megatile with integer number of standard cells, + // second with non-standard cell size to fill space exactly + // last magic cell size in range shortestMacigCell<magicCellsSize/standardCellSize<shortestMagicCell + + // the shortest magic cell (in terms of the usual cell size) + const double shortestMagicCell = 1.0; // this means that the last magic cell is at least as long as the standard cell + + extraSensitiveSpace = extraSpace - 4.*dx_dead; // because both the magic tiles may have a dead area + extraNCells = extraSensitiveSpace / dx_cell; + + if ( extraNCells < shortestMagicCell ) { // too small to make magic unit. remove one normal unit + nNormalUnit-=1; + extraSpace = dx_total - nNormalUnit*dx_unit; + extraSensitiveSpace = extraSpace - 4.*dx_dead; + extraNCells = extraSensitiveSpace / dx_cell; + } + + int imagic1 = int( floor( extraNCells ) ); // rounded down number of standard-sized cells + + double magic1size = imagic1>0 ? imagic1*dx_cell + 2*dx_dead : 0.; + + double magic2cellsize = extraSpace - magic1size - 2*dx_dead; + + if ( magic2cellsize/dx_cell < shortestMagicCell ) { // too small + imagic1 -= 1; // remove last standard cell + magic1size = imagic1>0 ? imagic1*dx_cell + 2*dx_dead : 0; + magic2cellsize = extraSpace - magic1size - 2*dx_dead; + } + + assert( magic2cellsize/dx_cell >= shortestMagicCell && magic2cellsize/dx_cell <= shortestMagicCell+1.0 && "problem in deciding magic unit size" ); + + dxInf.normal_nX = nNormalUnit; + dxInf.magic1_ncellsX = imagic1; + dxInf.magic1_unitDX = imagic1>0 ? imagic1*dx_cell + 2*dx_dead : 0; + + dxInf.magic2_unitDX = magic2cellsize + 2*dx_dead; + + } + } + + if ( magicStrategy==2 ) { + // check it fills exactly + if ( fabs( dxInf.normal_nX*dxInf.magic1_unitDX + dxInf.magic1_unitDX + dxInf.magic2_unitDX - dx_total ) < 0.01*dd4hep::mm ) { + cout << " SEcal05_Helpers ERROR : " << endl; + cout << dxInf.normal_nX*dxInf.magic1_unitDX << " " << dxInf.magic1_unitDX << " " << dxInf.magic2_unitDX << endl; + cout << dxInf.normal_nX*dxInf.magic1_unitDX + dxInf.magic1_unitDX + dxInf.magic2_unitDX << " " << dx_total << endl; + cout << dxInf.normal_nX*dxInf.magic1_unitDX + dxInf.magic1_unitDX + dxInf.magic2_unitDX - dx_total << endl; + assert(0 && "magic unit does not fill space exactly"); + } + + } + + return dxInf; +} + + +void SEcal05_Helpers::makeModule( dd4hep::Volume & mod_vol, // the volume we'll fill + dd4hep::DetElement & stave_det, // the detector element + dd4hep::rec::LayeredCalorimeterData & caloData, // the reco data we'll fill + dd4hep::Detector & theDetector, + dd4hep::SensitiveDetector & sens + ) { + // make the module + _caloData = &caloData; + + // calculate widths of module/tower/unit (in z-direction for barrel: across the slab/module + assert ( _ntowers.size()>0 && _unitsPerTower>0 && "_ntowers or _unitsPerTower not set" ); + + _module_dY_total=0; + for (size_t i=0; i<_ntowers.size(); i++) { + _module_dY_total = _ntowers[i]*_alveolus_total_dim_Y + 2.*_moduleGap; + } + + double alveolus_active_dim_Y = _alveolus_total_dim_Y - 2.*_towerGap; + double unit_dim_Y = alveolus_active_dim_Y/_unitsPerTower; + double unit_sensitive_dim_Y = unit_dim_Y - 2*_unitDeadEdge; // width of the sensitive area in each sensor + assert( unit_sensitive_dim_Y>0 && "negative-sized sensitive area..." ); // otherwise really weird! + + // get detector stuff + assert ( _x_det && "_x_det not set"); + int det_id = _x_det->id(); + xml_comp_t x_staves = _x_det->staves(); + + _carbon_fibre_material = theDetector.material("CarbonFiber"); + _radiator_material = theDetector.material(x_staves.materialStr()); + _air_material = theDetector.air(); + + dd4hep::VisAttr _radiator_visatt = theDetector.visAttributes( x_staves.visStr() ); + + // get segmentation stuff + assert (_geomseg && "segmentation not set"); + + dd4hep::DDSegmentation::WaferGridXY* waferSeg = dynamic_cast< dd4hep::DDSegmentation::WaferGridXY* > ( _geomseg->segmentation() ) ; + + + dd4hep::DDSegmentation::MegatileLayerGridXY* megatileSeg = dynamic_cast< dd4hep::DDSegmentation::MegatileLayerGridXY* > ( _geomseg->segmentation() ) ; + assert( (waferSeg || megatileSeg) && "no segmentation found" ); + + // set up the standard megatile size and offset + if ( megatileSeg ) { + megatileSeg->setMegaTileSizeXY( unit_sensitive_dim_Y, unit_sensitive_dim_Y ); + megatileSeg->setMegaTileOffsetXY( -unit_sensitive_dim_Y/2., -unit_sensitive_dim_Y/2. ); + } + + _module_thickness = getTotalThickness(); + + double currentLayerBase_pos_Z = 0; // this gets updated: it's the position of the bottom face of the next detector slice + + int layer_index = 0; // 1;// layer number - Daniel changes to c-type counting from 0...lets get rid of fortran habits! + + // to deal with initial layers + bool isFrontFace = true; + int myLayerNum = 0 ; // this is the sensitive layer number (one per sensitive) + unsigned int absorber_index(0); // keep track of which absorber layer we're in + + // keep track of thickness within a layer + // initialise + _layer_thickness = 0. ; + _layer_nRadiationLengths = 0. ; + _layer_nInteractionLengths = 0. ; + + //-------------------------------- + // loop over the layers + //--------------------------------- + + for(xml_coll_t li(*_x_det,_U(layer)); li; ++li) { // types of layers (i.e. thin/thick absorber) or "stack" + xml_comp_t x_layer = li; + // cout << " ---- NEW LAYER TYPE " << layer_index << " repeat " << x_layer.repeat() << endl; + + // Loop over number of repeats for this layer type + for (int j=0; j< x_layer.repeat(); j++) { // layers within this type (or "stack") + std::string l_name = dd4hep::_toString(layer_index,"layer%d"); + + // ######################### + // Build Structure Layer + // ######################### + + //---------------------------------------------------- + // position and thickness of absorber plates in the structure + //---------------------------------------------------- + double radiator_dim_Z(0); + double rad_pos_Z(0); + double this_struct_CFthick_beforeAbs(0); + double this_struct_CFthick_afterAbs(0); + + if ( isFrontFace ) { // the first part of the module depends on whether we have preshwer or not + if ( _preshower==1 ) { // don't include W+CF wrapping; only one side of alveolus + this_struct_CFthick_beforeAbs = 0; + this_struct_CFthick_afterAbs = _CF_front + _CF_alvWall; + radiator_dim_Z = 0; + } else { // include W+CF wrapping; only one side of alveolus + // cout << " -- no preshower, including absorber" << endl; + this_struct_CFthick_beforeAbs = _CF_front + _CF_absWrap; // allow for initial CF front plate also in no preshower case - djeans 6 july 2017 + this_struct_CFthick_afterAbs = _CF_absWrap + _CF_alvWall; + radiator_dim_Z = getAbsThickness( absorber_index++ ); + rad_pos_Z = radiator_dim_Z/2. + this_struct_CFthick_beforeAbs; // distance from top surface of structure to centre of radiator + } + isFrontFace=false; + } else { // internal layer: include W+CF wrapping; both sides of alveolus + this_struct_CFthick_beforeAbs = _CF_alvWall+_CF_absWrap; + this_struct_CFthick_afterAbs = _CF_alvWall+_CF_absWrap; + radiator_dim_Z = getAbsThickness( absorber_index++ ); + assert( radiator_dim_Z>0 && "no radiator!" ); + rad_pos_Z = this_struct_CFthick_beforeAbs + radiator_dim_Z/2.; // distance from top surface of structure to centre of radiator + } + + + // create the radiator volume + if ( radiator_dim_Z>0 ) { // only create the volume if we have radiator + std::vector < dimposXYStruct > absorbersheets = getAbsPlateXYDimensions( currentLayerBase_pos_Z + this_struct_CFthick_beforeAbs + radiator_dim_Z ); // add CF before abs. added djeans 21 nov 2016 + // create and place the absorber sheets + for ( size_t ipl=0; ipl<absorbersheets.size(); ipl++) { + dimposXYStruct plSize = absorbersheets[ipl]; + dd4hep::Box barrelStructureLayer_box( plSize.sizeX/2., + plSize.sizeY/2. - _CF_absWrap, // remove CF wrapping + radiator_dim_Z/2.); + + dd4hep::Volume barrelStructureLayer_vol( _det_name+"_"+l_name+"_"+dd4hep::_toString(int(ipl),"bs%02d"), + barrelStructureLayer_box, _radiator_material); + + barrelStructureLayer_vol.setVisAttributes( _radiator_visatt ); + + // Position the layer. + dd4hep::Position bsl_pos = getTranslatedPosition(plSize.posX, plSize.posY, currentLayerBase_pos_Z + rad_pos_Z ); + + // dd4hep::PlacedVolume barrelStructureLayer_phv = + mod_vol.placeVolume(barrelStructureLayer_vol, bsl_pos); + + } // loop over sheets + } + + // update layer thickness until front face of absorber + updateCaloLayers( this_struct_CFthick_beforeAbs, _carbon_fibre_material, false, false); + updateCaloLayers( radiator_dim_Z, _radiator_material, true, false ); + updateCaloLayers( this_struct_CFthick_afterAbs, _carbon_fibre_material, false, false); + + // update position within module + currentLayerBase_pos_Z += this_struct_CFthick_beforeAbs + radiator_dim_Z + this_struct_CFthick_afterAbs; + + // ######################### + // Build Slab + // ######################### + + //------------------------------- + // first sum the various materials for the caloData/caloLayer + //------------------------------- + int myLayerNumTemp = myLayerNum; + for(xml_coll_t si(x_layer,_U(slice)); si; ++si) { + xml_comp_t x_slice = si; + double s_thick = x_slice.thickness(); + dd4hep::Material slice_material = theDetector.material( x_slice.materialStr() ); + if (x_slice.materialStr().compare(x_staves.materialStr()) == 0){ + // this is absorber material + // check it's consistent with what we expect from the detector parameters + assert ( fabs( s_thick - getAbsThickness( absorber_index++ ) ) < 1e-5 && "inconsistent radiator thickness" ); + updateCaloLayers( s_thick, slice_material, true, false ); // absorber + } else if ( x_slice.isSensitive() ) { + double cell_size_x(0), cell_size_y(0); + if ( waferSeg ) { + cell_size_x = waferSeg->cellDimensions(0)[0]; + cell_size_y = waferSeg->cellDimensions(0)[1]; + } else if ( megatileSeg ) { + // setup megatile + int laytype = _layerConfig [ myLayerNumTemp%_layerConfig.size() ]; + if ( laytype==0 ) { + megatileSeg->setMegaTileCellsXY( myLayerNumTemp, _cells_across_megatile , _cells_across_megatile ); + } else if ( laytype==1 ) { + megatileSeg->setMegaTileCellsXY( myLayerNumTemp, _strips_across_megatile , _strips_along_megatile ); // strips in one orientation + } else if ( laytype==2 ) { + megatileSeg->setMegaTileCellsXY( myLayerNumTemp, _strips_along_megatile , _strips_across_megatile ); // and in the other + } else { + assert(0 && "unknown layer type"); + } + cell_size_x = megatileSeg->cellDimensions(myLayerNumTemp, 0)[0]; // dummy wafer + cell_size_y = megatileSeg->cellDimensions(myLayerNumTemp, 0)[1]; + } + updateCaloLayers( s_thick, slice_material, false, true, cell_size_x, cell_size_y ); // sensitive + myLayerNumTemp++; + } else { + updateCaloLayers( s_thick, slice_material, false, false ); + } + } + + //------------------------------------ + // then actually construct the slabs + //------------------------------------ + double slab_dim_Z = _layering->layer(layer_index)->thickness(); + double slab_pos_Z = currentLayerBase_pos_Z + slab_dim_Z/2.; // centre position of slab + + std::vector <dimposXYStruct> slabDims = getSlabXYDimensions( currentLayerBase_pos_Z + slab_dim_Z ); + + for (size_t islab = 0; islab<slabDims.size(); islab++) { + myLayerNumTemp = myLayerNum; + double slab_dim_X = slabDims[islab].sizeX; + + // make an air volume for the alveolus + dd4hep::Box l_box( slab_dim_X/2. , + slabDims[islab].sizeY/2. - _CF_alvWall, + slab_dim_Z/2. ); + + dd4hep::Volume l_vol( _det_name+"_alveolus_"+l_name, l_box, _air_material); + l_vol.setVisAttributes(theDetector.visAttributes( "GrayVis" ) ); + + dd4hep::DetElement l_det( stave_det, l_name+dd4hep::_toString(int(islab),"tower%02d") , det_id ); + dd4hep::Position l_pos = getTranslatedPosition(slabDims[islab].posX, slabDims[islab].posY, slab_pos_Z ); + dd4hep::PlacedVolume l_phv = mod_vol.placeVolume(l_vol,l_pos); + l_phv.addPhysVolID("tower", int(islab) ); + l_det.setPlacement(l_phv); + + // then fill it with the slab sublayers + int s_num(0); + double s_pos_Z = -slab_dim_Z / 2.; // position of sub-layer with respect to centre of this slab + + for(xml_coll_t si(x_layer,_U(slice)); si; ++si) { // the sub-layers + xml_comp_t x_slice = si; + std::string s_name = dd4hep::_toString(s_num,"slice%d"); + double s_thick = x_slice.thickness(); + + dd4hep::Material slice_material = theDetector.material( x_slice.materialStr() ); + + std::string vis_str = x_slice.visStr(); + + if ( !x_slice.isSensitive() ) { // not the sensitive slice: just a layer of stuff + + dd4hep::Box s_box( slab_dim_X/2. , slabDims[islab].sizeY/2. - _CF_alvWall, s_thick/2. ); + dd4hep::Volume s_vol(_det_name+"_"+l_name+"_"+s_name, s_box, slice_material); + s_vol.setVisAttributes(theDetector.visAttributes( vis_str )); + + dd4hep::Position s_pos( 0, 0, s_pos_Z + s_thick/2. ); + // dd4hep::PlacedVolume slice_phv = + l_vol.placeVolume(s_vol, s_pos ); + + } else { // sensitive slice + + // Normal squared wafers - this is just the sensitive part + // square piece of silicon, not including guard ring. guard ring material is not included + + dd4hep::Box WaferSiSolid( unit_sensitive_dim_Y/2., unit_sensitive_dim_Y/2., s_thick/2.); + + // get the standard cell size in X for this layer + double cell_size_x = waferSeg ? waferSeg->cellDimensions(0)[0] : megatileSeg->cellDimensions(myLayerNumTemp, 0)[0]; + double cell_size_y = waferSeg ? waferSeg->cellDimensions(0)[1] : megatileSeg->cellDimensions(myLayerNumTemp, 0)[1]; + + // work out how to make the magic units, if requested + dxinfo xseg = getNormalMagicUnitsInX( slab_dim_X, + unit_dim_Y, + cell_size_x, + _unitDeadEdge, + _magicMegatileStrategy ); + + int n_wafers_x = xseg.normal_nX; + int ncellsy = int( unit_sensitive_dim_Y/cell_size_y + 0.5 ); // should be exactly integer. take nearest integer to account for possible rounding errors. + + int wafer_num = 0; + + double wafer_pos_X = -slab_dim_X/2.; // keep track of wafer position in X + + for (int n_wafer_x = 0; n_wafer_x < n_wafers_x+2 ; n_wafer_x++) { // loop along slab, including magic megatile/wafer + + double megatile_size_x = unit_dim_Y; + int ncellsx(-1); + + bool isMagic = n_wafer_x >= n_wafers_x; + + if ( n_wafer_x==n_wafers_x ) { // first magic unit + megatile_size_x = xseg.magic1_unitDX; + ncellsx = xseg.magic1_ncellsX; + } else if ( n_wafer_x==n_wafers_x+1 ) { // second magic unit + megatile_size_x = xseg.magic2_unitDX; + ncellsx = 1; + } + + // cout << "ismagic " << isMagic << " wafer " << n_wafer_x << " / " << n_wafers_x << " : sizex " << megatile_size_x << " nx " << ncellsx << endl; + + if ( megatile_size_x<=0 ) continue; + + // cout << " PASSED" << endl; + + double megatile_sensitive_size_x = megatile_size_x - 2*_unitDeadEdge; + + for (int n_wafer_Y = 0; n_wafer_Y < _unitsPerTower; n_wafer_Y++) { // loop across slab (usually 2 wafers, or 1 EBU) [ie along beam dir for barrel module] + + double wafer_pos_Y = -alveolus_active_dim_Y/2.0 + (n_wafer_Y+0.5)*unit_dim_Y; + wafer_num++; + std::string Wafer_name; + if ( isMagic ) Wafer_name="magic"; + Wafer_name += dd4hep::_toString(wafer_num,"wafer%d"); + + dd4hep::Box* box = isMagic ? new dd4hep::Box( megatile_sensitive_size_x/2,unit_sensitive_dim_Y/2,s_thick/2.) : &WaferSiSolid; + dd4hep::Volume WaferSiLog(_det_name+"_"+l_name+"_"+s_name+"_"+Wafer_name,*box,slice_material); + + std::string wafer_vis_str = isMagic ? "YellowVis" : vis_str; + + WaferSiLog.setVisAttributes(theDetector.visAttributes( wafer_vis_str )); + WaferSiLog.setSensitiveDetector(sens); + + dd4hep::Position w_pos(wafer_pos_X + megatile_size_x/2., wafer_pos_Y, s_pos_Z + s_thick/2. ); + dd4hep::PlacedVolume wafer_phv = l_vol.placeVolume(WaferSiLog, w_pos ); + wafer_phv.addPhysVolID("wafer", wafer_num); + wafer_phv.addPhysVolID("layer", myLayerNumTemp ); + + if ( isMagic ) { + if ( megatileSeg ) { // define the special megatile + megatileSeg->setSpecialMegaTile( myLayerNumTemp, wafer_num, + megatile_sensitive_size_x, unit_sensitive_dim_Y, + -megatile_size_x/2., -unit_sensitive_dim_Y/2., // the offset + ncellsx, ncellsy ); // the segmentation + } + } else { // not magic + if ( waferSeg ) { // Normal squared wafers, this waferOffsetX is 0.0 // if its an odd number of cells, need to do something? + waferSeg->setWaferOffsetX(myLayerNumTemp, wafer_num, 0.0); + } + } // isMagic + + } // y-wafers + + wafer_pos_X += megatile_size_x; + + } // x-wafers + myLayerNumTemp++; + } // end sensitive slice + + // Increment Z position of slice. + s_pos_Z += s_thick; + + // Increment slice number. + ++s_num; + + } // end slice within one slab + } // slabs + myLayerNum = myLayerNumTemp; + currentLayerBase_pos_Z += slab_dim_Z; + layer_index++; // this is the structural layer counter (one per slab, not per sensitive layer) + } // layers in compact file + } // layer types in compact file + + // add material after last slab. Just CF + updateCaloLayers( _CF_alvWall + _CF_back, _carbon_fibre_material, false, false, -1, -1, true ); // the last layer + + return; +} diff --git a/Detector/DetCEPCv4/src/calorimeter/SEcal05_Helpers.h b/Detector/DetCEPCv4/src/calorimeter/SEcal05_Helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..80e8e829a336eb25410247cdc5e7433d70777684 --- /dev/null +++ b/Detector/DetCEPCv4/src/calorimeter/SEcal05_Helpers.h @@ -0,0 +1,309 @@ +#ifndef __SECAL05_HELPERS_H__ +#define __SECAL05_HELPERS_H__ 1 + +#include "DD4hep/DetFactoryHelper.h" + +#include "DDRec/DetectorData.h" + +#include "XML/Layering.h" +#include "XML/Utilities.h" + +#include "DD4hep/Segmentations.h" + +#include "DDSegmentation/MegatileLayerGridXY.h" + +#include "DDSegmentation/WaferGridXY.h" + +#include <iostream> + +#undef NDEBUG +#include <assert.h> + +using std::cout; +using std::endl; + +/* + +we build general ECAL modules on a horizontal table. + +X-Y are on the table +Z is vertically upwards +slabs are aligned along X +the lower Z side will face the IP + +2 shapes when looking down on table: + +XYtype = 0: (barrel and endcap) + ----------------------------- ^ Y + | | | + | | | + ----------------------------- ----> X + +XYtype = 1: (endcap) + ---------------------- + | \ + | \ + | \ + | | ^ + | | | dY_kink + ----------------------------- | + +2 shapes when looking from side: + +XZtype = 0: (endcap) + --------------------------------- + | | + | | + --------------------------------- + +XZtype = 1: (barrel) + -------------------------- ^ Z + / \ | + / \ | + / \ | + -------------------------------- ----> X + +the slabs are prefectly aligned at -ve X side +"magic" wafers are at +ve X + +local position: 0,0 defined as -veX,Y,Z corner + +we start building from Z=0, the face nearest IP, moving in the +ve Z direction + + +D.Jeans update: 03/2015 +dead space between slab end and module edge +other than 8-fold symmetry for barrel + + */ + +class SEcal05_Helpers { + + public: + + SEcal05_Helpers(); + + ~SEcal05_Helpers() { + delete _layering; + } + + // SET THE PARAMETERS + + void setDet( xml_det_t* x_det ) { + _x_det = x_det; + _layering = new dd4hep::Layering(*x_det); + _det_name = x_det->nameStr(); + } + + void setAbsLayers( int nl1, double th1, int nl2, double th2, int nl3=0, double th3=0 ); + + void setLayerConfig( std::vector < int > layerConfig ) { + _layerConfig=layerConfig; + } + + void setSegmentation( dd4hep::Segmentation & seg ) { + _geomseg = &seg; + } + + void setSegmentation( dd4hep::Segmentation * seg ) { + _geomseg = seg; + } + + void setNCells( int Ecal_cells_across_megatile, int Ecal_strips_across_megatile, int Ecal_strips_along_megatile) { + _cells_across_megatile = Ecal_cells_across_megatile ; + _strips_across_megatile = Ecal_strips_across_megatile ; + _strips_along_megatile = Ecal_strips_along_megatile ; + } + + void setMagicMegatileStrategy ( int i ) { + // magic megatile strategy + // 0: no magic megatile at lend of slab + // 1: magic megatile includes integer number of standard-sized cells + // 2: last cell of magic megatile adjusted to fill up to end of slab (size between 1 and 2 times normal cell size) + assert ( i>=0 && i<=2 ); + _magicMegatileStrategy = i; + } + + void setPreshower( bool p ) { + _preshower = p? 1 : 0; // do we have preshower layer? (if 1, first layer is sensitive; if 0, first layer is absorber) + } + + void setCFthickness( double absWrap, double alvWall, double front, double back ) { + _CF_absWrap = absWrap; // wrapping around absorber + _CF_alvWall = alvWall; // alveolar wall + _CF_front = front; // front (IP side) support plate + _CF_back = back; // back support plate + } + + void setModuleDimensions( int XYtype, // module shape in XY + int XZtype, // module shape in XZ + double dX_max, // maximum extent in X + double dY_kink = -999, // distance from lowerY edge to kink for XYtype=2 + double angle = M_PI/4. // angle, if not rectangular. pi/4 for octagon + ) { + if ( XYtype>0 ) assert ( XZtype==0 ); // endcap module has vertical edges + if ( XZtype>0 ) assert ( XYtype==0 ); // barrel module should have rectangular shadow + + _module_XYtype = XYtype; + _module_XZtype = XZtype; + _module_dX_max = dX_max; + _module_dY_kink = dY_kink; + _module_angle = angle; + + } + + void setTowersUnits( std::vector <int> ntowers, // a vector of modules, containing the specified # of towers/alveolii + double towerWidth, + int unitsPerTower, // # megatiles/units per tower + double moduleDeadEdge, // dead region at edge of module + double towerDeadEdge, // dead region at edge of tower + double unitDeadEdge // width of dead region at edge of each unit (e.g. wafer's guard ring) + ) { + _ntowers = ntowers; // number of towers (or alveoli) across Y + _alveolus_total_dim_Y = towerWidth; // width of tower (including dead area) + _unitsPerTower = unitsPerTower; // how many units (megatiles/wafers) across one tower + _moduleGap = moduleDeadEdge; // distance from tower boundary to edge of unit + _towerGap = towerDeadEdge; // distance from tower boundary to edge of unit + _unitDeadEdge = unitDeadEdge; // width of dead area around edge of unit + } + + void checkLayerConsistency(); + + float getTotalThickness(); + + void setTranslation( dd4hep::Position trans ) {_trans = trans;} + + // ---- this is the main workhorse + void makeModule( dd4hep::Volume & mod_vol, // the volume we'll fill + dd4hep::DetElement & stave_det, // the detector element + dd4hep::rec::LayeredCalorimeterData & caloData, // the reco data we'll fill + dd4hep::Detector & theDetector, + dd4hep::SensitiveDetector & sens + ); + + void setPlugLength( float ll ) { _plugLength = ll; } + + + private: + + void printSEcal05LayerInfo( dd4hep::rec::LayeredCalorimeterData::Layer & caloLayer); + + double getAbsThickness( unsigned int iAbsLay ); + + int getNumberOfAbsorberLayers() { + // total number of absorber layers + return _nlayers1+_nlayers2+_nlayers2; + } + + int getNumberOfStructuralAbsorberLayers() { + // number of absorber layers in the module (not in the slabs) + assert( _preshower==0 || _preshower==1 ); + return _preshower ? getNumberOfAbsorberLayers()/2 : (getNumberOfAbsorberLayers()-1)/2 ; + } + + struct dimposXYStruct { + double sizeX, sizeY; + double posX, posY; + }; + + struct dxinfo { + int normal_nX; + + double magic1_unitDX; + int magic1_ncellsX; + + double magic2_unitDX; + }; + + xml_det_t* _x_det; + dd4hep::Layering* _layering=NULL; + std::string _det_name; + + std::vector <dimposXYStruct> getAbsPlateXYDimensions( double ztop=-999 ); + + std::vector <dimposXYStruct> getSlabXYDimensions( double ztop=-999 ); + + + dd4hep::Position getTranslatedPosition(double x, double y, double z) { + return dd4hep::Position ( x, y, z ) + _trans; + } + + dxinfo getNormalMagicUnitsInX( double dx_total, double dx_unit, double dx_cell, double dx_dead , + int magicStrategy ); + + void updateCaloLayers(double thickness, + dd4hep::Material mat, + bool isAbsorber, + bool isSensitive, + double cell_size_x=0, double cell_size_y=0, + bool isFinal=false + ); + + + dd4hep::Segmentation* _geomseg; + + dd4hep::Material _air_material; + dd4hep::Material _carbon_fibre_material; + dd4hep::Material _radiator_material; + + unsigned int _cells_across_megatile; + unsigned int _strips_across_megatile; + unsigned int _strips_along_megatile; + + int _preshower; + + unsigned int _nlayers1; + unsigned int _nlayers2; + unsigned int _nlayers3; + + double _radiator_thickness1; + double _radiator_thickness2; + double _radiator_thickness3; + + std::vector < int > _layerConfig; // square or X or Y strips + + double _CF_absWrap; + double _CF_alvWall; + double _CF_front; + double _CF_back; + + // overall module size + int _module_XYtype; + int _module_XZtype; + double _module_dX_max; + double _module_dY_total; + double _module_dY_kink; + double _module_angle; + + // internal details + std::vector <int> _ntowers; + double _towerGap; + double _moduleGap; + int _unitsPerTower; + double _unitDeadEdge; + + dd4hep::rec::LayeredCalorimeterData* _caloData; + dd4hep::rec::LayeredCalorimeterData::Layer _caloLayer ; // this is the output info which is passed to reconstruction + + double _layer_thickness; + double _layer_nRadiationLengths; + double _layer_nInteractionLengths; + + double _totThick; + + double _alveolus_total_dim_Y; + double _module_thickness; + + int _magicMegatileStrategy; + + dd4hep::Position _trans; + + std::vector <dimposXYStruct> _constantSlabXYDimensions; + + + float _plugLength; + + +}; + +#endif diff --git a/Detector/DetEcalMatrix/CMakeLists.txt b/Detector/DetEcalMatrix/CMakeLists.txt index 569a9e8fdb5ae716b4d7982c4f6a5a4fb5a8944f..54407d226fed4c44d41a0294e3ac8a8f0ebef1db 100644 --- a/Detector/DetEcalMatrix/CMakeLists.txt +++ b/Detector/DetEcalMatrix/CMakeLists.txt @@ -24,8 +24,13 @@ set(DetEcalMatrix_src gaudi_add_module(DetEcalMatrix ${DetEcalMatrix_src} - INCLUDE_DIRS DD4hep ROOT Geant4 src/include - LINK_LIBRARIES GaudiKernel DD4hep ${DD4hep_COMPONENT_LIBRARIES} ROOT Geant4) + INCLUDE_DIRS + # DD4hep ROOT Geant4 src/include + LINK_LIBRARIES + # GaudiKernel + DD4hep ${DD4hep_COMPONENT_LIBRARIES} + # ROOT Geant4 +) set(LIBRARY_OUTPUT_PATH ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) message(STATUS "LIBRARY_OUTPUT_PATH -> ${LIBRARY_OUTPUT_PATH}") diff --git a/Detector/DetEcalMatrix/compact/det.xml b/Detector/DetEcalMatrix/compact/det.xml index bb4f486360a1c5bee3176f9ca2214653ddda0cf7..2cd46f4fe3081ca4bb416e503022108b450466a9 100644 --- a/Detector/DetEcalMatrix/compact/det.xml +++ b/Detector/DetEcalMatrix/compact/det.xml @@ -32,16 +32,19 @@ <detectors> <detector id="1" name="CaloDetector" type="EcalMatrix" readout="CaloHitsCollection" vis="VisibleGreen" sensitive="true"> - <position x="0" y="0" z="1835*mm+30*cm"/> + <!-- Use cm as unit if you want to use Pandora for reconstruction --> + <position x="200*cm" y="0" z="0"/> <dimensions dx="30*cm" dy="30*cm" dz="30*cm"/> </detector> </detectors> <readouts> <readout name="CaloHitsCollection"> - <segmentation type="CartesianGridXYZ" - grid_size_x="1*cm" - grid_size_y="1*cm" + <!-- <segmentation type="NoSegmentation"/> --> + + <segmentation type="CartesianGridXYZ" + grid_size_x="1*cm" + grid_size_y="1*cm" grid_size_z="1*cm"/> <id>system:8,x:32:-6,y:-6,z:-6</id> </readout> diff --git a/Detector/DetEcalMatrix/src/calorimeter/EcalMatrix.cpp b/Detector/DetEcalMatrix/src/calorimeter/EcalMatrix.cpp index 274330ba63acddec63b9c15abcdea8e8b3ac6d37..f12972c81dcdbc647b9112324e7d16b59e746ad8 100644 --- a/Detector/DetEcalMatrix/src/calorimeter/EcalMatrix.cpp +++ b/Detector/DetEcalMatrix/src/calorimeter/EcalMatrix.cpp @@ -16,6 +16,7 @@ #define MYDEBUG(x) std::cout << __FILE__ << ":" << __LINE__ << ": " << x << std::endl; #define MYDEBUGVAL(x) std::cout << __FILE__ << ":" << __LINE__ << ": " << #x << ": " << x << std::endl; +using dd4hep::rec::LayeredCalorimeterData; static dd4hep::Ref_t create_detector(dd4hep::Detector& theDetector, xml_h e, dd4hep::SensitiveDetector sens) { @@ -40,6 +41,51 @@ static dd4hep::Ref_t create_detector(dd4hep::Detector& theDetector, dd4hep::Transform3D transform(dd4hep::Rotation3D(), dd4hep::Position(pos.x(),pos.y(),pos.z())); dd4hep::PlacedVolume phv = motherVol.placeVolume(det_vol,transform); + //Create caloData object to extend driver with data required for reconstruction + LayeredCalorimeterData* caloData = new LayeredCalorimeterData ; + caloData->layoutType = LayeredCalorimeterData::BarrelLayout ; + caloData->inner_symmetry = 8 ;//nsides + caloData->outer_symmetry = 8; //nsides; + caloData->inner_phi0 = 0.; + caloData->outer_phi0 = 0.; + caloData->gap0 = 0.; //FIXME + caloData->gap1 = 0.; //FIXME + caloData->gap2 = 0.; //FIXME + // extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in mm. + caloData->extent[0] = 10*( pos.x()-dim.dx() );// from cm to mm + caloData->extent[1] = 10*( pos.x()+dim.dx() );// from cm to mm + caloData->extent[2] = 0 ; + caloData->extent[3] = 10*( pos.z()+dim.dz() );// from cm to mm + std::cout<<"rmin="<<caloData->extent[0]<<",rmax="<<caloData->extent[1]<<",zmin="<<caloData->extent[2]<<",zmax="<<caloData->extent[3]<<std::endl; + dd4hep::Readout readout = sens.readout(); + dd4hep::Segmentation seg = readout.segmentation(); + + std::cout << "TAO: " + << " field description: " << seg.segmentation()->fieldDescription() + // << " grid size x/y/z: " + // << seg.segmentation()->parameter("grid_size_x")->toString() + // << seg.segmentation()->parameter("grid_size_x")->toString() + // << seg.segmentation()->parameter("grid_size_x")->toString() + << std::endl; + + + double cellSize_x = ::atof( seg.segmentation()->parameter("grid_size_x")->value().c_str() ) * 10;// from cm to mm + double cellSize_y = ::atof( seg.segmentation()->parameter("grid_size_y")->value().c_str() ) * 10;// from cm to mm + double cellSize_z = ::atof( seg.segmentation()->parameter("grid_size_z")->value().c_str() ) * 10;// from cm to mm + int n_layer = int(2*dim.dx()*10/cellSize_x) ; // here the calorimeter is placed in barrel, so x direaction is layer direction + std::cout<<"cellx="<<cellSize_x<<",celly="<<cellSize_y<<",cellz="<<cellSize_z<<",dx="<<dim.dx()*10<<"mm,n_layer="<<n_layer<<std::endl; + for(int i=1 ; i <= n_layer; i++) + { + LayeredCalorimeterData::Layer caloLayer ; + caloLayer.distance = caloData->extent[0] + (i-0.5)*cellSize_x; //NEED TO START FROM ORIGIN, to mm + caloLayer.sensitive_thickness = cellSize_x ; + caloLayer.inner_thickness = cellSize_x ; + caloLayer.outer_thickness = cellSize_x ; + caloLayer.absorberThickness = cellSize_x; + caloLayer.cellSize0 = cellSize_y; + caloLayer.cellSize1 = cellSize_z; + caloData->layers.push_back(caloLayer); + } if ( x_det.isSensitive() ) { dd4hep::SensitiveDetector sd = sens; @@ -50,7 +96,7 @@ static dd4hep::Ref_t create_detector(dd4hep::Detector& theDetector, phv.addPhysVolID("system",x_det.id()); } sdet.setPlacement(phv); - + sdet.addExtension< LayeredCalorimeterData >(caloData) ; MYDEBUG("create_detector DONE. "); return sdet; } diff --git a/Detector/DetInterface/DetInterface/IGeoSvc.h b/Detector/DetInterface/DetInterface/IGeoSvc.h index 58df046d4aed0d5e22674f84db704c2d06bf749b..2925d7a2dec6ce96ffbe3f26779fadd1fa742c57 100644 --- a/Detector/DetInterface/DetInterface/IGeoSvc.h +++ b/Detector/DetInterface/DetInterface/IGeoSvc.h @@ -13,14 +13,18 @@ #include "GaudiKernel/IService.h" namespace dd4hep { -class Detector; -class DetElement; + class Detector; + class DetElement; + namespace DDSegmentation { + class BitFieldCoder; + } } // class G4VUserDetectorConstruction; class GAUDI_API IGeoSvc : virtual public IService { - +public: + typedef dd4hep::DDSegmentation::BitFieldCoder Decoder; public: /// InterfaceID DeclareInterfaceID(IGeoSvc, 1, 0); @@ -30,6 +34,9 @@ public: // receive Geant4 Geometry // virtual G4VUserDetectorConstruction* getGeant4Geo() = 0; + // short cut to retrieve the Decoder according to the Readout name + virtual Decoder* getDecoder(const std::string& readout_name) = 0; + virtual ~IGeoSvc() {} }; diff --git a/Detector/GeoSvc/CMakeLists.txt b/Detector/GeoSvc/CMakeLists.txt index 569c85334afb3ab6027dd66d158c6e6bd4b1afd6..2a5b97ded1389cd0a45a5f41ba8d5c562580a031 100644 --- a/Detector/GeoSvc/CMakeLists.txt +++ b/Detector/GeoSvc/CMakeLists.txt @@ -18,7 +18,13 @@ find_package(DD4hep COMPONENTS DDG4 DDRec REQUIRED) gaudi_add_module(GeoSvc src/GeoSvc.cpp INCLUDE_DIRS - DetInterface DD4hep GaudiKernel ROOT + # DetInterface + # DD4hep + # GaudiKernel + # ROOT LINK_LIBRARIES - DD4hep ${DD4hep_COMPONENT_LIBRARIES} GaudiKernel ROOT + DD4hep + ${DD4hep_COMPONENT_LIBRARIES} + GaudiKernel + # ROOT ) \ No newline at end of file diff --git a/Detector/GeoSvc/src/GeoSvc.cpp b/Detector/GeoSvc/src/GeoSvc.cpp index 305896c44546a12d3e34e3630f2632fe23a0806c..1739aa8a68e3996ea56d37849ffefa8dcd0b2f71 100644 --- a/Detector/GeoSvc/src/GeoSvc.cpp +++ b/Detector/GeoSvc/src/GeoSvc.cpp @@ -46,3 +46,34 @@ dd4hep::Detector* GeoSvc::lcdd() { return m_dd4hep_geo; } + +IGeoSvc::Decoder* +GeoSvc::getDecoder(const std::string& readout_name) { + + IGeoSvc::Decoder* decoder = nullptr; + + if (!lcdd()) { + error() << "Failed to get lcdd()" << endmsg; + return decoder; + } + + auto readouts = m_dd4hep_geo->readouts(); + if (readouts.find(readout_name) == readouts.end()) { + error() << "Failed to find readout name '" << readout_name << "'" + << " in DD4hep::readouts. " + << endmsg; + return decoder; + } + + dd4hep::Readout readout = lcdd()->readout(readout_name); + auto m_idspec = readout.idSpec(); + + decoder = m_idspec.decoder(); + + if (!decoder) { + error() << "Failed to get the decoder with readout '" + << readout_name << "'" << endmsg; + } + + return decoder; +} diff --git a/Detector/GeoSvc/src/GeoSvc.h b/Detector/GeoSvc/src/GeoSvc.h index 9c98daa9d58bb5f4786aa2881eb639716fc7d5ff..1be2b4ff4e0d4a504e216cc9b9a302dec001f5f6 100644 --- a/Detector/GeoSvc/src/GeoSvc.h +++ b/Detector/GeoSvc/src/GeoSvc.h @@ -28,6 +28,8 @@ public: dd4hep::DetElement getDD4HepGeo() override; dd4hep::Detector* lcdd() override; + Decoder* getDecoder(const std::string& readout_name) override; + private: // DD4hep XML compact file path @@ -38,4 +40,4 @@ private: }; -#endif GeoSvc_h +#endif // GeoSvc_h diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index f9f4c9d92f6f09025b391d2fb50a756371fe8006..8a0ba74979b16bc41d1e26dee535ac00fd12f51f 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -2,14 +2,23 @@ gaudi_subdir(Examples v0r0) find_package(podio REQUIRED) -find_package(plcio REQUIRED) +#find_package(plcio REQUIRED) find_package(LCIO REQUIRED) +find_package(EDM4HEP REQUIRED) +find_package(K4FWCore REQUIRED) +find_package(DD4hep COMPONENTS DDRec DDParsers REQUIRED) + +gaudi_depends_on_subdirs( + Detector/DetInterface +) set(Examples_srcs src/HelloWorld/*.cpp src/FirstSvc/*.cpp src/SecondAlg/*.cpp - src/PlcioTest/*.cpp + # src/PlcioTest/*.cpp + src/Edm4hepTest/*.cpp + src/DumpIDAlg/*.cpp ) # Headers and Libraries @@ -18,8 +27,11 @@ gaudi_install_headers(Examples) # Modules gaudi_add_module(Examples ${Examples_srcs} - INCLUDE_DIRS GaudiKernel FWCore ${plcio_INCLUDE_DIRS} ${podio_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} - LINK_LIBRARIES GaudiKernel FWCore ${podio_LIBRARIES} ${LCIO_LIBRARIES} $ENV{PLCIO}/lib/libplcio.so + INCLUDE_DIRS K4FWCore GaudiAlgLib GaudiKernel ${podio_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} + LINK_LIBRARIES K4FWCore GaudiAlgLib GaudiKernel ${LCIO_LIBRARIES} + DD4hep ${DD4hep_COMPONENT_LIBRARIES} + # Force loading the libraries. + -Wl,--no-as-needed EDM4HEP::edm4hep EDM4HEP::edm4hepDict ${podio_LIBRARIES} podio::podioRootIO -Wl,--as-needed ) # Unit tests @@ -35,6 +47,12 @@ gaudi_add_test(PlcioWriteAlg gaudi_add_test(PlcioReadAlg FRAMEWORK options/plcio_read.py) +gaudi_add_test(Edm4hepWriteAlg + FRAMEWORK options/edm4hep_write.py) + +gaudi_add_test(Edm4hepReadAlg + FRAMEWORK options/edm4hep_read.py) + gaudi_add_test(LCIOReadAlg FRAMEWORK options/LCIO_read.py) diff --git a/Examples/options/LCIO_read_pan.py b/Examples/options/LCIO_read_pan.py new file mode 100644 index 0000000000000000000000000000000000000000..97b5f9e974a0db059bb5a7d4a1da503d07887a16 --- /dev/null +++ b/Examples/options/LCIO_read_pan.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +from Gaudi.Configuration import * +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc") + +# read LCIO files +from Configurables import LCIOInput +read = LCIOInput("read") +read.inputs = [ +#"/cefs/data/FullSim/CEPC240/CEPC_v4/higgs/smart_final_states/E240.Pffh_invi.e0.p0.whizard195//ffh_inv.e0.p0.00001_1000_sim.slcio" +#"/junofs/users/wxfang/CEPC/CEPCOFF/doReco/reco_output/nnh_aa.e0.p0.00010_000000_rec.slcio" +"/cefs/higgs/wxfang/cepc/Pandora/CaloDigi/gamma/Digi_sim_0.slcio" +] +read.collections = { + #"COILCollection" : "SimTrackerHit", + #"EcalBarrelSiliconCollection" : "SimCalorimeterHit", + "MCParticle" : "MCParticle", + "ECALBarrel" : "CalorimeterHit", + "ECALEndcap" : "CalorimeterHit", + "ECALOther" : "CalorimeterHit", + "HCALBarrel" : "CalorimeterHit", + "HCALEndcap" : "CalorimeterHit", + "HCALOther" : "CalorimeterHit", + "MUON" : "CalorimeterHit", + "LCAL" : "CalorimeterHit", + "LHCAL" : "CalorimeterHit", + "BCAL" : "CalorimeterHit", + #"MarlinTrkTracks" : "Track" + #"TPCCollection" : "SimTrackerHit", + #"VXDCollection" : "SimTrackerHit" +} +############################################################################## +from Configurables import GearSvc +gearSvc = GearSvc("GearSvc") +gearSvc.GearXMLFile = "/junofs/users/wxfang/CEPC/CEPCOFF/doSim/fullDet/GearOutput.xml" +############################################################################## +from Configurables import PandoraPFAlg + +pandoralg = PandoraPFAlg("PandoraPFAlg") +## KEEP same with lcioinput name for the ReadXXX ########### +pandoralg.ReadMCParticle = "MCParticle" +pandoralg.ReadECALBarrel = "ECALBarrel" +pandoralg.ReadECALEndcap = "ECALEndcap" +pandoralg.ReadECALOther = "ECALOther" +pandoralg.ReadHCALBarrel = "HCALBarrel" +pandoralg.ReadHCALEndcap = "HCALEndcap" +pandoralg.ReadHCALOther = "HCALOther" +pandoralg.ReadMUON = "MUON" +pandoralg.ReadLCAL = "LCAL" +pandoralg.ReadLHCAL = "LHCAL" +pandoralg.ReadBCAL = "BCAL" +pandoralg.ReadKinkVertices = "KinkVertices" +pandoralg.ReadProngVertices = "ProngVertices" +pandoralg.ReadSplitVertices = "SplitVertices" +pandoralg.ReadV0Vertices = "V0Vertices" +pandoralg.ReadTracks = "MarlinTrkTracks" +pandoralg.WriteClusterCollection = "PandoraClusters" +pandoralg.WriteReconstructedParticleCollection = "PandoraPFOs" +pandoralg.WriteVertexCollection = "PandoraPFANewStartVertices" +pandoralg.AnaOutput = "/cefs/higgs/wxfang/cepc/Pandora/Ana/gamma/Ana_gamma_test.root" + +pandoralg.PandoraSettingsDefault_xml = "/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraSettingsDefault_wx.xml" +#### Do not chage the collection name, only add or delete ############### +pandoralg.TrackCollections = ["MarlinTrkTracks"] +pandoralg.ECalCaloHitCollections= ["ECALBarrel", "ECALEndcap", "ECALOther"] +pandoralg.HCalCaloHitCollections= ["HCALBarrel", "HCALEndcap", "HCALOther"] +pandoralg.LCalCaloHitCollections= ["LCAL"] +pandoralg.LHCalCaloHitCollections= ["LHCAL"] +pandoralg.MuonCaloHitCollections= ["MUON"] +pandoralg.MCParticleCollections = ["MCParticle"] +pandoralg.RelCaloHitCollections = ["RecoCaloAssociation_ECALBarrel", "RecoCaloAssociation_ECALEndcap", "RecoCaloAssociation_ECALOther", "RecoCaloAssociation_HCALBarrel", "RecoCaloAssociation_HCALEndcap", "RecoCaloAssociation_HCALOther", "RecoCaloAssociation_LCAL", "RecoCaloAssociation_LHCAL", "RecoCaloAssociation_MUON"] +pandoralg.RelTrackCollections = ["MarlinTrkTracksMCTruthLink"] +pandoralg.KinkVertexCollections = ["KinkVertices"] +pandoralg.ProngVertexCollections= ["ProngVertices"] +pandoralg.SplitVertexCollections= ["SplitVertices"] +pandoralg.V0VertexCollections = ["V0Vertices"] +pandoralg.ECalToMipCalibration = 160.0 +pandoralg.HCalToMipCalibration = 34.8 +pandoralg.ECalMipThreshold = 0.5 +pandoralg.HCalMipThreshold = 0.3 +pandoralg.ECalToEMGeVCalibration= 0.9 #for G2CD Digi, 1.007 for NewLDCaloDigi +pandoralg.HCalToEMGeVCalibration= 1.007 +pandoralg.ECalToHadGeVCalibrationBarrel= 1.12 #very small effect +pandoralg.ECalToHadGeVCalibrationEndCap= 1.12 +pandoralg.HCalToHadGeVCalibration= 1.07 +pandoralg.MuonToMipCalibration= 10.0 +pandoralg.DigitalMuonHits= 0 +pandoralg.MaxHCalHitHadronicEnergy = 1.0 +pandoralg.UseOldTrackStateCalculation= 0 +pandoralg.AbsorberRadLengthECal= 0.2854 +pandoralg.AbsorberIntLengthECal= 0.0101 +pandoralg.AbsorberRadLengthHCal= 0.0569 +pandoralg.AbsorberIntLengthHCal= 0.006 +pandoralg.AbsorberRadLengthOther= 0.0569 +pandoralg.AbsorberIntLengthOther= 0.006 + +############################################################################## + +# write PODIO file +from Configurables import PodioOutput +write = PodioOutput("write") +write.filename = "test.root" +write.outputCommands = ["keep *"] + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( + #TopAlg = [read, pandoralg, write], + TopAlg = [read, pandoralg], + EvtSel = 'NONE', + EvtMax = 10, + ExtSvc = [dsvc, gearSvc], + OutputLevel=INFO +) diff --git a/Examples/options/edm4hep_read.py b/Examples/options/edm4hep_read.py new file mode 100644 index 0000000000000000000000000000000000000000..998b300ec72179a375eb687f25dcbc09a742108b --- /dev/null +++ b/Examples/options/edm4hep_read.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +from Gaudi.Configuration import * + +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc", input="test.root") + +from Configurables import Edm4hepReadAlg +alg = Edm4hepReadAlg("Edm4hepReadAlg") +alg.HeaderCol.Path = "EventHeader" +alg.InputCol.Path = "MCParticle" + +from Configurables import PodioInput +podioinput = PodioInput("PodioReader", collections=[ + "EventHeader", + "MCParticle" + ]) + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( TopAlg = [podioinput, alg], + EvtSel = 'NONE', + EvtMax = 10, + ExtSvc = [dsvc], + OutputLevel=DEBUG +) diff --git a/Examples/options/edm4hep_write.py b/Examples/options/edm4hep_write.py new file mode 100644 index 0000000000000000000000000000000000000000..f5ad0bef5550d9cab2a7d6e451bb189fefa6120b --- /dev/null +++ b/Examples/options/edm4hep_write.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +from Gaudi.Configuration import * + +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc") + +from Configurables import Edm4hepWriteAlg +alg = Edm4hepWriteAlg("Edm4hepWriteAlg") +alg.HeaderCol.Path = "EventHeader" +alg.OutputCol.Path = "MCParticle" + +from Configurables import PodioOutput +out = PodioOutput("out") +out.filename = "test.root" +out.outputCommands = ["keep *"] + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( TopAlg = [alg, out], + EvtSel = 'NONE', + EvtMax = 10, + ExtSvc=[dsvc], + OutputLevel=DEBUG +) diff --git a/Examples/options/plcio_read.py b/Examples/options/plcio_read.py index d8b0b7395def1db1c04df844372967d7b42d4ab1..62c682b119b0acf413bbc3e1eca65983d4cd6343 100644 --- a/Examples/options/plcio_read.py +++ b/Examples/options/plcio_read.py @@ -2,8 +2,8 @@ from Gaudi.Configuration import * -from Configurables import CEPCDataSvc -dsvc = CEPCDataSvc("EventDataSvc", input="test.root") +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc", input="test.root") from Configurables import PlcioReadAlg alg = PlcioReadAlg("PlcioReadAlg") diff --git a/Examples/options/plcio_write.py b/Examples/options/plcio_write.py index 378aae8406012a0f008c3ce3ff6a5fb306297938..17bab8ed634928f0193f467e58d55aec30b54a54 100644 --- a/Examples/options/plcio_write.py +++ b/Examples/options/plcio_write.py @@ -2,8 +2,8 @@ from Gaudi.Configuration import * -from Configurables import CEPCDataSvc -dsvc = CEPCDataSvc("EventDataSvc") +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc") from Configurables import PlcioWriteAlg alg = PlcioWriteAlg("PlcioWriteAlg") diff --git a/Examples/options/tut_detsim.py b/Examples/options/tut_detsim.py index 2ecb5e3f6ea15ba4ce0dd5b6f8e37b33c102c1c2..3c9071ed5e8580691c2d7412e9478feb83500ea9 100644 --- a/Examples/options/tut_detsim.py +++ b/Examples/options/tut_detsim.py @@ -24,8 +24,8 @@ rndmengine.Seeds = [42] ############################################################################## # Event Data Svc ############################################################################## -from Configurables import CEPCDataSvc -dsvc = CEPCDataSvc("EventDataSvc") +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc") ############################################################################## @@ -58,18 +58,19 @@ from Configurables import SLCIORdr from Configurables import HepMCRdr from Configurables import GenPrinter -# gun = GtGunTool("GtGunTool") -# gun.Particles = ["pi+"] -# gun.Energies = [100.] # GeV +gun = GtGunTool("GtGunTool") +gun.Particles = ["pi+"] +gun.EnergyMins = [100.] # GeV +gun.EnergyMaxs = [100.] # GeV -# gun.ThetaMins = [] # rad; 45deg -# gun.ThetaMaxs = [] # rad; 45deg +gun.ThetaMins = [0] # rad; 45deg +gun.ThetaMaxs = [180.] # rad; 45deg -# gun.PhiMins = [] # rad; 0deg -# gun.PhiMaxs = [] # rad; 360deg +gun.PhiMins = [0] # rad; 0deg +gun.PhiMaxs = [360.] # rad; 360deg -stdheprdr = StdHepRdr("StdHepRdr") -stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep" +# stdheprdr = StdHepRdr("StdHepRdr") +# stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep" # lciordr = SLCIORdr("SLCIORdr") # lciordr.Input = "/cefs/data/stdhep/lcio250/signal/Higgs/E250.Pbbh.whizard195/E250.Pbbh_X.e0.p0.whizard195/Pbbh_X.e0.p0.00001.slcio" @@ -80,8 +81,8 @@ stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizar genprinter = GenPrinter("GenPrinter") genalg = GenAlgo("GenAlgo") -# genalg.GenTools = ["GtGunTool"] -genalg.GenTools = ["StdHepRdr"] +genalg.GenTools = ["GtGunTool"] +# genalg.GenTools = ["StdHepRdr"] # genalg.GenTools = ["StdHepRdr", "GenPrinter"] # genalg.GenTools = ["SLCIORdr", "GenPrinter"] # genalg.GenTools = ["HepMCRdr", "GenPrinter"] @@ -107,7 +108,8 @@ detsimalg.RunCmds = [ ] detsimalg.AnaElems = [ # example_anatool.name() - "ExampleAnaElemTool" + # "ExampleAnaElemTool" + "Edm4hepWriterAnaElemTool" ] detsimalg.RootDetElem = "WorldDetElemTool" diff --git a/Examples/options/tut_detsim_pan_matrix.py b/Examples/options/tut_detsim_pan_matrix.py new file mode 100644 index 0000000000000000000000000000000000000000..1d5bd4561d3f5bd4318455d7c6a9a54df88c5aa2 --- /dev/null +++ b/Examples/options/tut_detsim_pan_matrix.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python + +import os +print(os.environ["DD4HEP_LIBRARY_PATH"]) +import sys +# sys.exit(0) + +from Gaudi.Configuration import * + +############################################################################## +# Random Number Svc +############################################################################## +from Configurables import RndmGenSvc, HepRndm__Engine_CLHEP__RanluxEngine_ + +# rndmengine = HepRndm__Engine_CLHEP__RanluxEngine_() # The default engine in Gaudi +rndmengine = HepRndm__Engine_CLHEP__HepJamesRandom_() # The default engine in Geant4 +rndmengine.SetSingleton = True +rndmengine.Seeds = [42] + +# rndmgensvc = RndmGenSvc("RndmGenSvc") +# rndmgensvc.Engine = rndmengine.name() + + +############################################################################## +# Event Data Svc +############################################################################## +#from Configurables import CEPCDataSvc +#dsvc = CEPCDataSvc("EventDataSvc") +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc") + + +############################################################################## +# Geometry Svc +############################################################################## + +# geometry_option = "CepC_v4-onlyTracker.xml" +geometry_option = "CepC_v4-onlyVXD.xml" + +if not os.getenv("DETCEPCV4ROOT"): + print("Can't find the geometry. Please setup envvar DETCEPCV4ROOT." ) + sys.exit(-1) + +geometry_path = os.path.join(os.getenv("DETCEPCV4ROOT"), "compact", geometry_option) +if not os.path.exists(geometry_path): + print("Can't find the compact geometry file: %s"%geometry_path) + sys.exit(-1) + +from Configurables import GeoSvc +geosvc = GeoSvc("GeoSvc") +#geosvc.compact = geometry_path +geosvc.compact = "../Detector/DetEcalMatrix/compact/det.xml" + +############################################################################## +# Physics Generator +############################################################################## +from Configurables import GenAlgo +from Configurables import GtGunTool +from Configurables import StdHepRdr +from Configurables import SLCIORdr +from Configurables import HepMCRdr +from Configurables import GenPrinter + +gun = GtGunTool("GtGunTool") +gun.Particles = ["gamma","gamma"] +gun.EnergyMins= [10, 10] # GeV +gun.EnergyMaxs= [10, 10] # GeV +gun.ThetaMins = [90, 90] # degree +gun.ThetaMaxs = [90, 90] # degree +gun.PhiMins = [0, 1 ] # degree +gun.PhiMaxs = [0, 1 ] # degree + + +stdheprdr = StdHepRdr("StdHepRdr") +#stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep" +#stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep" +stdheprdr.Input = "/cefs/data/stdhep/CEPC250/higgs/E250.Pbbh.whizard195/E250.Pbbh_X.e0.p0.whizard195/Pbbh_X.e0.p0.00001.stdhep" + +# lciordr = SLCIORdr("SLCIORdr") +# lciordr.Input = "/cefs/data/stdhep/lcio250/signal/Higgs/E250.Pbbh.whizard195/E250.Pbbh_X.e0.p0.whizard195/Pbbh_X.e0.p0.00001.slcio" + +# hepmcrdr = HepMCRdr("HepMCRdr") +# hepmcrdr.Input = "example_UsingIterators.txt" + +genprinter = GenPrinter("GenPrinter") + +genalg = GenAlgo("GenAlgo") +genalg.GenTools = ["GtGunTool"] +#genalg.GenTools = ["StdHepRdr"] +# genalg.GenTools = ["StdHepRdr", "GenPrinter"] +# genalg.GenTools = ["SLCIORdr", "GenPrinter"] +# genalg.GenTools = ["HepMCRdr", "GenPrinter"] + +############################################################################## +# Detector Simulation +############################################################################## +from Configurables import DetSimSvc + +detsimsvc = DetSimSvc("DetSimSvc") + +# from Configurables import ExampleAnaElemTool +# example_anatool = ExampleAnaElemTool("ExampleAnaElemTool") + +from Configurables import DetSimAlg + +detsimalg = DetSimAlg("DetSimAlg") + +# detsimalg.VisMacs = ["vis.mac"] + +detsimalg.RunCmds = [ +# "/tracking/verbose 1", +] +detsimalg.AnaElems = [ + # example_anatool.name() + # "ExampleAnaElemTool" + "Edm4hepWriterAnaElemTool" +] +detsimalg.RootDetElem = "WorldDetElemTool" + +from Configurables import AnExampleDetElemTool +example_dettool = AnExampleDetElemTool("AnExampleDetElemTool") + +############################################################################## +from Configurables import CaloDigiAlg +example_CaloDigiAlg = CaloDigiAlg("CaloDigiAlg") +example_CaloDigiAlg.Scale = 1 +example_CaloDigiAlg.SimCaloHitCollection = "SimCalorimeterCol" +example_CaloDigiAlg.CaloHitCollection = "ECALBarrel" +example_CaloDigiAlg.CaloAssociationCollection = "RecoCaloAssociation_ECALBarrel" +############################################################################## +from Configurables import GearSvc +gearSvc = GearSvc("GearSvc") +#gearSvc.GearXMLFile = "/junofs/users/wxfang/CEPC/CEPCOFF/doSim/fullDet/GearOutput.xml" +gearSvc.GearXMLFile = "../Detector/DetCEPCv4/compact/FullDetGear.xml" +############################################################################## +#from Configurables import PandoraPFAlg +from Configurables import PandoraMatrixAlg + +#pandoralg = PandoraPFAlg("PandoraPFAlg") +pandoralg = PandoraMatrixAlg("PandoraMatrixAlg") +## KEEP same with lcioinput name for the ReadXXX ########### +pandoralg.ReadMCParticle = "MCParticle" +pandoralg.ReadECALBarrel = "ECALBarrel" +pandoralg.ReadECALEndcap = "ECALEndcap" +pandoralg.ReadECALOther = "ECALOther" +pandoralg.ReadHCALBarrel = "HCALBarrel" +pandoralg.ReadHCALEndcap = "HCALEndcap" +pandoralg.ReadHCALOther = "HCALOther" +pandoralg.ReadMUON = "MUON" +pandoralg.ReadLCAL = "LCAL" +pandoralg.ReadLHCAL = "LHCAL" +pandoralg.ReadBCAL = "BCAL" +pandoralg.ReadKinkVertices = "KinkVertices" +pandoralg.ReadProngVertices = "ProngVertices" +pandoralg.ReadSplitVertices = "SplitVertices" +pandoralg.ReadV0Vertices = "V0Vertices" +pandoralg.ReadTracks = "MarlinTrkTracks" +pandoralg.MCRecoCaloAssociation = "RecoCaloAssociation_ECALBarrel" +pandoralg.WriteClusterCollection = "PandoraClusters" +pandoralg.WriteReconstructedParticleCollection = "PandoraPFOs" +pandoralg.WriteVertexCollection = "PandoraPFANewStartVertices" +pandoralg.AnaOutput = "/cefs/higgs/wxfang/cepc/Pandora/Ana/gamma/Ana_gamma_Matrix_Rel_10GeV_test.root" + +pandoralg.PandoraSettingsDefault_xml = "/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraSettingsDefault_wx.xml" +#### Do not chage the collection name, only add or delete ############### +pandoralg.TrackCollections = ["MarlinTrkTracks"] +pandoralg.ECalCaloHitCollections= ["ECALBarrel", "ECALEndcap", "ECALOther"] +pandoralg.HCalCaloHitCollections= ["HCALBarrel", "HCALEndcap", "HCALOther"] +pandoralg.LCalCaloHitCollections= ["LCAL"] +pandoralg.LHCalCaloHitCollections= ["LHCAL"] +pandoralg.MuonCaloHitCollections= ["MUON"] +pandoralg.MCParticleCollections = ["MCParticle"] +pandoralg.RelCaloHitCollections = ["RecoCaloAssociation_ECALBarrel", "RecoCaloAssociation_ECALEndcap", "RecoCaloAssociation_ECALOther", "RecoCaloAssociation_HCALBarrel", "RecoCaloAssociation_HCALEndcap", "RecoCaloAssociation_HCALOther", "RecoCaloAssociation_LCAL", "RecoCaloAssociation_LHCAL", "RecoCaloAssociation_MUON"] +pandoralg.RelTrackCollections = ["MarlinTrkTracksMCTruthLink"] +pandoralg.KinkVertexCollections = ["KinkVertices"] +pandoralg.ProngVertexCollections= ["ProngVertices"] +pandoralg.SplitVertexCollections= ["SplitVertices"] +pandoralg.V0VertexCollections = ["V0Vertices"] +pandoralg.ECalToMipCalibration = 112 #1000MeV/8.918 #CEPC :160.0 +pandoralg.HCalToMipCalibration = 34.8 +pandoralg.ECalMipThreshold = 0.225# 8.918*0.225=2.00655 #CEPC 0.5 +pandoralg.HCalMipThreshold = 0.3 +pandoralg.ECalToEMGeVCalibration= 1.# BGO, to be tuned # CEPC: 0.9 for G2CD Digi, 1.007 for NewLDCaloDigi +pandoralg.HCalToEMGeVCalibration= 1.007 +pandoralg.ECalToHadGeVCalibrationBarrel= 1.12 #very small effect +pandoralg.ECalToHadGeVCalibrationEndCap= 1.12 +pandoralg.HCalToHadGeVCalibration= 1.07 +pandoralg.MuonToMipCalibration= 10.0 +pandoralg.DigitalMuonHits= 0 +pandoralg.MaxHCalHitHadronicEnergy = 1.0 +pandoralg.UseOldTrackStateCalculation= 0 +pandoralg.AbsorberRadLengthECal= 0.08945 #BG0: 1/11.18 mm , CEPC: 0.2854 = 1/3.504 mm +pandoralg.AbsorberIntLengthECal= 0.00448 #BG0: 1/223.2 mm , CEPC: 0.0101 = 1/99.46 mm +pandoralg.AbsorberRadLengthHCal= 0.0569 +pandoralg.AbsorberIntLengthHCal= 0.006 +pandoralg.AbsorberRadLengthOther= 0.0569 +pandoralg.AbsorberIntLengthOther= 0.006 + +############################################################################## + +# write PODIO file +from Configurables import PodioOutput +write = PodioOutput("write") +write.filename = "test.root" +write.outputCommands = ["keep *"] + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( + TopAlg = [genalg, detsimalg, example_CaloDigiAlg, pandoralg], + #TopAlg = [genalg, detsimalg], + #TopAlg = [genalg, detsimalg, write], + #TopAlg = [read, pandoralg], + EvtSel = 'NONE', + EvtMax = 10, + #ExtSvc = [rndmengine, dsvc, geosvc, gearSvc], + ExtSvc = [rndmengine, dsvc, geosvc, gearSvc,detsimsvc], + OutputLevel=INFO +) diff --git a/Examples/options/tut_detsim_pandora.py b/Examples/options/tut_detsim_pandora.py new file mode 100644 index 0000000000000000000000000000000000000000..b4ceaf07377898130aea5d39e6e304242cda1262 --- /dev/null +++ b/Examples/options/tut_detsim_pandora.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python + +import os +print(os.environ["DD4HEP_LIBRARY_PATH"]) +import sys +# sys.exit(0) + +from Gaudi.Configuration import * + +############################################################################## +# Random Number Svc +############################################################################## +from Configurables import RndmGenSvc, HepRndm__Engine_CLHEP__RanluxEngine_ + +# rndmengine = HepRndm__Engine_CLHEP__RanluxEngine_() # The default engine in Gaudi +rndmengine = HepRndm__Engine_CLHEP__HepJamesRandom_() # The default engine in Geant4 +rndmengine.SetSingleton = True +rndmengine.Seeds = [42] + +# rndmgensvc = RndmGenSvc("RndmGenSvc") +# rndmgensvc.Engine = rndmengine.name() + + +############################################################################## +# Event Data Svc +############################################################################## +#from Configurables import CEPCDataSvc +#dsvc = CEPCDataSvc("EventDataSvc") +from Configurables import K4DataSvc +dsvc = K4DataSvc("EventDataSvc") + + +############################################################################## +# Geometry Svc +############################################################################## + +# geometry_option = "CepC_v4-onlyTracker.xml" +geometry_option = "CepC_v4-onlyVXD.xml" + +if not os.getenv("DETCEPCV4ROOT"): + print("Can't find the geometry. Please setup envvar DETCEPCV4ROOT." ) + sys.exit(-1) + +geometry_path = os.path.join(os.getenv("DETCEPCV4ROOT"), "compact", geometry_option) +if not os.path.exists(geometry_path): + print("Can't find the compact geometry file: %s"%geometry_path) + sys.exit(-1) + +from Configurables import GeoSvc +geosvc = GeoSvc("GeoSvc") +geosvc.compact = geometry_path + +############################################################################## +# Physics Generator +############################################################################## +from Configurables import GenAlgo +from Configurables import GtGunTool +from Configurables import StdHepRdr +from Configurables import SLCIORdr +from Configurables import HepMCRdr +from Configurables import GenPrinter + +gun = GtGunTool("GtGunTool") +gun.Particles = ["gamma","gamma"] +gun.EnergyMins= [10, 10] # GeV +gun.EnergyMaxs= [10, 10] # GeV +gun.ThetaMins = [90, 90] # degree +gun.ThetaMaxs = [90, 90] # degree +gun.PhiMins = [0, 1 ] # degree +gun.PhiMaxs = [0, 1 ] # degree + + +stdheprdr = StdHepRdr("StdHepRdr") +#stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep" +#stdheprdr.Input = "/cefs/data/stdhep/CEPC250/2fermions/E250.Pbhabha.e0.p0.whizard195/bhabha.e0.p0.00001.stdhep" +stdheprdr.Input = "/cefs/data/stdhep/CEPC250/higgs/E250.Pbbh.whizard195/E250.Pbbh_X.e0.p0.whizard195/Pbbh_X.e0.p0.00001.stdhep" + +# lciordr = SLCIORdr("SLCIORdr") +# lciordr.Input = "/cefs/data/stdhep/lcio250/signal/Higgs/E250.Pbbh.whizard195/E250.Pbbh_X.e0.p0.whizard195/Pbbh_X.e0.p0.00001.slcio" + +# hepmcrdr = HepMCRdr("HepMCRdr") +# hepmcrdr.Input = "example_UsingIterators.txt" + +genprinter = GenPrinter("GenPrinter") + +genalg = GenAlgo("GenAlgo") +genalg.GenTools = ["GtGunTool"] +#genalg.GenTools = ["StdHepRdr"] +# genalg.GenTools = ["StdHepRdr", "GenPrinter"] +# genalg.GenTools = ["SLCIORdr", "GenPrinter"] +# genalg.GenTools = ["HepMCRdr", "GenPrinter"] + +############################################################################## +# Detector Simulation +############################################################################## +from Configurables import DetSimSvc + +detsimsvc = DetSimSvc("DetSimSvc") + +# from Configurables import ExampleAnaElemTool +# example_anatool = ExampleAnaElemTool("ExampleAnaElemTool") + +from Configurables import DetSimAlg + +detsimalg = DetSimAlg("DetSimAlg") + +# detsimalg.VisMacs = ["vis.mac"] + +detsimalg.RunCmds = [ +# "/tracking/verbose 1", +] +detsimalg.AnaElems = [ + # example_anatool.name() + # "ExampleAnaElemTool" + "Edm4hepWriterAnaElemTool" +] +detsimalg.RootDetElem = "WorldDetElemTool" + +from Configurables import AnExampleDetElemTool +example_dettool = AnExampleDetElemTool("AnExampleDetElemTool") + +############################################################################## +from Configurables import CaloDigiAlg +example_CaloDigiAlg = CaloDigiAlg("CaloDigiAlg") +example_CaloDigiAlg.Scale = 1 +example_CaloDigiAlg.SimCaloHitCollection = "SimCalorimeterCol" +example_CaloDigiAlg.CaloHitCollection = "ECALBarrel" +example_CaloDigiAlg.CaloAssociationCollection = "RecoCaloAssociation_ECALBarrel" +############################################################################## +from Configurables import GearSvc +gearSvc = GearSvc("GearSvc") +gearSvc.GearXMLFile = "../Detector/DetCEPCv4/compact/FullDetGear.xml" +############################################################################## +from Configurables import PandoraPFAlg + +pandoralg = PandoraPFAlg("PandoraPFAlg") +## KEEP same with lcioinput name for the ReadXXX ########### +pandoralg.ReadMCParticle = "MCParticle" +pandoralg.ReadECALBarrel = "ECALBarrel" +pandoralg.ReadECALEndcap = "ECALEndcap" +pandoralg.ReadECALOther = "ECALOther" +pandoralg.ReadHCALBarrel = "HCALBarrel" +pandoralg.ReadHCALEndcap = "HCALEndcap" +pandoralg.ReadHCALOther = "HCALOther" +pandoralg.ReadMUON = "MUON" +pandoralg.ReadLCAL = "LCAL" +pandoralg.ReadLHCAL = "LHCAL" +pandoralg.ReadBCAL = "BCAL" +pandoralg.ReadKinkVertices = "KinkVertices" +pandoralg.ReadProngVertices = "ProngVertices" +pandoralg.ReadSplitVertices = "SplitVertices" +pandoralg.ReadV0Vertices = "V0Vertices" +pandoralg.ReadTracks = "MarlinTrkTracks" +pandoralg.MCRecoCaloAssociation = "RecoCaloAssociation_ECALBarrel" +pandoralg.WriteClusterCollection = "PandoraClusters" +pandoralg.WriteReconstructedParticleCollection = "PandoraPFOs" +pandoralg.WriteVertexCollection = "PandoraPFANewStartVertices" +pandoralg.AnaOutput = "Ana.root" + +pandoralg.PandoraSettingsDefault_xml = "../Reconstruction/PFA/Pandora/PandoraSettingsDefault.xml" +#### Do not chage the collection name, only add or remove ############### +pandoralg.TrackCollections = ["MarlinTrkTracks"] +pandoralg.ECalCaloHitCollections= ["ECALBarrel", "ECALEndcap", "ECALOther"] +pandoralg.HCalCaloHitCollections= ["HCALBarrel", "HCALEndcap", "HCALOther"] +pandoralg.LCalCaloHitCollections= ["LCAL"] +pandoralg.LHCalCaloHitCollections= ["LHCAL"] +pandoralg.MuonCaloHitCollections= ["MUON"] +pandoralg.MCParticleCollections = ["MCParticle"] +pandoralg.RelCaloHitCollections = ["RecoCaloAssociation_ECALBarrel", "RecoCaloAssociation_ECALEndcap", "RecoCaloAssociation_ECALOther", "RecoCaloAssociation_HCALBarrel", "RecoCaloAssociation_HCALEndcap", "RecoCaloAssociation_HCALOther", "RecoCaloAssociation_LCAL", "RecoCaloAssociation_LHCAL", "RecoCaloAssociation_MUON"] +pandoralg.RelTrackCollections = ["MarlinTrkTracksMCTruthLink"] +pandoralg.KinkVertexCollections = ["KinkVertices"] +pandoralg.ProngVertexCollections= ["ProngVertices"] +pandoralg.SplitVertexCollections= ["SplitVertices"] +pandoralg.V0VertexCollections = ["V0Vertices"] +pandoralg.ECalToMipCalibration = 160.0 +pandoralg.HCalToMipCalibration = 34.8 +pandoralg.ECalMipThreshold = 0.5 +pandoralg.HCalMipThreshold = 0.3 +pandoralg.ECalToEMGeVCalibration= 0.9 #for G2CD Digi, 1.007 for NewLDCaloDigi +pandoralg.HCalToEMGeVCalibration= 1.007 +pandoralg.ECalToHadGeVCalibrationBarrel= 1.12 #very small effect +pandoralg.ECalToHadGeVCalibrationEndCap= 1.12 +pandoralg.HCalToHadGeVCalibration= 1.07 +pandoralg.MuonToMipCalibration= 10.0 +pandoralg.DigitalMuonHits= 0 +pandoralg.MaxHCalHitHadronicEnergy = 1.0 +pandoralg.UseOldTrackStateCalculation= 0 +pandoralg.AbsorberRadLengthECal= 0.2854 #= 1/3.504 mm +pandoralg.AbsorberIntLengthECal= 0.0101 #= 1/99.46 mm +pandoralg.AbsorberRadLengthHCal= 0.0569 +pandoralg.AbsorberIntLengthHCal= 0.006 +pandoralg.AbsorberRadLengthOther= 0.0569 +pandoralg.AbsorberIntLengthOther= 0.006 + +############################################################################## + +# write PODIO file +from Configurables import PodioOutput +write = PodioOutput("write") +write.filename = "test.root" +write.outputCommands = ["keep *"] + +# ApplicationMgr +from Configurables import ApplicationMgr +ApplicationMgr( + TopAlg = [genalg, detsimalg, example_CaloDigiAlg, pandoralg], + EvtSel = 'NONE', + EvtMax = 10, + ExtSvc = [rndmengine, dsvc, geosvc, gearSvc,detsimsvc], + OutputLevel=INFO +) diff --git a/Examples/src/DumpIDAlg/DumpIDAlg.cpp b/Examples/src/DumpIDAlg/DumpIDAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ae59e335bb44fcb32a428a5fb03f77c37df9f29 --- /dev/null +++ b/Examples/src/DumpIDAlg/DumpIDAlg.cpp @@ -0,0 +1,110 @@ +#include "DumpIDAlg.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "edm4hep/CaloHitContributionCollection.h" + +#include "DD4hep/Detector.h" +#include "DD4hep/IDDescriptor.h" +#include "DD4hep/Plugins.h" + +DECLARE_COMPONENT(DumpIDAlg) + +DumpIDAlg::DumpIDAlg(const std::string& name, ISvcLocator* svcLoc) +: GaudiAlgorithm(name, svcLoc), m_dd4hep_geo(nullptr), m_decoder(nullptr) +{ + +} + +StatusCode DumpIDAlg::initialize() +{ + m_geosvc = service<IGeoSvc>("GeoSvc"); + if (!m_geosvc) { + error() << "Failed to find GeoSvc." << endmsg; + return StatusCode::FAILURE; + } + m_dd4hep_geo = m_geosvc->lcdd(); + if (!m_dd4hep_geo) { + error() << "failed to retrieve dd4hep_geo: " << m_dd4hep_geo << endmsg; + return StatusCode::FAILURE; + } + + // get the DD4hep readout + const std::string name_readout = "EcalBarrelCollection"; + m_decoder = m_geosvc->getDecoder(name_readout); + if (!m_decoder) { + error() << "Failed to get the decoder. " << endmsg; + return StatusCode::FAILURE; + } + + // Book N-tuple 1 + NTuplePtr nt1( ntupleSvc(), "MyTuples/1" ); + if ( nt1 ) { + m_tuple_id = nt1; + } else { + m_tuple_id = ntupleSvc()->book( "MyTuples/1", CLID_RowWiseTuple, "Row-wise N-Tuple example" ); + if ( m_tuple_id ) { + m_tuple_id->addItem( "system", m_id_system ).ignore(); + m_tuple_id->addItem( "module", m_id_module ).ignore(); + m_tuple_id->addItem( "stave", m_id_stave ).ignore(); + m_tuple_id->addItem( "tower", m_id_tower ).ignore(); + m_tuple_id->addItem( "layer", m_id_layer ).ignore(); + m_tuple_id->addItem( "wafer", m_id_wafer ).ignore(); + m_tuple_id->addItem( "cellX", m_id_cellX ).ignore(); + m_tuple_id->addItem( "cellY", m_id_cellY ).ignore(); + + } else { // did not manage to book the N tuple.... + error() << " Cannot book N-tuple:" << long( m_tuple_id ) << endmsg; + return StatusCode::FAILURE; + } + } + + + return GaudiAlgorithm::initialize(); +} + +StatusCode DumpIDAlg::execute() +{ + + + auto ecalBarrelCol = m_EcalBarrelCol.get(); + for (auto calohit: *ecalBarrelCol) { + auto cellid = calohit.getCellID(); + + m_id_system = m_decoder->get(cellid, "system"); + m_id_module = m_decoder->get(cellid, "module"); + m_id_stave = m_decoder->get(cellid, "stave"); + m_id_tower = m_decoder->get(cellid, "tower"); + m_id_layer = m_decoder->get(cellid, "layer"); + m_id_wafer = m_decoder->get(cellid, "wafer"); + m_id_cellX = m_decoder->get(cellid, "cellX"); + m_id_cellY = m_decoder->get(cellid, "cellY"); + + info() << "Calo hit cellid: " << cellid + << " system: " << m_id_system + << " module: " << m_id_module + << " stave: " << m_id_stave + << " tower: " << m_id_tower + << " layer: " << m_id_layer + << " wafer: " << m_id_wafer + << " cellX: " << m_id_cellX + << " cellY: " << m_id_cellY + << endmsg; + + // calculate I/J/K + + m_tuple_id->write(); + + } + return StatusCode::SUCCESS; +} + +StatusCode DumpIDAlg::finalize() +{ + + return GaudiAlgorithm::finalize(); +} + + + + diff --git a/Examples/src/DumpIDAlg/DumpIDAlg.h b/Examples/src/DumpIDAlg/DumpIDAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..20bb9469ffaebe9f46fb50bf0a919cbf66218bb0 --- /dev/null +++ b/Examples/src/DumpIDAlg/DumpIDAlg.h @@ -0,0 +1,53 @@ +#ifndef DumpIDAlg_h +#define DumpIDAlg_h + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include "GaudiKernel/NTuple.h" + +#include "DetInterface/IGeoSvc.h" + +#include "DD4hep/Detector.h" + +namespace edm4hep { + class EventHeaderCollection; + class MCParticleCollection; + class SimCalorimeterHitCollection; + class CaloHitContributionCollection; +} + +class DumpIDAlg: public GaudiAlgorithm +{ +public: + + DumpIDAlg(const std::string& name, ISvcLocator* svcLoc); + + virtual StatusCode initialize(); + virtual StatusCode execute(); + virtual StatusCode finalize(); + +private: + SmartIF<IGeoSvc> m_geosvc; + dd4hep::Detector* m_dd4hep_geo; + dd4hep::DDSegmentation::BitFieldCoder* m_decoder; + + DataHandle<edm4hep::SimCalorimeterHitCollection> m_EcalBarrelCol{"EcalBarrelCollection", + Gaudi::DataHandle::Reader, this}; + +private: + // strore all the id for later analysis + NTuple::Tuple* m_tuple_id = nullptr; + + NTuple::Item<int> m_id_system; + NTuple::Item<int> m_id_module; + NTuple::Item<int> m_id_stave; + NTuple::Item<int> m_id_tower; + NTuple::Item<int> m_id_layer; + NTuple::Item<int> m_id_wafer; + NTuple::Item<int> m_id_cellX; + NTuple::Item<int> m_id_cellY; + +}; + + +#endif diff --git a/Examples/src/Edm4hepTest/Edm4hepReadAlg.cpp b/Examples/src/Edm4hepTest/Edm4hepReadAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f41d333b18a5da763b0c7d21ce7f879f29cda822 --- /dev/null +++ b/Examples/src/Edm4hepTest/Edm4hepReadAlg.cpp @@ -0,0 +1,66 @@ +#include "Edm4hepReadAlg.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "edm4hep/CaloHitContributionCollection.h" + +DECLARE_COMPONENT(Edm4hepReadAlg) + +Edm4hepReadAlg::Edm4hepReadAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc) +{ + declareProperty("HeaderCol", m_headerCol); + declareProperty("InputCol", m_mcParCol, "MCParticle collection (input)"); +} + +StatusCode Edm4hepReadAlg::initialize() +{ + debug() << "begin initialize Edm4hepReadAlg" << endmsg; + return GaudiAlgorithm::initialize(); +} + +StatusCode Edm4hepReadAlg::execute() +{ + debug() << "begin execute Edm4hepReadAlg" << endmsg; + + auto mcCol = m_mcParCol.get(); + for ( auto p : *mcCol ) { + info() << p.getObjectID().index << " : ["; + for ( auto it = p.daughters_begin(), end = p.daughters_end(); it != end; ++it ) { + info() << " " << it->getObjectID().index; + } + info() << " ]; "; + } + info() << "}" << endmsg; + + auto caloCol = m_calorimeterCol.get(); + for (auto calohit : *caloCol) { + unsigned int contrib_size = calohit.contributions_size(); + info() << " contributions_size: " + << contrib_size + << endmsg; + for (unsigned int i = 0; i < contrib_size; ++i) { + auto contrib = calohit.getContributions(i); + auto primary_particle = contrib.getParticle(); + + info() << " - #" << i << ": " + << " track with " + << " PDG: " << contrib.getPDG() // current track + << ". " + << " primary track with " + << " PDG: " << primary_particle.getPDG() + << endmsg; + + + } + + } + + return StatusCode::SUCCESS; +} + +StatusCode Edm4hepReadAlg::finalize() +{ + debug() << "begin finalize Edm4hepReadAlg" << endmsg; + return GaudiAlgorithm::finalize(); +} diff --git a/Examples/src/Edm4hepTest/Edm4hepReadAlg.h b/Examples/src/Edm4hepTest/Edm4hepReadAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..8a194a64f54c221ea47905dbc855f2048e24892a --- /dev/null +++ b/Examples/src/Edm4hepTest/Edm4hepReadAlg.h @@ -0,0 +1,36 @@ +#ifndef TEST_EDM4HEP_WRITE_ALG_H +#define TEST_EDM4HEP_WRITE_ALG_H + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" + +namespace edm4hep { + class EventHeaderCollection; + class MCParticleCollection; + class SimCalorimeterHitCollection; + class CaloHitContributionCollection; +} + +class Edm4hepReadAlg : public GaudiAlgorithm +{ + + public : + + Edm4hepReadAlg(const std::string& name, ISvcLocator* svcLoc); + + virtual StatusCode initialize(); + virtual StatusCode execute(); + virtual StatusCode finalize(); + + private : + + DataHandle<edm4hep::EventHeaderCollection> m_headerCol{"EventHeader", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCParticleCollection> m_mcParCol{"MCParticle", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::SimCalorimeterHitCollection> m_calorimeterCol{"SimCalorimeterCol", + Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CaloHitContributionCollection> m_caloContribCol{"SimCaloContributionCol", + Gaudi::DataHandle::Reader, this}; + +}; + +#endif // TEST_EDM4HEP_WRITE_ALG_H diff --git a/Examples/src/Edm4hepTest/Edm4hepWriteAlg.cpp b/Examples/src/Edm4hepTest/Edm4hepWriteAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b33d5e8045507a7514a7358aa8375f7e9326b544 --- /dev/null +++ b/Examples/src/Edm4hepTest/Edm4hepWriteAlg.cpp @@ -0,0 +1,54 @@ +#include "Edm4hepWriteAlg.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/MCParticleCollection.h" + +DECLARE_COMPONENT(Edm4hepWriteAlg) + +Edm4hepWriteAlg::Edm4hepWriteAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc) +{ + declareProperty("HeaderCol", m_headerCol); + declareProperty("OutputCol", m_mcParCol, "MCParticle collection (output)"); +} + +StatusCode Edm4hepWriteAlg::initialize() +{ + debug() << "begin initialize Edm4hepWriteAlg" << endmsg; + return GaudiAlgorithm::initialize(); +} + +StatusCode Edm4hepWriteAlg::execute() +{ + debug() << "begin execute Edm4hepWriteAlg" << endmsg; + + static int evtNo = 0; + + auto headers = m_headerCol.createAndPut(); + auto header = headers->create(); + header.setRunNumber(-999); + header.setEventNumber(evtNo++); + // header.setDetectorName("TEST"); + + //auto mcCol = new edm4hep::MCParticleCollection; + //m_mcParCol.put(mcCol); + auto mcCol = m_mcParCol.createAndPut(); + + auto p1 = mcCol->create(); + auto p2 = mcCol->create(); + + for ( int i = 0; i < 4; ++i ) { + auto d = mcCol->create(); + d.addToParents(p1); + d.addToParents(p2); + p1.addToDaughters(d); + p2.addToDaughters(d); + } + + return StatusCode::SUCCESS; +} + +StatusCode Edm4hepWriteAlg::finalize() +{ + debug() << "begin finalize Edm4hepWriteAlg" << endmsg; + return GaudiAlgorithm::finalize(); +} diff --git a/Examples/src/Edm4hepTest/Edm4hepWriteAlg.h b/Examples/src/Edm4hepTest/Edm4hepWriteAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..8058747476ab106edd3cdca52be0d04ba3110f33 --- /dev/null +++ b/Examples/src/Edm4hepTest/Edm4hepWriteAlg.h @@ -0,0 +1,30 @@ +#ifndef TEST_EDM4HEP_WRITE_ALG_H +#define TEST_EDM4HEP_WRITE_ALG_H + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" + +namespace edm4hep { + class EventHeaderCollection; + class MCParticleCollection; +} + +class Edm4hepWriteAlg : public GaudiAlgorithm +{ + + public : + + Edm4hepWriteAlg(const std::string& name, ISvcLocator* svcLoc); + + virtual StatusCode initialize(); + virtual StatusCode execute(); + virtual StatusCode finalize(); + + private : + + DataHandle<edm4hep::EventHeaderCollection> m_headerCol{"EventHeader", Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCParticleCollection> m_mcParCol{"MCParticle", Gaudi::DataHandle::Writer, this}; + +}; + +#endif // TEST_EDM4HEP_WRITE_ALG_H diff --git a/Examples/src/PlcioTest/PlcioReadAlg.h b/Examples/src/PlcioTest/PlcioReadAlg.h index 4b66b143f4247487d14133aa1153ec106ff346ac..f5aba7dc3f878d355eaa213b01e22620a057b678 100644 --- a/Examples/src/PlcioTest/PlcioReadAlg.h +++ b/Examples/src/PlcioTest/PlcioReadAlg.h @@ -11,7 +11,6 @@ namespace plcio { class PlcioReadAlg : public GaudiAlgorithm { - friend class AlgFactory<PlcioReadAlg>; public : diff --git a/Examples/src/PlcioTest/PlcioWriteAlg.h b/Examples/src/PlcioTest/PlcioWriteAlg.h index c34aa29edc45bf4760775cec7ecab37c9abf69f1..377173d09bbdd3616edfb89705ca490969a1d57f 100644 --- a/Examples/src/PlcioTest/PlcioWriteAlg.h +++ b/Examples/src/PlcioTest/PlcioWriteAlg.h @@ -11,7 +11,6 @@ namespace plcio { class PlcioWriteAlg : public GaudiAlgorithm { - friend class AlgFactory<PlcioWriteAlg>; public : diff --git a/FWCore/CMakeLists.txt b/FWCore/CMakeLists.txt deleted file mode 100644 index 3cc5478bb80f00bc90fa56717ebb8331131dab3e..0000000000000000000000000000000000000000 --- a/FWCore/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -################################################################################ -# Package: FWCore -################################################################################ -gaudi_subdir(FWCore v0r1) - -find_package(podio REQUIRED) -find_package(plcio REQUIRED) -find_package(LCIO REQUIRED) -find_package(ROOT COMPONENTS RIO Tree) - -# this declaration will not be needed in the future -gaudi_depends_on_subdirs(GaudiAlg GaudiKernel) -# gaudi_install_scripts() -gaudi_install_python_modules() - -gaudi_add_library(FWCore - src/*.cpp - INCLUDE_DIRS ${podio_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} ${plcio_INCLUDE_DIRS} ROOT - LINK_LIBRARIES GaudiAlgLib GaudiKernel ${podio_LIBRARIES} ${LCIO_LIBRARIES} ${plcio_LIBRARIES} ROOT - PUBLIC_HEADERS FWCore) - -gaudi_add_module(FWCorePlugins - src/components/*.cpp - LINK_LIBRARIES GaudiAlgLib GaudiKernel FWCore ROOT) - diff --git a/FWCore/FWCore/DataHandle.h b/FWCore/FWCore/DataHandle.h deleted file mode 100644 index 642d082380a708cbe88a2becbf74fc98418a47a9..0000000000000000000000000000000000000000 --- a/FWCore/FWCore/DataHandle.h +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef FWCORE_DATAHANDLE_H -#define FWCORE_DATAHANDLE_H - -#include "FWCore/DataWrapper.h" -#include "FWCore/PodioDataSvc.h" - -#include "GaudiKernel/AlgTool.h" -#include "GaudiKernel/Algorithm.h" -#include <GaudiKernel/DataObjectHandle.h> -#include <GaudiKernel/GaudiException.h> -#include <GaudiKernel/Property.h> -#include <GaudiKernel/ServiceLocatorHelper.h> - -#include "TTree.h" - -#include <type_traits> - -template <typename T> -class DataHandle : public DataObjectHandle<DataWrapper<T>> { - -public: - friend class Algorithm; - friend class AlgTool; - -public: - DataHandle(); - - /// Initialises mother class - DataHandle(DataObjID& descriptor, Gaudi::DataHandle::Mode a, IDataHandleHolder* fatherAlg); - - DataHandle(const std::string& k, Gaudi::DataHandle::Mode a, IDataHandleHolder* fatherAlg); - /** - * Retrieve object from transient data store - */ - const T* get(); - - /** - * Register object in transient store - */ - void put(T* object); - - /** - * Create and register object in transient store - */ - T* createAndPut(); - -private: - ServiceHandle<IDataProviderSvc> m_eds; - bool m_isGoodType{false}; - bool m_isCollection{false}; - T* m_dataPtr; -}; - -//--------------------------------------------------------------------------- -template <typename T> -DataHandle<T>::DataHandle(DataObjID& descriptor, Gaudi::DataHandle::Mode a, IDataHandleHolder* fatherAlg) - : DataObjectHandle<DataWrapper<T>>(descriptor, a, fatherAlg), m_eds("EventDataSvc", "DataHandle") { - -} -//--------------------------------------------------------------------------- -template <typename T> -DataHandle<T>::DataHandle(const std::string& descriptor, Gaudi::DataHandle::Mode a, IDataHandleHolder* fatherAlg) - : DataObjectHandle<DataWrapper<T>>(descriptor, a, fatherAlg), m_eds("EventDataSvc", "DataHandle") { - - if (a > 15) { // Gaudi::DataHandle::Mode is 'writer' - m_eds.retrieve(); - PodioDataSvc* pds; - pds = dynamic_cast<PodioDataSvc*>( m_eds.get()); - m_dataPtr = 0; - if (nullptr != pds) { - if (std::is_convertible<T*,podio::CollectionBase*>::value) { - // still handled in PodioOutput - } else { - TTree* tree = pds->eventDataTree(); - tree->Branch(descriptor.c_str(), &m_dataPtr); - } - } - } -} - -/** - * Try to retrieve from the transient store. If the retrieval succeded and - * this is the first time we retrieve, perform a dynamic cast to the desired - * object. Then finally set the handle as Read. - * If this is not the first time we cast and the cast worked, just use the - * static cast: we do not need the checks of the dynamic cast for every access! - */ -template <typename T> -const T* DataHandle<T>::get() { - DataObject* dataObjectp = nullptr; - auto sc = m_eds->retrieveObject(DataObjectHandle<DataWrapper<T>>::fullKey().key(), dataObjectp); - - if (LIKELY(sc.isSuccess())) { - if (UNLIKELY(!m_isGoodType && !m_isCollection)) { - // only do this once (if both are false after this, we throw exception) - m_isGoodType = nullptr != dynamic_cast<DataWrapper<T>*>(dataObjectp); - if (!m_isGoodType) { - auto tmp = dynamic_cast<DataWrapper<podio::CollectionBase>*>(dataObjectp); - if (tmp != nullptr) { - m_isCollection = nullptr != dynamic_cast<T*>(tmp->collectionBase()); - } - } - } - if (LIKELY(m_isGoodType)) { - DataObjectHandle<DataWrapper<T>>::setRead(); - return static_cast<DataWrapper<T>*>(dataObjectp)->getData(); - } else if (m_isCollection) { - // The reader does not know the specific type of the collection. So we need a reinterpret_cast if the handle was - // created by the reader. - DataWrapper<podio::CollectionBase>* tmp = static_cast<DataWrapper<podio::CollectionBase>*>(dataObjectp); - DataObjectHandle<DataWrapper<T>>::setRead(); - return reinterpret_cast<const T*>(tmp->collectionBase()); - } else { - std::string errorMsg("The type provided for " + DataObjectHandle<DataWrapper<T>>::toString() + - " is different from the one of the object in the store."); - throw GaudiException(errorMsg, "wrong product type", StatusCode::FAILURE); - } - } - std::string msg("Could not retrieve product " + DataObjectHandle<DataWrapper<T>>::toString()); - throw GaudiException(msg, "wrong product name", StatusCode::FAILURE); -} - -//--------------------------------------------------------------------------- -template <typename T> -void DataHandle<T>::put(T* objectp) { - DataWrapper<T>* dw = new DataWrapper<T>(); - m_dataPtr = objectp; - dw->setData(objectp); - DataObjectHandle<DataWrapper<T>>::put(dw); - -} -//--------------------------------------------------------------------------- -/** - * Create the collection, put it in the DataObjectHandle and return the - * pointer to the data. Call this function if you create a collection and - * want to save it. - */ -template <typename T> -T* DataHandle<T>::createAndPut() { - T* objectp = new T(); - this->put(objectp); - return objectp; -} - -// temporary to allow property declaration -namespace Gaudi { -template <class T> -class Property<::DataHandle<T>&> : public ::DataObjectHandleProperty { -public: - Property(const std::string& name, ::DataHandle<T>& value) : ::DataObjectHandleProperty(name, value) {} - - /// virtual Destructor - virtual ~Property() {} -}; -} - -#endif diff --git a/FWCore/FWCore/DataWrapper.h b/FWCore/FWCore/DataWrapper.h deleted file mode 100644 index a6ec7a48d1628767e94b527a875495ad720426c3..0000000000000000000000000000000000000000 --- a/FWCore/FWCore/DataWrapper.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef FWCORE_DATAWRAPPER_H -#define FWCORE_DATAWRAPPER_H - -#include <type_traits> - -// Include files -#include "GaudiKernel/DataObject.h" -#include "podio/CollectionBase.h" - -class GAUDI_API DataWrapperBase : public DataObject { -public: - // ugly hack to circumvent the usage of boost::any yet - // DataSvc would need a templated register method - virtual podio::CollectionBase* collectionBase() = 0; - virtual ~DataWrapperBase(){}; -}; - -template <class T> -class GAUDI_API DataWrapper : public DataWrapperBase { -public: - DataWrapper() : DataWrapperBase(), m_data(nullptr){}; - virtual ~DataWrapper(); - - const T* getData() { return m_data; } - void setData(T* data) { m_data = data; } - /// try to cast to collectionBase; may return nullptr; - virtual podio::CollectionBase* collectionBase(); - -private: - T* m_data; -}; - -template <class T> -DataWrapper<T>::~DataWrapper<T>() { - if (m_data != nullptr) delete m_data; -} - -template <class T> -podio::CollectionBase* DataWrapper<T>::collectionBase() { - if (std::is_base_of<podio::CollectionBase, T>::value) { - return reinterpret_cast<podio::CollectionBase*>(m_data); - } - return nullptr; -} - -#endif diff --git a/FWCore/FWCore/KeepDropSwitch.h b/FWCore/FWCore/KeepDropSwitch.h deleted file mode 100644 index d4bd4c0bc2d7525056b18d6f34914a7faa7a488e..0000000000000000000000000000000000000000 --- a/FWCore/FWCore/KeepDropSwitch.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef EXAMPLES_KEEPDROPSWITCH_H -#define EXAMPLES_KEEPDROPSWITCH_H - -#include <map> -#include <string> -#include <vector> - -std::vector<std::string> split(const std::string& s, char delim); - -int wildcmp(const char* wild, const char* string); - -class KeepDropSwitch { -public: - enum Cmd { KEEP, DROP, UNKNOWN }; - typedef std::vector<std::string> CommandLines; - KeepDropSwitch() {} - explicit KeepDropSwitch(const CommandLines& cmds) { m_commandlines = cmds; } - bool isOn(const std::string& astring) const; - -private: - bool getFlag(const std::string& astring) const; - Cmd extractCommand(const std::string cmdLine) const; - CommandLines m_commandlines; - mutable std::map<std::string, bool> m_cache; -}; - -#endif diff --git a/FWCore/FWCore/LCIODataSvc.h b/FWCore/FWCore/LCIODataSvc.h deleted file mode 100644 index 8bfa3261f7d4e6da0da9e4dc860aaa9a282f8f58..0000000000000000000000000000000000000000 --- a/FWCore/FWCore/LCIODataSvc.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef FWCORE_LCIODATASVC_H -#define FWCORE_LCIODATASVC_H - -#include "GaudiKernel/DataSvc.h" -#include "GaudiKernel/IConversionSvc.h" -// LCIO -#include "podio/CollectionBase.h" -#include "podio/CollectionIDTable.h" -#include "podio/EventStore.h" -#include "podio/ROOTReader.h" - -#include "IO/LCReader.h" -#include "EVENT/LCCollection.h" -#include "EVENT/MCParticle.h" -#include "plcio/MCParticleCollection.h" -#include "plcio/MCParticle.h" -#include "plcio/EventHeaderCollection.h" - -#include "src/components/LCIO2Plcio.h" -#include <utility> -// Forward declarations - -/** @class LCIOEvtSvc EvtDataSvc.h - * - * An EvtDataSvc for LCIO classes - * - * @author B. Hegner - */ -class LCIODataSvc : public DataSvc { -public: - - friend class SvcFactory<LCIODataSvc>; - - typedef std::vector<std::pair<std::string, podio::CollectionBase*>> CollRegistry; - - virtual StatusCode initialize(); - virtual StatusCode reinitialize(); - virtual StatusCode finalize(); - virtual StatusCode clearStore(); - - /// Standard Constructor - LCIODataSvc(const std::string& name, ISvcLocator* svc); - - /// Standard Destructor - virtual ~LCIODataSvc(); - - // Use DataSvc functionality except where we override - using DataSvc::registerObject; - /// Overriding standard behaviour of evt service - /// Register object with the data store. - virtual StatusCode registerObject(const std::string& fullPath, DataObject* pObject) final; - - StatusCode readCollection(const std::string& collectionName, int collectionID); - - virtual const CollRegistry& getCollections() const { return m_collections; } - virtual const CollRegistry& getReadCollections() const { return m_readCollections; } - virtual podio::CollectionIDTable* getCollectionIDs() { return m_collectionIDs; } - - /// Set the collection IDs (if reading a file) - void setCollectionIDs(podio::CollectionIDTable* collectionIds); - /// Resets caches of reader and event store, increases event counter - void endOfRead(); - - - TTree* eventDataTree() {return m_eventDataTree;} - -private: - - EVENT::LCEvent* evt = nullptr; - // eventDataTree - TTree* m_eventDataTree; - /// LCIO reader for ROOT files - IO::LCReader* m_reader; - /// LCIO reader for ROOT files - plcio::EventHeaderCollection* pl_evtcol; - /// the handle of DataProvider - IDataProviderSvc* m_pIDP{nullptr}; - /// podio::ROOTReader m_reader; - /// LCIO EventStore, used to initialise collections - /// podio::EventStore m_provider; - /// Counter of the event number - int m_eventNum{0}; - /// Number of events in the file / to process - int m_eventMax{-1}; - /// the current file index in the m_filenames vector - int m_fileIndex{0}; - - - SmartIF<IConversionSvc> m_cnvSvc; - - // special members for podio handling - std::vector<std::pair<std::string, podio::CollectionBase*>> m_collections; - std::vector<std::pair<std::string, podio::CollectionBase*>> m_readCollections; - podio::CollectionIDTable* m_collectionIDs; - -protected: -// bool exist_MCP = false; - LCIO2Plcio cvtor; -// EVENT::LCCollection* mcpcol_lc; -// plcio::MCParticleCollection* mcpcol_pl; - - /// ROOT file name the input is read from. Set by option filename - std::vector<std::string> m_filenames; - std::string m_filename; -}; -#endif // CORE_LCIODATASVC_H diff --git a/FWCore/FWCore/PodioDataSvc.h b/FWCore/FWCore/PodioDataSvc.h deleted file mode 100644 index 09194a30c404263f1b06f4457eafb02282a1e399..0000000000000000000000000000000000000000 --- a/FWCore/FWCore/PodioDataSvc.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef FWCORE_PODIODATASVC_H -#define FWCORE_PODIODATASVC_H - -#include "GaudiKernel/DataSvc.h" -#include "GaudiKernel/IConversionSvc.h" -// PODIO -#include "podio/CollectionBase.h" -#include "podio/CollectionIDTable.h" -#include "podio/EventStore.h" -#include "podio/ROOTReader.h" - -#include <utility> -// Forward declarations - -/** @class PodioEvtSvc EvtDataSvc.h - * - * An EvtDataSvc for PODIO classes - * - * @author B. Hegner - */ -class PodioDataSvc : public DataSvc { -public: - typedef std::vector<std::pair<std::string, podio::CollectionBase*>> CollRegistry; - - virtual StatusCode initialize(); - virtual StatusCode reinitialize(); - virtual StatusCode finalize(); - virtual StatusCode clearStore(); - - /// Standard Constructor - PodioDataSvc(const std::string& name, ISvcLocator* svc); - - /// Standard Destructor - virtual ~PodioDataSvc(); - - // Use DataSvc functionality except where we override - using DataSvc::registerObject; - /// Overriding standard behaviour of evt service - /// Register object with the data store. - virtual StatusCode registerObject(const std::string& fullPath, DataObject* pObject) final; - - StatusCode readCollection(const std::string& collectionName, int collectionID); - - virtual const CollRegistry& getCollections() const { return m_collections; } - virtual const CollRegistry& getReadCollections() const { return m_readCollections; } - virtual podio::CollectionIDTable* getCollectionIDs() { return m_collectionIDs; } - - /// Set the collection IDs (if reading a file) - void setCollectionIDs(podio::CollectionIDTable* collectionIds); - /// Resets caches of reader and event store, increases event counter - void endOfRead(); - - - TTree* eventDataTree() {return m_eventDataTree;} - - -private: - - // eventDataTree - TTree* m_eventDataTree; - /// PODIO reader for ROOT files - podio::ROOTReader m_reader; - /// PODIO EventStore, used to initialise collections - podio::EventStore m_provider; - /// Counter of the event number - int m_eventNum{0}; - /// Number of events in the file / to process - int m_eventMax{-1}; - - - SmartIF<IConversionSvc> m_cnvSvc; - - // special members for podio handling - std::vector<std::pair<std::string, podio::CollectionBase*>> m_collections; - std::vector<std::pair<std::string, podio::CollectionBase*>> m_readCollections; - podio::CollectionIDTable* m_collectionIDs; - -protected: - /// ROOT file name the input is read from. Set by option filename - std::vector<std::string> m_filenames; - std::string m_filename; -}; -#endif // CORE_PODIODATASVC_H diff --git a/FWCore/python/FWCore/__init__.py b/FWCore/python/FWCore/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/FWCore/python/FWCore/dump_joboptions.py b/FWCore/python/FWCore/dump_joboptions.py deleted file mode 100644 index eaf71c9aa02ca604f7c25c2777ed3f9e7cd00246..0000000000000000000000000000000000000000 --- a/FWCore/python/FWCore/dump_joboptions.py +++ /dev/null @@ -1,30 +0,0 @@ -from __future__ import print_function -import argparse -import ROOT - -parser = argparse.ArgumentParser(description='Job Options Dumper') -parser.add_argument( dest='fname', type=str, help="name of file to read") - - -def dump_joboptions(filename): - """ Simple and straightforward dump of the output of Gaudi's JobOptionsSvc - to stdout. - - Parameters - ---------- - - filename: str - The name of the CEPCSW output file containing joboptions to print - """ - f = ROOT.TFile(filename) - t = f.metadata - for event in t: - s = event.gaudiConfigOptions - for e in s: - print(e) - -if __name__ == "__main__": - args = parser.parse_args() - dump_joboptions(args.fname) - - diff --git a/FWCore/python/FWCore/joboptions.py b/FWCore/python/FWCore/joboptions.py deleted file mode 100644 index 47f8173d837c452551803be2690acb6d5e513ff2..0000000000000000000000000000000000000000 --- a/FWCore/python/FWCore/joboptions.py +++ /dev/null @@ -1,15 +0,0 @@ -import argparse - -def parse_standard_job_options(scriptname=""): - """ - Returns the parsed arguments, adding a parser with commonly needed opts: - - args.nevents -- number of events (int), specify with --nevents - - args.inputfile -- the input file (string), specify with --inputfile - - args.outputfile -- the output file (string), specify with --outputfile - """ - parser = argparse.ArgumentParser() - parser.add_argument('--inputfile', type=str, default='', help='specify an input file') - parser.add_argument('--outputfile', type=str, default='', help='specify an output file') - parser.add_argument('--nevents', type=int, default=None, help='specify number of events to process') - args, _ = parser.parse_known_args() - return args diff --git a/FWCore/src/KeepDropSwitch.cpp b/FWCore/src/KeepDropSwitch.cpp deleted file mode 100644 index 6617c03208e39556e2594ebe48d7bf0c29796b8b..0000000000000000000000000000000000000000 --- a/FWCore/src/KeepDropSwitch.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "FWCore/KeepDropSwitch.h" - -#include <iostream> -#include <sstream> -#include <stdexcept> - -int wildcmp(const char* wild, const char* string) { - // Written by Jack Handy - <A href="mailto:jakkhandy@hotmail.com">jakkhandy@hotmail.com</A> - const char *cp = nullptr, *mp = nullptr; - while ((*string) && (*wild != '*')) { - if ((*wild != *string) && (*wild != '?')) { - return 0; - } - wild++; - string++; - } - while (*string) { - if (*wild == '*') { - if (!*++wild) { - return 1; - } - mp = wild; - cp = string + 1; - } else if ((*wild == *string) || (*wild == '?')) { - wild++; - string++; - } else { - wild = mp; - string = cp++; - } - } - while (*wild == '*') { - wild++; - } - return !*wild; -} - -std::vector<std::string> split(const std::string& s, char delim) { - std::vector<std::string> elems; - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) { - if (item != "") elems.push_back(item); - } - return elems; -} - -bool KeepDropSwitch::isOn(const std::string& astring) const { - typedef std::map<std::string, bool>::const_iterator MIter; - MIter im = m_cache.find(astring); - if (im != m_cache.end()) - return im->second; - else { - bool val = getFlag(astring); - m_cache.insert(std::pair<std::string, bool>(astring, val)); - return val; - } -} - -bool KeepDropSwitch::getFlag(const std::string& astring) const { - bool flag = true; - for (const auto& cmdline : m_commandlines) { - std::vector<std::string> words = split(cmdline, ' '); - if (words.size() != 2) { - std::ostringstream msg; - msg << "malformed command string : " << cmdline; - throw std::invalid_argument(msg.str()); - } - std::string cmd = words[0]; - std::string pattern = words[1]; - Cmd theCmd = UNKNOWN; - if (cmd == "keep") - theCmd = KEEP; - else if (cmd == "drop") - theCmd = DROP; - else { - std::ostringstream msg; - msg << "malformed command in line: " << std::endl; - msg << cmdline << std::endl; - msg << "should be keep or drop, lower case" << std::endl; - throw std::invalid_argument(msg.str()); - } - bool match = wildcmp(pattern.c_str(), astring.c_str()); - if (not match) - continue; - else if (theCmd == KEEP) - flag = true; - else - flag = false; - } - return flag; -} - -KeepDropSwitch::Cmd KeepDropSwitch::extractCommand(const std::string cmdline) const { - std::vector<std::string> words = split(cmdline, ' '); - for (auto& word : words) - std::cout << "'" << word << "' "; - std::cout << std::endl; - return UNKNOWN; -} diff --git a/FWCore/src/PodioDataSvc.cpp b/FWCore/src/PodioDataSvc.cpp deleted file mode 100644 index ce7d3699d5b7cd7e09d59be617ab73222803ad6c..0000000000000000000000000000000000000000 --- a/FWCore/src/PodioDataSvc.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "FWCore/PodioDataSvc.h" -#include "GaudiKernel/IConversionSvc.h" -#include "GaudiKernel/IEventProcessor.h" -#include "GaudiKernel/ISvcLocator.h" - -#include "FWCore/DataWrapper.h" - -#include "TTree.h" - -/// Service initialisation -StatusCode PodioDataSvc::initialize() { - // Nothing to do: just call base class initialisation - StatusCode status = DataSvc::initialize(); - ISvcLocator* svc_loc = serviceLocator(); - - - // Attach data loader facility - m_cnvSvc = svc_loc->service("EventPersistencySvc"); - status = setDataLoader(m_cnvSvc); - - if (m_filename != "") { - m_filenames.push_back(m_filename); - } - - if (m_filenames.size() > 0) { - if (m_filenames[0] != "") { - m_reader.openFiles(m_filenames); - m_eventMax = m_reader.getEntries(); - auto idTable = m_reader.getCollectionIDTable(); - - setCollectionIDs(idTable); - m_provider.setReader(&m_reader); - } - } - return status; -} -/// Service reinitialisation -StatusCode PodioDataSvc::reinitialize() { - // Do nothing for this service - return StatusCode::SUCCESS; -} -/// Service finalization -StatusCode PodioDataSvc::finalize() { - m_cnvSvc = 0; // release - DataSvc::finalize().ignore(); - return StatusCode::SUCCESS; -} - -StatusCode PodioDataSvc::clearStore() { - for (auto& collNamePair : m_collections) { - if (collNamePair.second != nullptr) { - collNamePair.second->clear(); - } - } - for (auto& collNamePair : m_readCollections) { - if (collNamePair.second != nullptr) { - collNamePair.second->clear(); - } - } - DataSvc::clearStore().ignore(); - m_collections.clear(); - m_readCollections.clear(); - return StatusCode::SUCCESS; -} - -void PodioDataSvc::endOfRead() { - if (m_eventMax != -1) { - m_provider.clearCaches(); - m_reader.endOfEvent(); - if ( ++m_eventNum >= m_eventMax ) { - info() << "Reached end of file with event " << m_eventMax << endmsg; - IEventProcessor* eventProcessor; - service("ApplicationMgr", eventProcessor); - eventProcessor->stopRun(); - } - } -} - -void PodioDataSvc::setCollectionIDs(podio::CollectionIDTable* collectionIds) { - if (m_collectionIDs != nullptr) { - delete m_collectionIDs; - } - m_collectionIDs = collectionIds; -} - -/// Standard Constructor -PodioDataSvc::PodioDataSvc(const std::string& name, ISvcLocator* svc) - : DataSvc(name, svc), m_collectionIDs(new podio::CollectionIDTable()) { - - m_eventDataTree = new TTree("events", "Events tree"); - } - -/// Standard Destructor -PodioDataSvc::~PodioDataSvc() {} - -StatusCode PodioDataSvc::readCollection(const std::string& collName, int collectionID) { - podio::CollectionBase* collection(nullptr); - m_provider.get(collectionID, collection); - auto wrapper = new DataWrapper<podio::CollectionBase>; - int id = m_collectionIDs->add(collName); - collection->setID(id); - wrapper->setData(collection); - m_readCollections.emplace_back(std::make_pair(collName, collection)); - return DataSvc::registerObject(collName, wrapper); -} - -StatusCode PodioDataSvc::registerObject(const std::string& fullPath, DataObject* pObject) { - DataWrapperBase* wrapper = dynamic_cast<DataWrapperBase*>(pObject); - if (wrapper != nullptr) { - podio::CollectionBase* coll = wrapper->collectionBase(); - if (coll != nullptr) { - size_t pos = fullPath.find_last_of("/"); - std::string shortPath(fullPath.substr(pos + 1, fullPath.length())); - int id = m_collectionIDs->add(shortPath); - coll->setID(id); - m_collections.emplace_back(std::make_pair(shortPath, coll)); - } - } - return DataSvc::registerObject(fullPath, pObject); -} diff --git a/FWCore/src/components/CEPCDataSvc.cpp b/FWCore/src/components/CEPCDataSvc.cpp deleted file mode 100644 index fa870478432eaf570360b8bceb73406cf2e66692..0000000000000000000000000000000000000000 --- a/FWCore/src/components/CEPCDataSvc.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "CEPCDataSvc.h" - -#include "GaudiKernel/IConversionSvc.h" -#include "GaudiKernel/ISvcLocator.h" -#include "GaudiKernel/SvcFactory.h" - -// Instantiation of a static factory class used by clients to create -// instances of this service -DECLARE_SERVICE_FACTORY(CEPCDataSvc) - -/// Standard Constructor -CEPCDataSvc::CEPCDataSvc(const std::string& name, ISvcLocator* svc) - : PodioDataSvc(name, svc) -{ - declareProperty("inputs", m_filenames = {}, "Names of the files to read"); - declareProperty("input", m_filename = "", "Name of the file to read"); -} - -/// Standard Destructor -CEPCDataSvc::~CEPCDataSvc() {} diff --git a/FWCore/src/components/CEPCDataSvc.h b/FWCore/src/components/CEPCDataSvc.h deleted file mode 100644 index 4953799c435618413978cb309abbda04ae78e83d..0000000000000000000000000000000000000000 --- a/FWCore/src/components/CEPCDataSvc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FWCORE_CEPCDATASVC_H -#define FWCORE_CEPCDATASVC_H - -#include "FWCore/PodioDataSvc.h" - -class CEPCDataSvc : public PodioDataSvc -{ - friend class SvcFactory<CEPCDataSvc>; - -public: - /// Standard Constructor - CEPCDataSvc(const std::string& name, ISvcLocator* svc); - - /// Standard Destructor - virtual ~CEPCDataSvc(); -}; - -#endif // FWCORE_CEPCDATASVC_H diff --git a/FWCore/src/components/LCIO2Plcio.cpp b/FWCore/src/components/LCIO2Plcio.cpp deleted file mode 100644 index 72cd688a9469a06c26113ec76aaf5be6df189d39..0000000000000000000000000000000000000000 --- a/FWCore/src/components/LCIO2Plcio.cpp +++ /dev/null @@ -1,610 +0,0 @@ -#include "LCIO2Plcio.h" - -#include "lcio.h" -#include "EVENT/LCCollection.h" -#include "plcio/MCParticle.h" -#include "plcio/MCParticleConst.h" -#include "plcio/MCParticleCollection.h" -#include "plcio/LCRunHeader.h" -#include "plcio/LCRunHeaderCollection.h" -#include "EVENT/MCParticle.h" - -typedef std::vector<EVENT::MCParticle*> MCParticleVec ; - -CollectionsMap LCIO2Plcio::map_cols; -std::string LCIO2Plcio::CollName; - -void lp_info(std::string s){ - printf("[LCIO2Plcio]:\t\t%s.\n", &s[0]); -} - -template<typename T> -static plcio::FloatThree FloatThreeFROMConstPtr(const T* vpos){ - float tmp[3]; - for(unsigned i=0; i<3; i++){ - tmp[i] = vpos[i]; - } - return plcio::FloatThree(tmp); -} - -template<typename T> -static plcio::FloatThree FloatThreeFROMFloatVec(std::vector<T> vec){ - float tmp[3]; - for(unsigned i=0; i<3; i++){ - tmp[i] = vec[i]; - } - return plcio::FloatThree(tmp); -} - -template<typename T> -static plcio::DoubleThree DoubleThreeFROMConstPtr(const T* vpos){ - double tmp[3]; - for(unsigned i=0; i<3; i++) - tmp[i] = vpos[i]; - return plcio::DoubleThree(tmp); -} - -std::array<float, 6> vec6_2_arr6(std::vector<float> vec){ - std::array<float, 6> arr; - for(unsigned i=0; i<6; i++){ - arr[i] = vec[i]; - } - return arr; -} - -LCIO2Plcio::LCIO2Plcio(){ - map_cvt.insert(std::make_pair<std::string, fptr>("MCParticle", Convertor_MCParticle)); - map_cvt.insert(std::make_pair<std::string, fptr>("LCRunHeader", Convertor_LCRunHeader)); - map_cvt.insert(std::make_pair<std::string, fptr>("SimTrackerHit", Convertor_SimTrackerHit)); - map_cvt.insert(std::make_pair<std::string, fptr>("SimCalorimeterHit", Convertor_SimCalorimeterHit)); - map_cvt.insert(std::make_pair<std::string, fptr>("Cluster", Convertor_Cluster)); - map_cvt.insert(std::make_pair<std::string, fptr>("Track", Convertor_Track)); - map_cvt.insert(std::make_pair<std::string, fptr>("TrackerHit", Convertor_TrackerHit)); - map_cvt.insert(std::make_pair<std::string, fptr>("TPCHit", Convertor_TPCHit)); - map_cvt.insert(std::make_pair<std::string, fptr>("ReconstructedParticle", Convertor_ReconstructedParticle)); - map_cvt.insert(std::make_pair<std::string, fptr>("ParticleID", Convertor_ParticleID)); -} -LCIO2Plcio::LCIO2Plcio(EVENT::LCCollection* collection){ - LCIO2Plcio(); -} - -podio::CollectionBase* LCIO2Plcio::Convertor_LCRunHeader(EVENT::LCCollection* lc_col){ - plcio::LCRunHeaderCollection* pl_col = new plcio::LCRunHeaderCollection(); - - // Convert basic info from LCIO to plcio; - for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){ - EVENT::LCRunHeader* lc_var = (EVENT::LCRunHeader*) lc_col->getElementAt(i) ; - plcio::LCRunHeader pl_var = (plcio::LCRunHeader) pl_col->create(); - pl_var.setRunNumber( lc_var->getRunNumber() ); - pl_var.setDetectorName( lc_var->getDetectorName() ); - pl_var.setDescription( lc_var->getDescription() ); - - std::vector<std::string> vec_dct = *(lc_var->getActiveSubdetectors()); - for( unsigned j=0,N=vec_dct.size(); j<N; j++){ - pl_var.addActiveSubdetector( vec_dct[j] ); - } - } - return pl_col; -} - -void LCIO2Plcio::setMCParticle(EVENT::MCParticle* lc_var, plcio::MCParticle& pl_var){ - - pl_var.setPDG( lc_var->getPDG() ); - pl_var.setGeneratorStatus( lc_var->getGeneratorStatus() ); - pl_var.setSimulatorStatus( lc_var->getSimulatorStatus() ); - pl_var.setCharge( lc_var->getCharge() ); - pl_var.setTime( lc_var->getTime() ); - pl_var.setMass( lc_var->getMass() ); - pl_var.setStopped( lc_var->isStopped() ); - pl_var.setOverlay( lc_var->isOverlay() ); - pl_var.setBackscatter( lc_var->isBackscatter() ); - pl_var.setDecayedInTracker( lc_var->isDecayedInTracker() ); - pl_var.setDecayedInCalorimeter( lc_var->isDecayedInCalorimeter() ); - pl_var.setCreatedInSimulation( lc_var->isCreatedInSimulation() ); - pl_var.setVertexIsNotEndpointOfParent( lc_var->vertexIsNotEndpointOfParent() ); - pl_var.setHasLeftDetector( lc_var->hasLeftDetector() ); - - pl_var.setSpin( plcio::FloatThree( lc_var->getSpin() ) ); - pl_var.setColorFlow( plcio::IntTwo( lc_var->getColorFlow() ) ); - pl_var.setVertex( plcio::DoubleThree( lc_var->getVertex())); - pl_var.setEndpoint( plcio::DoubleThree( lc_var->getEndpoint() ) ); - pl_var.setMomentum( FloatThreeFROMConstPtr(lc_var->getMomentum()) ); - pl_var.setMomentumAtEndpoint( FloatThreeFROMConstPtr(lc_var->getMomentumAtEndpoint()) ); -} - -podio::CollectionBase* LCIO2Plcio::Convertor_MCParticle(EVENT::LCCollection* lc_col){ - plcio::MCParticleCollection* pl_col = new plcio::MCParticleCollection(); - - // Convert basic info from LCIO to plcio; - for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){ - EVENT::MCParticle* lc_var = (EVENT::MCParticle*) lc_col->getElementAt(i) ; - plcio::MCParticle pl_var = (plcio::MCParticle) pl_col->create(); - - setMCParticle(lc_var, pl_var); - // dealing each of 'Parents' of lcio::MCParticle ; - const MCParticleVec& veclc = lc_var->getParents(); - for(unsigned j=0; j<veclc.size(); j++){ - EVENT::MCParticle* vlcreg = veclc[j]; - for(unsigned k=0; k<i; ++k){ - if(((EVENT::MCParticle*) lc_col->getElementAt(k)) == vlcreg){ - // A loop for plcio's MCParticleCollection to recover plcio's relationship; - plcio::MCParticle mcprt = pl_col->at(k); - pl_var.addParent(mcprt); - mcprt.addDaughter(pl_var); - } - } - } - } - return pl_col; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_SimTrackerHit(EVENT::LCCollection* lc_col){ - plcio::SimTrackerHitCollection* pl_col = new plcio::SimTrackerHitCollection(); - - for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){ - EVENT::SimTrackerHit* lc_var = (EVENT::SimTrackerHit*) lc_col->getElementAt(i) ; - plcio::SimTrackerHit pl_var = (plcio::SimTrackerHit) pl_col->create(); - - pl_var.setCellID0( lc_var->getCellID0() ); - pl_var.setCellID1( lc_var->getCellID1() ); - pl_var.setEDep( lc_var->getEDep() ); - pl_var.setTime( lc_var->getTime() ); - pl_var.setPathLength( lc_var->getPathLength() ); - pl_var.setQuality( lc_var->getQuality() ); - pl_var.setPosition( lc_var->getPosition() ); - pl_var.setMomentum( lc_var->getMomentum() ); - pl_var.setOverlay( lc_var->isOverlay() ); - pl_var.setProducedBySecondary( lc_var->isProducedBySecondary() ); - - // Looping the LCIO::MCParticleCollection to pick Particle for Hits; - CollectionsVec vec_mcp; - vec_mcp = map_cols["MCParticle"]; - EVENT::LCCollection* hitcol_lc = (EVENT::LCCollection*) vec_mcp[0].first; - plcio::MCParticleCollection* hitcol_pl = (plcio::MCParticleCollection*) vec_mcp[0].second; - - int index = -1; - // search corresponding MCParticleCollection*; - EVENT::MCParticle* mcptr_reg = lc_var->getMCParticle(); - for( unsigned j=0, M=hitcol_lc->getNumberOfElements(); j<M; ++j){ - EVENT::MCParticle* mcpin_lc = (EVENT::MCParticle*) hitcol_lc->getElementAt(j); - if( mcpin_lc == mcptr_reg ){ - index = j; - } - } -// if( index != -1) lp_info("Cedar: Convertor SimTrackerHit Success."); - bool is_empty = false; - if( index == -1){ - if(mcptr_reg == nullptr) is_empty = true; -// lp_info("Convertor SimTrackerHit Problem."); -// printf("LCCollection size: %d\n", hitcol_lc->getNumberOfElements()); -// printf("MCParticleCollection size: %d\n", hitcol_pl->size()); -// printf("Index: %d\n", index); - } - if( is_empty == false ) - pl_var.setMCParticle( hitcol_pl->at(index) ); - - } - return pl_col; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_SimCalorimeterHit(EVENT::LCCollection* lc_col){ - plcio::SimCalorimeterHitCollection* pl_col = new plcio::SimCalorimeterHitCollection(); - - for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){ - EVENT::SimCalorimeterHit* lc_var = (EVENT::SimCalorimeterHit*) lc_col->getElementAt(i); - plcio::SimCalorimeterHit pl_var = (plcio::SimCalorimeterHit) pl_col->create(); - - pl_var.setCellID0( lc_var->getCellID0() ); - pl_var.setCellID1( lc_var->getCellID1() ); - pl_var.setEnergy( lc_var->getEnergy() ); - pl_var.setPosition( FloatThreeFROMConstPtr(lc_var->getPosition()) ); - - // converting from lc_var to pl_var on the contribution variables; - for( unsigned j=0, N=lc_var->getNMCContributions(); j<N; j++){ - plcio::ConstCaloHitContribution tmp( - lc_var->getPDGCont(j), lc_var->getEnergyCont(j), - lc_var->getTimeCont(j), FloatThreeFROMConstPtr(lc_var->getStepPosition(j)) - ); - pl_var.addContribution( tmp ); - } - } - return pl_col; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_Cluster(EVENT::LCCollection* lc_col){ - plcio::ClusterCollection* pl_col = new plcio::ClusterCollection(); - - for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){ - EVENT::Cluster* lc_var = (EVENT::Cluster*) lc_col->getElementAt(i); - plcio::Cluster pl_var = (plcio::Cluster) pl_col->create(); - - pl_var.setType(lc_var->getType()); - pl_var.setEnergy(lc_var->getEnergy()); - pl_var.setEnergyError(lc_var->getEnergyError()); - pl_var.setPhi(lc_var->getIPhi()); - pl_var.setITheta(lc_var->getITheta()); - pl_var.setPosition( FloatThreeFROMConstPtr(lc_var->getPosition()) ); - pl_var.setPositionError( vec6_2_arr6(lc_var->getPositionError()) ); - pl_var.setDirectionError( FloatThreeFROMFloatVec(lc_var->getDirectionError()) ); - - std::vector<float> lcio_seq0 = lc_var->getShape(); - for(unsigned j=0; j<lcio_seq0.size(); j++){ - pl_var.addShap( lcio_seq0[j] ); - } - - lcio_seq0 = lc_var->getHitContributions(); - for(unsigned j=0; j<lcio_seq0.size(); j++){ - pl_var.addHitContribution( lcio_seq0[j] ); - } - - lcio_seq0 = lc_var->getSubdetectorEnergies(); - for(unsigned j=0; j<lcio_seq0.size(); j++){ - pl_var.addSubdetectorEnergie( lcio_seq0[j] ); - } - - EVENT::ParticleIDVec lcio_seq1 = lc_var->getParticleIDs(); - for(unsigned j=0; j<lcio_seq1.size(); j++){ - EVENT::ParticleID* lc_locx = lcio_seq1[j]; - - pl_var.addParticleID( plcio::ConstParticleID( - lc_locx->getType(), - lc_locx->getPDG(), - lc_locx->getAlgorithmType(), - lc_locx->getLikelihood() - ) ); - } - - EVENT::CalorimeterHitVec lcio_seq2 = lc_var->getCalorimeterHits(); - for(unsigned j=0; j<lcio_seq2.size(); j++){ - EVENT::CalorimeterHit* lc_locx = lcio_seq2[j]; - - podio::CollectionIDTable col2id; - plcio::ObjectID tmp; - tmp.index = i; - tmp.collectionID = col2id.collectionID(CollName); - - pl_var.addHit( plcio::ConstCalorimeterHit( - lc_locx->getCellID0(), - lc_locx->getCellID1(), - lc_locx->getEnergy(), - lc_locx->getEnergyError(), - lc_locx->getTime(), - FloatThreeFROMConstPtr(lc_locx->getPosition()), - lc_locx->getType(), - tmp - ) ); - } - } - - for(unsigned i=0,N=lc_col->getNumberOfElements(); i<N; i++){ - EVENT::Cluster* lc_var = (EVENT::Cluster*) lc_col->getElementAt(i); - plcio::Cluster pl_var = pl_col->at(i); - EVENT::ClusterVec lcio_seq3 = lc_var->getClusters(); - - for(unsigned j=0; j<lcio_seq3.size(); j++){ - for(unsigned k=0,K=lc_col->getNumberOfElements(); k<K; k++){ - if(lcio_seq3[j] == lc_col->getElementAt(k)){ - pl_var.addCluster(pl_col->at(k)); - break; - } - } - } - } - - return pl_col; -} - -// QUEST::isAvailable dows not analyze; -podio::CollectionBase* LCIO2Plcio::Convertor_ParticleID(EVENT::LCCollection* lc_col){ - plcio::ParticleIDCollection* pl_col = new plcio::ParticleIDCollection(); - - for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){ - EVENT::ParticleID* lc_var = (EVENT::ParticleID*) lc_col->getElementAt(i); - plcio::ParticleID pl_var = (plcio::ParticleID) pl_col->create(); - - pl_var.setType( lc_var->getType() ); - pl_var.setPDG( lc_var->getPDG() ); - pl_var.setAlgorythmType( lc_var->getAlgorithmType() ); - pl_var.setLikelihood( lc_var->getLikelihood() ); - EVENT::FloatVec vec_float = lc_var->getParameters(); - for(unsigned j=0; j<vec_float.size(); j++){ - pl_var.addParameter(vec_float[j]); - } - } - return pl_col; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_ReconstructedParticle(EVENT::LCCollection* lc_col){ - plcio::ReconstructedParticleCollection* pl_col = new plcio::ReconstructedParticleCollection(); - - for(unsigned i=0,N=lc_col->getNumberOfElements(); i<N; i++){ - EVENT::ReconstructedParticle* lc_var = (EVENT::ReconstructedParticle*) lc_col->getElementAt(i); - plcio::ReconstructedParticle pl_var = (plcio::ReconstructedParticle) pl_col->create(); - - pl_var.setType( lc_var->getType() ); - pl_var.setEnergy( lc_var->getEnergy() ); - pl_var.setCharge( lc_var->getCharge() ); - pl_var.setMass( lc_var->getMass() ); - pl_var.setGoodnessOfPID( lc_var->getGoodnessOfPID() ); - - pl_var.setMomentum( FloatThreeFROMConstPtr(lc_var->getMomentum()) ); - pl_var.setReferencePoint( FloatThreeFROMConstPtr(lc_var->getReferencePoint()) ); - - std::vector<float> vec = lc_var->getCovMatrix(); - for(unsigned j=0,N=vec.size(); j<N; j++){ - pl_var.setCovMatrix( j, vec[j] ); - } - - // QUEST: boolean to int: isPrimary, str2int: getAlgorithmType; - // pl_var.setStartVertex( lc_var->getStartVertex() ) - // ignorant; - std::array<float, 6> arr_6; - EVENT::FloatVec fvec = lc_var->getStartVertex()->getCovMatrix(); - for(unsigned j=0; j<6; j++){ - arr_6[j] = fvec[j]; - } - pl_var.setStartVertex( plcio::ConstVertex( - lc_var->getStartVertex()->isPrimary(), - lc_var->getStartVertex()->getChi2(), - lc_var->getStartVertex()->getProbability(), - FloatThreeFROMConstPtr( lc_var->getStartVertex()->getPosition() ), - arr_6, - 0 - //lc_var->getStartVertex()->getAlgorithmType() - ) ); - - //pl_var.setParticleIDUsed( lc_var->getParticleIDUsed() ); - EVENT::ParticleID* lc_locx = lc_var->getParticleIDUsed(); - CollectionsVec vec_cols = map_cols["ParticleID"]; - EVENT::LCCollection* lc_mapcol = (EVENT::LCCollection*)vec_cols[0].first; - plcio::ParticleIDCollection* pl_mapcol = (plcio::ParticleIDCollection*)vec_cols[0].second; - - for(unsigned k=0, LCsize=lc_mapcol->getNumberOfElements(); k<LCsize; k++){ - if(lc_locx == lc_mapcol->getElementAt(k)) - pl_var.setParticleIDUsed(pl_mapcol->at(k)); - } - - - //pl_var.addCluster(); - std::vector<EVENT::Cluster*> vec_clust = lc_var->getClusters(); - for(unsigned j=0; j<vec_clust.size(); j++){ - CollectionsVec vec_cols = map_cols["Cluster"]; - EVENT::LCCollection* lc_mapcol = (EVENT::LCCollection*)vec_cols[0].first; - plcio::ClusterCollection* pl_mapcol = (plcio::ClusterCollection*)vec_cols[0].second; - - for(unsigned k=0; k<lc_mapcol->getNumberOfElements(); k++){ - if( vec_clust[j] == lc_mapcol->getElementAt(k) ) - pl_var.addCluster( pl_mapcol->at(k) ); - } - } - - //pl_var.addTrack(); - EVENT::TrackVec vec_track = lc_var->getTracks(); - for(unsigned j=0; j<vec_track.size(); j++){ - CollectionsVec vec_cols = map_cols["Track"]; - EVENT::LCCollection* lc_mapcol = (EVENT::LCCollection*)vec_cols[0].first; - plcio::TrackCollection* pl_mapcol = (plcio::TrackCollection*)vec_cols[0].second; - - for(unsigned k=0; k<lc_mapcol->getNumberOfElements(); k++) - if(vec_track[j] == lc_mapcol->getElementAt(k)) - pl_var.addTrack(pl_mapcol->at(k)); - } - - //pl_var.addParticleID( lc->getParticleIDs); - EVENT::ParticleIDVec vec_ParticleID = lc_var->getParticleIDs(); - for(unsigned j=0; j<vec_ParticleID.size(); j++){ - CollectionsVec vec_cols = map_cols["ParticleID"]; - EVENT::LCCollection* lc_mapcol = (EVENT::LCCollection*)vec_cols[0].first; - plcio::ParticleIDCollection* pl_mapcol = (plcio::ParticleIDCollection*)vec_cols[0].second; - - for(unsigned k=0,M=lc_mapcol->getNumberOfElements(); k<M; k++){ - if(vec_ParticleID[j] == lc_mapcol->getElementAt(k)) - pl_var.addParticleID( pl_mapcol->at(k) ); - } - } - } - //pl_var.addParticle(); - for(unsigned i=0, N=lc_col->getNumberOfElements(); i<N; i++){ - EVENT::ReconstructedParticle* lc_var = (EVENT::ReconstructedParticle*)lc_col->getElementAt(i); - EVENT::ReconstructedParticleVec vec_RecPtc = lc_var->getParticles(); - - for(unsigned j=0; j<vec_RecPtc.size(); j++){ - for(unsigned k=0, M=lc_col->getNumberOfElements(); k<M; k++){ - if(vec_RecPtc[j] == lc_col->getElementAt(k)) - pl_col->at(i).addParticle( pl_col->at(k) ); - } - } - } - - return pl_col; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_TrackerHit(EVENT::LCCollection* lc_col){ - plcio::TrackerHitCollection* pl_col = new plcio::TrackerHitCollection(); - - for(unsigned i=0,N=lc_col->getNumberOfElements(); i<N; i++){ - EVENT::TrackerHit* lc_var = (EVENT::TrackerHit*) lc_col->getElementAt(i); - plcio::TrackerHit pl_var = (plcio::TrackerHit) pl_col->create(); - - pl_var.setCellID0(lc_var->getCellID0()); - pl_var.setCellID1(lc_var->getCellID1()); - - pl_var.setType(lc_var->getType()); - pl_var.setQuality(lc_var->getQuality()); - pl_var.setTime(lc_var->getTime()); - pl_var.setEDep(lc_var->getEDep()); - pl_var.setEDepError(lc_var->getEDepError()); - pl_var.setEdx(lc_var->getdEdx()); - pl_var.setPosition( DoubleThreeFROMConstPtr(lc_var->getPosition())); - pl_var.setCovMatrix( vec6_2_arr6(lc_var->getCovMatrix())); - } - return pl_col; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_Track(EVENT::LCCollection* lc_col){ - plcio::TrackCollection* pl_col = new plcio::TrackCollection(); - - for(unsigned i=0,N=lc_col->getNumberOfElements(); i<N; i++){ - EVENT::Track* lc_var = (EVENT::Track*) lc_col->getElementAt(i); - plcio::Track pl_var = (plcio::Track) pl_col->create(); - - pl_var.setType( lc_var->getType() ); - pl_var.setChi2( lc_var->getChi2() ); - pl_var.setNdf( lc_var->getNdf() ); - pl_var.setDEdx( lc_var->getdEdx() ); - pl_var.setDEdxError( lc_var->getdEdxError() ); - pl_var.setRadiusOfInnermostHit( lc_var->getRadiusOfInnermostHit() ); - - //pl_var.addTrackerHit( lc_var->getTrackerHits() ); - //rely on TrackerHits collection; - //corresoponding with TrackerHit collection; - EVENT::TrackerHitVec lcio_seq1 = lc_var->getTrackerHits(); - for(unsigned j=0; j<lcio_seq1.size(); j++){ - EVENT::TrackerHit* lc_locx = lcio_seq1[j]; - CollectionsVec vec_cols = map_cols["TrackerHit"]; - EVENT::LCCollection* lc_mapcol = (EVENT::LCCollection*)vec_cols[0].first; - plcio::TrackerHitCollection* pl_mapcol = (plcio::TrackerHitCollection*) vec_cols[0].second; - - for(unsigned k=0; k<lc_mapcol->getNumberOfElements(); k++){ - if( lc_locx == lc_mapcol->getElementAt(k) ) - pl_var.addTrackerHit( pl_mapcol->at(k) ); - } - } - - //pl_var.( lc_var->getSubdetectorHitNumbers() ); - std::vector<int> lcio_IntVec1 = lc_var->getSubdetectorHitNumbers(); - for(unsigned j=0; j<lcio_IntVec1.size(); j++){ - pl_var.addSubDetectorHitNumber(lcio_IntVec1[j]); - } - - //pl_var.( lc_var->getTrackStates() ); - EVENT::TrackStateVec lcio_seq3 = lc_var->getTrackStates(); - for(unsigned j=0; j<lcio_seq3.size(); j++){ - EVENT::TrackState* lc_locx = lcio_seq3[j]; - std::array<float, 15> tmp_covM; - for(unsigned k=0; k<15; k++){ - tmp_covM[k] = lc_locx->getCovMatrix()[k]; - } - - plcio::TrackState tmp; - tmp.D0 = lc_locx->getD0(); - tmp.Z0 = lc_locx->getZ0(); - tmp.covMatrix = tmp_covM; - tmp.location = lc_locx->getLocation(); - tmp.omega = lc_locx->getOmega(); - tmp.phi = lc_locx->getPhi(); - tmp.referencePoint = FloatThreeFROMConstPtr( lc_locx->getReferencePoint() ); - tmp.tanLambda = lc_locx->getTanLambda(); - pl_var.addTrackState( tmp ); - } - } - - //pl_var.( lc_var->getTracks() ); - for(unsigned i=0; i<lc_col->getNumberOfElements(); i++){ - EVENT::Track* lc_var = (EVENT::Track*)lc_col->getElementAt(i); - EVENT::TrackVec lcio_seq2 = lc_var->getTracks(); - - for(unsigned j=0; j<lcio_seq2.size(); j++){ - EVENT::Track* lc_locx = lcio_seq2[j]; - for(unsigned k=0; k<lc_col->getNumberOfElements(); k++){ - if( lc_locx == lc_col->getElementAt(k) ) - pl_col->at(i).addTrack(pl_col->at(k)); - } - } - } - return pl_col; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_Vertex(EVENT::LCCollection* lc_col){ - plcio::VertexCollection* pl_col = new plcio::VertexCollection(); - - for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){ - EVENT::Vertex* lc_var = (EVENT::Vertex*) lc_col->getElementAt(i); - plcio::Vertex pl_var = (plcio::Vertex) pl_col->create(); - - // Quest: data.primary is an int value, set by boolean number; - pl_var.setPrimary( lc_var->isPrimary() ); - pl_var.setChi2( lc_var->getChi2() ); - pl_var.setProbability( lc_var->getProbability() ); - - float plcio_v[3]; - const float* lcio_v = lc_var->getPosition(); - plcio_v[0] = lcio_v[0]; - plcio_v[1] = lcio_v[1]; - plcio_v[2] = lcio_v[2]; - pl_var.setPosition( plcio::FloatThree(plcio_v) ); - - std::vector<float> vec_pra = lc_var->getParameters(); - for( unsigned j=0,M=vec_pra.size(); j<M; j++){ - pl_var.addParameter(vec_pra[j]); - } - - // convert string into int(type code); -// pl_var.setAlgorithmType( lc_var->getAlgorithmType() ); -// pl_var.setCovMatrix( lc_var->() ); -// pl_var.setAssociatedParticle( lc_var->() ); - } - return pl_col; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_TPCHit(EVENT::LCCollection* lc_col){ - plcio::TPCHitCollection* pl_col = new plcio::TPCHitCollection(); - - for( unsigned i=0,N=lc_col->getNumberOfElements() ; i< N ; ++i){ - EVENT::TPCHit* lc_var = (EVENT::TPCHit*) lc_col->getElementAt(i); - plcio::TPCHit pl_var = (plcio::TPCHit) pl_col->create(); - - pl_var.setCellID(lc_var->getCellID()); - pl_var.setTime(lc_var->getTime()); - pl_var.setCharge(lc_var->getCharge()); - pl_var.setQuality(lc_var->getQuality()); - - for( unsigned j=0,M=lc_var->getNRawDataWords(); j<M; j++){ - pl_var.addRawDataWord(lc_var->getRawDataWord(j)); - } - } - return pl_col; -} - -bool LCIO2Plcio::isReady(const std::string& TypeName){ - if( TypeName == "SimTrackerHit" ){ - std::vector<std::string>::iterator it = find( - vec_Types.begin(), vec_Types.end(), "MCParticle" - ); - if( it != vec_Types.end() ) - return true; - } - return false; -} - -podio::CollectionBase* LCIO2Plcio::Convertor_getPlcio(EVENT::LCCollection* lc_col){ - - podio::CollectionBase* collection(nullptr); - TypeName = lc_col->getTypeName(); - -// lp_info("Converting "+TypeName); - bool ready = true; - if( !ready ){ - lp_info("Not ready yet."); - lp_info("Please put MCParticle firstly in the python file, Please"); - return nullptr; - } - - fptr fp; - if( map_cvt.find(TypeName) == map_cvt.end()){ - lp_info("unrecognized "+TypeName); - }else{ - fp = *map_cvt[TypeName]; - } - - fp = *map_cvt[TypeName]; - collection = fp(lc_col); - -// maintain map<TypeName, CollVec>; - map_cols[TypeName].push_back( - std::pair<EVENT::LCCollection*, podio::CollectionBase*>(lc_col, collection) - ); - -// lp_info("done."); - return collection; -} diff --git a/FWCore/src/components/LCIO2Plcio.h b/FWCore/src/components/LCIO2Plcio.h deleted file mode 100644 index 3729105ce2c7dbf763c15d4524b4bde333b6d7a2..0000000000000000000000000000000000000000 --- a/FWCore/src/components/LCIO2Plcio.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef FWCORE_CONVERTOR_H -#define FWCORE_CONVERTOR_H - -// LCIO - -#include <map> -#include <iostream> -#include <string> -#include "lcio.h" -// #include "IO/LCReader.h" -// #include "EVENT/LCCollection.h" -#include "EVENT/Vertex.h" -#include "EVENT/SimTrackerHit.h" -#include "plcio/SimTrackerHit.h" -#include "plcio/SimTrackerHitCollection.h" -#include "EVENT/SimCalorimeterHit.h" -#include "plcio/SimCalorimeterHit.h" -#include "plcio/SimCalorimeterHitCollection.h" -#include "EVENT/MCParticle.h" -#include "plcio/MCParticle.h" -#include "plcio/MCParticleCollection.h" -#include "plcio/VertexCollection.h" -#include "EVENT/TPCHit.h" -#include "plcio/TPCHit.h" -#include "plcio/TPCHitCollection.h" -#include "EVENT/Cluster.h" -#include "plcio/Cluster.h" -#include "plcio/ClusterCollection.h" -#include "EVENT/ParticleID.h" -#include "EVENT/CalorimeterHit.h" -#include "plcio/CalorimeterHit.h" -#include "podio/CollectionIDTable.h" -#include "EVENT/Track.h" -#include "EVENT/TrackerHit.h" -#include "EVENT/TrackState.h" -#include "plcio/Track.h" -#include "plcio/TrackerHit.h" -#include "plcio/TrackCollection.h" -#include "plcio/TrackerHitCollection.h" -#include "EVENT/ReconstructedParticle.h" -#include "plcio/ReconstructedParticle.h" -#include "plcio/ReconstructedParticleCollection.h" -#include "plcio/ParticleID.h" -#include "plcio/ParticleIDCollection.h" - -#include <utility> -// Forward declarations - -/** @class LCIO2Plcio LCIO2Plcio.h - * - * An LCIO2Plcio for Converting from LCCollection to plcio collection; - * - * @author jhZou, gjCao - */ - -// typedef plcio::MCParticleCollection* (*fptr) (EVENT::LCCollection*); -typedef podio::CollectionBase* (*fptr) (EVENT::LCCollection*); -typedef std::vector<std::pair<EVENT::LCCollection*, podio::CollectionBase*>> CollectionsVec; -typedef std::map<std::string, CollectionsVec> CollectionsMap; - -class LCIO2Plcio{ -public: - - /// Standard Constructor - LCIO2Plcio(); - LCIO2Plcio(EVENT::LCCollection*); - - /// Standard Destructor - virtual ~LCIO2Plcio(){} - - void test(){ printf("MYTESTFUC\n"); } - void clear(){ map_cols.clear(); }; - -// plcio::MCParticleCollection* Convertor_getPlcio(EVENT::LCCollection*); - podio::CollectionBase* Convertor_getPlcio(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_MCParticle(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_LCRunHeader(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_SimTrackerHit(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_SimCalorimeterHit(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_Cluster(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_Track(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_TrackerHit(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_TPCHit(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_ReconstructedParticle(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_ParticleID(EVENT::LCCollection*); - - static podio::CollectionBase* Convertor_LCRelation(EVENT::LCCollection*); - static podio::CollectionBase* Convertor_Vertex(EVENT::LCCollection*); - - static void setMCParticle(EVENT::MCParticle*, plcio::MCParticle&); - void setCollName(const std::string &collName){ CollName = collName; }; - - bool isReady(const std::string&); - -private: - std::string TypeName; - static std::string CollName; - // maintain a log vec about data read; - std::vector<std::string> vec_Types; - - // maintain a map from keyword to function pointer. - std::map<std::string, fptr> map_cvt; - static CollectionsMap map_cols; - -// plcio::MCParticleCollection* hitcol_pl; -// EVENT::LCCollection* hitcol_lc; -}; -#endif // CORE_CONVERTOR_H diff --git a/FWCore/src/components/LCIODataSvc.cpp b/FWCore/src/components/LCIODataSvc.cpp deleted file mode 100644 index 3656f3ffc0770552333da606856a02209242921f..0000000000000000000000000000000000000000 --- a/FWCore/src/components/LCIODataSvc.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include "FWCore/LCIODataSvc.h" -#include "LCIO2Plcio.h" -#include "GaudiKernel/IConversionSvc.h" -#include "GaudiKernel/IEventProcessor.h" -#include "GaudiKernel/ISvcLocator.h" - -#include "IOIMPL/LCFactory.h" -#include "FWCore/DataWrapper.h" -#include "lcio.h" -#include "plcio/MCParticleCollection.h" -#include "plcio/MCParticle.h" -#include "plcio/EventHeaderCollection.h" -#include "EVENT/MCParticle.h" - -#include "TTree.h" - -typedef std::vector<lcio::MCParticle*> MCParticleVec ; - -DECLARE_SERVICE_FACTORY(LCIODataSvc) -/// Service initialisation -StatusCode LCIODataSvc::initialize() { - // Nothing to do: just call base class initialisation - StatusCode status = DataSvc::initialize(); - ISvcLocator* svc_loc = serviceLocator(); - - // Attach data loader facility - m_cnvSvc = svc_loc->service("EventPersistencySvc"); - status = setDataLoader(m_cnvSvc); - - if ( name() != "EventDataSvc" ) { - service("EventDataSvc", m_pIDP, true); - if ( m_pIDP == nullptr ) { - error() << "Could not get the EventDataSvc instance" << endmsg; - return StatusCode::FAILURE; - } - } - - m_reader = IOIMPL::LCFactory::getInstance()->createLCReader(); - - if (m_filename != "") { - m_filenames.push_back(m_filename); - } - - if (m_filenames.size() > 0) { - m_reader->open(m_filenames[0]); - m_eventMax = m_reader->getNumberOfEvents(); - } - - return status; -} -/// Service reinitialisation -StatusCode LCIODataSvc::reinitialize() { - // Do nothing for this service - return StatusCode::SUCCESS; -} -/// Service finalization -StatusCode LCIODataSvc::finalize() { - m_reader->close(); - delete m_reader; - m_reader = nullptr; - m_cnvSvc = 0; // release - DataSvc::finalize().ignore(); - return StatusCode::SUCCESS; -} - -StatusCode LCIODataSvc::clearStore() { - for (auto& collNamePair : m_collections) { - if (collNamePair.second != nullptr) { - collNamePair.second->clear(); - } - } - for (auto& collNamePair : m_readCollections) { - if (collNamePair.second != nullptr) { - collNamePair.second->clear(); - } - } - DataSvc::clearStore().ignore(); - m_collections.clear(); - m_readCollections.clear(); - return StatusCode::SUCCESS; -} - -void LCIODataSvc::endOfRead() { - if (m_eventMax != -1) { - // m_provider.clearCaches(); - // m_reader.endOfEvent(); - if ( ++m_eventNum >= m_eventMax ) { - if ( ++m_fileIndex < m_filenames.size() ) { // move to next file - m_reader->close(); - m_reader->open( m_filenames[m_fileIndex] ); - m_eventMax += m_reader->getNumberOfEvents(); - } - else { // reach to the end of the file list - info() << "Reached end of file with event " << m_eventMax << endmsg; - IEventProcessor* eventProcessor; - service("ApplicationMgr", eventProcessor); - eventProcessor->stopRun(); - } - } - } - evt = nullptr; -} - -void LCIODataSvc::setCollectionIDs(podio::CollectionIDTable* collectionIds) { - if (m_collectionIDs != nullptr) { - delete m_collectionIDs; - } - m_collectionIDs = collectionIds; -} - -/// Standard Constructor -LCIODataSvc::LCIODataSvc(const std::string& name, ISvcLocator* svc) - : DataSvc(name, svc), m_collectionIDs(new podio::CollectionIDTable()) { - - m_eventDataTree = new TTree("events", "Events tree"); - declareProperty("inputs", m_filenames = {}, "Names of the files to read"); - declareProperty("input", m_filename = "", "Name of the file to read"); - - } - -/// Standard Destructor -LCIODataSvc::~LCIODataSvc() {} - - -StatusCode LCIODataSvc::readCollection(const std::string& collName, int collectionID) { - - StatusCode stat = StatusCode::SUCCESS; - podio::CollectionBase* collection(nullptr); - - if( evt == nullptr ){ - evt = m_reader->readNextEvent(); - cvtor.clear(); - - // basicly set EventHeader; - pl_evtcol = new plcio::EventHeaderCollection(); - plcio::EventHeader evt_header; - evt_header = (plcio::EventHeader) pl_evtcol->create(); - evt_header.setEventNumber( evt->getEventNumber() ); - evt_header.setRunNumber( evt->getRunNumber() ); - evt_header.setTimeStamp( evt->getTimeStamp() ); - evt_header.setDetectorName( evt->getDetectorName() ); - - // wrap event header collection into Data service; - auto wrapper = new DataWrapper<podio::CollectionBase>; - int id = m_collectionIDs->add("EventHeader"); - pl_evtcol->setID(id); - wrapper->setData(pl_evtcol); - - if ( m_pIDP ) { - m_pIDP->registerObject("EventHeader", wrapper); - } - else { - m_readCollections.emplace_back(std::make_pair("EventHeader", pl_evtcol)); - DataSvc::registerObject("EventHeader", wrapper); - } - } - - debug() << "reading collection name: " << collName << "." << endmsg; - EVENT::LCCollection* lc_col; - std::vector<std::string> vec_colns = *evt->getCollectionNames(); - std::vector<std::string>::iterator it = find(vec_colns.begin(), vec_colns.end(), collName); - if( it != vec_colns.end() ){ - lc_col = evt->getCollection(collName); - } - else - return stat; -// debug() << "Got collection: " << collName << "." << endmsg; - - std::string TypeName = lc_col->getTypeName(); -// if( !exist_MCP && (TypeName == "MCParticle") ) exist_MCP = true; -// if( TypeName == "MCParticle" ){ -// if( !exist_MCP ) exist_MCP = true; -// mcpcol_pl = LCIO2Plcio::Core_MCParticle(lc_col); -// LCIO2Plcio::setLCIOMCParticleCollection(mcpcol_lc); -// LCIO2Plcio::setPlcioMCParticleCollection(mcpcol_pl); -// } - cvtor.setCollName(collName); - collection = cvtor.Convertor_getPlcio( lc_col ); - pl_evtcol->at(0)->addCollectionName(collName); - pl_evtcol->at(0)->addCollectionType(TypeName); - - auto wrapper = new DataWrapper<podio::CollectionBase>; - int id = m_collectionIDs->add(collName); - collection->setID(id); - wrapper->setData(collection); - -// info() << "readCollection completed." << endmsg; - - if ( m_pIDP ) { - stat = m_pIDP->registerObject(collName, wrapper); - } - else { - m_readCollections.emplace_back(std::make_pair(collName, collection)); - stat = DataSvc::registerObject(collName, wrapper); - } - return stat; -} - -StatusCode LCIODataSvc::registerObject(const std::string& fullPath, DataObject* pObject) { - DataWrapperBase* wrapper = dynamic_cast<DataWrapperBase*>(pObject); - if (wrapper != nullptr) { - podio::CollectionBase* coll = wrapper->collectionBase(); - if (coll != nullptr) { - size_t pos = fullPath.find_last_of("/"); - std::string shortPath(fullPath.substr(pos + 1, fullPath.length())); - int id = m_collectionIDs->add(shortPath); - coll->setID(id); - m_collections.emplace_back(std::make_pair(shortPath, coll)); - } - } - return DataSvc::registerObject(fullPath, pObject); -} diff --git a/FWCore/src/components/LCIOInput.cpp b/FWCore/src/components/LCIOInput.cpp deleted file mode 100644 index dab645881d2f0afce2407416e5a581bb76ae7c0a..0000000000000000000000000000000000000000 --- a/FWCore/src/components/LCIOInput.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "LCIOInput.h" - -#include "TFile.h" -#include "TROOT.h" - -#include "FWCore/DataWrapper.h" -#include "FWCore/LCIODataSvc.h" - -DECLARE_COMPONENT(LCIOInput) - -LCIOInput::LCIOInput(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) {} - -StatusCode LCIOInput::initialize() { - if (GaudiAlgorithm::initialize().isFailure()) return StatusCode::FAILURE; - - // check whether we have the LCIOEvtSvc active - auto pSvc = service( m_dataSvc ); - m_LCIODataSvc = dynamic_cast<LCIODataSvc*>(pSvc.get()); - if (nullptr == m_LCIODataSvc) return StatusCode::FAILURE; - - auto idTable = m_LCIODataSvc->getCollectionIDs(); - for (auto& name : m_collectionNames) { - debug() << "Finding collection " << name << " in collection registry." << endmsg; -/* - if (!idTable->present(name)) { - error() << "Requested product " << name << " not found." << endmsg; - return StatusCode::FAILURE; - } -*/ - m_collectionIDs.push_back(idTable->add(name)); - } - return StatusCode::SUCCESS; -} - -StatusCode LCIOInput::execute() { - size_t cntr = 0; - // Re-create the collections from ROOT file - for (auto& id : m_collectionIDs) { - const std::string& collName = m_collectionNames.value().at(cntr++); - debug() << "Registering collection to read " << collName << " with id " << id << endmsg; - if (m_LCIODataSvc->readCollection(collName, id).isFailure()) { - return StatusCode::FAILURE; - } - } - // Tell data service that we are done with requested collections - m_LCIODataSvc->endOfRead(); - return StatusCode::SUCCESS; -} - -StatusCode LCIOInput::finalize() { - if (GaudiAlgorithm::finalize().isFailure()) return StatusCode::FAILURE; - return StatusCode::SUCCESS; -} diff --git a/FWCore/src/components/LCIOInput.h b/FWCore/src/components/LCIOInput.h deleted file mode 100644 index 1ede535f1bd62a54e565a20e9abf005d85825603..0000000000000000000000000000000000000000 --- a/FWCore/src/components/LCIOInput.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef FWCORE_LCIOINPUT_H -#define FWCORE_LCIOINPUT_H -// Gaaudi -#include "GaudiAlg/GaudiAlgorithm.h" - -// STL -#include <string> -#include <vector> - -// forward declarations -// from FWCore: -class LCIODataSvc; - -/** @class LCIOInput FWCore/components/LCIOInput.h LCIOInput.h - * - * Class that allows to read ROOT files written with LCIOInput - * - * @author J. Lingemann - */ - -class LCIOInput : public GaudiAlgorithm { - friend class AlgFactory<LCIOInput>; - -public: - /// Constructor. - LCIOInput(const std::string& name, ISvcLocator* svcLoc); - /// Initialization of LCIOInput. Acquires the data service, opens root file and creates trees. - virtual StatusCode initialize(); - /// Execute. Re-creates collections that are specified to be read and sets references. - virtual StatusCode execute(); - /// Finalize. Closes ROOT file. - virtual StatusCode finalize(); - -private: - /// Name of collections to read. Set by option collections (this is temporary) - Gaudi::Property<std::string> m_dataSvc{ this, "DataSvc", "LCIOInputSvc" }; - Gaudi::Property<std::vector<std::string>> m_collectionNames{this, "collections", {}, "Places of collections to read"}; - /// Collection IDs (retrieved with CollectionIDTable from ROOT file, using collection names) - std::vector<int> m_collectionIDs; - /// Data service: needed to register objects and get collection IDs. Just an observing pointer. - LCIODataSvc* m_LCIODataSvc; -}; - -#endif diff --git a/FWCore/src/components/PodioInput.cpp b/FWCore/src/components/PodioInput.cpp deleted file mode 100644 index f031744cdbe8c27728eeed3356cc8bc030fcf9d5..0000000000000000000000000000000000000000 --- a/FWCore/src/components/PodioInput.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "PodioInput.h" - -#include "TFile.h" -#include "TROOT.h" - -#include "FWCore/DataWrapper.h" -#include "FWCore/PodioDataSvc.h" - -DECLARE_COMPONENT(PodioInput) - -PodioInput::PodioInput(const std::string& name, ISvcLocator* svcLoc) : GaudiAlgorithm(name, svcLoc) {} - -StatusCode PodioInput::initialize() { - if (GaudiAlgorithm::initialize().isFailure()) return StatusCode::FAILURE; - - // check whether we have the PodioEvtSvc active - m_podioDataSvc = dynamic_cast<PodioDataSvc*>(evtSvc().get()); - if (nullptr == m_podioDataSvc) return StatusCode::FAILURE; - - auto idTable = m_podioDataSvc->getCollectionIDs(); - for (auto& name : m_collectionNames) { - debug() << "Finding collection " << name << " in collection registry." << endmsg; - if (!idTable->present(name)) { - error() << "Requested product " << name << " not found." << endmsg; - return StatusCode::FAILURE; - } - m_collectionIDs.push_back(idTable->collectionID(name)); - } - return StatusCode::SUCCESS; -} - -StatusCode PodioInput::execute() { - size_t cntr = 0; - // Re-create the collections from ROOT file - for (auto& id : m_collectionIDs) { - const std::string& collName = m_collectionNames.value().at(cntr++); - debug() << "Registering collection to read " << collName << " with id " << id << endmsg; - if (m_podioDataSvc->readCollection(collName, id).isFailure()) { - return StatusCode::FAILURE; - } - } - // Tell data service that we are done with requested collections - m_podioDataSvc->endOfRead(); - return StatusCode::SUCCESS; -} - -StatusCode PodioInput::finalize() { - if (GaudiAlgorithm::finalize().isFailure()) return StatusCode::FAILURE; - return StatusCode::SUCCESS; -} diff --git a/FWCore/src/components/PodioInput.h b/FWCore/src/components/PodioInput.h deleted file mode 100644 index 0319d78f63a715edd5bd42d5e08823328ed759f2..0000000000000000000000000000000000000000 --- a/FWCore/src/components/PodioInput.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef FWCORE_PODIOINPUT_H -#define FWCORE_PODIOINPUT_H -// Gaaudi -#include "GaudiAlg/GaudiAlgorithm.h" - -// STL -#include <string> -#include <vector> - -// forward declarations -// from FWCore: -class PodioDataSvc; - -/** @class PodioInput FWCore/components/PodioInput.h PodioInput.h - * - * Class that allows to read ROOT files written with PodioOutput - * - * @author J. Lingemann - */ - -class PodioInput : public GaudiAlgorithm { - friend class AlgFactory<PodioInput>; - -public: - /// Constructor. - PodioInput(const std::string& name, ISvcLocator* svcLoc); - /// Initialization of PodioInput. Acquires the data service, opens root file and creates trees. - virtual StatusCode initialize(); - /// Execute. Re-creates collections that are specified to be read and sets references. - virtual StatusCode execute(); - /// Finalize. Closes ROOT file. - virtual StatusCode finalize(); - -private: - /// Name of collections to read. Set by option collections (this is temporary) - Gaudi::Property<std::vector<std::string>> m_collectionNames{this, "collections", {}, "Places of collections to read"}; - /// Collection IDs (retrieved with CollectionIDTable from ROOT file, using collection names) - std::vector<int> m_collectionIDs; - /// Data service: needed to register objects and get collection IDs. Just an observing pointer. - PodioDataSvc* m_podioDataSvc; -}; - -#endif diff --git a/FWCore/src/components/PodioOutput.cpp b/FWCore/src/components/PodioOutput.cpp deleted file mode 100644 index 26e6e37f6c367ec2a494b01a5606c578678e5de3..0000000000000000000000000000000000000000 --- a/FWCore/src/components/PodioOutput.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "PodioOutput.h" -#include "GaudiKernel/IJobOptionsSvc.h" -#include "FWCore/PodioDataSvc.h" -#include "TFile.h" - -DECLARE_COMPONENT(PodioOutput) - -PodioOutput::PodioOutput(const std::string& name, ISvcLocator* svcLoc) - : GaudiAlgorithm(name, svcLoc), m_firstEvent(true) {} - -StatusCode PodioOutput::initialize() { - if (GaudiAlgorithm::initialize().isFailure()) return StatusCode::FAILURE; - - // check whether we have the PodioEvtSvc active - m_podioDataSvc = dynamic_cast<PodioDataSvc*>(evtSvc().get()); - if (0 == m_podioDataSvc) return StatusCode::FAILURE; - - m_file = std::unique_ptr<TFile>(new TFile(m_filename.value().c_str(), "RECREATE", "data file")); - // Both trees are written to the ROOT file and owned by it - // PodioDataSvc has ownership of EventDataTree - m_datatree = m_podioDataSvc->eventDataTree(); - m_metadatatree = new TTree("metadata", "Metadata tree"); - m_switch = KeepDropSwitch(m_outputCommands); - return StatusCode::SUCCESS; -} - -void PodioOutput::resetBranches(const std::vector<std::pair<std::string, podio::CollectionBase*>>& collections, - bool prepare) { - for (auto& collNamePair : collections) { - auto collName = collNamePair.first; - if (m_switch.isOn(collName)) { - // Reconnect branches and collections - m_datatree->SetBranchAddress(collName.c_str(), collNamePair.second->getBufferAddress()); - auto colls = collNamePair.second->referenceCollections(); - if (colls != nullptr) { - int j = 0; - for (auto& c : (*colls)) { - m_datatree->SetBranchAddress((collName + "#" + std::to_string(j)).c_str(), &c); - ++j; - } - } - // vector members - auto vminfo = collNamePair.second->vectorMembers(); - if ( vminfo != nullptr ) { - int j = 0; - for ( auto& c : (*vminfo) ) { - m_datatree->SetBranchAddress((collName+"_"+std::to_string(j)).c_str(), c.second); - ++j; - } - } - } - if (prepare) { - collNamePair.second->prepareForWrite(); - } - } -} - -void PodioOutput::createBranches(const std::vector<std::pair<std::string, podio::CollectionBase*>>& collections, - bool prepare) { - for (auto& collNamePair : collections) { - auto collName = collNamePair.first; - // TODO: we need the class name in a better way - std::string className(typeid(*(collNamePair.second)).name()); - size_t pos = className.find_first_not_of("0123456789"); - className.erase(0, pos); - // demangling the namespace: due to namespace additional characters were introduced: - // e.g. N3fcc18TrackHit - // remove any number+char before the namespace: - pos = className.find_first_of("0123456789"); - size_t pos1 = className.find_first_not_of("0123456789", pos); - className.erase(0, pos1); - // replace any numbers between namespace and class with "::" - pos = className.find_first_of("0123456789"); - pos1 = className.find_first_not_of("0123456789", pos); - className.replace(pos, pos1 - pos, "::"); - - pos = className.find("Collection"); - className.erase(pos, pos + 10); - std::string collClassName = "vector<" + className + "Data>"; - int isOn = 0; - if (m_switch.isOn(collName)) { - isOn = 1; - m_datatree->Branch(collName.c_str(), collClassName.c_str(), collNamePair.second->getBufferAddress()); - // Create branches for collections holding relations - auto colls = collNamePair.second->referenceCollections(); - if (colls != nullptr) { - int j = 0; - for (auto& c : (*colls)) { - m_datatree->Branch((collName + "#" + std::to_string(j)).c_str(), c); - ++j; - } - } - // vector members - auto vminfo = collNamePair.second->vectorMembers(); - if ( vminfo != nullptr ) { - int j = 0; - for ( auto& c : (*vminfo) ) { - std::string typeName = "vector<" + c.first + ">"; - void* add = c.second; - m_datatree->Branch((collName+"_"+std::to_string(j)).c_str(), typeName.c_str(), add); - ++j; - } - } - } - debug() << isOn << " Registering collection " << collClassName << " " << collName.c_str() << " containing type " - << className << endmsg; - if (prepare) { - collNamePair.second->prepareForWrite(); - } - } -} - -StatusCode PodioOutput::execute() { - // for now assume identical content for every event - // register for writing - if (m_firstEvent) { - createBranches(m_podioDataSvc->getCollections(), true); - createBranches(m_podioDataSvc->getReadCollections(), false); - } else { - resetBranches(m_podioDataSvc->getCollections(), true); - resetBranches(m_podioDataSvc->getReadCollections(), false); - } - m_firstEvent = false; - debug() << "Filling DataTree .." << endmsg; - m_datatree->Fill(); - return StatusCode::SUCCESS; -} - -StatusCode PodioOutput::finalize() { - if (GaudiAlgorithm::finalize().isFailure()) return StatusCode::FAILURE; - // retrieve the configuration of the job - // and write it to file as vector of strings - std::vector<std::string> config_data; - auto jobOptionsSvc = service<IJobOptionsSvc>("JobOptionsSvc"); - auto configured_components = jobOptionsSvc->getClients(); - for (const auto& name : configured_components) { - auto properties = jobOptionsSvc->getProperties(name); - std::stringstream config_stream; - for (const auto& property : *properties) { - config_stream << name << " : " << property->name() << " = " << property->toString() << std::endl; - } - config_data.push_back(config_stream.str()); - } - m_metadatatree->Branch("gaudiConfigOptions", &config_data); - - m_metadatatree->Branch("CollectionIDs", m_podioDataSvc->getCollectionIDs()); - m_metadatatree->Fill(); - m_datatree->Write(); - m_file->Write(); - m_file->Close(); - info() << "Data written to: " << m_filename << endmsg; - return StatusCode::SUCCESS; -} diff --git a/FWCore/src/components/PodioOutput.h b/FWCore/src/components/PodioOutput.h deleted file mode 100644 index f1c93beabd1436202330011ffe741bcdfa5d2dab..0000000000000000000000000000000000000000 --- a/FWCore/src/components/PodioOutput.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef FWCORE_PODIOOUTPUT_H -#define FWCORE_PODIOOUTPUT_H - -#include "FWCore/KeepDropSwitch.h" -#include "GaudiAlg/GaudiAlgorithm.h" -#include "podio/CollectionBase.h" - -#include "TTree.h" - -#include <vector> - -// forward declarations -class TFile; -class PodioDataSvc; - -class PodioOutput : public GaudiAlgorithm { - friend class AlgFactory<PodioOutput>; - -public: - /// Constructor. - PodioOutput(const std::string& name, ISvcLocator* svcLoc); - - /// Initialization of PodioOutput. Acquires the data service, creates trees and root file. - virtual StatusCode initialize(); - /// Execute. For the first event creates branches for all collections known to PodioDataSvc and prepares them for - /// writing. For the following events it reconnects the branches with collections and prepares them for write. - virtual StatusCode execute(); - /// Finalize. Writes the meta data tree; writes file and cleans up all ROOT-pointers. - virtual StatusCode finalize(); - -private: - void resetBranches(const std::vector<std::pair<std::string, podio::CollectionBase*>>& collections, bool prepare); - void createBranches(const std::vector<std::pair<std::string, podio::CollectionBase*>>& collections, bool prepare); - /// First event or not - bool m_firstEvent; - /// Root file name the output is written to - Gaudi::Property<std::string> m_filename{this, "filename", "output.root", "Name of the file to create"}; - /// Commands which output is to be kept - Gaudi::Property<std::vector<std::string>> m_outputCommands{ - this, "outputCommands", {"keep *"}, "A set of commands to declare which collections to keep or drop."}; - /// Switch for keeping or dropping outputs - KeepDropSwitch m_switch; - /// Needed for collection ID table - PodioDataSvc* m_podioDataSvc; - /// The actual ROOT file - std::unique_ptr<TFile> m_file; - /// The tree to be filled with collections - TTree* m_datatree; - /// The tree to be filled with meta data - TTree* m_metadatatree; - /// The stored collections - std::vector<podio::CollectionBase*> m_storedCollections; -}; - -#endif diff --git a/Generator/CMakeLists.txt b/Generator/CMakeLists.txt index 16be6fa4eb3ab82774fb6376827d19d06d87759d..41f325ec59a21f336721425edae877e76a822e5b 100644 --- a/Generator/CMakeLists.txt +++ b/Generator/CMakeLists.txt @@ -21,8 +21,11 @@ include(${Geant4_USE_FILE}) find_package(ROOT COMPONENTS RIO Tree TreePlayer MathCore Net Graf3d Graf Gpad EG REQUIRED) find_package(LCIO) find_package(podio) -find_package(plcio) +find_package(EDM4HEP) find_package(HepMC) +find_package(CLHEP) +find_package(K4FWCore REQUIRED) + if(ROOT_FOUND) message("found ROOT: ${ROOT_INCLUDE_DIRS} ${ROOT_LIBRARIES}") endif(ROOT_FOUND) @@ -32,35 +35,26 @@ endif(LCIO_FOUND) if(podio_FOUND) message("found podio: ${podio_INCLUDE_DIRS} ${podio_LIBRARIES}") endif(podio_FOUND) -if(plcio_FOUND) - message("found plcio: ${plcio_INCLUDE_DIRS} ${plcio_LIBRARY_DIR}") -endif(plcio_FOUND) if(HepMC_FOUND) message("found HepMC: ${HepMC_INCLUDE_DIRS} ${HepMC_LIBRARY_DIR}") endif(HepMC_FOUND) +if(CLHEP_FOUND) + message("found CLHEP: ${CLHEP_INCLUDE_DIRS} ${CLHEP_LIBRARY_DIR}") +endif(CLHEP_FOUND) ############## for producing plcio library ############# INCLUDE_DIRECTORIES(${GenAlgo_incs}) gaudi_add_module(GenAlgo ${GenAlgo_srcs} INCLUDE_DIRS - GaudiKernel - FWCore - Geant4 - ${LCIO_INCLUDE_DIRS} - ${podio_INCLUDE_DIRS} - ${plcio_INCLUDE_DIRS} - ${ROOT_INCLUDE_DIRS} - HepMC + K4FWCore LINK_LIBRARIES - GaudiKernel - ${LCIO_LIBRARIES} - ${podio_LIBRARIES} ROOT - ${plcio_LIBRARY_DIR}/libplcio.so - ${plcio_LIBRARY_DIR}/libplcioDict.so - FWCore + K4FWCore + GaudiAlgLib GaudiKernel HepMC - Geant4 + CLHEP + LCIO + EDM4HEP::edm4hep EDM4HEP::edm4hepDict ) #gaudi_add_test(Reader FRAMEWORK options/read.py) diff --git a/Generator/src/GenAlgo.cpp b/Generator/src/GenAlgo.cpp index 74c2db30e0f75fc02bd2015b349ddade470c4f40..58f9d4e8b438085a5322e565f778506830e7ec14 100644 --- a/Generator/src/GenAlgo.cpp +++ b/Generator/src/GenAlgo.cpp @@ -5,7 +5,7 @@ #include "GaudiKernel/GaudiException.h" -#include "plcio/MCParticleCollection.h"//plico +#include "edm4hep/MCParticleCollection.h"//plico #include <iostream> #include <vector> diff --git a/Generator/src/GenAlgo.h b/Generator/src/GenAlgo.h index 0fd060dc2a004a32f3ec0d27e9b50e8f42d163ad..47745aefec9c8ac7a90819bf88c9eecf91fc7ab8 100644 --- a/Generator/src/GenAlgo.h +++ b/Generator/src/GenAlgo.h @@ -21,7 +21,6 @@ using namespace std; class GenAlgo: public GaudiAlgorithm { - friend class AlgFactory<GenAlgo>; public: GenAlgo(const std::string& name, ISvcLocator* pSvcLocator); @@ -43,7 +42,7 @@ private: int m_evtid; int m_evtMax; //MyHepMC::GenEvent m_event; - DataHandle<plcio::MCParticleCollection> m_hdl{"MCParticle", Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCParticleCollection> m_hdl{"MCParticle", Gaudi::DataHandle::Writer, this}; }; diff --git a/Generator/src/GenEvent.cpp b/Generator/src/GenEvent.cpp index 1cd5ccb3c6bcc02df464106e391b846a77bbd159..3e40c65b8476c83a48e98fc4b596e60d15bcab5f 100644 --- a/Generator/src/GenEvent.cpp +++ b/Generator/src/GenEvent.cpp @@ -1,12 +1,12 @@ #include "GenEvent.h" -#include "plcio/MCParticleCollection.h"//plico +#include "edm4hep/MCParticleCollection.h"//plico using namespace std; namespace MyHepMC{ //GenEvent::GenEvent(){ -GenEvent::GenEvent(plcio::MCParticleCollection& mcCol) +GenEvent::GenEvent(edm4hep::MCParticleCollection& mcCol) : m_mc_vec(mcCol){ m_event_id=-1; @@ -24,11 +24,11 @@ void GenEvent::SetEventHeader(long event_id_, long run_id_, float time_, string m_det_name = det_name_; } /* -void GenEvent::SetMCCollection(plcio::MCParticleCollection vec_){ +void GenEvent::SetMCCollection(edm4hep::MCParticleCollection vec_){ m_mc_vec = vec_; } */ -plcio::MCParticleCollection GenEvent::getMCVec(){ +edm4hep::MCParticleCollection GenEvent::getMCVec(){ return m_mc_vec; } diff --git a/Generator/src/GenEvent.h b/Generator/src/GenEvent.h index dae1b3772d3044ad3434898ec1c216ab41493d57..72895413a5d06438fcffe72495ef56b646921c5c 100644 --- a/Generator/src/GenEvent.h +++ b/Generator/src/GenEvent.h @@ -1,25 +1,25 @@ #ifndef GenEvent_h #define GenEvent_h 1 -#include "plcio/MCParticleCollection.h"//plico +#include "edm4hep/MCParticleCollection.h"//plico namespace MyHepMC { class GenEvent{ public: //GenEvent(); - GenEvent(plcio::MCParticleCollection& mcCol); + GenEvent(edm4hep::MCParticleCollection& mcCol); ~GenEvent(); void SetEventHeader(long event_id_, long run_id_, float time_, std::string det_name_); - //void SetMCCollection(plcio::MCParticleCollection vec_); + //void SetMCCollection(edm4hep::MCParticleCollection vec_); long getID(); long getRun(); long getTime(); void ReSet(); std::string getName(); - plcio::MCParticleCollection getMCVec(); - plcio::MCParticleCollection& m_mc_vec; - //plcio::MCParticleCollection m_mc_vec; + edm4hep::MCParticleCollection getMCVec(); + edm4hep::MCParticleCollection& m_mc_vec; + //edm4hep::MCParticleCollection m_mc_vec; private: long m_event_id; long m_run_id; diff --git a/Generator/src/GtGunTool.cpp b/Generator/src/GtGunTool.cpp index a8f65da3863f1622f63997fef74ebc77c36c4a05..df29f4a2821f0324d574fc71e316bd05f3054447 100644 --- a/Generator/src/GtGunTool.cpp +++ b/Generator/src/GtGunTool.cpp @@ -15,11 +15,12 @@ GtGunTool::initialize() { error() << "Please specify the list of particle names/pdgs" << endmsg; return StatusCode::FAILURE; } - if (m_energies.value().size() != m_particles.value().size()) { + + if (m_energymins.value().size() != m_particles.value().size()) { error() << "Mismatched energies and particles." << endmsg; return StatusCode::FAILURE; } - + // others should be empty or specify if (m_thetamins.value().size() && m_thetamins.value().size() != m_particles.value().size()) { @@ -78,10 +79,10 @@ GtGunTool::mutate(MyHepMC::GenEvent& event) { } } - double energy = m_energies.value()[i]; + double energy = m_energymins.value()[i]==m_energymaxs.value()[i] ? m_energymins.value()[i] : CLHEP::RandFlat::shoot(m_energymins.value()[i], m_energymaxs.value()[i]); // create the MC particle - plcio::MCParticle mcp = event.m_mc_vec.create(); + edm4hep::MCParticle mcp = event.m_mc_vec.create(); mcp.setPDG(pdgcode); mcp.setGeneratorStatus(1); mcp.setSimulatorStatus(1); @@ -96,45 +97,16 @@ GtGunTool::mutate(MyHepMC::GenEvent& event) { // direction // by default, randomize the direction - double costheta = CLHEP::RandFlat::shoot(-1, 1); - double phi = 360*CLHEP::RandFlat::shoot()*CLHEP::degree; + double theta = m_thetamins.value()[i]==m_thetamaxs.value()[i] ? m_thetamins.value()[i] : CLHEP::RandFlat::shoot(m_thetamins.value()[i], m_thetamaxs.value()[i]); + double phi = m_phimins .value()[i]==m_phimaxs .value()[i] ? m_phimins .value()[i] : CLHEP::RandFlat::shoot(m_phimins .value()[i], m_phimaxs .value()[i]); + double costheta = cos(theta*acos(-1)/180); + double phi_ = phi*acos(-1)/180; double sintheta = sqrt(1.-costheta*costheta); - - // check if theta min/max is set - - if (i < m_thetamins.value().size() - && i < m_thetamaxs.value().size()) { - double thetamin = m_thetamins.value()[i]; - double thetamax = m_thetamaxs.value()[i]; - - if (thetamin == thetamax) { // fixed theta - costheta = cos(thetamin); - sintheta = sin(thetamin); - info() << "theta is fixed: " << thetamin << endmsg; - } - } - - if (i < m_phimins.value().size() - && i < m_phimaxs.value().size()) { - double phimin = m_phimins.value()[i]; - double phimax = m_phimaxs.value()[i]; - - if (phimin == phimax) { // fixed phi - phi = phimin; - info() << "phi is fixed: " << phimin << endmsg; - } - } - - debug() << "Direction: " - << " cos(theta): " << costheta - << " phi: " << phi - << endmsg; - - double px = p*sintheta*cos(phi); - double py = p*sintheta*sin(phi); + double px = p*sintheta*cos(phi_); + double py = p*sintheta*sin(phi_); double pz = p*costheta; - - mcp.setMomentum(plcio::FloatThree(px,py,pz)); + std::cout<<"GenGt p="<<p<<", px="<<px<<",py="<<py<<",pz="<<pz<<",theta="<<theta<<",phi="<<phi<<std::endl; + mcp.setMomentum(edm4hep::Vector3f(px,py,pz)); // mcp.setMomentumAtEndpoint(); // mcp.setSpin(); // mcp.setColorFlow(); diff --git a/Generator/src/GtGunTool.h b/Generator/src/GtGunTool.h index 22b02a811a19be2ce5a16ca1cdd4726635a0be4b..388c14d4d555bc4d3b436ebc90fabdca26f22337 100644 --- a/Generator/src/GtGunTool.h +++ b/Generator/src/GtGunTool.h @@ -34,7 +34,8 @@ private: Gaudi::Property<std::vector<std::string>> m_particles{this, "Particles"}; - Gaudi::Property<std::vector<double>> m_energies{this, "Energies"}; + Gaudi::Property<std::vector<double>> m_energymins{this, "EnergyMins"}; + Gaudi::Property<std::vector<double>> m_energymaxs{this, "EnergyMaxs"}; Gaudi::Property<std::vector<double>> m_thetamins{this, "ThetaMins"}; Gaudi::Property<std::vector<double>> m_thetamaxs{this, "ThetaMaxs"}; diff --git a/Generator/src/HepMCRdr.cpp b/Generator/src/HepMCRdr.cpp index b8c81809efb2efb4e0e25a5f4d3a9f3f624fdc60..c4bfb60d738e0780c523fe2f46f6ab7282c3c0b6 100644 --- a/Generator/src/HepMCRdr.cpp +++ b/Generator/src/HepMCRdr.cpp @@ -7,12 +7,10 @@ #include "HepMC/Polarization.h" -#include "plcio/MCParticle.h" //plcio -#include "plcio/MCParticleObj.h" -#include "plcio/MCParticleCollection.h" -#include "plcio/DoubleThree.h" -#include "plcio/FloatThree.h" -#include "plcio/EventHeaderCollection.h" +#include "edm4hep/MCParticle.h" //edm4hep +#include "edm4hep/MCParticleObj.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/EventHeaderCollection.h" @@ -21,7 +19,7 @@ #include <fstream> -using namespace plcio; +using namespace edm4hep; using namespace std; DECLARE_COMPONENT(HepMCRdr) @@ -41,7 +39,7 @@ bool HepMCRdr::mutate(MyHepMC::GenEvent& event){ int index = 0 ; for ( HepMC::GenEvent::particle_iterator p = evt->particles_begin(); p != evt->particles_end(); ++p ) { //std::cout<<"start mc "<<index<<std::endl; - plcio::MCParticle mcp = event.m_mc_vec.create(); + edm4hep::MCParticle mcp = event.m_mc_vec.create(); pmcid_lmcid.insert(std::pair<int, int>((*p)->barcode(),index)); index++; //std::cout<<"map<id,i>:"<<mc->id()<<","<< i <<std::endl; @@ -55,35 +53,35 @@ bool HepMCRdr::mutate(MyHepMC::GenEvent& event){ if ( (*p)->production_vertex() ){ HepMC::GenVertex* vertex_pro = (*p)->production_vertex(); double three[3] = {vertex_pro->point3d().x(), vertex_pro->point3d().y(), vertex_pro->point3d().z()}; - mcp.setVertex (plcio::DoubleThree (three)); + mcp.setVertex (edm4hep::Vector3d (three)); } - else mcp.setVertex(plcio::DoubleThree()); + else mcp.setVertex(edm4hep::Vector3d()); if ( (*p)->end_vertex() ){ HepMC::GenVertex* vertex_end = (*p)->end_vertex(); double three[3] = {vertex_end->point3d().x(), vertex_end->point3d().y(), vertex_end->point3d().z()}; - mcp.setEndpoint (plcio::DoubleThree (three)); + mcp.setEndpoint (edm4hep::Vector3d (three)); } - else mcp.setEndpoint (plcio::DoubleThree()); - mcp.setMomentum (plcio::FloatThree(float((*p)->momentum().px()), float((*p)->momentum().py()), float((*p)->momentum().pz()) )); - mcp.setMomentumAtEndpoint (plcio::FloatThree(float((*p)->momentum().px()), float((*p)->momentum().py()), float((*p)->momentum().pz()) )); + else mcp.setEndpoint (edm4hep::Vector3d()); + mcp.setMomentum (edm4hep::Vector3f(float((*p)->momentum().px()), float((*p)->momentum().py()), float((*p)->momentum().pz()) )); + mcp.setMomentumAtEndpoint (edm4hep::Vector3f(float((*p)->momentum().px()), float((*p)->momentum().py()), float((*p)->momentum().pz()) )); const HepMC::Polarization & polar = (*p)->polarization(); - mcp.setSpin (plcio::FloatThree(polar.normal3d().x(), polar.normal3d().y(), polar.normal3d().z()) ); + mcp.setSpin (edm4hep::Vector3f(polar.normal3d().x(), polar.normal3d().y(), polar.normal3d().z()) ); int two[2] = {1, (*p)->flow(1)}; - mcp.setColorFlow (plcio::IntTwo (two) ); + mcp.setColorFlow (edm4hep::Vector2i (two) ); } // second loop for setting parents and daughters index = 0 ; for ( HepMC::GenEvent::particle_iterator p = evt->particles_begin(); p != evt->particles_end(); ++p ) { - plcio::MCParticle pmc = event.m_mc_vec.at(index); + edm4hep::MCParticle pmc = event.m_mc_vec.at(index); index++; if ( (*p)->production_vertex() ) { for ( HepMC::GenVertex::particle_iterator mother = (*p)->production_vertex()-> particles_begin(HepMC::parents); mother != (*p)->production_vertex()-> particles_end(HepMC::parents); ++mother ) { - pmc.addParent( event.m_mc_vec.at( pmcid_lmcid.at((*mother)->barcode()) ) ); + pmc.addToParents( event.m_mc_vec.at( pmcid_lmcid.at((*mother)->barcode()) ) ); } } if ( (*p)->end_vertex() ) { for ( HepMC::GenVertex::particle_iterator des =(*p)->end_vertex()-> particles_begin(HepMC::descendants); des != (*p)->end_vertex()-> particles_end(HepMC::descendants); ++des ) { - pmc.addDaughter( event.m_mc_vec.at( pmcid_lmcid.at((*des)->barcode()) ) ); + pmc.addToDaughters( event.m_mc_vec.at( pmcid_lmcid.at((*des)->barcode()) ) ); } } } diff --git a/Generator/src/SLCIORdr.cpp b/Generator/src/SLCIORdr.cpp index 9db71153961d29ece2a4479d36bddfa8fb7dde98..2f0b940a339e0aa63a4a709220a4f0c56f2b0843 100644 --- a/Generator/src/SLCIORdr.cpp +++ b/Generator/src/SLCIORdr.cpp @@ -12,12 +12,10 @@ #include "IMPL/LCCollectionVec.h" -#include "plcio/MCParticle.h" //plcio -#include "plcio/MCParticleObj.h" -#include "plcio/MCParticleCollection.h" -#include "plcio/DoubleThree.h" -#include "plcio/FloatThree.h" -#include "plcio/EventHeaderCollection.h" +#include "edm4hep/MCParticle.h" //edm4hep +#include "edm4hep/MCParticleObj.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/EventHeaderCollection.h" @@ -28,7 +26,7 @@ using namespace lcio; using namespace IMPL; -using namespace plcio; +using namespace edm4hep; using namespace std; DECLARE_COMPONENT(SLCIORdr) @@ -75,7 +73,7 @@ bool SLCIORdr::mutate(MyHepMC::GenEvent& event){ for(i=0;i<NHEP;i++){ if(p==lcCol->getElementAt(i)) break; } - if(i==NHEP) cout << "HepLCIOInterfaceNew: error" << endl; + if(i==NHEP) cout << "Heedm4hepInterfaceNew: error" << endl; mcp->addParent(dynamic_cast<MCParticleImpl*>(lcMCVec->getElementAt(i))); } //ignore daughter table, auto-regonize relationship while addParent() @@ -88,8 +86,8 @@ bool SLCIORdr::mutate(MyHepMC::GenEvent& event){ for(i=0;i<NHEP;i++){ if(d==lcCol->getElementAt(i)) break; } - if(i==NHEP) cout << "HepLCIOInterfaceNew: error" << endl; - mcp->addDaughter(dynamic_cast<MCParticleImpl*>(lcMCVec->getElementAt(i))); + if(i==NHEP) cout << "Heedm4hepInterfaceNew: error" << endl; + mcp->addToDaughters(dynamic_cast<MCParticleImpl*>(lcMCVec->getElementAt(i))); } */ @@ -108,7 +106,7 @@ bool SLCIORdr::mutate(MyHepMC::GenEvent& event){ for (int i=0; i < n_mc; i++){ MCParticleImpl* mc = (MCParticleImpl*) lcMCVec->getElementAt(i); //std::cout<<"At mc :"<< i <<std::endl; - plcio::MCParticle mcp = event.m_mc_vec.create(); + edm4hep::MCParticle mcp = event.m_mc_vec.create(); pmcid_lmcid.insert(std::pair<int, int>(mc->id(),i)); //std::cout<<"map<id,i>:"<<mc->id()<<","<< i <<std::endl; @@ -120,8 +118,8 @@ bool SLCIORdr::mutate(MyHepMC::GenEvent& event){ mcp.setMass (mc->getMass()); mcp.setVertex (mc->getVertex()); mcp.setEndpoint (mc->getEndpoint()); - mcp.setMomentum (FloatThree(float(mc->getMomentum()[0]), float(mc->getMomentum()[1]), float(mc->getMomentum()[2]) )); - mcp.setMomentumAtEndpoint (FloatThree(float(mc->getMomentumAtEndpoint()[0]), float(mc->getMomentumAtEndpoint()[1]), float(mc->getMomentumAtEndpoint()[2]) )); + mcp.setMomentum (Vector3f(float(mc->getMomentum()[0]), float(mc->getMomentum()[1]), float(mc->getMomentum()[2]) )); + mcp.setMomentumAtEndpoint (Vector3f(float(mc->getMomentumAtEndpoint()[0]), float(mc->getMomentumAtEndpoint()[1]), float(mc->getMomentumAtEndpoint()[2]) )); mcp.setSpin (mc->getSpin()); mcp.setColorFlow (mc->getColorFlow()); } @@ -131,16 +129,16 @@ bool SLCIORdr::mutate(MyHepMC::GenEvent& event){ MCParticleImpl* mc = (MCParticleImpl*) lcMCVec->getElementAt(i); const MCParticleVec & mc_parents = mc->getParents(); const MCParticleVec & mc_daughters = mc->getDaughters(); - plcio::MCParticle pmc = event.m_mc_vec.at(i); + edm4hep::MCParticle pmc = event.m_mc_vec.at(i); //std::cout<<"mc at "<< i<<", parent size "<<mc_parents.size() <<std::endl; for(unsigned int j=0; j< mc_parents.size(); j++){int p_id = mc_parents.at(j)->id(); //std::cout<<"parent id "<<p_id<<std::endl; - pmc.addParent( event.m_mc_vec.at( pmcid_lmcid.at(p_id) ) ); + pmc.addToParents( event.m_mc_vec.at( pmcid_lmcid.at(p_id) ) ); } //std::cout<<"mc at "<< i<<", daughter size "<<mc_daughters.size() <<std::endl; for(unsigned int j=0; j< mc_daughters.size(); j++){int d_id = mc_daughters.at(j)->id(); //std::cout<<"daughter id "<<d_id<<std::endl; - pmc.addDaughter( event.m_mc_vec.at( pmcid_lmcid.at(d_id) ) ); + pmc.addToDaughters( event.m_mc_vec.at( pmcid_lmcid.at(d_id) ) ); } } event.SetEventHeader( m_processed_event, -99, 9999, "Generator"); diff --git a/Generator/src/StdHepRdr.cpp b/Generator/src/StdHepRdr.cpp index b81abb0569a52df5a3674290d9f8a958f33aba35..09fa9ddc009f7be254dcd414154a726b7a4db0d1 100644 --- a/Generator/src/StdHepRdr.cpp +++ b/Generator/src/StdHepRdr.cpp @@ -7,12 +7,10 @@ #include "IMPL/MCParticleImpl.h" -#include "plcio/MCParticle.h" //plcio -#include "plcio/MCParticleObj.h" -#include "plcio/MCParticleCollection.h" -#include "plcio/DoubleThree.h" -#include "plcio/FloatThree.h" -#include "plcio/EventHeaderCollection.h" +#include "edm4hep/MCParticle.h" //edm4hep +#include "edm4hep/MCParticleObj.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/EventHeaderCollection.h" @@ -23,7 +21,7 @@ using namespace lcio; using namespace IMPL; -using namespace plcio; +using namespace edm4hep; using namespace std; DECLARE_COMPONENT(StdHepRdr) @@ -42,7 +40,7 @@ bool StdHepRdr::mutate(MyHepMC::GenEvent& event){ for (int i=0; i < n_mc; i++){ MCParticleImpl* mc = (MCParticleImpl*) mc_vec->getElementAt(i); //std::cout<<"At mc :"<< i <<std::endl; - plcio::MCParticle mcp = event.m_mc_vec.create(); + edm4hep::MCParticle mcp = event.m_mc_vec.create(); pmcid_lmcid.insert(std::pair<int, int>(mc->id(),i)); //std::cout<<"map<id,i>:"<<mc->id()<<","<< i <<std::endl; @@ -54,8 +52,8 @@ bool StdHepRdr::mutate(MyHepMC::GenEvent& event){ mcp.setMass (mc->getMass()); mcp.setVertex (mc->getVertex()); mcp.setEndpoint (mc->getEndpoint()); - mcp.setMomentum (FloatThree(float(mc->getMomentum()[0]), float(mc->getMomentum()[1]), float(mc->getMomentum()[2]) )); - mcp.setMomentumAtEndpoint (FloatThree(float(mc->getMomentumAtEndpoint()[0]), float(mc->getMomentumAtEndpoint()[1]), float(mc->getMomentumAtEndpoint()[2]) )); + mcp.setMomentum (Vector3f(float(mc->getMomentum()[0]), float(mc->getMomentum()[1]), float(mc->getMomentum()[2]) )); + mcp.setMomentumAtEndpoint (Vector3f(float(mc->getMomentumAtEndpoint()[0]), float(mc->getMomentumAtEndpoint()[1]), float(mc->getMomentumAtEndpoint()[2]) )); mcp.setSpin (mc->getSpin()); mcp.setColorFlow (mc->getColorFlow()); } @@ -65,16 +63,16 @@ bool StdHepRdr::mutate(MyHepMC::GenEvent& event){ MCParticleImpl* mc = (MCParticleImpl*) mc_vec->getElementAt(i); const MCParticleVec & mc_parents = mc->getParents(); const MCParticleVec & mc_daughters = mc->getDaughters(); - plcio::MCParticle pmc = event.m_mc_vec.at(i); + edm4hep::MCParticle pmc = event.m_mc_vec.at(i); //std::cout<<"mc at "<< i<<", parent size "<<mc_parents.size() <<std::endl; for(unsigned int j=0; j< mc_parents.size(); j++){int p_id = mc_parents.at(j)->id(); //std::cout<<"parent id "<<p_id<<std::endl; - pmc.addParent( event.m_mc_vec.at( pmcid_lmcid.at(p_id) ) ); + pmc.addToParents( event.m_mc_vec.at( pmcid_lmcid.at(p_id) ) ); } //std::cout<<"mc at "<< i<<", daughter size "<<mc_daughters.size() <<std::endl; for(unsigned int j=0; j< mc_daughters.size(); j++){int d_id = mc_daughters.at(j)->id(); //std::cout<<"daughter id "<<d_id<<std::endl; - pmc.addDaughter( event.m_mc_vec.at( pmcid_lmcid.at(d_id) ) ); + pmc.addToDaughters( event.m_mc_vec.at( pmcid_lmcid.at(d_id) ) ); } } diff --git a/README.md b/README.md index d8d717f5780d40b0c0a5d4ebad3b93d5c653d8d2..aacb61725ed65ad568174932febb2bc8b6af56c8 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,12 @@ Please refer to https://github.com/HEP-FCC/FCCSW ## Quick start ``` -$ source /cvmfs/cepcsw.ihep.ac.cn/prototype/setup.sh -$ git clone git@cepcgit.ihep.ac.cn:cepc-prototype/CEPCSW.git +$ source /cvmfs/cepcsw.ihep.ac.cn/prototype/releases/externals/97.0.2/setup.sh +$ git clone git@github.com:cepc/CEPCSW.git $ cd CEPCSW +$ git checkout lcg97 $ mkdir build && cd build -$ cmake .. +$ cmake .. -DHOST_BINARY_TAG=${BINARY_TAG} $ make $ ./run gaudirun.py '$EXAMPLESROOT/options/helloalg.py' ``` diff --git a/Reconstruction/Digi_Calo/CMakeLists.txt b/Reconstruction/Digi_Calo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..507720ca40cd718c485744ef5e95e68c0c674bd8 --- /dev/null +++ b/Reconstruction/Digi_Calo/CMakeLists.txt @@ -0,0 +1,25 @@ +gaudi_subdir(Digi_Calo v0r0) + +find_package(DD4hep COMPONENTS DDG4 REQUIRED) +find_package(EDM4HEP REQUIRED ) +message("EDM4HEP_INCLUDE_DIRS: ${EDM4HEP_INCLUDE_DIR}") +message("EDM4HEP_LIB: ${EDM4HEP_LIBRARIES}") +include_directories(${EDM4HEP_INCLUDE_DIR}) + +find_package(CLHEP REQUIRED) +find_package(podio REQUIRED ) + +set(srcs + src/*.cpp +) + +gaudi_depends_on_subdirs( + Detector/DetInterface +) +## Modules +gaudi_add_module(Digi_Calo ${srcs} + INCLUDE_DIRS FWCore GaudiKernel GaudiAlgLib CLHEP DD4hep + LINK_LIBRARIES FWCore GaudiKernel GaudiAlgLib CLHEP DD4hep ${DD4hep_COMPONENT_LIBRARIES} DDRec + -Wl,--no-as-needed + EDM4HEP::edm4hep EDM4HEP::edm4hepDict +) diff --git a/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp b/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93e2fb35c0fa217382f588947fb6ce7db60d0f90 --- /dev/null +++ b/Reconstruction/Digi_Calo/src/CaloDigiAlg.cpp @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#include "CaloDigiAlg.h" + + +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/Vector3f.h" + +#include "DD4hep/Detector.h" +#include <DD4hep/Objects.h> + + +#include <math.h> +#include <cmath> +#include <algorithm> + +DECLARE_COMPONENT( CaloDigiAlg ) + +CaloDigiAlg::CaloDigiAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc), + _nEvt(0) +{ + + // Input collections + declareProperty("SimCaloHitCollection", r_SimCaloCol, "Handle of the Input SimCaloHit collection"); + + // Output collections + declareProperty("CaloHitCollection", w_DigiCaloCol, "Handle of Digi CaloHit collection"); + + declareProperty("CaloAssociationCollection", w_CaloAssociationCol, "Handle of CaloAssociation collection"); + +} + +StatusCode CaloDigiAlg::initialize() +{ + + std::cout<<"CaloDigiAlg::m_scale="<<m_scale<<std::endl; + m_geosvc = service<IGeoSvc>("GeoSvc"); + if ( !m_geosvc ) throw "CaloDigiAlg :Failed to find GeoSvc ..."; + dd4hep::Detector* m_dd4hep = m_geosvc->lcdd(); + if ( !m_dd4hep ) throw "CaloDigiAlg :Failed to get dd4hep::Detector ..."; + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + return GaudiAlgorithm::initialize(); +} + +StatusCode CaloDigiAlg::execute() +{ + std::map<unsigned long long, edm4hep::SimCalorimeterHit> id_hit_map; + std::map<unsigned long long, std::vector<edm4hep::SimCalorimeterHit> > id_hits_map; + edm4hep::CalorimeterHitCollection* caloVec = w_DigiCaloCol.createAndPut(); + edm4hep::MCRecoCaloAssociationCollection* caloAssoVec = w_CaloAssociationCol.createAndPut(); + const edm4hep::SimCalorimeterHitCollection* SimHitCol = r_SimCaloCol.get(); + double tot_e = 0 ; + if(SimHitCol == 0) + { + std::cout<<"not found SimCalorimeterHitCollection"<< std::endl; + return StatusCode::SUCCESS; + } + std::cout<<"digi, input sim hit size="<< SimHitCol->size() <<std::endl; + for( int i = 0; i < SimHitCol->size(); i++ ) + { + edm4hep::SimCalorimeterHit SimHit = SimHitCol->at(i); + unsigned long long id = SimHit.getCellID(); + float en = SimHit.getEnergy(); + tot_e += en; + if ( id_hit_map.find(id) != id_hit_map.end()) id_hit_map[id].setEnergy(id_hit_map[id].getEnergy() + en); + else id_hit_map[id] = SimHit ; + + if ( id_hits_map.find(id) != id_hits_map.end()) id_hits_map[id].push_back(SimHit); + else + { + std::vector<edm4hep::SimCalorimeterHit> vhit; + vhit.push_back(SimHit); + id_hits_map[id] = vhit ; + } + } + for(std::map<unsigned long long, edm4hep::SimCalorimeterHit>::iterator iter = id_hit_map.begin(); iter != id_hit_map.end(); iter++) + { + auto caloHit = caloVec->create(); + caloHit.setCellID((iter->second).getCellID()); + caloHit.setEnergy((iter->second).getEnergy()*m_scale); + dd4hep::Position position = m_cellIDConverter->position(caloHit.getCellID()); + edm4hep::Vector3f vpos(position.x()*10, position.y()*10, position.z()*10);// cm to mm + caloHit.setPosition(vpos); + //std::cout << "sim hit id =" << caloHit.getCellID() <<",x="<<position.x()<<",y="<<position.y()<<",z="<<position.z() <<",real x="<<(iter->second).getPosition().x <<",y="<<(iter->second).getPosition().y<<",z="<<(iter->second).getPosition().z<< std::endl; + + if( id_hits_map.find(iter->first) != id_hits_map.end()) + { + for(unsigned int i=0; i< id_hits_map[iter->first].size(); i++) + { + auto asso = caloAssoVec->create(); + asso.setRec(caloHit); + asso.setSim(id_hits_map[iter->first].at(i)); + asso.setWeight(id_hits_map[iter->first].at(i).getEnergy()/(iter->second).getEnergy()); + } + } + else std::cout<<"Error in Digi Calo"<<std::endl; + } + + std::cout<<"total sim e ="<< tot_e <<std::endl; + std::cout<<"digi, output digi hit size="<< caloVec->size() <<std::endl; + std::cout<<"digi, output caloAssoVec hit size="<< caloAssoVec->size() <<std::endl; + _nEvt ++ ; + + return StatusCode::SUCCESS; +} + +StatusCode CaloDigiAlg::finalize() +{ + info() << "Processed " << _nEvt << " events " << endmsg; + return GaudiAlgorithm::finalize(); +} diff --git a/Reconstruction/Digi_Calo/src/CaloDigiAlg.h b/Reconstruction/Digi_Calo/src/CaloDigiAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..c1a82c8867450cf7335dce74d4743d0e7e9b374e --- /dev/null +++ b/Reconstruction/Digi_Calo/src/CaloDigiAlg.h @@ -0,0 +1,58 @@ +#ifndef Calo_DIGI_ALG_H +#define Calo_DIGI_ALG_H + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include "edm4hep/SimCalorimeterHitConst.h" +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CalorimeterHit.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "edm4hep/MCRecoCaloAssociationCollection.h" + +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> +#include "DetInterface/IGeoSvc.h" + + + + +class CaloDigiAlg : public GaudiAlgorithm +{ + +public: + + CaloDigiAlg(const std::string& name, ISvcLocator* svcLoc); + + /** Called at the begin of the job before anything is read. + * Use to initialize the processor, e.g. book histograms. + */ + virtual StatusCode initialize() ; + + /** Called for every event - the working horse. + */ + virtual StatusCode execute() ; + + /** Called after data processing for clean up. + */ + virtual StatusCode finalize() ; + +protected: + + SmartIF<IGeoSvc> m_geosvc; + typedef std::vector<float> FloatVec; + + int _nEvt ; + float m_length; + dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; + + Gaudi::Property<float> m_scale{ this, "Scale", 1 }; + + // Input collections + DataHandle<edm4hep::SimCalorimeterHitCollection> r_SimCaloCol{"SimCaloCol", Gaudi::DataHandle::Reader, this}; + // Output collections + DataHandle<edm4hep::CalorimeterHitCollection> w_DigiCaloCol{"DigiCaloCol", Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCRecoCaloAssociationCollection> w_CaloAssociationCol{"MCRecoCaloAssociationCollection", Gaudi::DataHandle::Writer, this}; +}; + +#endif diff --git a/Reconstruction/Digitisers/CMakeLists.txt b/Reconstruction/Digitisers/CMakeLists.txt index b025fbcb4e2423afe6e98b1137e0086fa1b53808..56952b161a470fb392408a69fa0e50f740258e6b 100644 --- a/Reconstruction/Digitisers/CMakeLists.txt +++ b/Reconstruction/Digitisers/CMakeLists.txt @@ -4,18 +4,20 @@ find_package(CLHEP REQUIRED) find_package(GEAR REQUIRED) find_package(GSL REQUIRED ) find_package(LCIO REQUIRED ) +find_package(podio REQUIRED ) +find_package(K4FWCore REQUIRED) gaudi_depends_on_subdirs( Service/GearSvc Service/EventSeeder ) -set(Digitisers_srcs - src/*.cpp -) +# set(Digitisers_srcs +# src/*.cpp +# ) -# Modules -gaudi_add_module(Digitisers ${Digitisers_srcs} - INCLUDE_DIRS GaudiKernel FWCore CLHEP gear ${plcio_INCLUDE_DIRS} ${GSL_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} - LINK_LIBRARIES GaudiKernel FWCore CLHEP $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} $ENV{PLCIO}/lib/libplcio.so ${LCIO_LIBRARIES} -) +# # Modules +# gaudi_add_module(Digitisers ${Digitisers_srcs} +# INCLUDE_DIRS K4FWCore GaudiKernel GaudiAlgLib CLHEP gear ${plcio_INCLUDE_DIRS} ${GSL_INCLUDE_DIRS} ${LCIO_INCLUDE_DIRS} +# LINK_LIBRARIES K4FWCore GaudiKernel GaudiAlgLib CLHEP $ENV{GEAR}/lib/libgearsurf.so ${GSL_LIBRARIES} $ENV{PLCIO}/lib/libplcio.so ${LCIO_LIBRARIES} +# ) diff --git a/Reconstruction/Digitisers/src/PlanarDigiAlg.h b/Reconstruction/Digitisers/src/PlanarDigiAlg.h index 30386b64b84d2a8b09acc7b78299afceb11951cd..0b7b12b7d59a5b3ac089a4eb28a00089b2046d3c 100644 --- a/Reconstruction/Digitisers/src/PlanarDigiAlg.h +++ b/Reconstruction/Digitisers/src/PlanarDigiAlg.h @@ -44,7 +44,6 @@ class IEventSeeder; class PlanarDigiAlg : public GaudiAlgorithm { - friend class AlgFactory<PlanarDigiAlg>; public: diff --git a/Reconstruction/PFA/Pandora/CED/.cepcenv/01-09-01/status/install.yml b/Reconstruction/PFA/Pandora/CED/.cepcenv/01-09-01/status/install.yml new file mode 100644 index 0000000000000000000000000000000000000000..9f2056abf76bd61b3cbb656e013a5088e599ab26 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/.cepcenv/01-09-01/status/install.yml @@ -0,0 +1,20 @@ +clean: + end: 2018-09-04 10:38:21.535016 + finished: true + start: 2018-09-04 10:38:21.503623 +compile: + end: 2018-09-04 10:38:21.449716 + finished: true + start: 2018-09-04 10:38:07.382890 +download: + end: 2018-09-04 10:35:56.326883 + finished: true + start: 2018-09-04 10:35:55.941740 +extract: + end: 2018-09-04 10:35:56.510664 + finished: true + start: 2018-09-04 10:35:56.368258 +pre_compile: + end: 2018-09-04 10:37:33.127719 + finished: true + start: 2018-09-04 10:37:33.110630 diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced.cc b/Reconstruction/PFA/Pandora/CED/CED/ced.cc new file mode 100644 index 0000000000000000000000000000000000000000..654444652e75bb0c8c5737b6787b4e0481055d67 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced.cc @@ -0,0 +1,382 @@ +/* "C" event display. + * Communications related part. + * +*ik + * Alexey Zhelezov, DESY/ITEP, 2005 */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> + +#include <ced.h> + +//hauke +//#include <stropts.h> +#include <poll.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <netdb.h> +#include <sys/socket.h> /* for AF_INET */ +#include <iostream> + + +//http://www.rhyolite.com/pipermail/dcc/2004/001986.html +#ifndef POLLRDNORM //fg: should be defined in poll.h +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM 0x100 /* Writing now will not block. */ +# define POLLWRBAND 0x200 /* Priority data may be written. */ +#endif +//end hauke + +static int ced_fd=-1; // CED connection socket + +static unsigned short ced_port=7927; // port No of CED (assume localhost) +static char ced_host[30]; + +// Return 0 if can be connected, -1 otherwise. +/*static*/ int ced_connect(void){ + static time_t last_attempt=0; + time_t ct; + struct sockaddr_in addr; + + if(ced_fd>=0){ + return 0; // already connected; + } + time(&ct); + if(ct-last_attempt<5){ + return -1; // don't try reconnect all the time + } + addr.sin_family=AF_INET; + addr.sin_port=htons(ced_port); + addr.sin_addr.s_addr=inet_addr(ced_host); + memset(&addr.sin_zero, 0, sizeof(addr.sin_zero)); //not nessesary because sin_zero is not used! + + ced_fd=socket(PF_INET,SOCK_STREAM,0); + if(connect(ced_fd,(struct sockaddr *)&addr,sizeof(addr)) != 0){ + if(!last_attempt){ + perror("WARNING:CED: can't connect to CED"); + } + time(&last_attempt); + close(ced_fd); + ced_fd=-1; + return -1; + } + fprintf(stderr,"INFO:CED: connected to CED\n"); + return 0; +} + + +typedef struct { + unsigned size; // size of one item in bytes + unsigned char *b; // "body" - data are stored here + // (here is some trick :) + unsigned long count; // number of usefull items + unsigned long alloced; // number of allocated items + ced_draw_cb draw; // draw fucation, NOT used in CED client +} ced_element; + +typedef struct { + ced_element *e; + unsigned e_count; +} ced_event; + +//static ced_event eve = {0,0}; + +static ced_event eve = {0,0}; + +// NOT used in CED client +static ced_event ceve = {0,0}; // current event on screen + +// we reserve this size just before ced_element.b data +#define HDR_SIZE 8 + +unsigned ced_register_element(unsigned item_size,ced_draw_cb draw_func){ + ced_element *pe; + if(!(eve.e_count&0xf)){ + eve.e=(ced_element *) realloc(eve.e,(eve.e_count+0x10)*sizeof(ced_element)); + } + + pe=eve.e+eve.e_count; + memset(pe,0,sizeof(*pe)); + pe->size=item_size; + pe->draw=draw_func; + return eve.e_count++; +} + +static void ced_reset(void){ + unsigned i; + + for(i=0;i<eve.e_count;i++){ + eve.e[i].count=0; + // if( eve.e[i].alloced > 0){ + // eve.e[i].alloced=0; //hauke: 15.12.11 + // //free(eve.e[i].b-HDR_SIZE); + // } + } +} + +static void ced_buf_alloc(ced_element *pe,unsigned count){ + if(!pe->b){ + + //std::cout << "malloc requestet: " << count*pe->size+HDR_SIZE << "bytes" << std::endl; + pe->b=(unsigned char *) malloc(count*pe->size+HDR_SIZE); + //printf("malloc: ask for NEW %lu bytes pointer: %p\n ", count*pe->size+HDR_SIZE, pe->b); //hauke + if(pe->b==NULL){ //hauke + printf("ERROR: malloc failed!\n"); + exit(1); + } + }else{ + //free(pe->b-HDR_SIZE); + //pe->b=(unsigned char *) malloc(count*pe->size+HDR_SIZE); + + //std::cout << "realloc requestet: " << count*pe->size+HDR_SIZE << "bytes" << std::endl; + pe->b=(unsigned char *) realloc(pe->b-HDR_SIZE,count*pe->size+HDR_SIZE); + + //printf("malloc: ask for %lu bytes, pointer: %p\n", count*pe->size+HDR_SIZE,pe->b);//hauke + if(pe->b==NULL){ //hauke + printf("ERROR: malloc failed!\n"); + exit(1); + } + } + pe->b+=HDR_SIZE; + pe->alloced=count; +} + +void *ced_add(unsigned id){ + ced_element *pe; + if(id >= eve.e_count){ + fprintf(stderr,"BUG:CED: attempt to access not registered element\n"); + return 0; + } + pe=eve.e+id; + + if(pe->count==pe->alloced){ + ced_buf_alloc(pe,pe->alloced+256); + } + + return (pe->b+(pe->count++)*pe->size); +} + +static void ced_event_copy(ced_event *trg){ + unsigned i; + ced_element *pe; + //std::cout << "trg->e_count: " << trg->e_count << std::endl; + //std::cout << "eve.e_count: " << eve.e_count << std::endl; + + //eve.e_count = 0; + if(trg->e_count<eve.e_count){ + //free(trg->e); + trg->e=(ced_element*) realloc(trg->e,eve.e_count*sizeof(ced_element)); + + //trg->e=(ced_element*) malloc(eve.e_count*sizeof(ced_element)); + } + + + for(i=0;i<eve.e_count;i++){ + pe=trg->e+i; + if(i<trg->e_count){ + //if(pe->alloced > 0){ + // free(pe->b); + // pe->b=NULL; + // pe->alloced=0; + //} + + + //if(pe->alloced > 0){ + // std::cout << "try to free" << std::endl; + // free(pe->b-HDR_SIZE); + // pe->alloced = 0; + // std::cout << "finished" << std::endl; + //} + + if(pe->alloced<eve.e[i].alloced) { + ced_buf_alloc(pe,eve.e[i].alloced); + //std::cout << "test1 " << std::endl; + } + pe->count=eve.e[i].count; + + }else{ + memcpy(pe,eve.e+i,sizeof(ced_element)); + if(pe->b){ + pe->b=0; + // std::cout << "test2 " << std::endl; + ced_buf_alloc(pe,pe->alloced); + } + } + if(pe->count){ + memcpy(pe->b,eve.e[i].b,pe->count*pe->size); + } + } + trg->e_count=eve.e_count; +} + +void ced_do_draw_event(void){ + unsigned int i,j; + ced_element *pe; + unsigned char *pdata; + for(i=0;i<ceve.e_count;i++){ + //printf("ceve.e_count: %i\n", ceve.e_count); + //for(i=ceve.e_count-1; i >=0;i--){ //quick hack, change order so that the detector is drawn at last + //printf("i = %i\n", i); + + pe=ceve.e+i; + if(!pe->draw) + continue; + for(pdata=pe->b,j=0;j<pe->count;j++,pdata+=pe->size) + (*(pe->draw))(pdata); + } +} + +typedef enum { + DRAW_EVENT=10000 +} MSG_TYPE; + +int ced_process_input(void *data){ + struct _phdr{ + unsigned size; + unsigned type; + unsigned char b[4]; + } *hdr = (_phdr*) data; + unsigned count; + ced_element *pe; + + if(!data){ // new client is connected + ced_reset(); + return 0; + } + + if(hdr->type == DRAW_EVENT){ + ced_event_copy(&ceve); + ced_reset(); + return 1; + } + if(hdr->type>=eve.e_count){ + fprintf(stderr,"WARNING:CED: undefined element type (%u), ignored\n", + hdr->type); + return 0; + } + pe=eve.e+hdr->type; + if((hdr->size-HDR_SIZE)%pe->size){ + fprintf(stderr,"BUG:CED: size alignment is wrong for element %u\n", hdr->type); + return 0; + } + count=(hdr->size-HDR_SIZE)/pe->size; + if(!count) + return 0; + if(count>=pe->alloced) + ced_buf_alloc(pe,count+256); + memcpy(pe->b,hdr->b,count*pe->size); + pe->count=count; + return 0; +} + +void ced_send_event(void){ + struct _phdr{ + int size; + unsigned type; + } *hdr,draw_hdr; + unsigned i,problem=0; + int sent_sum; + char *buf; + int sent; + ced_element *pe; + + if(ced_connect()) + return; + for(i=0;i<eve.e_count && !problem;i++){ + //printf("i=%i\n",i); + pe=eve.e+i; + if(!pe->count) + continue; + + //unsigned hauke; + //printf("size of unsigned %i\n", sizeof(hauke)); + hdr=(struct _phdr *)(pe->b-HDR_SIZE); // !!! HERE is the trick :) + hdr->type=i; + //printf("pe->count %i, pe->size %i\n",pe->count, pe->size); + hdr->size=HDR_SIZE+pe->count*pe->size; + sent_sum=0; + //if(hdr->size > 10000000){printf("U P S! This data set is realy big! (%f kB)(%i counts)\n",(hdr->size)/1024.0,pe->count);} + buf=(char *)hdr; + //printf("hdr->size=%i\n",hdr->size); + while(sent_sum<hdr->size){ + //printf("sent_sum = %i, hdr->size=%i\n",sent_sum,hdr->size); + sent=write(ced_fd,buf+sent_sum,hdr->size-sent_sum); + + //printf("byte: %u\n", buf[sent_sum]); + if(sent<0){ + printf("send < 0\n"); + problem=1; + break; + } + sent_sum+=sent; + } + } + if(!problem){ + draw_hdr.size=HDR_SIZE; + draw_hdr.type=DRAW_EVENT; + if(write(ced_fd,&draw_hdr,HDR_SIZE)!=HDR_SIZE) + problem=1; + } + if(problem){ + perror("WARNING:CED: can't send event, till next time..."); + close(ced_fd); + ced_fd=-1; + } +} + + +//hauke +int ced_selected_id_noblock() { + int id=-1 ; + struct pollfd fds[1]; + fds[0].fd=ced_fd; + fds[0].events = POLLRDNORM | POLLIN; + if(poll(fds,1,0) > 0){ + if(recv(ced_fd, &id, sizeof(int) , 0 ) > 0){ + return id; + }else{ + return -1; + } + }else{ + return -1; + } +} + +int ced_selected_id() { + int id=-1 ; + if(recv(ced_fd, &id, sizeof(int) , 0 ) > 0){ + return id; + }else{ + return -1; + } +} +#include <signal.h> +// API +void ced_client_init(const char *hostname,unsigned short port){ + struct hostent *host = gethostbyname(hostname); + snprintf(ced_host, 30, "%u.%u.%u.%u\n",(unsigned char)host->h_addr[0] ,(unsigned char)host->h_addr[1] ,(unsigned char)host->h_addr[2] ,(unsigned char)host->h_addr[3]); + + + //printf("ip: %s\n", ced_host); + //ced_host=host->h_addr; + ced_port=port; + signal(SIGPIPE,SIG_IGN); +} + +void ced_new_event(void){ + ced_reset(); +} + +void ced_draw_event(void){ + ced_send_event(); + ced_reset(); +} diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced.h b/Reconstruction/PFA/Pandora/CED/CED/ced.h new file mode 100644 index 0000000000000000000000000000000000000000..ccf355c27378db6a22b0bd473aad5b2f2aecb38b --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced.h @@ -0,0 +1,146 @@ +/* "C" event display. + * Main part. + * + * Alexey Zhelezov, DESY/ITEP, 2005 */ + +/* + * This file is internal. It must not be + * included into enduser application. + */ + +#ifndef __CED_H +#define __CED_H + +#include "ced_cli.h" + +//#ifdef __cplusplus +// extern "C" { +//#endif + + +//char trusted_hosts[50]; +//extern static char testchar; + +typedef void (*ced_draw_cb)(void *data); + + +/* + * Register new element type. Order is important! + * Appropriate code must be defined in both + * client and server parts. + * + * item_size - size of one item in bytes. + * draw_func - function to call to draw one item, + * called from ced_do_draw_event() + * not used on client side. + */ +unsigned ced_register_element(unsigned item_size,ced_draw_cb draw_func); + +/* + * To be called from element functions + * on client side. + * Return allocated space for one item + * with size, specified by ced_register_element() + * + * Example: assume struct Dummy { int i; }; is item. + * + * DummyID=ced_register_element(sizeof(struct Dummy),0); + * ... + * struct Dummy *item=(struct Dummy *)ced_add_element(DummyID); + * item->i=0; + * This will add one Dummy item to the event + */ +void *ced_add(unsigned id); + +/* + * To be called in paint function + * + * It calls user defined functions for + * each item of all elements types. + */ +void ced_do_draw_event(void); + +/* + * Server side function. + * Must be used to process all incoming + * messages from client. + * + * It return positive value when + * new event must be drawn. + * + * Example: + * glut_tcp_server(7285,my_process_input) + * + * my_process_input(x){ + * if(ced_process_input(x)>0) + * <do redraw> + */ +int ced_process_input(void *data); + +//------------ +void addLayerDescriptionToMenu(int,char *);//glced.c +void selectFromMenu(int id);//glced.c +void toggleHelpWindow(void);//glced.c +void updateLayerEntryInPopupMenu(int); //glced.c +int buildMenuPopup(void);//glced.c + + +#define VERSION_CONFIG 3 +struct CEDsettings{ + bool trans; //grid or surface view + bool persp; //perspectivic view or flat projection + bool antia; //anti aliasing + bool light; //light source + bool picking_highlight; //marker at picking position + double detector_trans[NUMBER_DETECTOR_LAYER]; + double detector_cut_angle[NUMBER_DETECTOR_LAYER]; + double detector_cut_z[NUMBER_DETECTOR_LAYER]; + bool detector_picking; +// double cut_angle; //deprecated +// double trans_value; //deprecated +// double z_cutting; //deprecated + bool layer[CED_MAX_LAYER]; + bool phi_projection; + bool z_projection; + double view[3]; + double va; //vertical angle of view + double ha; //horionzional angle of view + bool fixed_view; + int win_h; //height of the window (pixel) + int win_w; //wight of the window (pixel) + double zoom; + double fisheye_alpha; + double world_size; + double fisheye_world_size; + double bgcolor[4]; + bool show_axes; + bool fps; + double screenshot_sections; + int font; //size of text (menu, shortcuts, text in ced window) + bool autoshot; // If true, generate screencapture in every new event + int autoshot_scale; // If true, generate screencapture in every new event +}; + +/* +//important: +// - sum of all layers must be smaler than max_layer! +// - number_popup_layer must be smaler than number_data_layer + +#define CED_MAX_LAYER 100 +#define NUMBER_POPUP_LAYER 20 +#define NUMBER_DATA_LAYER 25 +#define NUMBER_DETECTOR_LAYER 20 + + +#define CED_MAX_LAYER_CHAR 400 +*/ + +//------------- + +//#ifdef __cplusplus +// } +//#endif + + + +#endif /* __CED_H */ diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced_cli.cc b/Reconstruction/PFA/Pandora/CED/CED/ced_cli.cc new file mode 100644 index 0000000000000000000000000000000000000000..8c063e12483823a54b7920d92057a2331a5d56e3 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced_cli.cc @@ -0,0 +1,539 @@ +/* "C" event display. + * Client side elements definitions. + * + * Alexey Zhelezov, DESY/ITEP, 2005 */ +#include <string.h> + +#include <ced_cli.h> +#include <ced.h> +#include <stdio.h> +//#include <iostream> + +#include <math.h> + + +/* + * Hit element + */ + +static unsigned HIT_ID=0; + +void ced_hit(float x,float y,float z,unsigned type,unsigned size,unsigned color){ + ced_hit_ID(x,y,z, type & 0xFF,( type >> CED_LAYER_SHIFT ) & 0xFF, size,color, 0); +} + +//deprecated +void ced_hit_ID_old(float x,float y,float z,unsigned type, unsigned size,unsigned color, unsigned lcioID){ + ced_hit_ID(x,y,z,type & 0xFF,(type >> CED_LAYER_SHIFT) & 0xFF,size,color,lcioID); +} + +void ced_hit_ID(float x,float y,float z,unsigned type,unsigned layer, unsigned size,unsigned color, unsigned lcioID){ + CED_Hit *h=(CED_Hit *)ced_add(HIT_ID); + if(!h) + return; + h->p.x=x; + h->p.y=y; + h->p.z=z; + h->type=type; + // if(layer > 255){ //downward compability + // h->layer=layer >> CED_LAYER_SHIFT; + // }else{ + h->layer=layer; + // } + h->size=size; + h->color=color; + h->lcioID=lcioID; +} + +/* + * Line element + */ + +static unsigned LINE_ID=0; + +void ced_line(float x0,float y0,float z0, + float x1,float y1,float z1, + unsigned type, unsigned width,unsigned color){ + ced_line_ID(x0,y0,z0,x1,y1,z1, type, width, color, 0); +} + +void ced_line_ID(float x0,float y0,float z0, + float x1,float y1,float z1, + unsigned layer, unsigned width,unsigned color, unsigned lcioID){ +// //test for picking +// //static int anz; +// float length=(x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) + (z1-z0)*(z1-z0); +// //printf("CEDLINE length: %f\n x0 %f y0 %f z0 %f, x1 %f, y1 %f z1 %f", length, x0, y0, z0, x1, y1, z1); +// +// if(length > 500.0){ +// //std::cout << "devide line (length=" << length << ")" << std::endl; +// ced_line_ID(x0,y0,z0, +// (x1-x0)/2.0+x0,(y1-y0)/2.0+y0,(z1-z0)/2.0+z0, +// layer, width, color, lcioID); +// ced_line_ID( +// (x1-x0)/2.0+x0,(y1-y0)/2.0+y0,(z1-z0)/2.0+z0, +// +// x1,y1,z1, +// layer, width, color, lcioID); +// //todo +// //printf("seperate line %i\n", anz++); +// return; +// +// } + +/* +//test + if( random()%100000 > 99990){ + double size[]={10,100,50}; + double position[]={x0,y0,z0}; + double rotate[] = {20,50,70}; + int color=1; + int lcio_id=5; + int layer=5; + //ced_geobox(size, position, color ); + ced_geobox_ID(size, position, layer, 0xff00ff, 5); + ced_geobox(size, position, color); + + } + +//end test +*/ + + CED_Line *l=(CED_Line *)ced_add(LINE_ID); + if(!l) + return; + l->p0.x=x0; + l->p0.y=y0; + l->p0.z=z0; + l->p1.x=x1; + l->p1.y=y1; + l->p1.z=z1; + if(layer > 255){ //downward compability + l->type=layer >> CED_LAYER_SHIFT; + }else{ + l->type=layer; + } + + //printf("layer pre: %i after: %i\n" , layer, l->type); + +// l->type=type; + l->width=width; + l->color=color; + l->lcioID=lcioID; +} +/* + * GeoCylinder + */ +static unsigned GEOC_ID=0; + +void ced_geocylinder(float d,unsigned sides,float rotate,float z,float shift, + unsigned color){ + CED_GeoCylinder *c=(CED_GeoCylinder *)ced_add(GEOC_ID); + if(!c) + return; + c->d=d; + c->sides=sides; + c->rotate=rotate; + c->z=z; + c->shift=shift; + c->color=color; +} + +/* + * Rotated Geocylinder + * Extension of the cylinder subject to a 3-DOF rotation + * @author: SD + * @date: 26.08.08 + */ +static unsigned GEOCR_ID=0; + +void ced_geocylinder_r(float d, double z, double * center, double * rotate, unsigned sides, + unsigned int color, int layer){ + int iDim; + CED_GeoCylinderR *c=(CED_GeoCylinderR *)ced_add(GEOCR_ID); + if(!c) return; + for (iDim = 0; iDim < 3; iDim ++ ) { + c->center[iDim] = center[iDim]; + c->rotate[iDim] = rotate[iDim]; + } + c->d=d; + c->sides=sides; + c->color=color; + c->z=z; + if(layer > 255){ //downward compability + c->layer=layer >> CED_LAYER_SHIFT; + }else{ + c->layer=layer; + } + + //c->layer=layer; +} + +void ced_geocylinders(unsigned n,CED_GeoCylinder *all){ + CED_GeoCylinder *c; + unsigned i; + for(i=0;i<n;i++){ + c=(CED_GeoCylinder *)ced_add(GEOC_ID); + if(!c) + return; + memcpy(c,all+i,sizeof(CED_GeoCylinder)); + } +} + +static unsigned GEOT_ID=0; + +void ced_geotubes(unsigned n,CED_GeoTube *all){ + CED_GeoTube *c; + unsigned i; + for(i=0;i<n;i++){ + c=(CED_GeoTube *)ced_add(GEOT_ID); + if(!c) + return; + memcpy(c,all+i,sizeof(CED_GeoTube)); + } +} + + +static unsigned GEOB_ID=0; + +void ced_geobox(double * sizes, double * center, unsigned int color ) { + int iDim; + CED_GeoBox * box = (CED_GeoBox*) ced_add(GEOB_ID); + if ( ! box ) return; + for ( iDim = 0; iDim < 3; iDim ++ ) { + box->sizes[iDim] = sizes[iDim]; + box->center[iDim] = center[iDim]; + } + box->color = color; + +} + +void rotate3d(double *vektor, double *rotate){ + //double cords2[3]; + double r_rad[3]={rotate[0]/360*2*3.14159265358979323846, rotate[1]/360*2*3.14159265358979323846, rotate[2]/360*2*3.14159265358979323846}; + double cords1[3] = {vektor[0], vektor[1], vektor[2]}; + + vektor[0] = ( cos(r_rad[1])*cos(r_rad[2]) )*cords1[0] + + (-cos(r_rad[0])*sin(r_rad[2]) + sin(r_rad[0])*sin(r_rad[1])*cos(r_rad[2]) )*cords1[1] + + ( sin(r_rad[0])*sin(r_rad[2]) + cos(r_rad[0])*sin(r_rad[1])*cos(r_rad[2]) )*cords1[2]; + vektor[1] = ( cos(r_rad[1])*sin(r_rad[2]) ) * cords1[0] + + ( cos(r_rad[0])*cos(r_rad[2]) + sin(r_rad[0])*sin(r_rad[1])*sin(r_rad[2])) * cords1[1] + + ( -sin(r_rad[0])*cos(r_rad[2]) + cos(r_rad[0])*sin(r_rad[1])*sin(r_rad[2]) ) * cords1[2]; + vektor[2] = (-sin(r_rad[1])) * cords1[0] + + ( sin(r_rad[0])*cos(r_rad[1])) * cords1[1] + + ( cos(r_rad[0])*cos(r_rad[1])) * cords1[2]; + +} + +void ced_geobox_r_ID(double *size, double *position, double *rotate, unsigned int layer, unsigned int color, unsigned int lcio_id) { + + int i; + double vektor1[3], vektor2[3]; + //unsigned int type = layer; //<< CED_LAYER_SHIFT; + //unsigned int type = layer; + + double cubematrix[12][6] ={ {-1,-1,-1, +1,-1,-1}, + {-1,-1,-1, -1,+1,-1}, + {-1,-1,-1, -1,-1,+1}, + {+1,-1,-1, +1,+1,-1}, + {+1,-1,-1, +1,-1,+1}, + {+1,+1,-1, +1,+1,+1}, + {+1,+1,-1, -1,+1,-1}, + {+1,+1,+1, -1,+1,+1}, + {+1,+1,+1, +1,-1,+1}, + {-1,+1,+1, -1,-1,+1}, + {-1,+1,+1, -1,+1,-1}, + {-1,-1,+1, +1,-1,+1} }; + + for(i=0;i<12;i++){ + vektor1[0] = cubematrix[i][0]*size[0]/2; + vektor1[1] = cubematrix[i][1]*size[1]/2; + vektor1[2] = cubematrix[i][2]*size[2]/2; + + vektor2[0] = cubematrix[i][3]*size[0]/2; + vektor2[1] = cubematrix[i][4]*size[1]/2; + vektor2[2] = cubematrix[i][5]*size[2]/2; + + rotate3d(vektor1,rotate); + rotate3d(vektor2,rotate); + + + ced_line_ID(position[0]+vektor1[0], position[1]+vektor1[1], position[2]+vektor1[2], + position[0]+vektor2[0], position[1]+vektor2[1], position[2]+vektor2[2], + layer, 1,color, lcio_id); + } +} + +void ced_geobox_ID(double *size, double *position, unsigned int layer, unsigned int color, unsigned int lcio_id) { + double rotate[3]={0.0, 0.0, 0.0}; + ced_geobox_r_ID(size, position, rotate, layer, color, lcio_id); +} + + +void ced_geoboxes(unsigned int nBox, CED_GeoBox * allBoxes ) { + + CED_GeoBox * box; + unsigned int iBox; + for ( iBox = 0; iBox < nBox ; iBox++ ) { + box = (CED_GeoBox *) ced_add(GEOB_ID); + if ( ! box ) return; + memcpy( box, allBoxes + iBox, sizeof(CED_GeoBox) ); + } +} + +static unsigned GEOBR_ID=0; + +void ced_geobox_r(double * sizes, double * center, double * rotate, unsigned int color, unsigned int layer) { + int iDim; + CED_GeoBoxR * box = (CED_GeoBoxR*) ced_add(GEOBR_ID); + if ( ! box ) return; + for ( iDim = 0; iDim < 3; iDim ++ ) { + box->sizes[iDim] = sizes[iDim]; + box->center[iDim] = center[iDim]; + box->rotate[iDim] = rotate[iDim]; + } + box->color = color; + + if(layer > 255){ //downward compability + box->layer=layer >> CED_LAYER_SHIFT; + }else{ + box->layer=layer; + } + +// box->layer = layer; +} + +static unsigned GEOBRS_ID=0; + +void ced_geobox_r_solid(double * sizes, double * center, double * rotate, unsigned int color, unsigned int layer) { + int iDim; + CED_GeoBoxR * box = (CED_GeoBoxR*) ced_add(GEOBRS_ID); + if ( ! box ) return; + for ( iDim = 0; iDim < 3; iDim ++ ) { + box->sizes[iDim] = sizes[iDim]; + box->center[iDim] = center[iDim]; + box->rotate[iDim] = rotate[iDim]; + } + box->color = color; + + if(layer > 255){ //downward compability + box->layer=layer >> CED_LAYER_SHIFT; + }else{ + box->layer=layer; + } + +// box->layer = layer; +} + +static unsigned LEGEND_ID=0; + +void ced_legend(float ene_min, float ene_max, unsigned int color_steps, unsigned int ** rgb_matrix, unsigned int ticks, char scale) { + CED_Legend * legend = (CED_Legend*) ced_add(LEGEND_ID); + if ( ! legend ) return; + + legend->ene_min = ene_min; + legend->ene_max = ene_max; + legend->color_steps = color_steps; + legend->ticks = ticks; + legend->scale = scale; + + const unsigned int numberOfColours = 3; + unsigned int i,j; + for (i = 0; i < numberOfColours; i ++ ) { + for (j = 0; j < color_steps; j ++ ) { + legend->rgb_matrix[j][i] = rgb_matrix[j][i]; + } + } +} +//hauke +static unsigned TEXT_ID=0; + +void ced_describe_layer(const char *message, int id) { + //printf("ced_describe layer id=%i text: %s\n", id, message); + + if(id >= CED_MAX_LAYER){ + printf("WARNING: ced_describe_layer: Index out of range!\n"); + return; + } + + CED_TEXT *text = (CED_TEXT*) ced_add(TEXT_ID); + if(!text){ + printf("WARNING: ced_describe_layer: cant register CED_TEXT"); + return; + } + + strncpy(text->text,message,CED_MAX_LAYER_CHAR-1); + text->text[CED_MAX_LAYER_CHAR-1] = 0; + text->id=id; + + //text->x=xCordinate; + //text->y=yCordinate; +} + +/* +static unsigned LAYER_TEXT_ID=0; + +void ced_layer_text(char *message, int id) { + LAYER_TEXT *obj = (LAYER_TEXT*) ced_add(LAYER_TEXT_ID); + if (!obj){ + printf("ced_layer_text FAILED\n"); + return; + } + strncpy(obj->str,message,CED_MAX_LAYER_CHAR-1); + obj->id=id; + //printf("ced_layer_text\n"); +} +*/ + +static unsigned PICKING_TEXT_ID=0; + +void ced_picking_text(const char *message, int id) { + CED_PICKING_TEXT *text = (CED_PICKING_TEXT*) ced_add(PICKING_TEXT_ID); + if(!text){ + printf("WARNING: ced_picking_text: cant register CED_PICKING_TEXT"); + return; + } + + strncpy(text->text,message,999); + text->id=id; + //text->text[CED_MAX_LAYER_CHAR-1] = 0; + //text->id=id; + //text->x=xCordinate; + //text->y=yCordinate; +} +//end hauke + +static unsigned CONER_ID=0; + +void ced_cone_r(float base, float height, double *center, double *rotate, unsigned int layer, float *RGBAcolor) { + ced_cone_r_ID(base,height,center,rotate,layer, RGBAcolor, 0); +} + +void ced_cone_r_ID(float base, float height, double *center, double *rotate, unsigned int layer, float *RGBAcolor, int lcioid) { + CED_ConeR * cone = (CED_ConeR*) ced_add(CONER_ID); + if ( ! cone ) return; + + cone->base = base; + cone->height = height; + + if(layer > 255){ //downward compability + cone->layer=layer >> CED_LAYER_SHIFT; + }else{ + cone->layer=layer; + } + +// cone->layer = layer; + cone->lcioid = lcioid; + + const unsigned int dim = 3; + const unsigned int channel = 4; + unsigned int i, j; + + // ced_line_ID(0,0,0, center[0], center[1], center[2], type, width, RGBAcolor, lcioid); + + //ced_line_ID(center[0], center[1], center[2], rotate[0], rotate[1], rotate[2], layer, 1, RGBAcolor, lcioid); + //printf("CONE: from %f %f %f to %f %f %f\n", center[0], center[1], center[2], rotate[0], rotate[1], rotate[2]); + + for (i = 0; i < dim; i ++ ) { + cone->center[i] = center[i]; + cone->rotate[i] = rotate[i]; + } + for (j = 0; j < channel; j ++ ) { + cone->RGBAcolor[j] = RGBAcolor[j]; + } +} + +static unsigned ELLIPSOID_ID=0; + +void ced_ellipsoid_r(double *size, double *center, double *rotate, unsigned int layer, int color) { + ced_ellipsoid_r_ID(size, center, rotate, layer, color, 0); +} + +void ced_ellipsoid_r_ID(double *size, double *center, double *rotate, unsigned int layer, int color, int lcioID) { + + CED_EllipsoidR * eli = (CED_EllipsoidR*) ced_add(ELLIPSOID_ID); + if ( ! eli ) return; + + const unsigned int dim = 3; + unsigned int i; + for (i = 0; i < dim; i ++ ) { + eli->center[i] = center[i]; + eli->rotate[i] = rotate[i]; + eli->size[i] = size[i]; + } + eli->color = color; + + if(layer > 255){ //downward compability + eli->layer=layer >> CED_LAYER_SHIFT; + }else{ + eli->layer=layer; + } + +// eli->layer = layer; + eli->lcioid = lcioID; +} + +static unsigned CLUELLIPSE_ID=0; + +void ced_cluellipse_r(float radius, float height, float *center, double *rotate, unsigned int layer, int color) { + ced_cluellipse_r_ID(radius, height, center, rotate, layer, color, 0); +} + +void ced_cluellipse_r_ID(float radius, float height, float *center, double *rotate, unsigned int layer, int color, int lcioid) { //hauke + + CED_CluEllipseR * eli = (CED_CluEllipseR*) ced_add(CLUELLIPSE_ID); + if ( ! eli ) return; + + const unsigned int dim = 3; + unsigned int i; + for (i = 0; i < dim; i ++ ) { + eli->center[i] = center[i]; + eli->rotate[i] = rotate[i]; + } + eli->radius = radius; + eli->height = height; + + if(layer > 255){ //downward compability + eli->layer=layer >> CED_LAYER_SHIFT; + }else{ + eli->layer=layer; + } + +// eli->layer = layer; + eli->color = color; + eli->lcioid=lcioid; +} + + +void ced_register_elements(void){ + + //1: + GEOC_ID =ced_register_element(sizeof(CED_GeoCylinder),0); + //2: + GEOCR_ID =ced_register_element(sizeof(CED_GeoCylinderR), 0); + //3: + LINE_ID =ced_register_element(sizeof(CED_Line),0); + //4: + HIT_ID =ced_register_element(sizeof(CED_Hit),0); + //5: + GEOB_ID =ced_register_element(sizeof(CED_GeoBox), 0); + //6: + GEOBR_ID =ced_register_element(sizeof(CED_GeoBoxR), 0); + //7: + GEOBRS_ID =ced_register_element(sizeof(CED_GeoBoxR), 0); + //8: + CONER_ID =ced_register_element(sizeof(CED_ConeR), 0); + //9: + ELLIPSOID_ID =ced_register_element(sizeof(CED_EllipsoidR), 0); + //10: + CLUELLIPSE_ID =ced_register_element(sizeof(CED_CluEllipseR), 0); + //11: + TEXT_ID =ced_register_element(sizeof(CED_TEXT),0); //hauke: the order of this items is important + //12: + LEGEND_ID =ced_register_element(sizeof(CED_Legend), 0); + //13: + GEOT_ID =ced_register_element(sizeof(CED_GeoTube),0); + //14: + PICKING_TEXT_ID =ced_register_element(sizeof(CED_PICKING_TEXT),0); +} + diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced_cli.h b/Reconstruction/PFA/Pandora/CED/CED/ced_cli.h new file mode 100644 index 0000000000000000000000000000000000000000..a92164b00f4aae239918a02e4874c058553d0cb4 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced_cli.h @@ -0,0 +1,432 @@ +/* "C" event display. + * Enduser accessable API. + * + * Alexey Zhelezov, DESY/ITEP, 2005 + */ + +#ifndef __CED_CLI_H +#define __CED_CLI_H + +#include <ced_config.h> + + +//important: +// - sum of all layers must be smaler than max_layer! +// - number_popup_layer must be smaler than number_data_layer + +//#define CED_MAX_LAYER 100 +//#define NUMBER_POPUP_LAYER 20 +//#define NUMBER_DATA_LAYER 25 +//#define NUMBER_DETECTOR_LAYER 20 +// +// +//#define CED_MAX_LAYER_CHAR 400 + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This is the first function to call (before any other). + * + * host - host with CED (must be "localhost") + * port - server port number (let say 7285 :) + * + * NOTE: ced_register_elements() must be called + * separately. + */ +void ced_client_init(const char *host,unsigned short port); + +/* + * Cancel current event output. So, all elements + * queued will be discarded. + * + * Good to call at the begining of every event processing. + */ +void ced_new_event(void); + + +/* + * This function really attempt to display event in CED. + * When CED is not available, this function discard + * current event information. + * + * NOTE: between ced_new_event() and ced_draw_event() + * must be some element creation calls. + */ +void ced_draw_event(void); + +/* + * This function really attempt to display event in CED. + * Unlike ced_draw_event() does not reset the event. + * + * NOTE: between ced_new_event() and ced_draw_event() + * must be some element creation calls. + */ +void ced_send_event(void); + +int ced_selected_id(void); + +//hauke +int ced_selected_id_noblock(void); + + +/********************************************* + * + * The following is elements API. + * + *********************************************/ + +void ced_register_elements(void); + +typedef enum { + CED_TYPE_SHIFT=0x0, + CED_LAYER_SHIFT=0x8 +} CED_TYPE_BITS; + +/* +typedef enum { + CED_TYPE_SHIFT=0x0, + CED_LAYER_SHIFT=0x0 +} CED_TYPE_BITS; +*/ + + +typedef struct { + float x; + float y; + float z; +} CED_Point; + +//class CED_Point{ +// public: +// CED_Point(float _x, float _y, float _z){ +// x=_x; +// y=_y; +// z=_z; +// } +// +// CED_Point(void){ +// } +// float x; +// float y; +// float z; +//}; + + +/* + * Hit element + */ + +typedef enum { + CED_HIT_POINT=0, + CED_HIT_CROSS, + CED_HIT_STAR, + CED_HIT_BOX, + CED_HIT_VXD +} CED_HIT_TYPE; + +typedef struct { + CED_Point p; + unsigned type; // point, star, etc + unsigned layer; //layer + unsigned color; // in ARGB form (so, 0xff0000 is RED) + unsigned size; // size of point/size of cross + unsigned lcioID; // unique id of LICO object +} CED_Hit; + +void ced_hit(float x,float y,float z,unsigned type,unsigned size,unsigned color); + +//to give a bit of downward compatibility +void ced_hit_ID_old(float x,float y,float z,unsigned type, unsigned size,unsigned color, unsigned lcioID); + + +void ced_hit_ID(float x,float y,float z,unsigned type,unsigned layer, unsigned size,unsigned color, unsigned lcioID); + +/* + * Line element + */ + +typedef struct { + CED_Point p0; + CED_Point p1; + unsigned type; // not yet defined... + unsigned width; // not yet defined... + unsigned color; // in ARGB form (so, 0xff0000 is RED) + unsigned lcioID; // unique id of LICO object + +} CED_Line; + +void ced_line(float x0,float y0,float z0, + float x1,float y1,float z1, + unsigned type,unsigned width,unsigned color); +void ced_line_ID(float x0,float y0,float z0, + float x1,float y1,float z1, + unsigned type,unsigned width,unsigned color, unsigned lcioID); + +/* + * GeoCylinder + */ +typedef struct { + float d; // radius + unsigned sides; // poligon order + float rotate; // angle degree + float z; // 1/2 length + float shift; // in z + unsigned color; +} CED_GeoCylinder; + +/* + * GeoTube + */ +typedef struct { + float r_o; // outer radius + float r_i; // inner radius + unsigned edges_o; // edges outer + unsigned edges_i; // edges inner + float rotate_o; // angle degree, rotate outer cylinder + float rotate_i; //rotate inner cylinder + float z; // 1/2 length + float shift; // shift in z + unsigned color; // color + unsigned type; //describes the layer where this element lies + bool classic_inner; //draw the outer detector lines in classic view? + bool classic_outer; //draw the inner detector lines in classic view? +} CED_GeoTube; + + +/** Same as CED_GeoTube but here as C++ struct with contstructor. This is allows + * to dynamically allocate the detector structure (in an std::vector using the constructor) + * without knowing the exact number of detector elements a priori (such as the #layers in the FTD). + * This wasn't poassible with the static allocation using the C type struct. + * ( Used in MArlinCED::drawGearDetector ). + */ +struct CEDGeoTube{ + CEDGeoTube(double r_out, + double r_in, + int edges_out, + int edges_in, + double rotate_out, + double rotate_in, + double zlength, + double zshift, + int col, + int layer, + bool classic_i, + bool classic_o ) : + r_o(r_out), + r_i(r_in), + edges_o(edges_out), + edges_i (edges_in), + rotate_o (rotate_out), + rotate_i (rotate_in), + z( zlength), + shift (zshift), + color (col), + type(layer), + classic_inner(classic_i), + classic_outer(classic_o) {} + float r_o; // outer radius + float r_i; // inner radius + unsigned edges_o; // edges outer + unsigned edges_i; // edges inner + float rotate_o; // angle degree, rotate outer cylinder + float rotate_i; //rotate inner cylinder + float z; // 1/2 length + float shift; // shift in z + unsigned color; // color + unsigned type; //describes the layer where this element lies + bool classic_inner; //draw the outer detector lines in classic view? + bool classic_outer; //draw the inner detector lines in classic view? +} ; + +void ced_geotubes(unsigned n,CED_GeoTube *all); + + +void ced_geocylinder(float d,unsigned sides,float rotate,float z,float shift, + unsigned color); + +void ced_geocylinders(unsigned n,CED_GeoCylinder *all); + +/* + * GeoCylinder rotatable + * @author: S.Daraszewicz (UoE) + * @date: 01.09.09 + */ +typedef struct { + float d; // radius + unsigned sides; // poligon order + float center[3]; // cylinder centre z,y,z + float rotate[3]; // rotation angles wrt x,y,z axis + float z; // length + unsigned color; // colour + unsigned layer; // layer the Cylinder to be displayed onto +} CED_GeoCylinderR; + + +void ced_geocylinder_r(float d, double z, double * center, double * rotate, unsigned sides, + unsigned int color, int layer); + + + /** GeoBox structure + */ + typedef struct { + /** The three box sizes in mm */ + double sizes[3]; + /** position of the center of the box*/ + double center[3]; + /** box color */ + unsigned int color; + } CED_GeoBox; + + /** Send/Draw a box at position center (x,y,z in mm) with lengths along the + * axes specified in sizes. + * + * @author A.Bulgheroni, INFN + */ + void ced_geobox(double * sizes, double * center, unsigned int color ); + void ced_geobox_ID(double *size, double *position, unsigned int layer, unsigned int color, unsigned int lcio_id); + void ced_geobox_r_ID(double *size, double *position, double *rotate, unsigned int layer, unsigned int color, unsigned int lcio_id); + void rotate3d(double *vektor, double *rotate); + + + + /* + * @author A.Bulgheroni, INFN + */ + void ced_geoboxes( unsigned int nBox, CED_GeoBox * allBoxes); + + typedef struct { + /** The three box sizes in mm */ + double sizes[3]; + /** position of the center of the box*/ + double center[3]; + /** box color */ + unsigned int color; + /** rotation angle in degrees */ + double rotate[3]; + /** layer for toggling display */ + unsigned int layer; + } CED_GeoBoxR; + +void ced_geobox_r(double * sizes, double * center, double * rotate, unsigned int color, unsigned int layer); +void ced_geobox_r_solid(double * sizes, double * center, double * rotate, unsigned int color, unsigned int layer); + +//hauke + typedef struct{ + char text[1000]; + int id; + } CED_PICKING_TEXT; + +void ced_picking_text(const char *, int number); + +//-------- + + typedef struct{ + char text[400]; + int id; + } CED_TEXT; + + +void ced_describe_layer(const char *, int); //, int, int); + + + typedef struct{ + char str[400]; + unsigned int id; + } LAYER_TEXT; + +void ced_layer_text(char *, int); +//end hauke + + +/* + * Energy spectrum colour map legend. + * @author: S.Daraszewicz (UoE) + * @date: 01.09.09 + */ + typedef struct { + /** min energy on the legend */ + float ene_max; + /** max energy on the legend */ + float ene_min; + /** number of ticks on the legend */ + unsigned int ticks; + /** spectrum colour steps */ + unsigned int color_steps; + /** spectrum colour matrix */ + unsigned int rgb_matrix[512][3]; //FIX ME: 512 size not changed with color_steps + /** LOG or LIN */ + char scale; + } CED_Legend; + +void ced_legend(float ene_min, float ene_max, unsigned int color_steps, unsigned int ** rgb_matrix, unsigned int ticks, char scale); + + typedef struct { + /** position of the centre of the base */ + double center[3]; + /** rotation matrix */ + double rotate[3]; + /** layer for toggling display */ + unsigned int layer; + /** base radius */ + float base; + /** height */ + float height; + /** RGBA color */ + float RGBAcolor[4]; + unsigned lcioid; //hauke + } CED_ConeR; + + +void ced_cone_r(float base, float height, double *center, double *rotate, unsigned int layer, float *RGBAcolor); +void ced_cone_r_ID(float base, float height, double *center, double *rotate, unsigned int layer, float *RGBAcolor, int lcioid); //hauke + + + typedef struct { + /** position of the centre of the base */ + double center[3]; + /** rotation matrix */ + double rotate[3]; + /** layer for toggling display */ + unsigned int layer; + /** xyz size */ + double size[3]; + /** RGBA color */ + int color; + unsigned lcioid; //hauke + } CED_EllipsoidR; + + +void ced_ellipsoid_r(double *size, double *center, double *rotate, unsigned int layer, int color); +void ced_ellipsoid_r_ID(double *size, double *center, double *rotate, unsigned int layer, int color, int lcioid); //hauke + + + typedef struct { + /** position of the centre of the base */ + double center[3]; + /** rotation matrix */ + double rotate[3]; + /** layer for toggling display */ + unsigned int layer; + /** base radius */ + float radius; + /** half height */ + float height; + /** RGBA color */ + int color; + unsigned lcioid; //hauke + } CED_CluEllipseR; + + +void ced_cluellipse_r(float radius, float height, float *center, double *rotate, unsigned int layer, int color); +void ced_cluellipse_r_ID(float radius, float height, float *center, double *rotate, unsigned int layer, int color, int lcioid); //hauke + + +#ifdef __cplusplus + } +#endif + + +#endif /* __CED_CLI_H */ diff --git a/Reconstruction/PFA/Pandora/CED/CED/ced_config.h b/Reconstruction/PFA/Pandora/CED/CED/ced_config.h new file mode 100644 index 0000000000000000000000000000000000000000..66214eada39ed69548a69765def00a0020f7a637 --- /dev/null +++ b/Reconstruction/PFA/Pandora/CED/CED/ced_config.h @@ -0,0 +1,204 @@ +/********************************************************** +* ced_config.h, CED config file * +* Hauke Hoelbe, DESY, 2011 * +* Headerfile to adapt CED before the build. * +**********************************************************/ + +#ifndef __CED_CONFIG +#define __CED_CONFIG + +#include "ced_cli.h" + + +/********************************************************** +* Handling * +**********************************************************/ +//enable zoom function by right click and pull +#define ZOOM_RIGHT_CLICK 0 + +//time when 2 clicks should be a double click, in 1/1000000 secounds +#define DOUBLE_CLICK_TIME 300000 + +//data layer keys +#define DATALAYER_SHORTKEY_00 '0' +#define DATALAYER_SHORTKEY_01 '1' +#define DATALAYER_SHORTKEY_02 '2' +#define DATALAYER_SHORTKEY_03 '3' +#define DATALAYER_SHORTKEY_04 '4' +#define DATALAYER_SHORTKEY_05 '5' +#define DATALAYER_SHORTKEY_06 '6' +#define DATALAYER_SHORTKEY_07 '7' +#define DATALAYER_SHORTKEY_08 '8' +#define DATALAYER_SHORTKEY_09 '9' +#define DATALAYER_SHORTKEY_10 ')' +#define DATALAYER_SHORTKEY_11 '!' +#define DATALAYER_SHORTKEY_12 '@' +#define DATALAYER_SHORTKEY_13 '#' +#define DATALAYER_SHORTKEY_14 '$' +#define DATALAYER_SHORTKEY_15 '%' +#define DATALAYER_SHORTKEY_16 '^' +#define DATALAYER_SHORTKEY_17 '&' +#define DATALAYER_SHORTKEY_18 '*' +#define DATALAYER_SHORTKEY_19 '(' +#define DATALAYER_SHORTKEY_20 't' +#define DATALAYER_SHORTKEY_21 'y' +#define DATALAYER_SHORTKEY_22 'u' +#define DATALAYER_SHORTKEY_23 'i' +#define DATALAYER_SHORTKEY_24 'o' + +//detector layer keys +#define DETECTORLAYER_SHORTKEY_00 'j' +#define DETECTORLAYER_SHORTKEY_01 'k' +#define DETECTORLAYER_SHORTKEY_02 'l' +#define DETECTORLAYER_SHORTKEY_03 ';' +#define DETECTORLAYER_SHORTKEY_04 '\'' +#define DETECTORLAYER_SHORTKEY_05 'p' +#define DETECTORLAYER_SHORTKEY_06 '[' +#define DETECTORLAYER_SHORTKEY_07 ']' +#define DETECTORLAYER_SHORTKEY_08 '\\' +#define DETECTORLAYER_SHORTKEY_09 'T' +#define DETECTORLAYER_SHORTKEY_10 'Y' +#define DETECTORLAYER_SHORTKEY_11 'U' +#define DETECTORLAYER_SHORTKEY_12 'I' +#define DETECTORLAYER_SHORTKEY_13 'O' +#define DETECTORLAYER_SHORTKEY_14 'P' +#define DETECTORLAYER_SHORTKEY_15 '{' +#define DETECTORLAYER_SHORTKEY_16 '}' +#define DETECTORLAYER_SHORTKEY_17 '|' +#define DETECTORLAYER_SHORTKEY_18 'a' +#define DETECTORLAYER_SHORTKEY_19 'e' + + +/********************************************************** +* Colors and appearance * +**********************************************************/ +//size of the boarder line in filled (new view) of detector components. +#define CED_GEOTUBE_LINE_WIDTH 0.3 + +//maximal transparency of boarder lines +//#define CED_GEOTUBE_LINE_MAX_TRANS 0.2 +#define CED_GEOTUBE_LINE_MAX_TRANS 1.0 + + +//names and values of color apairs in popup menu +#define CED_BGCOLOR_OPTION1_NAME "Gainsboro" +#define CED_BGCOLOR_OPTION1_COLORCODE 0.862745,0.862745,0.862745,0 + +#define CED_BGCOLOR_OPTION2_NAME "Lightgrey" +#define CED_BGCOLOR_OPTION2_COLORCODE 0.827451,0.827451,0.827451,0 + +#define CED_BGCOLOR_OPTION3_NAME "Darkgray" +#define CED_BGCOLOR_OPTION3_COLORCODE 0.662745,0.662745,0.662745,0 + +#define CED_BGCOLOR_OPTION4_NAME "Gray" +#define CED_BGCOLOR_OPTION4_COLORCODE 0.501961,0.501961,0.501961,0 + +#define CED_BGCOLOR_OPTION5_NAME "Silver" +#define CED_BGCOLOR_OPTION5_COLORCODE 0.7529,0.7529,0.7529,0 + +#define CED_BGCOLOR_OPTION6_NAME "Dimgray" +#define CED_BGCOLOR_OPTION6_COLORCODE 0.4118,0.4118,0.4118,0 + +#define CED_BGCOLOR_OPTION7_NAME "Lightsteelblue" +#define CED_BGCOLOR_OPTION7_COLORCODE 0.6902,0.7686 ,0.8706,0 + +#define CED_BGCOLOR_OPTION8_NAME "Steelblue" +#define CED_BGCOLOR_OPTION8_COLORCODE 0.2745,0.5098,0.70588,0 + +#define CED_BGCOLOR_OPTION9_NAME "Seagreen" +#define CED_BGCOLOR_OPTION9_COLORCODE 0.18039,0.54509,0.34117,0 + +#define CED_BGCOLOR_OPTION10_NAME "Orange" +#define CED_BGCOLOR_OPTION10_COLORCODE 1,0.647,0,0 + +#define CED_BGCOLOR_OPTION11_NAME "Yellow" +#define CED_BGCOLOR_OPTION11_COLORCODE 1,1,0,0 + +#define CED_BGCOLOR_OPTION12_NAME "Violett" +#define CED_BGCOLOR_OPTION12_COLORCODE 0.9333,0.5098,0.9333,0 + +#define CED_BGCOLOR_OPTION13_NAME "Black" +#define CED_BGCOLOR_OPTION13_COLORCODE 0,0,0,0 + +#define CED_BGCOLOR_OPTION14_NAME "Blue" +#define CED_BGCOLOR_OPTION14_COLORCODE 0,0.2,0.4,0 + +#define CED_BGCOLOR_OPTION15_NAME "White" +#define CED_BGCOLOR_OPTION15_COLORCODE 1,1,1,0 + + + + +//Color of xyz axes +#define AXES_COLOR 0.2,0.2,0.8 + +//Width of xyz axes +#define AXES_LINE_SIZE 0.5 + + +//Help frame: Frame fill color, and transp +#define HELP_FRAME_FILL_COLOR 0.5,1,1,0.8 + +//Help frame: Frame boarder color and transp +#define HELP_FRAME_BOARDER_COLOR 0.1,0.8,1.0,0.8 + +//Help frame: Frame boarder line width +#define HELP_FRAME_BOARDER_LINE_SIZE 3. + +//Help frame: Text color, and transp +#define HELP_FRAME_TEXT_COLOR 0.0,0.0,0.0 + + + + +/********************************************************** +* Layers * +**********************************************************/ +//number of total number of layers +#define CED_MAX_LAYER 100 + +//number of layers shown in popup menu +#define NUMBER_POPUP_LAYER 20 + +//number of layers reserved for data +#define NUMBER_DATA_LAYER 25 + +//number of layers reserved for detector components +#define NUMBER_DETECTOR_LAYER 20 + +//layer description text: maximal number of chars for one entry +#define CED_MAX_LAYER_CHAR 400 + +/********************************************************** +* Graphics * +**********************************************************/ + +//Camera field of view, in degree +#define CAMERA_FIELD_OF_VIEW 45 + +//Camera min distance (hint: min and max should be close together) +#define CAMERA_MIN_DISTANCE 100 + +//Camera max distance (hint: min and max should be close together) +#define CAMERA_MAX_DISTANCE 50000.0*mm.sf+50000/mm.sf + +//Where the camera stands +#define CAMERA_POSITION 0,0,2000 + + + +//Fisheye alpha factor +#define FISHEYE_ALPHA 1e-3 +#define FISHEYE_ZOOM 8. + +/********************************************************** +* Debug * +**********************************************************/ + +//show pickable points: +//#define DEBUG_PICKING 1 + + + + +#endif diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt b/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..46344f83049f4e45f51d5646fd3d24c142f70402 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/CMakeLists.txt @@ -0,0 +1,56 @@ +gaudi_subdir(GaudiPandora v0r0) + +find_package(CLHEP REQUIRED) +#find_package(GSL REQUIRED )##don't use this, use CEPC LCIO version one , due to the ClusterShape.cc file which is from LCIO +#message("GSL: ${GSL_LIBRARIES} ") +set (gsl_include "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/include") +set (gsl_lib1 "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/lib/libgsl.so") +set (gsl_lib2 "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/lib/libgslcblas.so") +find_package(LCIO REQUIRED ) +find_package(GEAR REQUIRED) +message("ENV GEAR: $ENV{GEAR}") + + +find_package(EDM4HEP REQUIRED ) +include_directories(${EDM4HEP_INCLUDE_DIR}) + +find_package(PandoraSDK REQUIRED ) +include_directories(${PandoraSDK_INCLUDE_DIRS}) +link_libraries(${PandoraSDK_LIBRARIES}) +find_package(LCContent REQUIRED ) +include_directories(${LCContent_INCLUDE_DIRS}) +link_libraries(${LCContent_LIBRARIES}) + + +list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") +find_package(ROOT 5.26.00 REQUIRED COMPONENTS Eve Geom RGL EG) + +#In order to use ClusterShape.cc +include_directories("../CED/CED/") +include_directories("../MarlinUtil/01-08/source/") + +gaudi_depends_on_subdirs( + Service/EventSeeder + Service/GearSvc +) + +set(dir_srcs + src/PandoraPFAlg.cpp + src/MCParticleCreator.cpp + src/GeometryCreator.cpp + src/CaloHitCreator.cpp + src/TrackCreator.cpp + src/PfoCreator.cpp + ../CED/CED/*.cc + ../MarlinUtil/01-08/source/*.cc +) +set(dir_include include) +# Modules +gaudi_add_module(GaudiPandora ${dir_srcs} + INCLUDE_DIRS ${gsl_include} ${dir_include} GaudiKernel FWCore CLHEP ${LCIO_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} gear + LINK_LIBRARIES ${gsl_lib1} ${gsl_lib2} GaudiKernel FWCore CLHEP ROOT ${LCIO_LIBRARIES} $ENV{GEAR}/lib/libgear.so $ENV{GEAR}/lib/libgearxml.so + -Wl,--no-as-needed + EDM4HEP::edm4hep EDM4HEP::edm4hepDict + -Wl,--as-needed + +) diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/CaloHitCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/CaloHitCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..91fd1ccd04f1de4ce7de89d83048171882564ab2 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/CaloHitCreator.h @@ -0,0 +1,254 @@ +/** + * + * @brief Header file for the calo hit creator class. + * + * $Log: $ + */ + +#ifndef CALO_HIT_CREATOR_H +#define CALO_HIT_CREATOR_H 1 + +#include "GaudiKernel/ISvcLocator.h" +#include "edm4hep/CalorimeterHit.h" + +#include "gear/LayerLayout.h" + +#include "Api/PandoraApi.h" + +#include <string> + +typedef std::vector<edm4hep::CalorimeterHit *> CalorimeterHitVector; + +namespace gear { class GearMgr; } + +class CollectionMaps; +/** + * @brief CaloHitCreator class + */ +class CaloHitCreator +{ +public: + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_eCalCaloHitCollections; ///< The ecal calorimeter hit collections + StringVector m_hCalCaloHitCollections; ///< The hcal calorimeter hit collections + StringVector m_lCalCaloHitCollections; ///< The lcal calorimeter hit collections + StringVector m_lHCalCaloHitCollections; ///< The lhcal calorimeter hit collections + StringVector m_muonCaloHitCollections; ///< The muon calorimeter hit collections + + float m_absorberRadLengthECal; ///< The absorber radiation length in the ECal + float m_absorberIntLengthECal; ///< The absorber interaction length in the ECal + float m_absorberRadLengthHCal; ///< The absorber radiation length in the HCal + float m_absorberIntLengthHCal; ///< The absorber interaction length in the HCal + float m_absorberRadLengthOther; ///< The absorber radiation length in other detector regions + float m_absorberIntLengthOther; ///< The absorber interaction length in other detector regions + + float m_eCalToMip; ///< The calibration from deposited ECal energy to mip + float m_hCalToMip; ///< The calibration from deposited HCal energy to mip + float m_muonToMip; ///< The calibration from deposited Muon energy to mip + float m_eCalMipThreshold; ///< Threshold for creating calo hits in the ECal, units mip + float m_hCalMipThreshold; ///< Threshold for creating calo hits in the HCal, units mip + float m_muonMipThreshold; ///< Threshold for creating calo hits in the HCal, units mip + + float m_eCalToEMGeV; ///< The calibration from deposited ECal energy to EM energy + float m_eCalToHadGeVBarrel; ///< The calibration from deposited ECal barrel energy to hadronic energy + float m_eCalToHadGeVEndCap; ///< The calibration from deposited ECal endcap energy to hadronic energy + float m_hCalToEMGeV; ///< The calibration from deposited HCal energy to EM energy + float m_hCalToHadGeV; ///< The calibration from deposited HCal energy to hadronic energy + int m_muonDigitalHits; ///< Muon hits are treated as digital (energy from hit count) + float m_muonHitEnergy; ///< The energy for a digital muon calorimeter hit, units GeV + + float m_maxHCalHitHadronicEnergy; ///< The maximum hadronic energy allowed for a single hcal hit + int m_nOuterSamplingLayers; ///< Number of layers from edge for hit to be flagged as an outer layer hit + float m_layersFromEdgeMaxRearDistance; ///< Maximum number of layers from candidate outer layer hit to rear of detector + + int m_hCalEndCapInnerSymmetryOrder; ///< HCal end cap inner symmetry order (missing from ILD00 gear file) + float m_hCalEndCapInnerPhiCoordinate; ///< HCal end cap inner phi coordinate (missing from ILD00 gear file) + + // For Strip Splitting method and hybrid ECAL. + int m_stripSplittingOn; ///< To use SSA, this should be true (default is false) + int m_useEcalScLayers; ///< To use scintillator layers ~ hybrid ECAL, this should be true (default is false) + float m_eCalSiToMip; ///< The calibration from deposited Si-layer energy to mip + float m_eCalScToMip; ///< The calibration from deposited Sc-layer energy to mip + float m_eCalSiMipThreshold; ///< Threshold for creating calo hits in the Si-layers of ECAL, units mip + float m_eCalScMipThreshold; ///< Threshold for creating calo hits in the Sc-layers of ECAL, units mip + float m_eCalSiToEMGeV; ///< The calibration from deposited Si-layer energy to EM energy + float m_eCalScToEMGeV; ///< The calibration from deposited Sc-layer energy to EM energy + float m_eCalSiToHadGeVBarrel; ///< The calibration from deposited Si-layer energy on the enecaps to hadronic energy + float m_eCalScToHadGeVBarrel; ///< The calibration from deposited Sc-layer energy on the endcaps to hadronic energy + float m_eCalSiToHadGeVEndCap; ///< The calibration from deposited Si-layer energy on the enecaps to hadronic energy + float m_eCalScToHadGeVEndCap; ///< The calibration from deposited Sc-layer energy on the endcaps to hadronic energy + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc, bool encoder_style); + + /** + * @brief Destructor + */ + ~CaloHitCreator(); + + /** + * @brief Create calo hits + * + */ + pandora::StatusCode CreateCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Get the calorimeter hit vector + * + * @return The calorimeter hit vector + */ + const CalorimeterHitVector &GetCalorimeterHitVector() const; + + /** + * @brief Reset the calo hit creator + */ + void Reset(); + +private: + /** + * @brief Create ecal calo hits + * + */ + pandora::StatusCode CreateECalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create hcal calo hits + * + */ + pandora::StatusCode CreateHCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create muon calo hits + * + */ + pandora::StatusCode CreateMuonCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create lcal calo hits + * + */ + pandora::StatusCode CreateLCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create lhcal calo hits + * + */ + pandora::StatusCode CreateLHCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Get common calo hit properties: position, parent address, input energy and time + * + */ + void GetCommonCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const; + + /** + * @brief Get end cap specific calo hit properties: cell size, absorber radiation and interaction lengths, normal vector + * + */ + void GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const; + + /** + * @brief Get barrel specific calo hit properties: cell size, absorber radiation and interaction lengths, normal vector + * + */ + void GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const; + + /** + * @brief Get number of active layers from position of a calo hit to the edge of the detector + * + */ + int GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCaloHit) const; + + /** + * @brief Get the maximum radius of a calo hit in a polygonal detector structure + * + */ + float GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const; + + /** + * @brief Get the layer coding string from the provided cell id encoding string + * + * @param encodingString the cell id encoding string + * + * @return the layer coding string + */ + std::string GetLayerCoding(const std::string &encodingString) const; + + /** + * @brief Get the stave coding string from the provided cell id encoding string + * + * @param encodingString the cell id encoding string + * + * @return the stave coding string + */ + std::string GetStaveCoding(const std::string &encodingString) const; + + const Settings m_settings; ///< The calo hit creator settings + + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create calo hits + + float m_eCalBarrelOuterZ; ///< ECal barrel outer z coordinate + float m_hCalBarrelOuterZ; ///< HCal barrel outer z coordinate + float m_muonBarrelOuterZ; ///< Muon barrel outer z coordinate + float m_coilOuterR; ///< Coil outer r coordinate + + float m_eCalBarrelInnerPhi0; ///< ECal barrel inner phi0 coordinate + unsigned int m_eCalBarrelInnerSymmetry; ///< ECal barrel inner symmetry order + float m_hCalBarrelInnerPhi0; ///< HCal barrel inner phi0 coordinate + unsigned int m_hCalBarrelInnerSymmetry; ///< HCal barrel inner symmetry order + float m_muonBarrelInnerPhi0; ///< Muon barrel inner phi0 coordinate + unsigned int m_muonBarrelInnerSymmetry; ///< Muon barrel inner symmetry order + + float m_hCalEndCapOuterR; ///< HCal endcap outer r coordinate + float m_hCalEndCapOuterZ; ///< HCal endcap outer z coordinate + float m_hCalBarrelOuterR; ///< HCal barrel outer r coordinate + float m_hCalBarrelOuterPhi0; ///< HCal barrel outer phi0 coordinate + unsigned int m_hCalBarrelOuterSymmetry; ///< HCal barrel outer symmetry order + + float m_hCalBarrelLayerThickness; ///< HCal barrel layer thickness + float m_hCalEndCapLayerThickness; ///< HCal endcap layer thickness + + CalorimeterHitVector m_calorimeterHitVector; ///< The calorimeter hit vector + std::string m_encoder_str; + std::string m_encoder_str_MUON ; + std::string m_encoder_str_LCal ; + std::string m_encoder_str_LHCal; + gear::GearMgr* _GEAR; +}; + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline const CalorimeterHitVector &CaloHitCreator::GetCalorimeterHitVector() const +{ + return m_calorimeterHitVector; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline void CaloHitCreator::Reset() +{ + m_calorimeterHitVector.clear(); +} + +#endif // #ifndef CALO_HIT_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/GeometryCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/GeometryCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..bb43d8a0f86a5211485a1e4cb301e3886da941a9 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/GeometryCreator.h @@ -0,0 +1,155 @@ +/** + * + * @brief Header file for the geometry creator class. + * + * $Log: $ + */ + +#ifndef GEOMETRY_CREATOR_H +#define GEOMETRY_CREATOR_H 1 + +#include "Api/PandoraApi.h" + +#include "GaudiKernel/ISvcLocator.h" +namespace gear { class CalorimeterParameters; class GearMgr; } + +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief GeometryCreator class + */ +class GeometryCreator +{ +public: + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + float m_absorberRadLengthECal; ///< The absorber radiation length in the ECal + float m_absorberIntLengthECal; ///< The absorber interaction length in the ECal + float m_absorberRadLengthHCal; ///< The absorber radiation length in the HCal + float m_absorberIntLengthHCal; ///< The absorber interaction length in the HCal + float m_absorberRadLengthOther; ///< The absorber radiation length in other detector regions + float m_absorberIntLengthOther; ///< The absorber interaction length in other detector regions + + int m_eCalEndCapInnerSymmetryOrder; ///< ECal end cap inner symmetry order (missing from ILD gear files) + float m_eCalEndCapInnerPhiCoordinate; ///< ECal end cap inner phi coordinate (missing from ILD gear files) + int m_eCalEndCapOuterSymmetryOrder; ///< ECal end cap outer symmetry order (missing from ILD gear files) + float m_eCalEndCapOuterPhiCoordinate; ///< ECal end cap outer phi coordinate (missing from ILD gear files) + + int m_hCalEndCapInnerSymmetryOrder; ///< HCal end cap inner symmetry order (missing from ILD gear files) + float m_hCalEndCapInnerPhiCoordinate; ///< HCal end cap inner phi coordinate (missing from ILD gear files) + int m_hCalEndCapOuterSymmetryOrder; ///< HCal end cap outer symmetry order (missing from ILD gear files) + float m_hCalEndCapOuterPhiCoordinate; ///< HCal end cap outer phi coordinate (missing from ILD gear files) + + int m_hCalRingInnerSymmetryOrder; ///< HCal ring inner symmetry order (missing from ILD gear files) + float m_hCalRingInnerPhiCoordinate; ///< HCal ring inner phi coordinate (missing from ILD gear files) + int m_hCalRingOuterSymmetryOrder; ///< HCal ring outer symmetry order (missing from ILD gear files) + float m_hCalRingOuterPhiCoordinate; ///< HCal ring outer phi coordinate (missing from ILD gear files) + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + GeometryCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~GeometryCreator(); + + /** + * @brief Create geometry + */ + pandora::StatusCode CreateGeometry(ISvcLocator* svcloc); + +private: + typedef std::map<pandora::SubDetectorType, PandoraApi::Geometry::SubDetector::Parameters> SubDetectorTypeMap; + typedef std::map<std::string, PandoraApi::Geometry::SubDetector::Parameters> SubDetectorNameMap; + + /** + * @brief Set mandatory sub detector parameters + * + * @param subDetectorTypeMap the sub detector type map + */ + void SetMandatorySubDetectorParameters(SubDetectorTypeMap &subDetectorTypeMap) const; + + /** + * @brief Set additional sub detector parameters + * + * @param subDetectorNameMap the sub detector name map (for smaller sub detectors, identified uniquely only by name) + */ + void SetAdditionalSubDetectorParameters(SubDetectorNameMap &subDetectorNameMap) const; + + /** + * @brief Set sub detector parameters to their gear default values + * + * @param inputParameters input parameters, from gear + * @param subDetectorName the sub detector name + * @param subDetectorType the sub detector type + * @param parameters the sub detector parameters + */ + void SetDefaultSubDetectorParameters(const gear::CalorimeterParameters &inputParameters, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const; + + /** + * @brief Set positions of gaps in ILD detector and add information missing from GEAR parameters file + * + * @param subDetectorTypeMap the sub detector type map + * @param subDetectorNameMap the sub detector name map (for smaller sub detectors, identified uniquely only by name) + */ + pandora::StatusCode SetILDSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap, SubDetectorNameMap &subDetectorNameMap) const; + + /** + * @brief Add information missing from GEAR parameters file for ILD SDHCAL detector + * + * @param subDetectorTypeMap the sub detector type map + */ + pandora::StatusCode SetILD_SDHCALSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap) const; + + /** + * @brief Specify positions of hcal barrel box gaps - ILD specific + */ + pandora::StatusCode CreateHCalBarrelBoxGaps() const; + + /** + * @brief Specify positions of hcal end cap box gaps - ILD specific + */ + pandora::StatusCode CreateHCalEndCapBoxGaps() const; + + /** + * @brief Specify positions of hcal barrel concentric polygon gaps - ILD specific + */ + pandora::StatusCode CreateHCalBarrelConcentricGaps() const; + + /** + * @brief Create box gaps at regular positions on polygonal prism, oriented along main z axis - ILD specific + * + * @param symmetryOrder the pandora geometry parameters + * @param phi0 the phi coordinate + * @param innerRadius the inner r coordinate + * @param outerRadius the outer r coordinate + * @param minZ the minimum z coordinate + * @param maxZ the maximum z coordinate + * @param gapWidth the gap width + * @param vertexOffset position offset for vertex that doesn't point back to origin of xy plane + */ + pandora::StatusCode CreateRegularBoxGaps(unsigned int symmetryOrder, float phi0, float innerRadius, float outerRadius, float minZ, + float maxZ, float gapWidth, pandora::CartesianVector vertexOffset = pandora::CartesianVector(0, 0, 0)) const; + + const Settings m_settings; ///< The geometry creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create the geometry + gear::GearMgr* _GEAR; +}; + +#endif // #ifndef GEOMETRY_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/MCParticleCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/MCParticleCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..0926f870b6dc8738a7122f1a412f2ece40077f7a --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/MCParticleCreator.h @@ -0,0 +1,88 @@ +/** + * + * @brief Header file for the mc particle creator class. + * + * $Log: $ + */ + +#ifndef MC_PARTICLE_CREATOR_H +#define MC_PARTICLE_CREATOR_H 1 + +#include "edm4hep/MCParticle.h" +#include "Api/PandoraApi.h" + +#include "CaloHitCreator.h" +#include "TrackCreator.h" +/** + * @brief MCParticleCreator class + */ + +class CollectionMaps; + +class MCParticleCreator +{ +public: + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_mcParticleCollections; ///< The mc particle collections + StringVector m_CaloHitRelationCollections; ///< The SimCaloHit to CaloHit particle relations + StringVector m_TrackRelationCollections; ///< The SimTrackerHit to TrackerHit particle relations + float m_bField; ///< m_bField + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + MCParticleCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~MCParticleCreator(); + + /** + * @brief Create MCParticles + * + */ + pandora::StatusCode CreateMCParticles(const CollectionMaps& collectionMaps ) const; + + /** + * @brief Create Track to mc particle relationships + * + */ + pandora::StatusCode CreateTrackToMCParticleRelationships(const CollectionMaps& collectionMaps, const TrackVector &trackVector) const; + + void Reset(); + /** + * @brief Create calo hit to mc particle relationships + * + */ + pandora::StatusCode CreateCaloHitToMCParticleRelationships(const CollectionMaps& collectionMaps, const CalorimeterHitVector &calorimeterHitVector) const; + +private: + const Settings m_settings; ///< The mc particle creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create the mc particles + const float m_bField; ///< The bfield + std::map<unsigned int, const edm4hep::MCParticle*>* m_id_pMC_map; +}; + +inline void MCParticleCreator::Reset() +{ + m_id_pMC_map->clear(); +} + +#endif // #ifndef MC_PARTICLE_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/PandoraPFAlg.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/PandoraPFAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..0e447790098de21001fb6c07cc3915af81ca8b8a --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/PandoraPFAlg.h @@ -0,0 +1,306 @@ +#ifndef PandoraPFAlg_H +#define PandoraPFAlg_H + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +//#include <gsl/gsl_rng.h> +#include "edm4hep/ClusterCollection.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/VertexCollection.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/MCRecoCaloAssociation.h" +#include "edm4hep/MCRecoTrackerAssociation.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" +#include "edm4hep/MCRecoCaloAssociationCollection.h" +#include "edm4hep/MCRecoParticleAssociation.h" +#include "edm4hep/MCRecoParticleAssociationCollection.h" + +#include "Api/PandoraApi.h" + +#ifdef MONITORING +#include "TApplication.h" +#endif + +#include <iostream> +#include <random> +#include <string> +#include <unistd.h> + + +#include "CaloHitCreator.h" +#include "GeometryCreator.h" +#include "MCParticleCreator.h" +#include "PfoCreator.h" +#include "TrackCreator.h" + +#include "TROOT.h" +#include "TTree.h" +#include "TFile.h" + + +/* PandoraPFAlg ========== <br> + * + */ +namespace pandora {class Pandora;} + + +class CollectionMaps +{ +public: + CollectionMaps(); + void clear(); + std::map<std::string, std::vector<edm4hep::MCParticle> > collectionMap_MC; + std::map<std::string, std::vector<edm4hep::CalorimeterHit> > collectionMap_CaloHit; + std::map<std::string, std::vector<edm4hep::Vertex> > collectionMap_Vertex; + std::map<std::string, std::vector<edm4hep::Track> > collectionMap_Track; + std::map<std::string, std::vector<edm4hep::MCRecoCaloAssociation> > collectionMap_CaloRel; + std::map<std::string, std::vector<edm4hep::MCRecoTrackerAssociation> > collectionMap_TrkRel; +}; + + + +class PandoraPFAlg : public GaudiAlgorithm +{ + +public: + + PandoraPFAlg(const std::string& name, ISvcLocator* svcLoc); + + /** Called at the begin of the job before anything is read. + * Use to initialize the processor, e.g. book histograms. + */ + virtual StatusCode initialize() ; + + /** Called for every event - the working horse. + */ + virtual StatusCode execute() ; + + /** Called after data processing for clean up. + */ + virtual StatusCode finalize() ; + + void FinaliseSteeringParameters(ISvcLocator* svcloc); + pandora::StatusCode RegisterUserComponents() const; + void Reset(); + typedef std::vector<float> FloatVector; + typedef std::vector<std::string> StringVector; + + + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + std::string m_pandoraSettingsXmlFile; ///< The pandora settings xml file + + float m_innerBField; ///< The bfield in the main tracker, ecal and hcal, units Tesla + float m_muonBarrelBField; ///< The bfield in the muon barrel, units Tesla + float m_muonEndCapBField; ///< The bfield in the muon endcap, units Tesla + + FloatVector m_inputEnergyCorrectionPoints; ///< The input energy points for non-linearity energy correction + FloatVector m_outputEnergyCorrectionPoints; ///< The output energy points for non-linearity energy correction + }; + + + /** + * @brief Get address of the pandora instance + * + * @return address of the pandora instance + */ + const pandora::Pandora *GetPandora() const; + StatusCode updateMap(); + StatusCode Ana(); + StatusCode CreateMCRecoParticleAssociation(); +protected: + + typedef std::vector<float> FloatVec; + + int _nEvt ; + + + + Gaudi::Property< std::string > m_PandoraSettingsXmlFile { this, "PandoraSettingsDefault_xml", "/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraSettingsDefault_wx.xml" }; + Gaudi::Property<int> m_NEventsToSkip { this, "NEventsToSkip", 0 }; + + Gaudi::Property< std::vector<std::string> > m_TrackCollections{ this, "TrackCollections", {"MarlinTrkTracks"} }; + Gaudi::Property< std::vector<std::string> > m_ECalCaloHitCollections{ this, "ECalCaloHitCollections", {"ECALBarrel","ECALEndcap","ECALOther"} }; + Gaudi::Property< std::vector<std::string> > m_HCalCaloHitCollections{ this, "HCalCaloHitCollections", {"HCALBarrel","HCALEndcap","HCALOther"} }; + Gaudi::Property< std::vector<std::string> > m_LCalCaloHitCollections{ this, "LCalCaloHitCollections", {"LCAL"} }; + Gaudi::Property< std::vector<std::string> > m_LHCalCaloHitCollections{ this, "LHCalCaloHitCollections", {"LHCAL"} }; + Gaudi::Property< std::vector<std::string> > m_MuonCaloHitCollections{ this, "MuonCaloHitCollections", {"MUON"} }; + Gaudi::Property< std::vector<std::string> > m_MCParticleCollections{ this, "MCParticleCollections", {"MCParticle"} }; + Gaudi::Property< std::vector<std::string> > m_RelCaloHitCollections{ this, "RelCaloHitCollections", {"RelationCaloHit","RelationMuonHit"} }; + Gaudi::Property< std::vector<std::string> > m_RelTrackCollections{ this, "RelTrackCollections", {"MarlinTrkTracksMCTruthLink"} }; + Gaudi::Property< std::vector<std::string> > m_KinkVertexCollections{ this, "KinkVertexCollections", {"KinkVertices"} }; + Gaudi::Property< std::vector<std::string> > m_ProngVertexCollections{ this, "ProngVertexCollections", {"ProngVertices"} }; + Gaudi::Property< std::vector<std::string> > m_SplitVertexCollections{ this, "SplitVertexCollections", {"SplitVertices"} }; + Gaudi::Property< std::vector<std::string> > m_V0VertexCollections{ this, "V0VertexCollections", {"V0Vertices"} }; + Gaudi::Property< std::string > m_ClusterCollectionName { this, "ClusterCollectionName", "PandoraClusters" }; + Gaudi::Property< std::string > m_PFOCollectionName { this, "PFOCollectionName", "PandoraPFOs" }; + Gaudi::Property<float> m_ECalToMipCalibration{ this, "ECalToMipCalibration", 160.0 }; + Gaudi::Property<float> m_HCalToMipCalibration{ this, "HCalToMipCalibration", 34.8 }; + Gaudi::Property<float> m_ECalMipThreshold{ this, "ECalMipThreshold", 0.5 }; + Gaudi::Property<float> m_HCalMipThreshold{ this, "HCalMipThreshold", 0.3 }; + Gaudi::Property<float> m_ECalToEMGeVCalibration{ this, "ECalToEMGeVCalibration", 1.007 }; + Gaudi::Property<float> m_HCalToEMGeVCalibration{ this, "HCalToEMGeVCalibration", 1.007 }; + Gaudi::Property<float> m_ECalToHadGeVCalibrationBarrel{ this, "ECalToHadGeVCalibrationBarrel", 1.12 }; + Gaudi::Property<float> m_ECalToHadGeVCalibrationEndCap{ this, "ECalToHadGeVCalibrationEndCap", 1.12 }; + Gaudi::Property<float> m_HCalToHadGeVCalibration{ this, "HCalToHadGeVCalibration", 1.07 }; + Gaudi::Property<float> m_MuonToMipCalibration{ this, "MuonToMipCalibration", 10.0 }; + Gaudi::Property<int> m_DigitalMuonHits{ this, "DigitalMuonHits", 0 }; + Gaudi::Property<float> m_MaxHCalHitHadronicEnergy{ this, "MaxHCalHitHadronicEnergy", 1.0 }; + Gaudi::Property<int> m_UseOldTrackStateCalculation{ this, "UseOldTrackStateCalculation", 0 }; + + + Gaudi::Property<float> m_AbsorberRadLengthECal{ this, "AbsorberRadLengthECal", 0.2854 }; + Gaudi::Property<float> m_AbsorberIntLengthECal{ this, "AbsorberIntLengthECal", 0.0101 }; + Gaudi::Property<float> m_AbsorberRadLengthHCal{ this, "AbsorberRadLengthHCal", 0.0569 }; + Gaudi::Property<float> m_AbsorberIntLengthHCal{ this, "AbsorberIntLengthHCal", 0.006 }; + Gaudi::Property<float> m_AbsorberRadLengthOther{ this, "AbsorberRadLengthOther", 0.0569 }; + Gaudi::Property<float> m_AbsorberIntLengthOther{ this, "AbsorberIntLengthOther", 0.006 }; + Gaudi::Property< std::string > m_StartVertexCollectionName { this, "StartVertexCollectionName", "PandoraPFANewStartVertices" }; + Gaudi::Property< std::string > m_StartVertexAlgorithmName { this, "StartVertexAlgorithmName", "PandoraPFANew" }; + Gaudi::Property<float> m_EMStochasticTerm{ this, "EMStochasticTerm", 0.17 }; + Gaudi::Property<float> m_HadStochasticTerm{ this, "HadStochasticTerm", 0.6 }; + Gaudi::Property<float> m_EMConstantTerm{ this, "EMConstantTerm", 0.01 }; + Gaudi::Property<float> m_HadConstantTerm{ this, "HadConstantTerm", 0.03 }; + Gaudi::Property<float> m_MuonHitEnergy{ this, "MuonHitEnergy", 0.5 }; + Gaudi::Property<int> m_NOuterSamplingLayers{ this, "NOuterSamplingLayers", 3 }; + Gaudi::Property<float> m_LayersFromEdgeMaxRearDistance{ this, "LayersFromEdgeMaxRearDistance", 250.f }; + Gaudi::Property<float> m_MuonBarrelBField{ this, "MuonBarrelBField", -1.5f }; + Gaudi::Property<float> m_MuonEndCapBField{ this, "MuonEndCapBField", 0.01f }; + Gaudi::Property<int> m_ShouldFormTrackRelationships{ this, "ShouldFormTrackRelationships", 1 }; + Gaudi::Property<int> m_MinTrackHits{ this, "MinTrackHits", 5 }; + Gaudi::Property<int> m_MinFtdTrackHits{ this, "MinFtdTrackHits", 0 }; + Gaudi::Property<int> m_MaxTrackHits{ this, "MaxTrackHits", 5000 }; + Gaudi::Property<float> m_D0TrackCut{ this, "D0TrackCut", 50. }; + Gaudi::Property<float> m_Z0TrackCut{ this, "Z0TrackCut", 50. }; + Gaudi::Property<int> m_UseNonVertexTracks{ this, "UseNonVertexTracks", 1 }; + Gaudi::Property<int> m_UseUnmatchedNonVertexTracks{ this, "UseUnmatchedNonVertexTracks", 0 }; + Gaudi::Property<int> m_UseUnmatchedVertexTracks{ this, "UseUnmatchedVertexTracks", 1 }; + Gaudi::Property<float> m_UnmatchedVertexTrackMaxEnergy{ this, "UnmatchedVertexTrackMaxEnergy", 5. }; + Gaudi::Property<float> m_D0UnmatchedVertexTrackCut{ this, "D0UnmatchedVertexTrackCut", 5. }; + Gaudi::Property<float> m_Z0UnmatchedVertexTrackCut{ this, "Z0UnmatchedVertexTrackCut", 5. }; + Gaudi::Property<float> m_ZCutForNonVertexTracks{ this, "ZCutForNonVertexTracks", 250. }; + Gaudi::Property<int> m_ReachesECalNTpcHits{ this, "ReachesECalNTpcHits", 11 }; + Gaudi::Property<int> m_ReachesECalNFtdHits{ this, "ReachesECalNFtdHits", 4 }; + Gaudi::Property<float> m_ReachesECalTpcOuterDistance{ this, "ReachesECalTpcOuterDistance", -100. }; + Gaudi::Property<int> m_ReachesECalMinFtdLayer{ this, "ReachesECalMinFtdLayer", 9 }; + Gaudi::Property<float> m_ReachesECalTpcZMaxDistance{ this, "ReachesECalTpcZMaxDistance", -50. }; + Gaudi::Property<float> m_ReachesECalFtdZMaxDistance{ this, "ReachesECalFtdZMaxDistance", -1. }; + Gaudi::Property<float> m_CurvatureToMomentumFactor{ this, "CurvatureToMomentumFactor", 0.3 / 2000. }; + Gaudi::Property<float> m_MinTrackECalDistanceFromIp{ this, "MinTrackECalDistanceFromIp", 100. }; + + Gaudi::Property<float> m_MaxTrackSigmaPOverP { this, "MaxTrackSigmaPOverP", 0.15 }; + Gaudi::Property<float> m_MinMomentumForTrackHitChecks { this, "MinMomentumForTrackHitChecks", 1. }; + Gaudi::Property<float> m_TpcMembraneMaxZ { this, "TpcMembraneMaxZ", 10. }; + Gaudi::Property<float> m_MinTpcHitFractionOfExpected { this, "MinTpcHitFractionOfExpected", 0.20 }; + Gaudi::Property<int> m_MinFtdHitsForTpcHitFraction { this, "MinFtdHitsForTpcHitFraction", 2 }; + Gaudi::Property<float> m_MaxTpcInnerRDistance { this, "MaxTpcInnerRDistance", 50.0 }; + Gaudi::Property<int> m_ECalEndCapInnerSymmetryOrder { this, "ECalEndCapInnerSymmetryOrder", 4 }; + Gaudi::Property<float> m_ECalEndCapInnerPhiCoordinate { this, "ECalEndCapInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_ECalEndCapOuterSymmetryOrder { this, "ECalEndCapOuterSymmetryOrder", 8 }; + Gaudi::Property<float> m_ECalEndCapOuterPhiCoordinate { this, "ECalEndCapOuterPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalEndCapInnerSymmetryOrder { this, "HCalEndCapInnerSymmetryOrder", 4 }; + Gaudi::Property<float> m_HCalEndCapInnerPhiCoordinate { this, "HCalEndCapInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalEndCapOuterSymmetryOrder { this, "HCalEndCapOuterSymmetryOrder", 16 }; + Gaudi::Property<float> m_HCalEndCapOuterPhiCoordinate { this, "HCalEndCapOuterPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalRingInnerSymmetryOrder { this, "HCalRingInnerSymmetryOrder", 8 }; + Gaudi::Property<float> m_HCalRingInnerPhiCoordinate { this, "HCalRingInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalRingOuterSymmetryOrder { this, "HCalRingOuterSymmetryOrder", 16 }; + Gaudi::Property<float> m_HCalRingOuterPhiCoordinate { this, "HCalRingOuterPhiCoordinate", 0. }; + Gaudi::Property<bool> m_StripSplittingOn { this, "StripSplittingOn", false }; + Gaudi::Property<bool> m_UseEcalScLayers { this, "UseEcalScLayers", false }; + Gaudi::Property<float> m_ECalSiToMipCalibration { this, "ECalSiToMipCalibration", 1. }; + Gaudi::Property<float> m_ECalScToMipCalibration { this, "ECalScToMipCalibration", 1. }; + Gaudi::Property<float> m_ECalSiMipThreshold { this, "ECalSiMipThreshold", 0. }; + Gaudi::Property<float> m_ECalScMipThreshold { this, "ECalScMipThreshold", 0. }; + Gaudi::Property<float> m_ECalSiToEMGeVCalibration { this, "ECalSiToEMGeVCalibration", 1. }; + Gaudi::Property<float> m_ECalScToEMGeVCalibration { this, "ECalScToEMGeVCalibration", 1. }; + Gaudi::Property<float> m_ECalSiToHadGeVCalibrationEndCap { this, "ECalSiToHadGeVCalibrationEndCap", 1. }; + Gaudi::Property<float> m_ECalScToHadGeVCalibrationEndCap { this, "ECalScToHadGeVCalibrationEndCap", 1. }; + Gaudi::Property<float> m_ECalSiToHadGeVCalibrationBarrel { this, "ECalSiToHadGeVCalibrationBarrel", 1. }; + Gaudi::Property<float> m_ECalScToHadGeVCalibrationBarrel { this, "ECalScToHadGeVCalibrationBarrel", 1. }; + + Gaudi::Property<FloatVector> m_InputEnergyCorrectionPoints { this, "InputEnergyCorrectionPoints", {} }; + Gaudi::Property<FloatVector> m_OutputEnergyCorrectionPoints { this, "OutputEnergyCorrectionPoints", {} }; + + + static pandora::Pandora *m_pPandora; + GeometryCreator *m_pGeometryCreator; ///< The geometry creator + CaloHitCreator *m_pCaloHitCreator; ///< The calo hit creator + TrackCreator *m_pTrackCreator; ///< The track creator + MCParticleCreator *m_pMCParticleCreator; ///< The mc particle creator + PfoCreator *m_pPfoCreator; ///< The pfo creator + + Settings m_settings; ///< The settings for the pandora pfa new algo + CollectionMaps *m_CollectionMaps; ///< The settings for the pandora pfa new algo + GeometryCreator::Settings m_geometryCreatorSettings; ///< The geometry creator settings + TrackCreator::Settings m_trackCreatorSettings; ///< The track creator settings + CaloHitCreator::Settings m_caloHitCreatorSettings; ///< The calo hit creator settings + MCParticleCreator::Settings m_mcParticleCreatorSettings; ///< The mc particle creator settings + PfoCreator::Settings m_pfoCreatorSettings; ///< The pfo creator settings + + std::string m_detectorName; ///< The detector name + unsigned int m_nRun; ///< The run number + unsigned int m_nEvent; ///< The event number + //### For Ana ################# + TFile* m_fout; + TTree* m_tree; + std::vector<int > m_pReco_PID; + std::vector<float> m_pReco_mass; + std::vector<float> m_pReco_energy; + std::vector<float> m_pReco_px; + std::vector<float> m_pReco_py; + std::vector<float> m_pReco_pz; + std::vector<float> m_pReco_charge; + + std::vector<int> m_mc_p_size; + std::vector<int> m_mc_pid ; + std::vector<float> m_mc_mass ; + std::vector<float> m_mc_px ; + std::vector<float> m_mc_py ; + std::vector<float> m_mc_pz ; + std::vector<float> m_mc_charge; + int m_hasConversion; + + Gaudi::Property< std::string > m_AnaOutput{ this, "AnaOutput", "/junofs/users/wxfang/MyGit/CEPCSW/Reconstruction/PFA/Pandora/GaudiPandora/Ana.root" }; + //###################### + + DataHandle<edm4hep::MCParticleCollection> m_mcParCol_r {"MCParticle", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALBarrel_r{"ECALBarrel", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALEndcap_r{"ECALEndcap", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALOther_r {"ECALOther", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALBarrel_r{"HCALBarrel", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALEndcap_r{"HCALEndcap", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALOther_r {"HCALOther", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_MUON_r {"MUON", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_LCAL_r {"LCAL", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_LHCAL_r {"LHCAL", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_BCAL_r {"BCAL", Gaudi::DataHandle::Reader, this}; + + DataHandle<edm4hep::VertexCollection> m_KinkVertices_r {"KinkVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_ProngVertices_r {"ProngVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_SplitVertices_r {"SplitVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_V0Vertices_r {"V0Vertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackCollection> m_MarlinTrkTracks_r {"MarlinTrkTracks",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoCaloAssociationCollection> m_MCRecoCaloAssociation_r {"MCRecoCaloAssociation",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoTrackerAssociationCollection> m_MCRecoTrackerAssociation_r {"MCRecoTrackerAssociation",Gaudi::DataHandle::Reader, this}; + + DataHandle<edm4hep::ClusterCollection> m_ClusterCollection_w {"PandoraClusters",Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::ReconstructedParticleCollection> m_ReconstructedParticleCollection_w {"PandoraPFOs" ,Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::VertexCollection> m_VertexCollection_w {"PandoraPFANewStartVertices",Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCRecoParticleAssociationCollection> m_MCRecoParticleAssociation_w {"pfoMCRecoParticleAssociation",Gaudi::DataHandle::Writer, this}; + +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/PfoCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/PfoCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..7619cd9fb36210b0ee50bf3413d39c18c4a1782f --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/PfoCreator.h @@ -0,0 +1,212 @@ +/** + * @brief Header file for the pfo creator class. + * + * $Log: $ + */ + +#ifndef PFO_CREATOR_H +#define PFO_CREATOR_H 1 + +#include "FWCore/DataHandle.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/ClusterCollection.h" +#include "edm4hep/Cluster.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/ReconstructedParticle.h" +#include "edm4hep/VertexCollection.h" +#include "edm4hep/Vertex.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/Track.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/CalorimeterHit.h" + +#include "ClusterShapes.h" +#include "Api/PandoraApi.h" + +class CollectionMaps; +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief PfoCreator class + */ +class PfoCreator +{ +public: + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + std::string m_clusterCollectionName; ///< The name of the cluster output collection + std::string m_pfoCollectionName; ///< The name of the pfo output collection + std::string m_startVertexCollectionName; ///< The name of the start vertex output collection + std::string m_startVertexAlgName; ///< The name of the algorithm to fill the start vertex output collection + float m_emStochasticTerm; ///< The stochastic term for EM shower energy resolution + float m_hadStochasticTerm; ///< The stochastic term for Hadronic shower energy resolution + float m_emConstantTerm; ///< The constant term for EM shower energy resolution + float m_hadConstantTerm; ///< The constant term for Hadronic shower energy resolution + }; + + /** + * @brief Constructor + * + */ + PfoCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~PfoCreator(); + + /** + * @brief Create particle flow objects + * + */ + pandora::StatusCode CreateParticleFlowObjects(CollectionMaps& collectionMaps, DataHandle<edm4hep::ClusterCollection>& _pClusterCollection, DataHandle<edm4hep::ReconstructedParticleCollection>& _pReconstructedParticleCollection, DataHandle<edm4hep::VertexCollection>& _pStartVertexCollection); + + CollectionMaps* m_collectionMaps; + +private: + /** + * @brief index for the subdetector + */ + enum Index + { + ECAL_INDEX = 0, + HCAL_INDEX = 1, + YOKE_INDEX = 2, + LCAL_INDEX = 3, + LHCAL_INDEX = 4, + BCAL_INDEX = 5 + }; + + /** + * @brief initialise sub detector name strings + * + * @param subDetectorNames to receive the list of sub detector names + */ + void InitialiseSubDetectorNames(pandora::StringVector &subDetectorNames) const; + + /** + * @brief Set sub detector energies for a cluster + * + * @param subDetectorNames the list of sub detector names + * @param pLcioCluster the address of the cluster to be set sub detector energies + * @param pandoraCaloHitList the pandora calorimeter hit list + * @param hitE the vector to receive the energy of hits + * @param hitX the vector to receive the x position of hits + * @param hitY the vector to receive the y position of hits + * @param hitZ the vector to receive the z position of hits + */ + void SetClusterSubDetectorEnergies(const pandora::StringVector &subDetectorNames, edm4hep::Cluster *const pLcioCluster, + const pandora::CaloHitList &pandoraCaloHitList, pandora::FloatVector &hitE, pandora::FloatVector &hitX, pandora::FloatVector &hitY, + pandora::FloatVector &hitZ) const; + + /** + * @brief Set cluster energies and errors + * + * @param pPandoraPfo the address of the pandora pfo + * @param pPandoraCluster the address of the pandora cluster + * @param pLcioCluster the address of the cluster to be set energies and erros + * @param clusterCorrectEnergy a number to receive the cluster correct energy + */ + void SetClusterEnergyAndError(const pandora::ParticleFlowObject *const pPandoraPfo, const pandora::Cluster *const pPandoraCluster, + edm4hep::Cluster *const pLcioCluster, float &clusterCorrectEnergy) const; + + /** + * @brief Set cluster position, errors and other shape info, by calculating culster shape first + * + * @param nHitsInCluster number of hits in cluster + * @param hitE the vector of the energy of hits + * @param hitX the vector of the x position of hits + * @param hitY the vector of the y position of hits + * @param hitZ the vector of the z position of hits + * @param pLcioCluster the cluster to be set positions and errors + * @param clusterPosition a CartesianVector to receive the cluster position + */ + void SetClusterPositionAndError(const unsigned int nHitsInCluster, pandora::FloatVector &hitE, pandora::FloatVector &hitX, + pandora::FloatVector &hitY, pandora::FloatVector &hitZ, edm4hep::Cluster *const pLcioCluster, pandora::CartesianVector &clusterPositionVec) const; + + /** + * @brief Calculate reference point for pfo with tracks + * + * @param pPandoraPfo the address of the pandora pfo + * @param referencePoint a CartesianVector to receive the reference point + */ + pandora::StatusCode CalculateTrackBasedReferencePoint(const pandora::ParticleFlowObject *const pPandoraPfo, pandora::CartesianVector &referencePoint) const; + + /** + * @brief Set reference point of the reconstructed particle + * + * @param referencePoint a CartesianVector of the reference point + * @param pReconstructedParticle the address of the reconstructed particle to be reference point + */ + void SetRecoParticleReferencePoint(const pandora::CartesianVector &referencePoint, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Add tracks to reconstructed particle + * + * @param pPandoraPfo the address of the pandora pfo + * @param pReconstructedParticle the address of the reconstructed particle to be added tracks + */ + void AddTracksToRecoParticle(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Set properties of reconstructed particle from pandora pfo + * + * @param pPandoraPfo the address of the pandora pfo + * @param pReconstructedParticle the address of the reconstructed particle to be set properties + */ + void SetRecoParticlePropertiesFromPFO(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Whether parent and daughter tracks are associated with the same pfo + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated with reconstructed particle + * + * @return boolean + */ + bool IsValidParentTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether sibling tracks are associated with the same pfo + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated with reconstructed particle + * + * @return boolean + */ + bool HasValidSiblingTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether the track is the closest (of those associated with the same pfo) to the interaction point + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated to reconstructed particle + * + * @return boolean + */ + bool IsClosestTrackToIP(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether at least one track sibling track is associated to the reconstructed particle + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated to reconstructed particle + * + * @return boolean + */ + bool AreAnyOtherSiblingsInList(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + const Settings m_settings; ///< The pfo creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object from which to extract the pfos +}; + +#endif // #ifndef PFO_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/TrackCreator.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/TrackCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..de380e3f6d4b921a422ad6414d3d772b0f755820 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/TrackCreator.h @@ -0,0 +1,316 @@ +/** + * @brief Header file for the track creator class. + * + * $Log: $ + */ + +#ifndef TRACK_CREATOR_H +#define TRACK_CREATOR_H 1 + + + + +#include "GaudiKernel/ISvcLocator.h" + +#include "edm4hep/Track.h" +#include "edm4hep/TrackConst.h" +#include "edm4hep/TrackState.h" +#include "edm4hep/ReconstructedParticleConst.h" + +#include "Api/PandoraApi.h" +#include "Objects/Helix.h" + +namespace gear { class GearMgr; } + +class CollectionMaps; + +typedef std::vector<const edm4hep::Track *> TrackVector; +typedef std::set<unsigned int> TrackList; +typedef std::map<edm4hep::ConstTrack, int> TrackToPidMap; +/* +inline LCCollectionVec *newTrkCol(const std::string &name, LCEvent *evt , bool isSubset) +{ + LCCollectionVec* col = new LCCollectionVec( LCIO::TRACK ) ; + + LCFlagImpl hitFlag(0) ; + hitFlag.setBit( LCIO::TRBIT_HITS ) ; + col->setFlag( hitFlag.getFlag() ) ; + evt->addCollection( col , name ) ; + col->setSubset( isSubset ) ; + + return col ; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief TrackCreator class + */ +class TrackCreator +{ +public: + typedef std::vector<double> DoubleVector; + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_trackCollections; ///< The reconstructed track collections + StringVector m_kinkVertexCollections; ///< The kink vertex collections + StringVector m_prongVertexCollections; ///< The prong vertex collections + StringVector m_splitVertexCollections; ///< The split vertex collections + StringVector m_v0VertexCollections; ///< The v0 vertex collections + + StringVector m_prongSplitVertexCollections; ///< Concatenated list of prong and split vertex collections + int m_shouldFormTrackRelationships; ///< Whether to form pandora track relationships using v0 and kink info + + int m_minTrackHits; ///< Track quality cut: the minimum number of track hits + int m_minFtdTrackHits; ///< Track quality cut: the minimum number of FTD track hits for FTD only tracks + int m_maxTrackHits; ///< Track quality cut: the maximum number of track hits + + float m_d0TrackCut; ///< Track d0 cut used to determine whether track can be used to form pfo + float m_z0TrackCut; ///< Track z0 cut used to determine whether track can be used to form pfo + + int m_usingNonVertexTracks; ///< Whether can form pfos from tracks that don't start at vertex + int m_usingUnmatchedNonVertexTracks; ///< Whether can form pfos from unmatched tracks that don't start at vertex + int m_usingUnmatchedVertexTracks; ///< Whether can form pfos from unmatched tracks that start at vertex + float m_unmatchedVertexTrackMaxEnergy; ///< Maximum energy for unmatched vertex track + + float m_d0UnmatchedVertexTrackCut; ///< d0 cut used to determine whether unmatched vertex track can form pfo + float m_z0UnmatchedVertexTrackCut; ///< z0 cut used to determine whether unmatched vertex track can form pfo + float m_zCutForNonVertexTracks; ///< Non vtx track z cut to determine whether track can be used to form pfo + + int m_reachesECalNTpcHits; ///< Minimum number of tpc hits to consider track as reaching ecal + int m_reachesECalNFtdHits; ///< Minimum number of ftd hits to consider track as reaching ecal + float m_reachesECalTpcOuterDistance; ///< Max distance from track to tpc r max to id whether track reaches ecal + int m_reachesECalMinFtdLayer; ///< Min layer in Ftd for tracks to be considered to have reached decal + float m_reachesECalTpcZMaxDistance; ///< Max distance from track to tpc z max to id whether track reaches ecal + float m_reachesECalFtdZMaxDistance; ///< Max distance from track hit to ftd z position to identify ftd hits + float m_curvatureToMomentumFactor; ///< Constant relating track curvature in b field to momentum + + float m_minTrackECalDistanceFromIp; ///< Sanity check on separation between ip and track projected ecal position + float m_maxTrackSigmaPOverP; ///< Track fraction momentum error cut + float m_minMomentumForTrackHitChecks; ///< Min track momentum required to perform final quality checks on number of hits + + float m_tpcMembraneMaxZ; ///< Tpc membrane max z coordinate + float m_maxTpcInnerRDistance; ///< Track cut on distance from tpc inner r to id whether track can form pfo + float m_minTpcHitFractionOfExpected; ///< Minimum fraction of TPC hits compared to expected + int m_minFtdHitsForTpcHitFraction; ///< Minimum number of FTD hits to ignore TPC hit fraction + }; + + /** + * @brief Constructor + * + */ + TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc); + + /** + * @brief Destructor + */ + ~TrackCreator(); + + /** + * @brief Create associations between tracks, V0s, kinks, etc + * + */ + pandora::StatusCode CreateTrackAssociations(const CollectionMaps& collectionMaps); + + /** + * @brief Create tracks, insert user code here + * + */ + pandora::StatusCode CreateTracks(const CollectionMaps& collectionMaps); + + /** + * @brief Get the track vector + * + * @return The track vector + */ + const TrackVector &GetTrackVector() const; + + /** + * @brief Reset the track creator + */ + void Reset(); + +private: + /** + * @brief Extract kink information from specified lcio collections + * + */ + pandora::StatusCode ExtractKinks(const CollectionMaps& collectionMaps); + + /** + * @brief Extract prong and split information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractProngsAndSplits(const EVENT::LCEvent *const pLCEvent); + + /** + * @brief Extract v0 information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractV0s(const EVENT::LCEvent *const pLCEvent); + + /** + * @brief Whether the track vertex conflicts with previously provided relationship information + * + * @param trackVec the vector of tracks associated with the vertex + */ + bool IsConflictingRelationship(const edm4hep::ConstReconstructedParticle &Particle) const; + + /** + * @brief Whether a track is a v0 track + * + * + */ + bool IsV0(unsigned int pTrack_id) const; + + /** + * @brief Whether a track is a parent track + * + * + */ + bool IsParent(unsigned int pTrack_id) const; + + /** + * @brief Whether a track is a daughter track + * + */ + bool IsDaughter(unsigned int pTrack_id) const; + + /** + * @brief Copy track states stored in tracks to pandora track parameters + * + */ + void GetTrackStates(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Copy track state from track state instance to pandora input track state + * + */ + void CopyTrackState(const edm4hep::TrackState & pTrackState, pandora::InputTrackState &inputTrackState) const; + + /** + * @brief Obtain track time when it reaches ECAL + * + */ + float CalculateTrackTimeAtCalorimeter(const edm4hep::Track *const pTrack) const; + + /** + * @brief Decide whether track reaches the ecal surface + * + */ + void TrackReachesECAL(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Determine whether a track can be used to form a pfo under the following conditions: + * 1) if the track proves to be associated with a cluster, OR + * 2) if the track proves to have no cluster associations + * + */ + void DefineTrackPfoUsage(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Whether track passes the quality cuts required in order to be used to form a pfo + * + * + * @return boolean + */ + bool PassesQualityCuts(const edm4hep::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Get number of hits in TPC of a track + * + */ + int GetNTpcHits(const edm4hep::Track *const pTrack) const; + + /** + * @brief Get number of hits in FTD of a track + * + */ + int GetNFtdHits(const edm4hep::Track *const pTrack) const; + + const Settings m_settings; ///< The track creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create tracks and track relationships + + float m_bField; ///< The bfield + + float m_tpcInnerR; ///< The tpc inner radius + float m_tpcOuterR; ///< The tpc outer radius + unsigned int m_tpcMaxRow; ///< The tpc maximum row number + float m_tpcZmax; ///< The tpc maximum z coordinate + float m_cosTpc; ///< Cos(theta) value at end of tpc + + DoubleVector m_ftdInnerRadii; ///< List of ftd inner radii + DoubleVector m_ftdOuterRadii; ///< List of ftd outer radii + DoubleVector m_ftdZPositions; ///< List of ftd z positions + unsigned int m_nFtdLayers; ///< Number of ftd layers + float m_tanLambdaFtd; ///< Tan lambda for first ftd layer + + int m_eCalBarrelInnerSymmetry; ///< ECal barrel inner symmetry order + float m_eCalBarrelInnerPhi0; ///< ECal barrel inner phi 0 + float m_eCalBarrelInnerR; ///< ECal barrel inner radius + float m_eCalEndCapInnerZ; ///< ECal endcap inner z + + float m_minEtdZPosition; ///< Min etd z position + float m_minSetRadius; ///< Min set radius + + TrackVector m_trackVector; ///< The track vector + TrackList m_v0TrackList; ///< The list of v0 tracks + TrackList m_parentTrackList; ///< The list of parent tracks + TrackList m_daughterTrackList; ///< The list of daughter tracks + TrackToPidMap m_trackToPidMap; ///< The map from track addresses to particle ids, where set by kinks/V0s + gear::GearMgr* _GEAR; +}; + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline const TrackVector &TrackCreator::GetTrackVector() const +{ + return m_trackVector; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline void TrackCreator::Reset() +{ + m_trackVector.clear(); + m_v0TrackList.clear(); + m_parentTrackList.clear(); + m_daughterTrackList.clear(); + m_trackToPidMap.clear(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline bool TrackCreator::IsV0(unsigned int pTrack_id) const // should check here, if id is correct one to do this +{ + return (m_v0TrackList.end() != m_v0TrackList.find(pTrack_id)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline bool TrackCreator::IsParent(unsigned int pTrack_id) const +{ + return (m_parentTrackList.end() != m_parentTrackList.find(pTrack_id)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline bool TrackCreator::IsDaughter(unsigned int pTrack_id) const +{ + return (m_daughterTrackList.end() != m_daughterTrackList.find(pTrack_id)); +} + +#endif // #ifndef TRACK_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/Utility.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/Utility.h new file mode 100644 index 0000000000000000000000000000000000000000..0bd75b5d94f4725581e44176a02fbb94a99088fa --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/Utility.h @@ -0,0 +1,6 @@ +#ifndef MYUTILITY +#define MYUTILITY 1 + +#include <sstream> +std::string Convert (float number); +#endif diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/include/cellIDDecoder.h b/Reconstruction/PFA/Pandora/GaudiPandora/include/cellIDDecoder.h new file mode 100644 index 0000000000000000000000000000000000000000..6503f352d754fdac3279dab087abd6a359994145 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/include/cellIDDecoder.h @@ -0,0 +1,120 @@ +#ifndef cellIDDecoder_h +#define cellIDDecoder_h 1 + +#include "EVENT/LCCollection.h" +#include "UTIL/BitField64.h" +#include "lcio.h" +#include <string> + +// fixes problem in gcc 4.0.3 +#include "EVENT/LCParameters.h" + +//##################### changed for EMD4HEP ######## + +namespace ID_UTIL{ + + + /** Convenient class for decoding cellIDs from collection parameter LCIO::CellIDEncoding. + * See UTIL::BitField64 for a description of the encoding string. + * + * @see BitField64 + * @version $Id: CellIDDecoder.h,v 1.9.16.1 2011-03-04 14:09:07 engels Exp $ + */ + template <class T> + class CellIDDecoder { + + public: + + CellIDDecoder() = default ; + CellIDDecoder(const CellIDDecoder& ) = delete ; + CellIDDecoder& operator=(const CellIDDecoder& ) = delete ; + + + /** Constructor takes encoding string as argument. + */ + CellIDDecoder( const std::string& encoder_str ) : _oldHit(0) { + + if( encoder_str.length() == 0 ){ + throw( lcio::Exception( "CellIDDecoder : string of length zero provided as encoder string" ) ) ; + } + _b = new UTIL::BitField64( encoder_str ) ; + + } + + /** Constructor reads encoding string from collection parameter LCIO::CellIDEncoding. + */ + CellIDDecoder( const EVENT::LCCollection* col ) : _oldHit(0) { + + std::string initString("") ; + + if( col !=0 ) + initString = col->getParameters().getStringVal( lcio::LCIO::CellIDEncoding ) ; + + if( initString.size() == 0 ) { + + initString = _defaultEncoding ; + + std::cout << " ----------------------------------------- " << std::endl + << " WARNING: CellIDDecoder - no CellIDEncoding parameter in collection ! " + << std::endl + << " -> using default : \"" << initString << "\"" + << std::endl + << " ------------------------------------------ " + << std::endl ; + } + + _b = new UTIL::BitField64( initString ) ; + } + + ~CellIDDecoder(){ + + delete _b ; + } + + + /** Provides access to the bit fields, e.g. <br> + * int layer = myCellIDEncoding( hit )[ "layer" ] ; + * + */ + inline const UTIL::BitField64 & operator()( const T* hit ){ + + if( hit != _oldHit && hit ) { + auto id = hit->getCellID(); + unsigned int id0 = id&0xFFFFFFFF; + unsigned int id1 = id>>32; + //lcio::long64 val = lcio::long64( hit->getCellID0() & 0xffffffff ) | ( lcio::long64( hit->getCellID1() ) << 32 ) ; + lcio::long64 val = lcio::long64( id0 & 0xffffffff ) | ( lcio::long64( id1 ) << 32 ) ; + + _b->setValue( val ) ; + + _oldHit = hit ; + } + + return *_b ; + } + + + /** This can be used to set the default encoding that is used if no + * CellIDEncoding parameter is set in the collection, e.g. in older lcio files. + */ + static void setDefaultEncoding(const std::string& defaultEncoding ) { + + _defaultEncoding = std::string( defaultEncoding ) ; + } + + protected: + UTIL::BitField64* _b{} ; + const T* _oldHit{NULL} ; + + static std::string _defaultEncoding; + } ; + + template <class T> + std::string CellIDDecoder<T>::_defaultEncoding + = std::string("byte0:8,byte1:8,byte2:8,byte3:8,byte4:8,byte5:8,byte6:8,byte7:8") ; + + +} // namespace +#endif + + diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c7fb1da1bcbc516ee597faf3b04d6f8eec33c4a --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/CaloHitCreator.cpp @@ -0,0 +1,823 @@ +/** + * + * @brief Implementation of the calo hit creator class. + * + * $Log: $ + */ + + +#include "gear/GearParameters.h" +#include "gear/CalorimeterParameters.h" +#include "gear/GearDistanceProperties.h" +#include "gear/GearPointProperties.h" +#include "gear/GEAR.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/LayerLayout.h" + +#include "cellIDDecoder.h" +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" + +#include "PandoraPFAlg.h" +#include "CaloHitCreator.h" + +#include <algorithm> +#include <cmath> +#include <limits> + + +CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc, bool encoder_style) : + m_settings(settings), + m_pPandora(pPandora) +{ + m_encoder_str = ""; + m_encoder_str_MUON = ""; + m_encoder_str_LCal = ""; + m_encoder_str_LHCal = ""; + if(encoder_style==0) // LCIO style + { + m_encoder_str = "M:3,S-1:3,I:9,J:9,K-1:6"; + m_encoder_str_MUON="S-1:4,M:3,K-1:6,I:16,GRZone:3,J:32:16"; + m_encoder_str_LCal="I:10,J:10,K:10,S-1:2"; + m_encoder_str_LHCal=m_encoder_str; + } + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + m_eCalBarrelOuterZ = (_GEAR->getEcalBarrelParameters().getExtent()[3]); + m_hCalBarrelOuterZ = (_GEAR->getHcalBarrelParameters().getExtent()[3]); + m_muonBarrelOuterZ = (_GEAR->getYokeBarrelParameters().getExtent()[3]); + m_coilOuterR = (_GEAR->getGearParameters("CoilParameters").getDoubleVal("Coil_cryostat_outer_radius")); + m_eCalBarrelInnerPhi0 = (_GEAR->getEcalBarrelParameters().getPhi0()); + m_eCalBarrelInnerSymmetry = (_GEAR->getEcalBarrelParameters().getSymmetryOrder()); + m_hCalBarrelInnerPhi0 = (_GEAR->getHcalBarrelParameters().getPhi0()); + m_hCalBarrelInnerSymmetry = (_GEAR->getHcalBarrelParameters().getSymmetryOrder()); + m_muonBarrelInnerPhi0 = (_GEAR->getYokeBarrelParameters().getPhi0()); + m_muonBarrelInnerSymmetry = (_GEAR->getYokeBarrelParameters().getSymmetryOrder()); + m_hCalEndCapOuterR = (_GEAR->getHcalEndcapParameters().getExtent()[1]); + m_hCalEndCapOuterZ = (_GEAR->getHcalEndcapParameters().getExtent()[3]); + m_hCalBarrelOuterR = (_GEAR->getHcalBarrelParameters().getExtent()[1]); + m_hCalBarrelOuterPhi0 =((std::find(_GEAR->getHcalBarrelParameters().getIntKeys().begin(), + _GEAR->getHcalBarrelParameters().getIntKeys().end(), + "Hcal_outer_polygon_phi0") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ? + _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_phi0") + : 0)); + m_hCalBarrelOuterSymmetry = ((std::find(_GEAR->getHcalBarrelParameters().getIntKeys().begin(), + _GEAR->getHcalBarrelParameters().getIntKeys().end(), + "Hcal_outer_polygon_order") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ? + _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_order") + : 0)); + + + const gear::LayerLayout &hCalEndCapLayerLayout(_GEAR->getHcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &hCalBarrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); + m_hCalEndCapLayerThickness = hCalEndCapLayerLayout.getThickness(hCalEndCapLayerLayout.getNLayers() - 1); + m_hCalBarrelLayerThickness = hCalBarrelLayerLayout.getThickness(hCalBarrelLayerLayout.getNLayers() - 1); + if ((m_hCalEndCapLayerThickness < std::numeric_limits<float>::epsilon()) || (m_hCalBarrelLayerThickness < std::numeric_limits<float>::epsilon())) + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +CaloHitCreator::~CaloHitCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateCaloHits(const CollectionMaps& collectionMaps) +{ + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateECalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateMuonCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateLCalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateLHCalCaloHits(collectionMaps)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateECalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_eCalCaloHitCollections.begin(), iterEnd = m_settings.m_eCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getEcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getEcalBarrelParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + const std::string layerCodingString(m_encoder_str); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("CreateECalCaloHits pCaloHit Collection type mismatch"); + + float eCalToMip(m_settings.m_eCalToMip), eCalMipThreshold(m_settings.m_eCalMipThreshold), eCalToEMGeV(m_settings.m_eCalToEMGeV), + eCalToHadGeVBarrel(m_settings.m_eCalToHadGeVBarrel), eCalToHadGeVEndCap(m_settings.m_eCalToHadGeVEndCap); + + // Hybrid ECAL including pure ScECAL. + if (m_settings.m_useEcalScLayers) + { + std::string collectionName(*iter); + std::transform(collectionName.begin(), collectionName.end(), collectionName.begin(), ::tolower); + + if (collectionName.find("ecal", 0) == std::string::npos) + std::cout << "WARNING: mismatching hybrid Ecal collection name. " << collectionName << std::endl; + + if (collectionName.find("si", 0) != std::string::npos) + { + eCalToMip = m_settings.m_eCalSiToMip; + eCalMipThreshold = m_settings.m_eCalSiMipThreshold; + eCalToEMGeV = m_settings.m_eCalSiToEMGeV; + eCalToHadGeVBarrel = m_settings.m_eCalSiToHadGeVBarrel; + eCalToHadGeVEndCap = m_settings.m_eCalSiToHadGeVEndCap; + } + else if (collectionName.find("sc", 0) != std::string::npos) + { + eCalToMip = m_settings.m_eCalScToMip; + eCalMipThreshold = m_settings.m_eCalScMipThreshold; + eCalToEMGeV = m_settings.m_eCalScToEMGeV; + eCalToHadGeVBarrel = m_settings.m_eCalScToHadGeVBarrel; + eCalToHadGeVEndCap = m_settings.m_eCalScToHadGeVEndCap; + } + } + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::ECAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1; + caloHitParameters.m_isInOuterSamplingLayer = false; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + + if (std::fabs(pCaloHit->getPosition()[2]) < m_eCalBarrelOuterZ) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_eCalBarrelInnerSymmetry, m_eCalBarrelInnerPhi0, + cellIdDecoder(pCaloHit)[ staveCoding], caloHitParameters, absorberCorrection); + + caloHitParameters.m_hadronicEnergy = eCalToHadGeVBarrel * pCaloHit->getEnergy(); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + caloHitParameters.m_hadronicEnergy = eCalToHadGeVEndCap * pCaloHit->getEnergy(); + } + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * eCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < eCalMipThreshold) + continue; + + caloHitParameters.m_electromagneticEnergy = eCalToEMGeV * pCaloHit->getEnergy(); + + // ATTN If using strip splitting, must correct cell sizes for use in PFA to minimum of strip width and strip length + if (m_settings.m_stripSplittingOn) + { + const float splitCellSize(std::min(caloHitParameters.m_cellSize0.Get(), caloHitParameters.m_cellSize1.Get())); + caloHitParameters.m_cellSize0 = splitCellSize; + caloHitParameters.m_cellSize1 = splitCellSize; + } + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"Failed to extract ecal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"Failed to extract ecal calo hit" << std::endl; + } + } + } + catch (...) + { + std::cout<< "Failed to extract ecal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateHCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_hCalCaloHitCollections.begin(), iterEnd = m_settings.m_hCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getHcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + const std::string layerCodingString(m_encoder_str); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("CreateHCalCaloHits Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::HCAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers); + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + + if (std::fabs(pCaloHit->getPosition()[2]) < m_hCalBarrelOuterZ) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_hCalBarrelInnerSymmetry, m_hCalBarrelInnerPhi0, + m_hCalBarrelInnerSymmetry - int(cellIdDecoder(pCaloHit)[ staveCoding] / 2), caloHitParameters, absorberCorrection); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + } + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_hCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_hCalMipThreshold) + continue; + + caloHitParameters.m_hadronicEnergy = std::min(m_settings.m_hCalToHadGeV * pCaloHit->getEnergy(), m_settings.m_maxHCalHitHadronicEnergy); + caloHitParameters.m_electromagneticEnergy = m_settings.m_hCalToEMGeV * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract hcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"Failed to extract hcal calo hit" << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract hcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateMuonCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_muonCaloHitCollections.begin(), iterEnd = m_settings.m_muonCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getYokeEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getYokeBarrelParameters().getLayerLayout()); + const gear::LayerLayout &plugLayerLayout(_GEAR->getYokePlugParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_MUON); + const std::string layerCodingString(m_encoder_str_MUON); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("Muon Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::MUON; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1; + caloHitParameters.m_isInOuterSamplingLayer = true; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + const float radius(std::sqrt(pCaloHit->getPosition()[0] * pCaloHit->getPosition()[0] + + pCaloHit->getPosition()[1] * pCaloHit->getPosition()[1])); + + const bool isWithinCoil(radius < m_coilOuterR); + const bool isInBarrelRegion(std::fabs(pCaloHit->getPosition()[2]) < m_muonBarrelOuterZ); + + float absorberCorrection(1.); + + if (isInBarrelRegion && isWithinCoil) + { + this->GetEndCapCaloHitProperties(pCaloHit, plugLayerLayout, caloHitParameters, absorberCorrection); + } + else if (isInBarrelRegion) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_muonBarrelInnerSymmetry, m_muonBarrelInnerPhi0, + cellIdDecoder(pCaloHit)[ staveCoding ], caloHitParameters, absorberCorrection); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + } + + if (m_settings.m_muonDigitalHits > 0) + { + caloHitParameters.m_isDigital = true; + caloHitParameters.m_inputEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_hadronicEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_electromagneticEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_mipEquivalentEnergy = 1.f; + } + else + { + caloHitParameters.m_isDigital = false; + caloHitParameters.m_inputEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_hadronicEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_electromagneticEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_muonToMip; + } + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract muon hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract muon hit" << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract muon hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateLCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_lCalCaloHitCollections.begin(), iterEnd = m_settings.m_lCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getLcalParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LCal); + const std::string layerCodingString(m_encoder_str_LCal); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("LCal Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::ECAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = false; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_eCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_eCalMipThreshold) + continue; + + caloHitParameters.m_electromagneticEnergy = m_settings.m_eCalToEMGeV * pCaloHit->getEnergy(); + caloHitParameters.m_hadronicEnergy = m_settings.m_eCalToHadGeVEndCap * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract lcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract lcal calo hit" << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract lcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateLHCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_lHCalCaloHitCollections.begin(), iterEnd = m_settings.m_lHCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getLHcalParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LHCal); + const std::string layerCodingString(m_encoder_str_LHCal); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("LHCal Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::HCAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers); + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_hCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_hCalMipThreshold) + continue; + + caloHitParameters.m_hadronicEnergy = std::min(m_settings.m_hCalToHadGeV * pCaloHit->getEnergy(), m_settings.m_maxHCalHitHadronicEnergy); + caloHitParameters.m_electromagneticEnergy = m_settings.m_hCalToEMGeV * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract lhcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract lhcal calo hit" << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract lhcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetCommonCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const +{ + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + const pandora::CartesianVector positionVector(pCaloHitPosition[0], pCaloHitPosition[1], pCaloHitPosition[2]); + + caloHitParameters.m_cellGeometry = pandora::RECTANGULAR; + caloHitParameters.m_positionVector = positionVector; + caloHitParameters.m_expectedDirection = positionVector.GetUnitVector(); + caloHitParameters.m_pParentAddress = pCaloHit; + caloHitParameters.m_inputEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_time = pCaloHit->getTime(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::ENDCAP; + + const int physicalLayer(std::min(static_cast<int>(caloHitParameters.m_layer.Get()), layerLayout.getNLayers() - 1)); + caloHitParameters.m_cellSize0 = layerLayout.getCellSize0(physicalLayer); + caloHitParameters.m_cellSize1 = layerLayout.getCellSize1(physicalLayer); + caloHitParameters.m_cellThickness = layerLayout.getThickness(physicalLayer); + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.getAbsorberThickness(physicalLayer)); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING CaloHitCreator::GetEndCapCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.getNLayers(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.getAbsorberThickness(i)); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + + caloHitParameters.m_cellNormalVector = (pCaloHit->getPosition()[2] > 0) ? pandora::CartesianVector(0, 0, 1) : + pandora::CartesianVector(0, 0, -1); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::BARREL; + + const int physicalLayer(std::min(static_cast<int>(caloHitParameters.m_layer.Get()), layerLayout.getNLayers() - 1)); + caloHitParameters.m_cellSize0 = layerLayout.getCellSize0(physicalLayer); + caloHitParameters.m_cellSize1 = layerLayout.getCellSize1(physicalLayer); + caloHitParameters.m_cellThickness = layerLayout.getThickness(physicalLayer); + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.getAbsorberThickness(physicalLayer)); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNIN CaloHitCreator::GetBarrelCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.getNLayers(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.getAbsorberThickness(i)); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + + if (barrelSymmetryOrder > 2) + { + const float phi = barrelPhi0 + (2. * M_PI * static_cast<float>(staveNumber) / static_cast<float>(barrelSymmetryOrder)); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(-std::sin(phi), std::cos(phi), 0); + } + else + { + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + + if (pCaloHitPosition[1] != 0) + { + const float phi = barrelPhi0 + std::atan(pCaloHitPosition[0] / pCaloHitPosition[1]); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(std::sin(phi), std::cos(phi), 0); + } + else + { + caloHitParameters.m_cellNormalVector = (pCaloHitPosition[0] > 0) ? pandora::CartesianVector(1, 0, 0) : + pandora::CartesianVector(-1, 0, 0); + } + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int CaloHitCreator::GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCaloHit) const +{ + // Calo hit coordinate calculations + const float barrelMaximumRadius(this->GetMaximumRadius(pCaloHit, m_hCalBarrelOuterSymmetry, m_hCalBarrelOuterPhi0)); + const float endCapMaximumRadius(this->GetMaximumRadius(pCaloHit, m_settings.m_hCalEndCapInnerSymmetryOrder, m_settings.m_hCalEndCapInnerPhiCoordinate)); + const float caloHitAbsZ(std::fabs(pCaloHit->getPosition()[2])); + + // Distance from radial outer + float radialDistanceToEdge(std::numeric_limits<float>::max()); + + if (caloHitAbsZ < m_eCalBarrelOuterZ) + { + radialDistanceToEdge = (m_hCalBarrelOuterR - barrelMaximumRadius) / m_hCalBarrelLayerThickness; + } + else + { + radialDistanceToEdge = (m_hCalEndCapOuterR - endCapMaximumRadius) / m_hCalEndCapLayerThickness; + } + + // Distance from rear of endcap outer + float rearDistanceToEdge(std::numeric_limits<float>::max()); + + if (caloHitAbsZ >= m_eCalBarrelOuterZ) + { + rearDistanceToEdge = (m_hCalEndCapOuterZ - caloHitAbsZ) / m_hCalEndCapLayerThickness; + } + else + { + const float rearDistance((m_eCalBarrelOuterZ - caloHitAbsZ) / m_hCalBarrelLayerThickness); + + if (rearDistance < m_settings.m_layersFromEdgeMaxRearDistance) + { + const float overlapDistance((m_hCalEndCapOuterR - endCapMaximumRadius) / m_hCalEndCapLayerThickness); + rearDistanceToEdge = std::max(rearDistance, overlapDistance); + } + } + + return static_cast<int>(std::min(radialDistanceToEdge, rearDistanceToEdge)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +float CaloHitCreator::GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const +{ + + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + if (symmetryOrder <= 2) + return std::sqrt((pCaloHitPosition[0] * pCaloHitPosition[0]) + (pCaloHitPosition[1] * pCaloHitPosition[1])); + + float maximumRadius(0.f); + const float twoPi(2.f * M_PI); + + for (unsigned int i = 0; i < symmetryOrder; ++i) + { + const float phi = phi0 + i * twoPi / static_cast<float>(symmetryOrder); + float radius = pCaloHitPosition[0] * std::cos(phi) + pCaloHitPosition[1] * std::sin(phi); + + if (radius > maximumRadius) + maximumRadius = radius; + } + + return maximumRadius; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +std::string CaloHitCreator::GetLayerCoding(const std::string &encodingString) const +{ + if (encodingString.find("layer") != std::string::npos) + return std::string("layer"); + + if (encodingString.find("K-1") != std::string::npos) + return std::string("K-1"); + + if (encodingString.find("K") != std::string::npos) + return std::string("K"); + + return std::string("unknown_layer_encoding"); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +std::string CaloHitCreator::GetStaveCoding(const std::string &encodingString) const +{ + if (encodingString.find("stave") != std::string::npos) + return std::string("stave"); + + if (encodingString.find("S-1") != std::string::npos) + return std::string("S-1"); + + return std::string("unknown_stave_encoding") ; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +CaloHitCreator::Settings::Settings() : + m_absorberRadLengthECal(1.f), + m_absorberIntLengthECal(1.f), + m_absorberRadLengthHCal(1.f), + m_absorberIntLengthHCal(1.f), + m_absorberRadLengthOther(1.f), + m_absorberIntLengthOther(1.f), + m_eCalToMip(1.f), + m_hCalToMip(1.f), + m_muonToMip(1.f), + m_eCalMipThreshold(0.f), + m_hCalMipThreshold(0.f), + m_muonMipThreshold(0.f), + m_eCalToEMGeV(1.f), + m_eCalToHadGeVBarrel(1.f), + m_eCalToHadGeVEndCap(1.f), + m_hCalToEMGeV(1.f), + m_hCalToHadGeV(1.f), + m_muonDigitalHits(1), + m_muonHitEnergy(0.5f), + m_maxHCalHitHadronicEnergy(10000.f), + m_nOuterSamplingLayers(3), + m_layersFromEdgeMaxRearDistance(250.f), + m_hCalEndCapInnerSymmetryOrder(4), + m_hCalEndCapInnerPhiCoordinate(0.f), + m_stripSplittingOn(0), + m_useEcalScLayers(0), + m_eCalSiToMip(1.f), + m_eCalScToMip(1.f), + m_eCalSiMipThreshold(0.f), + m_eCalScMipThreshold(0.f), + m_eCalSiToEMGeV(1.f), + m_eCalScToEMGeV(1.f), + m_eCalSiToHadGeVBarrel(1.f), + m_eCalScToHadGeVBarrel(1.f), + m_eCalSiToHadGeVEndCap(1.f), + m_eCalScToHadGeVEndCap(1.f) +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/GeometryCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/GeometryCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c88f7ba826fcf806b9a25f253cf51e06d1a92e2 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/GeometryCreator.cpp @@ -0,0 +1,420 @@ +/** + * + * @brief Implementation of the geometry creator class. + * + * $Log: $ + */ +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" +#include "gear/BField.h" +#include "gear/GEAR.h" +#include "gear/GearParameters.h" +#include "gear/CalorimeterParameters.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/LayerLayout.h" +#include "GeometryCreator.h" + +GeometryCreator::GeometryCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora) +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +GeometryCreator::~GeometryCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateGeometry(ISvcLocator* svcloc) +{ + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + try + { + SubDetectorTypeMap subDetectorTypeMap; + this->SetMandatorySubDetectorParameters(subDetectorTypeMap); + + SubDetectorNameMap subDetectorNameMap; + this->SetAdditionalSubDetectorParameters(subDetectorNameMap); + + if (std::string::npos != _GEAR->getDetectorName().find("ILD")) + this->SetILDSpecificGeometry(subDetectorTypeMap, subDetectorNameMap); + + for (SubDetectorTypeMap::const_iterator iter = subDetectorTypeMap.begin(), iterEnd = subDetectorTypeMap.end(); iter != iterEnd; ++iter) + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::SubDetector::Create(*m_pPandora, iter->second)); + + for (SubDetectorNameMap::const_iterator iter = subDetectorNameMap.begin(), iterEnd = subDetectorNameMap.end(); iter != iterEnd; ++iter) + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::SubDetector::Create(*m_pPandora, iter->second)); + } + catch (gear::Exception &exception) + { + std::cout << "Failure in marlin pandora geometry creator, gear exception: " << exception.what() << std::endl; + throw exception; + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetMandatorySubDetectorParameters(SubDetectorTypeMap &subDetectorTypeMap) const +{ + std::cout << "Begin SetMandatorySubDetectorParameters:" << std::endl; + PandoraApi::Geometry::SubDetector::Parameters eCalBarrelParameters, eCalEndCapParameters, hCalBarrelParameters, hCalEndCapParameters, + muonBarrelParameters, muonEndCapParameters; + + this->SetDefaultSubDetectorParameters(_GEAR->getEcalBarrelParameters(), "ECalBarrel", pandora::ECAL_BARREL, eCalBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getEcalEndcapParameters(), "ECalEndCap", pandora::ECAL_ENDCAP, eCalEndCapParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getHcalBarrelParameters(), "HCalBarrel", pandora::HCAL_BARREL, hCalBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getHcalEndcapParameters(), "HCalEndCap", pandora::HCAL_ENDCAP, hCalEndCapParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getYokeBarrelParameters(), "MuonBarrel", pandora::MUON_BARREL, muonBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getYokeEndcapParameters(), "MuonEndCap", pandora::MUON_ENDCAP, muonEndCapParameters); + + subDetectorTypeMap[pandora::ECAL_BARREL] = eCalBarrelParameters; + subDetectorTypeMap[pandora::ECAL_ENDCAP] = eCalEndCapParameters; + subDetectorTypeMap[pandora::HCAL_BARREL] = hCalBarrelParameters; + subDetectorTypeMap[pandora::HCAL_ENDCAP] = hCalEndCapParameters; + subDetectorTypeMap[pandora::MUON_BARREL] = muonBarrelParameters; + subDetectorTypeMap[pandora::MUON_ENDCAP] = muonEndCapParameters; + + PandoraApi::Geometry::SubDetector::Parameters trackerParameters; + const gear::TPCParameters &tpcParameters(_GEAR->getTPCParameters()); + trackerParameters.m_subDetectorName = "Tracker"; + trackerParameters.m_subDetectorType = pandora::INNER_TRACKER; + trackerParameters.m_innerRCoordinate = tpcParameters.getPadLayout().getPlaneExtent()[0]; + trackerParameters.m_innerZCoordinate = 0.f; + trackerParameters.m_innerPhiCoordinate = 0.f; + trackerParameters.m_innerSymmetryOrder = 0; + trackerParameters.m_outerRCoordinate = tpcParameters.getPadLayout().getPlaneExtent()[1]; + trackerParameters.m_outerZCoordinate = tpcParameters.getMaxDriftLength(); + trackerParameters.m_outerPhiCoordinate = 0.f; + trackerParameters.m_outerSymmetryOrder = 0; + trackerParameters.m_isMirroredInZ = true; + trackerParameters.m_nLayers = 0; + subDetectorTypeMap[pandora::INNER_TRACKER] = trackerParameters; + + PandoraApi::Geometry::SubDetector::Parameters coilParameters; + const gear::GearParameters &gearParameters(_GEAR->getGearParameters("CoilParameters")); + coilParameters.m_subDetectorName = "Coil"; + coilParameters.m_subDetectorType = pandora::COIL; + coilParameters.m_innerRCoordinate = gearParameters.getDoubleVal("Coil_cryostat_inner_radius"); + coilParameters.m_innerZCoordinate = 0.f; + coilParameters.m_innerPhiCoordinate = 0.f; + coilParameters.m_innerSymmetryOrder = 0; + coilParameters.m_outerRCoordinate = gearParameters.getDoubleVal("Coil_cryostat_outer_radius"); + coilParameters.m_outerZCoordinate = gearParameters.getDoubleVal("Coil_cryostat_half_z"); + coilParameters.m_outerPhiCoordinate = 0.f; + coilParameters.m_outerSymmetryOrder = 0; + coilParameters.m_isMirroredInZ = true; + coilParameters.m_nLayers = 0; + subDetectorTypeMap[pandora::COIL] = coilParameters; + std::cout << "End SetMandatorySubDetectorParameters" << std::endl; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetAdditionalSubDetectorParameters(SubDetectorNameMap &subDetectorNameMap) const +{ + std::cout << "Begin SetAdditionalSubDetectorParameters:" << std::endl; + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getEcalPlugParameters(), "ECalPlug", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << " warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getHcalRingParameters(), "HCalRing", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout<< "warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getLcalParameters(), "LCal", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << "warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getLHcalParameters(), "LHCal", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << "warning pandora geometry creator: " << exception.what() << std::endl; + } + std::cout << "End SetAdditionalSubDetectorParameters" << std::endl; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetDefaultSubDetectorParameters(const gear::CalorimeterParameters &inputParameters, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const +{ + const gear::LayerLayout &layerLayout = inputParameters.getLayerLayout(); + + parameters.m_subDetectorName = subDetectorName; + parameters.m_subDetectorType = subDetectorType; + parameters.m_innerRCoordinate = inputParameters.getExtent()[0]; + parameters.m_innerZCoordinate = inputParameters.getExtent()[2]; + parameters.m_innerPhiCoordinate = inputParameters.getPhi0(); + parameters.m_innerSymmetryOrder = inputParameters.getSymmetryOrder(); + parameters.m_outerRCoordinate = inputParameters.getExtent()[1]; + parameters.m_outerZCoordinate = inputParameters.getExtent()[3]; + parameters.m_outerPhiCoordinate = inputParameters.getPhi0(); + parameters.m_outerSymmetryOrder = inputParameters.getSymmetryOrder(); + parameters.m_isMirroredInZ = true; + parameters.m_nLayers = layerLayout.getNLayers(); + + // ATTN Not always going to be correct for any optional subdetectors, but impact of this is negligible for ILD + const float radiationLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + for (int i = 0; i < layerLayout.getNLayers(); ++i) + { + PandoraApi::Geometry::LayerParameters layerParameters; + layerParameters.m_closestDistanceToIp = layerLayout.getDistance(i) + (0.5 * (layerLayout.getThickness(i) + layerLayout.getAbsorberThickness(i))); + layerParameters.m_nRadiationLengths = radiationLength * layerLayout.getAbsorberThickness(i); + layerParameters.m_nInteractionLengths = interactionLength * layerLayout.getAbsorberThickness(i); + parameters.m_layerParametersVector.push_back(layerParameters); + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::SetILDSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap, SubDetectorNameMap &subDetectorNameMap) const +{ + // Set positions of gaps in ILD detector and add information missing from GEAR parameters file + try + { + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerPhiCoordinate = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_phi0"); + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerSymmetryOrder = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order"); + } + catch (gear::Exception &) + { + // aLaVideauGeometry + return this->SetILD_SDHCALSpecificGeometry(subDetectorTypeMap); + } + + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_eCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_eCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_eCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_eCalEndCapOuterPhiCoordinate; + + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_hCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_hCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_hCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_hCalEndCapOuterPhiCoordinate; + + subDetectorNameMap["HCalRing"].m_innerSymmetryOrder = m_settings.m_hCalRingInnerSymmetryOrder; + subDetectorNameMap["HCalRing"].m_innerPhiCoordinate = m_settings.m_hCalRingInnerPhiCoordinate; + subDetectorNameMap["HCalRing"].m_outerSymmetryOrder = m_settings.m_hCalRingOuterSymmetryOrder; + subDetectorNameMap["HCalRing"].m_outerPhiCoordinate = m_settings.m_hCalRingOuterPhiCoordinate; + + // Gaps in detector active material + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalBarrelBoxGaps()); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalEndCapBoxGaps()); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalBarrelConcentricGaps()); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::SetILD_SDHCALSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap) const +{ + // Non-default values (and those missing from GEAR parameters file)... + // The following 2 parameters have no sense for Videau Geometry, set them to 0 + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerPhiCoordinate = 0; + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerSymmetryOrder = 0; + + // Endcap is identical to standard ILD geometry, only HCAL barrel is different + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_eCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_eCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_eCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_eCalEndCapOuterPhiCoordinate; + + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_hCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_hCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_hCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_hCalEndCapOuterPhiCoordinate; + + // TODO implement gaps between modules + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalBarrelBoxGaps() const +{ + const std::string detectorName(_GEAR->getDetectorName()); + + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + const unsigned int innerSymmetryOrder(hCalBarrelParameters.getSymmetryOrder()); + const unsigned int outerSymmetryOrder(hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order")); + + if ((0 == innerSymmetryOrder) || (2 != outerSymmetryOrder / innerSymmetryOrder)) + { + std::cout << " Detector " << detectorName << " doesn't conform to expected ILD-specific geometry" << std::endl; + return pandora::STATUS_CODE_INVALID_PARAMETER; + } + + const float innerRadius(hCalBarrelParameters.getExtent()[0]); + const float outerRadius(hCalBarrelParameters.getExtent()[1]); + const float outerZ(hCalBarrelParameters.getExtent()[3]); + const float phi0(hCalBarrelParameters.getPhi0()); + + const float staveGap(hCalBarrelParameters.getDoubleVal("Hcal_stave_gaps")); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(innerSymmetryOrder, phi0, innerRadius, outerRadius, + -outerZ, outerZ, staveGap)); + + const float outerPseudoPhi0(M_PI / static_cast<float>(innerSymmetryOrder)); + const float cosOuterPseudoPhi0(std::cos(outerPseudoPhi0)); + + if ((0 == outerPseudoPhi0) || (0.f == cosOuterPseudoPhi0)) + { + std::cout << " Detector " << detectorName << " doesn't conform to expected ILD-specific geometry" << std::endl; + return pandora::STATUS_CODE_INVALID_PARAMETER; + } + + const float middleStaveGap(hCalBarrelParameters.getDoubleVal("Hcal_middle_stave_gaps")); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(innerSymmetryOrder, outerPseudoPhi0, + innerRadius / cosOuterPseudoPhi0, outerRadius, -outerZ, outerZ, middleStaveGap)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalEndCapBoxGaps() const +{ + const gear::CalorimeterParameters &hCalEndCapParameters = _GEAR->getHcalEndcapParameters(); + + const float staveGap(hCalEndCapParameters.getDoubleVal("Hcal_stave_gaps")); + const float innerRadius(hCalEndCapParameters.getExtent()[0]); + const float outerRadius(hCalEndCapParameters.getExtent()[1]); + const float innerZ(hCalEndCapParameters.getExtent()[2]); + const float outerZ(hCalEndCapParameters.getExtent()[3]); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(m_settings.m_hCalEndCapInnerSymmetryOrder, + m_settings.m_hCalEndCapInnerPhiCoordinate, innerRadius, outerRadius, innerZ, outerZ, staveGap, + pandora::CartesianVector(-innerRadius, 0, 0))); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(m_settings.m_hCalEndCapInnerSymmetryOrder, + m_settings.m_hCalEndCapInnerPhiCoordinate, innerRadius, outerRadius, -outerZ, -innerZ, staveGap, + pandora::CartesianVector(innerRadius, 0, 0))); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalBarrelConcentricGaps() const +{ + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + const float gapWidth(hCalBarrelParameters.getDoubleVal("Hcal_stave_gaps")); + + PandoraApi::Geometry::ConcentricGap::Parameters gapParameters; + + gapParameters.m_minZCoordinate = -0.5f * gapWidth; + gapParameters.m_maxZCoordinate = 0.5f * gapWidth; + gapParameters.m_innerRCoordinate = hCalBarrelParameters.getExtent()[0]; + gapParameters.m_innerPhiCoordinate = hCalBarrelParameters.getPhi0(); + gapParameters.m_innerSymmetryOrder = hCalBarrelParameters.getSymmetryOrder(); + gapParameters.m_outerRCoordinate = hCalBarrelParameters.getExtent()[1]; + gapParameters.m_outerPhiCoordinate = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_phi0"); + gapParameters.m_outerSymmetryOrder = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order"); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::ConcentricGap::Create(*m_pPandora, gapParameters)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateRegularBoxGaps(unsigned int symmetryOrder, float phi0, float innerRadius, float outerRadius, + float minZ, float maxZ, float gapWidth, pandora::CartesianVector vertexOffset) const +{ + const pandora::CartesianVector basicGapVertex(pandora::CartesianVector(-0.5f * gapWidth, innerRadius, minZ) + vertexOffset); + const pandora::CartesianVector basicSide1(gapWidth, 0, 0); + const pandora::CartesianVector basicSide2(0, outerRadius - innerRadius, 0); + const pandora::CartesianVector basicSide3(0, 0, maxZ - minZ); + + for (unsigned int i = 0; i < symmetryOrder; ++i) + { + const float phi = phi0 + (2. * M_PI * static_cast<float>(i) / static_cast<float>(symmetryOrder)); + const float sinPhi(std::sin(phi)); + const float cosPhi(std::cos(phi)); + + PandoraApi::Geometry::BoxGap::Parameters gapParameters; + + gapParameters.m_vertex = pandora::CartesianVector(cosPhi * basicGapVertex.GetX() + sinPhi * basicGapVertex.GetY(), + -sinPhi * basicGapVertex.GetX() + cosPhi * basicGapVertex.GetY(), basicGapVertex.GetZ()); + gapParameters.m_side1 = pandora::CartesianVector(cosPhi * basicSide1.GetX() + sinPhi * basicSide1.GetY(), + -sinPhi * basicSide1.GetX() + cosPhi * basicSide1.GetY(), basicSide1.GetZ()); + gapParameters.m_side2 = pandora::CartesianVector(cosPhi * basicSide2.GetX() + sinPhi * basicSide2.GetY(), + -sinPhi * basicSide2.GetX() + cosPhi * basicSide2.GetY(), basicSide2.GetZ()); + gapParameters.m_side3 = pandora::CartesianVector(cosPhi * basicSide3.GetX() + sinPhi * basicSide3.GetY(), + -sinPhi * basicSide3.GetX() + cosPhi * basicSide3.GetY(), basicSide3.GetZ()); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::BoxGap::Create(*m_pPandora, gapParameters)); + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +GeometryCreator::Settings::Settings() : + m_absorberRadLengthECal(1.f), + m_absorberIntLengthECal(1.f), + m_absorberRadLengthHCal(1.f), + m_absorberIntLengthHCal(1.f), + m_absorberRadLengthOther(1.f), + m_absorberIntLengthOther(1.f), + m_eCalEndCapInnerSymmetryOrder(4), + m_eCalEndCapInnerPhiCoordinate(0.f), + m_eCalEndCapOuterSymmetryOrder(8), + m_eCalEndCapOuterPhiCoordinate(0.f), + m_hCalEndCapInnerSymmetryOrder(4), + m_hCalEndCapInnerPhiCoordinate(0.f), + m_hCalEndCapOuterSymmetryOrder(16), + m_hCalEndCapOuterPhiCoordinate(0.f), + m_hCalRingInnerSymmetryOrder(8), + m_hCalRingInnerPhiCoordinate(0.f), + m_hCalRingOuterSymmetryOrder(16), + m_hCalRingOuterPhiCoordinate(0.f) +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/MCParticleCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/MCParticleCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9042a82183231212b3362656c9d38ab8ef6bbf0 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/MCParticleCreator.cpp @@ -0,0 +1,226 @@ +/** + * + * @brief Implementation of the mc particle creator class. + * + * $Log: $ + */ + + +#include "edm4hep/MCParticleConst.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCRecoCaloAssociation.h" +#include "edm4hep/SimCalorimeterHitConst.h" +#include "edm4hep/CaloHitContributionConst.h" +#include "edm4hep/Track.h" +#include "edm4hep/MCRecoTrackerAssociation.h" +#include "edm4hep/SimTrackerHitConst.h" +#include "PandoraPFAlg.h" +#include "MCParticleCreator.h" + +#include <cmath> +#include <limits> +#include <assert.h> + +MCParticleCreator::MCParticleCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora), + m_bField(settings.m_bField) +{ +m_id_pMC_map = new std::map<unsigned int, const edm4hep::MCParticle*>; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +MCParticleCreator::~MCParticleCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode MCParticleCreator::CreateMCParticles(const CollectionMaps& collectionMaps ) const +{ + for (StringVector::const_iterator iter = m_settings.m_mcParticleCollections.begin(), iterEnd = m_settings.m_mcParticleCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_MC.find(*iter) == collectionMaps.collectionMap_MC.end()) continue; + try + { + const std::vector<edm4hep::MCParticle>& pMCParticleCollection = (collectionMaps.collectionMap_MC.find(*iter))->second; + std::cout<<"Do CreateMCParticles, collection:"<<(*iter)<<", size="<<pMCParticleCollection.size()<<std::endl; + for (int im = 0; im < pMCParticleCollection.size(); im++) + { + try + { + const edm4hep::MCParticle& pMcParticle = pMCParticleCollection.at(im); + PandoraApi::MCParticle::Parameters mcParticleParameters; + mcParticleParameters.m_energy = sqrt(pMcParticle.getMomentum()[0] * pMcParticle.getMomentum()[0] + pMcParticle.getMomentum()[1] * pMcParticle.getMomentum()[1] + pMcParticle.getMomentum()[2] * pMcParticle.getMomentum()[2] + pMcParticle.getMass() * pMcParticle.getMass()); + mcParticleParameters.m_particleId = pMcParticle.getPDG(); + mcParticleParameters.m_mcParticleType = pandora::MC_3D; + mcParticleParameters.m_pParentAddress = &pMcParticle; + unsigned int p_id = pMcParticle.id(); + const edm4hep::MCParticle* p_mc = &pMcParticle; + (*m_id_pMC_map) [p_id] = p_mc; + mcParticleParameters.m_momentum = pandora::CartesianVector(pMcParticle.getMomentum()[0], pMcParticle.getMomentum()[1], + pMcParticle.getMomentum()[2]); + mcParticleParameters.m_vertex = pandora::CartesianVector(pMcParticle.getVertex()[0], pMcParticle.getVertex()[1], + pMcParticle.getVertex()[2]); + mcParticleParameters.m_endpoint = pandora::CartesianVector(pMcParticle.getEndpoint()[0], pMcParticle.getEndpoint()[1], + pMcParticle.getEndpoint()[2]); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::MCParticle::Create(*m_pPandora, mcParticleParameters)); + + // Create parent-daughter relationships + for(std::vector<edm4hep::ConstMCParticle>::const_iterator itDaughter = pMcParticle.daughters_begin(), + itDaughterEnd = pMcParticle.daughters_end(); itDaughter != itDaughterEnd; ++itDaughter) + { + for (int ida = 0; ida < pMCParticleCollection.size(); ida++) + { + if(pMCParticleCollection.at(ida).id()==(*itDaughter).id()) + { + + const edm4hep::MCParticle& dMcParticle = pMCParticleCollection.at(ida); + if(&pMcParticle == &dMcParticle){std::cout<< "error, mother and daughter are the same mc particle, don't save SetMCParentDaughterRelationship"<<std::endl;} + else PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*m_pPandora, &pMcParticle, &dMcParticle)); + break; + } + } + } + + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract MCParticle: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract MCParticle: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract MCParticles collection: " << *iter << ", " << std::endl; + } + } + return pandora::STATUS_CODE_SUCCESS; +} + + +pandora::StatusCode MCParticleCreator::CreateCaloHitToMCParticleRelationships(const CollectionMaps& collectionMaps, const CalorimeterHitVector &calorimeterHitVector) const +{ + typedef std::map<const edm4hep::MCParticle *, float> MCParticleToEnergyWeightMap; + MCParticleToEnergyWeightMap mcParticleToEnergyWeightMap; + + for (StringVector::const_iterator iter = m_settings.m_CaloHitRelationCollections.begin(), iterEnd = m_settings.m_CaloHitRelationCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloRel.find(*iter) == collectionMaps.collectionMap_CaloRel.end()) continue; + try + { + const std::vector<edm4hep::MCRecoCaloAssociation>& pMCRecoCaloAssociationCollection = (collectionMaps.collectionMap_CaloRel.find(*iter))->second; + + for (unsigned i_calo=0; i_calo < calorimeterHitVector.size(); i_calo++) + { + try + { + mcParticleToEnergyWeightMap.clear(); + for(unsigned ic=0; ic < pMCRecoCaloAssociationCollection.size(); ic++) + { + if( pMCRecoCaloAssociationCollection.at(ic).getRec().id() != (*(calorimeterHitVector.at(i_calo))).id() ) continue; + + const edm4hep::ConstSimCalorimeterHit pSimHit = pMCRecoCaloAssociationCollection.at(ic).getSim(); + for (int iCont = 0, iEnd = pSimHit.contributions_size(); iCont < iEnd; ++iCont) + { + edm4hep::ConstCaloHitContribution conb = pSimHit.getContributions(iCont); + const edm4hep::ConstMCParticle ipa = conb.getParticle(); + float ien = conb.getEnergy(); + if( m_id_pMC_map->find(ipa.id()) == m_id_pMC_map->end() ) continue; + const edm4hep::MCParticle * p_tmp = (*m_id_pMC_map)[ipa.id()]; + mcParticleToEnergyWeightMap[p_tmp] += ien; + } + + } + + for (MCParticleToEnergyWeightMap::const_iterator mcParticleIter = mcParticleToEnergyWeightMap.begin(), + mcParticleIterEnd = mcParticleToEnergyWeightMap.end(); mcParticleIter != mcParticleIterEnd; ++mcParticleIter) + { + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*m_pPandora, + calorimeterHitVector.at(i_calo), mcParticleIter->first, mcParticleIter->second)); + } + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"Failed to extract calo hit to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"Failed to extract calo hit to mc particle relationship " << std::endl; + } + } + } + catch (...) + { + std::cout<<"Failed to extract calo hit to mc particle relationships collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + + +pandora::StatusCode MCParticleCreator::CreateTrackToMCParticleRelationships(const CollectionMaps& collectionMaps, const TrackVector &trackVector) const +{ + for (unsigned ik = 0; ik < trackVector.size(); ik++) + { + const edm4hep::Track *pTrack = trackVector.at(ik); + // Get reconstructed momentum at dca + const pandora::Helix helixFit(pTrack->getTrackStates(0).phi, pTrack->getTrackStates(0).D0, pTrack->getTrackStates(0).Z0, pTrack->getTrackStates(0).omega, pTrack->getTrackStates(0).tanLambda, m_bField); + const float recoMomentum(helixFit.GetMomentum().GetMagnitude()); + // Use momentum magnitude to identify best mc particle + edm4hep::MCParticle *pBestMCParticle = NULL; + float bestDeltaMomentum(std::numeric_limits<float>::max()); + try + { + for (StringVector::const_iterator iter = m_settings.m_TrackRelationCollections.begin(), iterEnd = m_settings.m_TrackRelationCollections.end(); iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_TrkRel.find(*iter) == collectionMaps.collectionMap_TrkRel.end()) continue; + const std::vector<edm4hep::MCRecoTrackerAssociation>& pMCRecoTrackerAssociationCollection = (collectionMaps.collectionMap_TrkRel.find(*iter))->second; + for(unsigned ith=0 ; ith<pTrack->trackerHits_size(); ith++) + { + for(unsigned ic=0; ic < pMCRecoTrackerAssociationCollection.size(); ic++) + { + if( pMCRecoTrackerAssociationCollection.at(ic).getRec().id() != pTrack->getTrackerHits(ith).id() ) continue; + const edm4hep::ConstSimTrackerHit pSimHit = pMCRecoTrackerAssociationCollection.at(ic).getSim(); + const edm4hep::ConstMCParticle ipa = pSimHit.getMCParticle(); + if( m_id_pMC_map->find(ipa.id()) == m_id_pMC_map->end() ) continue; + const float trueMomentum(pandora::CartesianVector(ipa.getMomentum()[0], ipa.getMomentum()[1], ipa.getMomentum()[2]).GetMagnitude()); + const float deltaMomentum(std::fabs(recoMomentum - trueMomentum)); + if (deltaMomentum < bestDeltaMomentum) + { + pBestMCParticle =const_cast<edm4hep::MCParticle*>((*m_id_pMC_map)[ipa.id()]); + bestDeltaMomentum = deltaMomentum; + } + } + } + } + + if (NULL == pBestMCParticle) continue; + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackToMCParticleRelationship(*m_pPandora, pTrack, pBestMCParticle)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"Failed to extract track to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"Failed to extract track to mc particle relationship" << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + + +MCParticleCreator::Settings::Settings() +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/PandoraPFAlg.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/PandoraPFAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d2e9db69f1a2184b3bbf1f3c6d27d344a2432a2c --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/PandoraPFAlg.cpp @@ -0,0 +1,684 @@ +#include "GearSvc/IGearSvc.h" +#include "PandoraPFAlg.h" +#include "EventSeeder/IEventSeeder.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/Vector3d.h" +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CaloHitContribution.h" +#include "edm4hep/ClusterConst.h" +//#include "UTIL/ILDConf.h" +#include <cmath> +#include <algorithm> +#include "gear/BField.h" +#include <gear/GEAR.h> + +#include "LCContent.h" + + +pandora::Pandora* PandoraPFAlg::m_pPandora=0; + +DECLARE_COMPONENT( PandoraPFAlg ) + +template<typename T ,typename T1> +StatusCode getCol(T & t, T1 & t1) +{ + try { + t1 = t.get(); + } + catch ( GaudiException &e ) { + std::cout << "Collection " << t.fullKey() << " is unavailable in event " << std::endl; + } + return StatusCode::SUCCESS; +} + + + +PandoraPFAlg::PandoraPFAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc), + _nEvt(0) +{ + m_CollectionMaps = new CollectionMaps(); + + declareProperty("ReadMCParticle" , m_mcParCol_r, "Handle of the MCParticle input collection" ); + declareProperty("ReadECALBarrel" , m_ECALBarrel_r, "Handle of the ECALBarrel input collection" ); + declareProperty("ReadECALEndcap" , m_ECALEndcap_r, "Handle of the ECALEndcap input collection" ); + declareProperty("ReadECALOther" , m_ECALOther_r, "Handle of the ECALOther input collection" ); + declareProperty("ReadHCALBarrel" , m_HCALBarrel_r, "Handle of the HCALBarrel input collection" ); + declareProperty("ReadHCALEndcap" , m_HCALEndcap_r, "Handle of the HCALEndcap input collection" ); + declareProperty("ReadHCALOther" , m_HCALOther_r, "Handle of the HCALOther input collection" ); + declareProperty("ReadMUON" , m_MUON_r, "Handle of the MUON input collection" ); + declareProperty("ReadLCAL" , m_LCAL_r, "Handle of the LCAL input collection" ); + declareProperty("ReadLHCAL" , m_LHCAL_r, "Handle of the LHCAL input collection" ); + declareProperty("ReadBCAL" , m_BCAL_r, "Handle of the BCAL input collection" ); + declareProperty("ReadKinkVertices" , m_KinkVertices_r, "Handle of the KinkVertices input collection" ); + declareProperty("ReadProngVertices" , m_ProngVertices_r, "Handle of the ProngVertices input collection" ); + declareProperty("ReadSplitVertices" , m_SplitVertices_r, "Handle of the SplitVertices input collection" ); + declareProperty("ReadV0Vertices" , m_V0Vertices_r, "Handle of the V0Vertices input collection" ); + declareProperty("ReadTracks" , m_MarlinTrkTracks_r, "Handle of the Tracks input collection" ); + declareProperty("MCRecoCaloAssociation" , m_MCRecoCaloAssociation_r, "Handle of the MCRecoCaloAssociation input collection" ); + declareProperty("MCRecoTrackerAssociation" , m_MCRecoTrackerAssociation_r, "Handle of the MCRecoTrackerAssociation input collection" ); + declareProperty("WriteClusterCollection" , m_ClusterCollection_w, "Handle of the ClusterCollection output collection" ); + declareProperty("WriteReconstructedParticleCollection", m_ReconstructedParticleCollection_w, "Handle of the ReconstructedParticleCollection output collection" ); + declareProperty("WriteVertexCollection" , m_VertexCollection_w, "Handle of the VertexCollection output collection" ); + +} + + +void PandoraPFAlg::FinaliseSteeringParameters(ISvcLocator* svcloc) +{ + // ATTN: This function seems to be necessary for operations that cannot easily be performed at construction of the processor, + // when the steering file is parsed e.g. the call to GEAR to get the inner bfield + + m_caloHitCreatorSettings.m_absorberRadLengthECal = m_geometryCreatorSettings.m_absorberRadLengthECal; + m_caloHitCreatorSettings.m_absorberIntLengthECal = m_geometryCreatorSettings.m_absorberIntLengthECal; + m_caloHitCreatorSettings.m_absorberRadLengthHCal = m_geometryCreatorSettings.m_absorberRadLengthHCal; + m_caloHitCreatorSettings.m_absorberIntLengthHCal = m_geometryCreatorSettings.m_absorberIntLengthHCal; + m_caloHitCreatorSettings.m_absorberRadLengthOther = m_geometryCreatorSettings.m_absorberRadLengthOther; + m_caloHitCreatorSettings.m_absorberIntLengthOther = m_geometryCreatorSettings.m_absorberIntLengthOther; + + m_caloHitCreatorSettings.m_hCalEndCapInnerSymmetryOrder = m_geometryCreatorSettings.m_hCalEndCapInnerSymmetryOrder; + m_caloHitCreatorSettings.m_hCalEndCapInnerPhiCoordinate = m_geometryCreatorSettings.m_hCalEndCapInnerPhiCoordinate; + + m_trackCreatorSettings.m_prongSplitVertexCollections = m_trackCreatorSettings.m_prongVertexCollections; + m_trackCreatorSettings.m_prongSplitVertexCollections.insert(m_trackCreatorSettings.m_prongSplitVertexCollections.end(), + m_trackCreatorSettings.m_splitVertexCollections.begin(), m_trackCreatorSettings.m_splitVertexCollections.end()); + + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + gear::GearMgr* _GEAR = iSvc->getGearMgr(); + m_settings.m_innerBField = _GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z(); + std::cout<<"m_innerBField="<<m_settings.m_innerBField<<std::endl; + m_mcParticleCreatorSettings.m_bField = m_settings.m_innerBField; +} + + + + +StatusCode PandoraPFAlg::initialize() +{ + + std::cout<<"init PandoraPFAlg"<<std::endl; + + std::string s_output =m_AnaOutput; + m_fout = new TFile(s_output.c_str(),"RECREATE"); + m_tree = new TTree("evt","tree"); + m_tree->Branch("m_pReco_PID" , &m_pReco_PID); + m_tree->Branch("m_pReco_mass" , &m_pReco_mass); + m_tree->Branch("m_pReco_energy", &m_pReco_energy); + m_tree->Branch("m_pReco_px" , &m_pReco_px); + m_tree->Branch("m_pReco_py" , &m_pReco_py); + m_tree->Branch("m_pReco_pz" , &m_pReco_pz); + m_tree->Branch("m_pReco_charge", &m_pReco_charge); + + m_tree->Branch("m_mc_p_size", &m_mc_p_size); + m_tree->Branch("m_mc_pid" , &m_mc_pid ); + m_tree->Branch("m_mc_mass" , &m_mc_mass ); + m_tree->Branch("m_mc_px" , &m_mc_px ); + m_tree->Branch("m_mc_py" , &m_mc_py ); + m_tree->Branch("m_mc_pz" , &m_mc_pz ); + m_tree->Branch("m_mc_charge", &m_mc_charge); + m_tree->Branch("m_hasConversion", &m_hasConversion); + + // XML file + m_settings.m_pandoraSettingsXmlFile = m_PandoraSettingsXmlFile ; + // Hadronic energy non-linearity correction + m_settings.m_inputEnergyCorrectionPoints = m_InputEnergyCorrectionPoints; + m_settings.m_outputEnergyCorrectionPoints = m_OutputEnergyCorrectionPoints; + // B-field parameters + m_settings.m_muonBarrelBField = m_MuonBarrelBField; + m_settings.m_muonEndCapBField = m_MuonEndCapBField; + + m_trackCreatorSettings.m_trackCollections = m_TrackCollections ; + m_trackCreatorSettings.m_kinkVertexCollections = m_KinkVertexCollections; + m_trackCreatorSettings.m_prongVertexCollections = m_ProngVertexCollections; + m_trackCreatorSettings.m_splitVertexCollections = m_SplitVertexCollections; + m_trackCreatorSettings.m_v0VertexCollections = m_V0VertexCollections; + + m_caloHitCreatorSettings.m_eCalCaloHitCollections = m_ECalCaloHitCollections; + m_caloHitCreatorSettings.m_hCalCaloHitCollections = m_HCalCaloHitCollections; + m_caloHitCreatorSettings.m_lCalCaloHitCollections = m_LCalCaloHitCollections; + m_caloHitCreatorSettings.m_lHCalCaloHitCollections = m_LHCalCaloHitCollections; + m_caloHitCreatorSettings.m_muonCaloHitCollections = m_MuonCaloHitCollections; + m_mcParticleCreatorSettings.m_mcParticleCollections = m_MCParticleCollections; + m_mcParticleCreatorSettings.m_CaloHitRelationCollections = m_RelCaloHitCollections; + m_mcParticleCreatorSettings.m_TrackRelationCollections = m_RelTrackCollections; + + + // Absorber properties + m_geometryCreatorSettings.m_absorberRadLengthECal = m_AbsorberRadLengthECal; + m_geometryCreatorSettings.m_absorberIntLengthECal = m_AbsorberIntLengthECal; + m_geometryCreatorSettings.m_absorberRadLengthHCal = m_AbsorberRadLengthHCal; + m_geometryCreatorSettings.m_absorberIntLengthHCal = m_AbsorberIntLengthHCal; + m_geometryCreatorSettings.m_absorberRadLengthOther = m_AbsorberRadLengthOther; + m_geometryCreatorSettings.m_absorberIntLengthOther = m_AbsorberIntLengthOther; + + // Name of PFO collection written by GaudiPandora + + m_pfoCreatorSettings.m_clusterCollectionName = m_ClusterCollectionName;// not used + m_pfoCreatorSettings.m_pfoCollectionName = m_PFOCollectionName;// + m_pfoCreatorSettings.m_startVertexCollectionName = m_StartVertexCollectionName; // + m_pfoCreatorSettings.m_startVertexAlgName = m_StartVertexAlgorithmName;// + + m_pfoCreatorSettings.m_emStochasticTerm = m_EMStochasticTerm; + m_pfoCreatorSettings.m_hadStochasticTerm = m_HadStochasticTerm; + m_pfoCreatorSettings.m_emConstantTerm = m_EMConstantTerm; + m_pfoCreatorSettings.m_hadConstantTerm = m_HadConstantTerm; + + // Calibration constants + m_caloHitCreatorSettings.m_eCalToMip = m_ECalToMipCalibration; + m_caloHitCreatorSettings.m_hCalToMip = m_HCalToMipCalibration; + m_caloHitCreatorSettings.m_eCalMipThreshold = m_ECalMipThreshold; + m_caloHitCreatorSettings.m_muonToMip = m_MuonToMipCalibration; + m_caloHitCreatorSettings.m_hCalMipThreshold = m_HCalMipThreshold; + m_caloHitCreatorSettings.m_eCalToEMGeV = m_ECalToEMGeVCalibration; + m_caloHitCreatorSettings.m_hCalToEMGeV = m_HCalToEMGeVCalibration; + m_caloHitCreatorSettings.m_eCalToHadGeVEndCap = m_ECalToHadGeVCalibrationEndCap; + m_caloHitCreatorSettings.m_eCalToHadGeVBarrel = m_ECalToHadGeVCalibrationBarrel; + m_caloHitCreatorSettings.m_hCalToHadGeV = m_HCalToHadGeVCalibration; + m_caloHitCreatorSettings.m_muonDigitalHits = m_DigitalMuonHits; + m_caloHitCreatorSettings.m_muonHitEnergy = m_MuonHitEnergy; + m_caloHitCreatorSettings.m_maxHCalHitHadronicEnergy = m_MaxHCalHitHadronicEnergy; + m_caloHitCreatorSettings.m_nOuterSamplingLayers = m_NOuterSamplingLayers; + m_caloHitCreatorSettings.m_layersFromEdgeMaxRearDistance = m_LayersFromEdgeMaxRearDistance; + + // Track relationship parameters + m_trackCreatorSettings.m_shouldFormTrackRelationships = m_ShouldFormTrackRelationships; + // Initial track hit specifications + m_trackCreatorSettings.m_minTrackHits = m_MinTrackHits; + m_trackCreatorSettings.m_minFtdTrackHits = m_MinFtdTrackHits; + m_trackCreatorSettings.m_maxTrackHits = m_MaxTrackHits; + ////m_trackCreatorSettings.m_useOldTrackStateCalculation = m_UseOldTrackStateCalculation; + // Track PFO usage parameters + m_trackCreatorSettings.m_d0TrackCut = m_D0TrackCut; + m_trackCreatorSettings.m_z0TrackCut = m_Z0TrackCut; + m_trackCreatorSettings.m_usingNonVertexTracks = m_UseNonVertexTracks; + m_trackCreatorSettings.m_usingUnmatchedNonVertexTracks = m_UseUnmatchedNonVertexTracks; + m_trackCreatorSettings.m_usingUnmatchedVertexTracks = m_UseUnmatchedVertexTracks; + m_trackCreatorSettings.m_unmatchedVertexTrackMaxEnergy = m_UnmatchedVertexTrackMaxEnergy; + m_trackCreatorSettings.m_d0UnmatchedVertexTrackCut = m_D0UnmatchedVertexTrackCut; + m_trackCreatorSettings.m_z0UnmatchedVertexTrackCut = m_Z0UnmatchedVertexTrackCut; + m_trackCreatorSettings.m_zCutForNonVertexTracks = m_ZCutForNonVertexTracks; + // Track "reaches ecal" parameters + m_trackCreatorSettings.m_reachesECalNTpcHits = m_ReachesECalNTpcHits; + m_trackCreatorSettings.m_reachesECalNFtdHits = m_ReachesECalNFtdHits; + m_trackCreatorSettings.m_reachesECalTpcOuterDistance = m_ReachesECalTpcOuterDistance; + m_trackCreatorSettings.m_reachesECalMinFtdLayer = m_ReachesECalMinFtdLayer; + m_trackCreatorSettings.m_reachesECalTpcZMaxDistance = m_ReachesECalTpcZMaxDistance; + m_trackCreatorSettings.m_reachesECalFtdZMaxDistance = m_ReachesECalFtdZMaxDistance; + m_trackCreatorSettings.m_curvatureToMomentumFactor = m_CurvatureToMomentumFactor; + m_trackCreatorSettings.m_minTrackECalDistanceFromIp = m_MinTrackECalDistanceFromIp; + // Final track quality parameters + m_trackCreatorSettings.m_maxTrackSigmaPOverP = m_MaxTrackSigmaPOverP; + m_trackCreatorSettings.m_minMomentumForTrackHitChecks = m_MinMomentumForTrackHitChecks; + m_trackCreatorSettings.m_tpcMembraneMaxZ = m_TpcMembraneMaxZ; + m_trackCreatorSettings.m_minTpcHitFractionOfExpected = m_MinTpcHitFractionOfExpected; + m_trackCreatorSettings.m_minFtdHitsForTpcHitFraction = m_MinFtdHitsForTpcHitFraction; + m_trackCreatorSettings.m_maxTpcInnerRDistance = m_MaxTpcInnerRDistance; + + + // Additional geometry parameters + m_geometryCreatorSettings.m_eCalEndCapInnerSymmetryOrder = m_ECalEndCapInnerSymmetryOrder; + m_geometryCreatorSettings.m_eCalEndCapInnerPhiCoordinate = m_ECalEndCapInnerPhiCoordinate; + m_geometryCreatorSettings.m_eCalEndCapOuterSymmetryOrder = m_ECalEndCapOuterSymmetryOrder; + m_geometryCreatorSettings.m_eCalEndCapOuterPhiCoordinate = m_ECalEndCapOuterPhiCoordinate; + m_geometryCreatorSettings.m_hCalEndCapInnerSymmetryOrder = m_HCalEndCapInnerSymmetryOrder; + m_geometryCreatorSettings.m_hCalEndCapInnerPhiCoordinate = m_HCalEndCapInnerPhiCoordinate; + m_geometryCreatorSettings.m_hCalEndCapOuterSymmetryOrder = m_HCalEndCapOuterSymmetryOrder; + m_geometryCreatorSettings.m_hCalEndCapOuterPhiCoordinate = m_HCalEndCapOuterPhiCoordinate; + m_geometryCreatorSettings.m_hCalRingInnerSymmetryOrder = m_HCalRingInnerSymmetryOrder; + m_geometryCreatorSettings.m_hCalRingInnerPhiCoordinate = m_HCalRingInnerPhiCoordinate; + m_geometryCreatorSettings.m_hCalRingOuterSymmetryOrder = m_HCalRingOuterSymmetryOrder; + m_geometryCreatorSettings.m_hCalRingOuterPhiCoordinate = m_HCalRingOuterPhiCoordinate; + + // For Strip Splitting method and also for hybrid ECAL + m_caloHitCreatorSettings.m_stripSplittingOn = m_StripSplittingOn; + m_caloHitCreatorSettings.m_useEcalScLayers = m_UseEcalScLayers; + // Parameters for hybrid ECAL + // Energy to MIP for Si-layers and Sc-layers, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToMip = m_ECalSiToMipCalibration; + //Sc + m_caloHitCreatorSettings.m_eCalScToMip = m_ECalScToMipCalibration; + // MipThreshold for Si-layers and Sc-layers, respectively. + // Si + m_caloHitCreatorSettings.m_eCalSiMipThreshold = m_ECalSiMipThreshold; + //Sc + m_caloHitCreatorSettings.m_eCalScMipThreshold = m_ECalScMipThreshold; + // EcalToEM for Si-layers and Sc-layers, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToEMGeV = m_ECalSiToEMGeVCalibration; + //Sc + m_caloHitCreatorSettings.m_eCalScToEMGeV = m_ECalScToEMGeVCalibration; + // EcalToHad for Si-layers and Sc-layers of the endcaps, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToHadGeVEndCap = m_ECalSiToHadGeVCalibrationEndCap; + //Sc + m_caloHitCreatorSettings.m_eCalScToHadGeVEndCap = m_ECalScToHadGeVCalibrationEndCap; + // EcalToHad for Si-layers and Sc-layers of the barrel, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToHadGeVBarrel = m_ECalSiToHadGeVCalibrationBarrel; + //Sc + m_caloHitCreatorSettings.m_eCalScToHadGeVBarrel = m_ECalScToHadGeVCalibrationBarrel; + + try + { + ISvcLocator* svcloc = serviceLocator(); + this->FinaliseSteeringParameters(svcloc); + m_pPandora = new pandora::Pandora(); + m_pMCParticleCreator = new MCParticleCreator(m_mcParticleCreatorSettings, m_pPandora); + m_pGeometryCreator = new GeometryCreator(m_geometryCreatorSettings, m_pPandora); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pGeometryCreator->CreateGeometry(svcloc)); + m_pCaloHitCreator = new CaloHitCreator(m_caloHitCreatorSettings, m_pPandora, svcloc, 0); + m_pTrackCreator = new TrackCreator(m_trackCreatorSettings, m_pPandora, svcloc); + m_pPfoCreator = new PfoCreator(m_pfoCreatorSettings, m_pPandora); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->RegisterUserComponents()); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*m_pPandora, m_settings.m_pandoraSettingsXmlFile)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to initialize gaudi pandora: " << statusCodeException.ToString() << std::endl; + throw statusCodeException; + } + catch (...) + { + std::cout << "Failed to initialize gaudi pandora: unrecognized exception" << std::endl; + throw; + } + + + return GaudiAlgorithm::initialize(); +} + +StatusCode PandoraPFAlg::execute() +{ + + try + { + + updateMap(); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateMCParticles(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pCaloHitCreator->CreateCaloHits(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateCaloHitToMCParticleRelationships(*m_CollectionMaps, m_pCaloHitCreator->GetCalorimeterHitVector() )); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pTrackCreator->CreateTrackAssociations(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pTrackCreator->CreateTracks(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateTrackToMCParticleRelationships(*m_CollectionMaps, m_pTrackCreator->GetTrackVector() )); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pPandora)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pPfoCreator->CreateParticleFlowObjects(*m_CollectionMaps, m_ClusterCollection_w, m_ReconstructedParticleCollection_w, m_VertexCollection_w)); + + StatusCode sc0 = CreateMCRecoParticleAssociation(); + StatusCode sc = Ana(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pPandora)); + this->Reset(); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Gaudi pandora failed to process event: " << statusCodeException.ToString() << std::endl; + throw statusCodeException; + } + catch (...) + { + std::cout << "Gaudi pandora failed to process event: unrecognized exception" << std::endl; + throw; + } + + info() << "PandoraPFAlg Processed " << _nEvt << " events " << endmsg; + _nEvt ++ ; + + return StatusCode::SUCCESS; +} + +StatusCode PandoraPFAlg::finalize() +{ + info() << "Finalized. Processed " << _nEvt << " events " <<",saved tree with entries="<<m_tree->GetEntries()<< endmsg; + m_fout->cd(); + m_tree->Write(); + m_fout->Close(); + delete m_pPandora; + delete m_pGeometryCreator; + delete m_pCaloHitCreator; + delete m_pTrackCreator; + delete m_pMCParticleCreator; + delete m_pPfoCreator; + return GaudiAlgorithm::finalize(); +} + + + + +pandora::StatusCode PandoraPFAlg::RegisterUserComponents() const +{ + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterAlgorithms(*m_pPandora)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterBasicPlugins(*m_pPandora)); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterBFieldPlugin(*m_pPandora, + m_settings.m_innerBField, m_settings.m_muonBarrelBField, m_settings.m_muonEndCapBField)); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterNonLinearityEnergyCorrection(*m_pPandora, + "NonLinearity", pandora::HADRONIC, m_settings.m_inputEnergyCorrectionPoints, m_settings.m_outputEnergyCorrectionPoints)); + + return pandora::STATUS_CODE_SUCCESS; +} + + +void PandoraPFAlg::Reset() +{ + m_pCaloHitCreator->Reset(); + m_pTrackCreator->Reset(); + m_pMCParticleCreator->Reset(); + + std::vector<int>() .swap(m_pReco_PID ); + std::vector<float>().swap(m_pReco_mass); + std::vector<float>().swap(m_pReco_energy); + std::vector<float>().swap(m_pReco_px); + std::vector<float>().swap(m_pReco_py); + std::vector<float>().swap(m_pReco_pz); + std::vector<float>().swap(m_pReco_charge); + + std::vector<int>() .swap(m_mc_p_size); + std::vector<int>() .swap(m_mc_pid ); + std::vector<float>().swap(m_mc_mass ); + std::vector<float>().swap(m_mc_px ); + std::vector<float>().swap(m_mc_py ); + std::vector<float>().swap(m_mc_pz ); + std::vector<float>().swap(m_mc_charge); + m_hasConversion = 0; + + m_CollectionMaps->clear(); +} + +const pandora::Pandora *PandoraPFAlg::GetPandora() const +{ + if (NULL == m_pPandora) + throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + return m_pPandora; +} +PandoraPFAlg::Settings::Settings() : + m_innerBField(3.5f), + m_muonBarrelBField(-1.5f), + m_muonEndCapBField(0.01f) +{ +} +CollectionMaps::CollectionMaps() +{ +} +void CollectionMaps::clear() +{ +collectionMap_MC.clear(); +collectionMap_CaloHit.clear(); +collectionMap_Vertex.clear(); +collectionMap_Track.clear(); +collectionMap_CaloRel.clear(); +collectionMap_TrkRel.clear(); +} + +StatusCode PandoraPFAlg::updateMap() +{ + const edm4hep::MCParticleCollection* MCParticle = nullptr; + const edm4hep::CalorimeterHitCollection* ECALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* ECALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* ECALOther = nullptr; + const edm4hep::CalorimeterHitCollection* HCALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* HCALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* HCALOther = nullptr; + const edm4hep::CalorimeterHitCollection* MUON = nullptr; + const edm4hep::CalorimeterHitCollection* LCAL = nullptr; + const edm4hep::CalorimeterHitCollection* LHCAL = nullptr; + const edm4hep::CalorimeterHitCollection* BCAL = nullptr; + const edm4hep::VertexCollection* KinkVertices = nullptr; + const edm4hep::VertexCollection* ProngVertices = nullptr; + const edm4hep::VertexCollection* SplitVertices = nullptr; + const edm4hep::VertexCollection* V0Vertices = nullptr; + const edm4hep::TrackCollection* MarlinTrkTracks = nullptr; + const edm4hep::MCRecoCaloAssociationCollection* mcRecoCaloAssociation = nullptr; + const edm4hep::MCRecoTrackerAssociationCollection* mcRecoTrackerAssociation = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + sc = getCol(m_ECALBarrel_r, ECALBarrel ); + sc = getCol(m_ECALEndcap_r, ECALEndcap ); + sc = getCol(m_ECALOther_r , ECALOther ); + sc = getCol(m_HCALBarrel_r, HCALBarrel ); + sc = getCol(m_HCALEndcap_r, HCALEndcap ); + sc = getCol(m_HCALOther_r , HCALOther ); + sc = getCol(m_MUON_r , MUON ); + sc = getCol(m_LCAL_r , LCAL ); + sc = getCol(m_LHCAL_r , LHCAL ); + sc = getCol(m_BCAL_r , BCAL ); + sc = getCol(m_KinkVertices_r , KinkVertices ); + sc = getCol(m_ProngVertices_r , ProngVertices); + sc = getCol(m_SplitVertices_r , SplitVertices); + sc = getCol(m_V0Vertices_r , V0Vertices ); + sc = getCol(m_MarlinTrkTracks_r , MarlinTrkTracks ); + sc = getCol(m_MCRecoCaloAssociation_r , mcRecoCaloAssociation ); + sc = getCol(m_MCRecoTrackerAssociation_r , mcRecoTrackerAssociation); + + if (NULL != MCParticle ) + { + std::vector<edm4hep::MCParticle> v_mc; + m_CollectionMaps->collectionMap_MC ["MCParticle"] = v_mc; + for(unsigned int i=0 ; i< MCParticle->size(); i++) m_CollectionMaps->collectionMap_MC ["MCParticle"].push_back(MCParticle->at(i)); + } + if (NULL != ECALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["ECALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< ECALBarrel->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALBarrel"].push_back(ECALBarrel->at(i)); + } + if (NULL != ECALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["ECALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< ECALEndcap->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALEndcap"].push_back(ECALEndcap->at(i)); + } + if (NULL != ECALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["ECALOther"] = v_cal ; + for(unsigned int i=0 ; i< ECALOther->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALOther"].push_back(ECALOther->at(i)); + } + if (NULL != HCALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["HCALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< HCALBarrel->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALBarrel"].push_back(HCALBarrel->at(i)); + } + if (NULL != HCALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["HCALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< HCALEndcap->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALEndcap"].push_back(HCALEndcap->at(i)); + } + if (NULL != HCALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["HCALOther"] = v_cal ; + for(unsigned int i=0 ; i< HCALOther->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALOther"].push_back(HCALOther->at(i)); + } + if (NULL != MUON ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["MUON"] = v_cal ; + for(unsigned int i=0 ; i< MUON->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["MUON"].push_back(MUON->at(i)); + } + if (NULL != LCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["LCAL"] = v_cal ; + for(unsigned int i=0 ; i< LCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["LCAL"].push_back(LCAL->at(i)); + } + if (NULL != LHCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["LHCAL"] = v_cal ; + for(unsigned int i=0 ; i< LHCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["LHCAL"].push_back(LHCAL->at(i)); + } + if (NULL != BCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->collectionMap_CaloHit["BCAL"] = v_cal ; + for(unsigned int i=0 ; i< BCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["BCAL"].push_back(BCAL->at(i)); + } + if (NULL != KinkVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->collectionMap_Vertex["KinkVertices"] = v_cal ; + for(unsigned int i=0 ; i< KinkVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["KinkVertices"].push_back(KinkVertices->at(i)); + } + if (NULL != ProngVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->collectionMap_Vertex["ProngVertices"] = v_cal ; + for(unsigned int i=0 ; i< ProngVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["ProngVertices"].push_back(ProngVertices->at(i)); + } + if (NULL != SplitVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->collectionMap_Vertex["SplitVertices"] = v_cal ; + for(unsigned int i=0 ; i< SplitVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["SplitVertices"].push_back(SplitVertices->at(i)); + } + if (NULL != V0Vertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->collectionMap_Vertex["V0Vertices"] = v_cal ; + for(unsigned int i=0 ; i< V0Vertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["V0Vertices"].push_back(V0Vertices->at(i)); + } + if (NULL != MarlinTrkTracks ) + { + std::vector<edm4hep::Track> v_cal; + m_CollectionMaps->collectionMap_Track["MarlinTrkTracks"] = v_cal ; + for(unsigned int i=0 ; i< MarlinTrkTracks->size(); i++) m_CollectionMaps->collectionMap_Track ["MarlinTrkTracks"].push_back(MarlinTrkTracks->at(i)); + } + if (NULL != mcRecoCaloAssociation ) + { + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + m_CollectionMaps->collectionMap_CaloRel["RecoCaloAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoCaloAssociation->size(); i++) m_CollectionMaps->collectionMap_CaloRel ["RecoCaloAssociation"].push_back(mcRecoCaloAssociation->at(i)); + } + if (NULL != mcRecoTrackerAssociation ) + { + std::vector<edm4hep::MCRecoTrackerAssociation> v_cal; + m_CollectionMaps->collectionMap_TrkRel["RecoTrackerAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoTrackerAssociation->size(); i++) m_CollectionMaps->collectionMap_TrkRel ["RecoTrackerAssociation"].push_back(mcRecoTrackerAssociation->at(i)); + } + return StatusCode::SUCCESS; +} + + + + +StatusCode PandoraPFAlg::Ana() +{ + int n_current = m_tree->GetEntries()+1; + const edm4hep::ReconstructedParticleCollection* reco_col = m_ReconstructedParticleCollection_w.get(); + const edm4hep::MCRecoParticleAssociationCollection* reco_associa_col = m_MCRecoParticleAssociation_w.get(); + for(int i=0; i<reco_col->size();i++) + { + const edm4hep::ReconstructedParticle pReco = reco_col->at(i); + const float px = pReco.getMomentum()[0]; + const float py = pReco.getMomentum()[1]; + const float pz = pReco.getMomentum()[2]; + const float energy = pReco.getEnergy(); + const float mass = pReco.getMass(); + const float charge = pReco.getCharge(); + const int type = pReco.getType(); + m_pReco_PID.push_back(type); + m_pReco_mass.push_back(mass); + m_pReco_charge.push_back(charge); + m_pReco_energy.push_back(energy); + m_pReco_px.push_back(px); + m_pReco_py.push_back(py); + m_pReco_pz.push_back(pz); + for(int j=0; j < reco_associa_col->size(); j++) + { + if(reco_associa_col->at(j).getRec().id() != pReco.id() ) continue; + std::cout<<"MC pid ="<<reco_associa_col->at(j).getSim().getPDG()<<",weight="<<reco_associa_col->at(j).getWeight()<<", px="<<reco_associa_col->at(j).getSim().getMomentum()[0]<<", py="<<reco_associa_col->at(j).getSim().getMomentum()[1]<<",pz="<<reco_associa_col->at(j).getSim().getMomentum()[2]<<std::endl; + } + } + const edm4hep::MCParticleCollection* MCParticle = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + if (NULL != MCParticle ) + { + for(unsigned int i=0 ; i< MCParticle->size(); i++) + { + m_mc_p_size.push_back(MCParticle->at(i).parents_size()); + m_mc_pid .push_back(MCParticle->at(i).getPDG()); + m_mc_mass .push_back(MCParticle->at(i).getMass()); + m_mc_px .push_back(MCParticle->at(i).getMomentum()[0]); + m_mc_py .push_back(MCParticle->at(i).getMomentum()[1]); + m_mc_pz .push_back(MCParticle->at(i).getMomentum()[2]); + m_mc_charge.push_back(MCParticle->at(i).getCharge()); + //if(MCParticle->at(i).parents_size()==0) std::cout<<"MYDBUG evt="<<n_current<<", mc i="<<i<<",px="<<MCParticle->at(i).getMomentum()[0]<<",py="<<MCParticle->at(i).getMomentum()[1]<<",pz="<<MCParticle->at(i).getMomentum()[2]<<std::endl; + if (MCParticle->at(i).getPDG() != 22) continue; + int hasEm = 0; + int hasEp = 0; + for(unsigned int j =0 ; j< MCParticle->at(i).daughters_size(); j++) + { + if (MCParticle->at(i).getDaughters(j).getPDG() == 11 ) hasEm=1; + else if (MCParticle->at(i).getDaughters(j).getPDG() == -11 ) hasEp=1; + } + if(hasEm && hasEp) m_hasConversion=1; + } + } + m_tree->Fill(); + return StatusCode::SUCCESS; +} + + +// create simple MCRecoParticleAssociation using calorimeter hit only now +StatusCode PandoraPFAlg::CreateMCRecoParticleAssociation() +{ + edm4hep::MCRecoParticleAssociationCollection* pMCRecoParticleAssociationCollection = m_MCRecoParticleAssociation_w.createAndPut(); + const edm4hep::ReconstructedParticleCollection* reco_col = m_ReconstructedParticleCollection_w.get(); + for(int i=0; i<reco_col->size();i++) + { + std::map<int, edm4hep::ConstMCParticle> mc_map; + std::map<int, float > id_edep_map; + float tot_en = 0 ; + const edm4hep::ReconstructedParticle pReco = reco_col->at(i); + for(int j=0; j < pReco.clusters_size(); j++) + { + edm4hep::ConstCluster cluster = pReco.getClusters(j); + for(int k=0; k < cluster.hits_size(); k++) + { + edm4hep::ConstCalorimeterHit hit = cluster.getHits(k); + for(std::map<std::string, std::vector<edm4hep::MCRecoCaloAssociation> >::iterator iter = m_CollectionMaps->collectionMap_CaloRel.begin(); iter != m_CollectionMaps->collectionMap_CaloRel.end(); iter++) + { + for(std::vector<edm4hep::MCRecoCaloAssociation>::iterator it = iter->second.begin(); it != iter->second.end(); it ++) + { + if(it->getRec().id() != hit.id()) continue; + for(std::vector<edm4hep::ConstCaloHitContribution>::const_iterator itc = it->getSim().contributions_begin(); itc != it->getSim().contributions_end(); itc++) + { + if(mc_map.find(itc->getParticle().id()) == mc_map.end()) mc_map[itc->getParticle().id()] = itc->getParticle() ; + if(id_edep_map.find(itc->getParticle().id()) != id_edep_map.end()) id_edep_map[itc->getParticle().id()] = id_edep_map[itc->getParticle().id()] + itc->getEnergy() ; + else id_edep_map[itc->getParticle().id()] = itc->getEnergy() ; + tot_en += itc->getEnergy() ; + } + } + } + } + } + for(std::map<int, edm4hep::ConstMCParticle>::iterator it = mc_map.begin(); it != mc_map.end(); it ++) + { + edm4hep::MCRecoParticleAssociation association = pMCRecoParticleAssociationCollection->create(); + association.setRec(pReco); + association.setSim(it->second); + if(tot_en==0) + { + association.setWeight(0); + std::cout<<"Found 0 cluster energy"<<std::endl; + } + else if(id_edep_map.find(it->first) != id_edep_map.end()) association.setWeight(id_edep_map[it->first]/tot_en); + else std::cout<<"Error in creating MCRecoParticleAssociation"<<std::endl; + } + } + return StatusCode::SUCCESS; +} + + diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/PfoCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/PfoCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce3cedd677748da435ee71bd1897c94a20ac7f67 --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/PfoCreator.cpp @@ -0,0 +1,410 @@ +/** + * @brief Implementation of the pfo creator class. + * + * $Log: $ + */ + + +#include "Api/PandoraApi.h" + +#include "Objects/Cluster.h" +#include "Objects/ParticleFlowObject.h" +#include "Objects/Track.h" + +#include "Pandora/PdgTable.h" +#include "PfoCreator.h" +#include "PandoraPFAlg.h" + +#include <algorithm> +#include <cmath> + +PfoCreator::PfoCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora) +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PfoCreator::~PfoCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode PfoCreator::CreateParticleFlowObjects(CollectionMaps& collectionMaps, DataHandle<edm4hep::ClusterCollection>& _pClusterCollection, DataHandle<edm4hep::ReconstructedParticleCollection>& _pReconstructedParticleCollection, DataHandle<edm4hep::VertexCollection>& _pStartVertexCollection) +{ + m_collectionMaps = &collectionMaps; + edm4hep::ClusterCollection* pClusterCollection = _pClusterCollection.createAndPut(); + edm4hep::ReconstructedParticleCollection* pReconstructedParticleCollection = _pReconstructedParticleCollection.createAndPut(); + edm4hep::VertexCollection* pStartVertexCollection = _pStartVertexCollection.createAndPut(); + + const pandora::PfoList *pPandoraPfoList = NULL; + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pPandora, pPandoraPfoList)); + + pandora::StringVector subDetectorNames; + this->InitialiseSubDetectorNames(subDetectorNames); + + std::cout<<"pPandoraPfoList size="<<pPandoraPfoList->size()<<std::endl; + for (pandora::PfoList::const_iterator pIter = pPandoraPfoList->begin(), pIterEnd = pPandoraPfoList->end(); pIter != pIterEnd; ++pIter) + { + const pandora::ParticleFlowObject *const pPandoraPfo(*pIter); + edm4hep::ReconstructedParticle pReconstructedParticle0 = pReconstructedParticleCollection->create(); + edm4hep::ReconstructedParticle* pReconstructedParticle = &pReconstructedParticle0; + + const bool hasTrack(!pPandoraPfo->GetTrackList().empty()); + const pandora::ClusterList &clusterList(pPandoraPfo->GetClusterList()); + + float clustersTotalEnergy(0.f); + pandora::CartesianVector referencePoint(0.f, 0.f, 0.f), clustersWeightedPosition(0.f, 0.f, 0.f); + for (pandora::ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter) + { + const pandora::Cluster *const pPandoraCluster(*cIter); + pandora::CaloHitList pandoraCaloHitList; + pPandoraCluster->GetOrderedCaloHitList().FillCaloHitList(pandoraCaloHitList); + pandoraCaloHitList.insert(pandoraCaloHitList.end(), pPandoraCluster->GetIsolatedCaloHitList().begin(), pPandoraCluster->GetIsolatedCaloHitList().end()); + + pandora::FloatVector hitE, hitX, hitY, hitZ; + edm4hep::Cluster p_Cluster0 = pClusterCollection->create(); + edm4hep::Cluster* p_Cluster = &p_Cluster0; + this->SetClusterSubDetectorEnergies(subDetectorNames, p_Cluster, pandoraCaloHitList, hitE, hitX, hitY, hitZ); + + float clusterCorrectEnergy(0.f); + this->SetClusterEnergyAndError(pPandoraPfo, pPandoraCluster, p_Cluster, clusterCorrectEnergy); + + pandora::CartesianVector clusterPosition(0.f, 0.f, 0.f); + const unsigned int nHitsInCluster(pandoraCaloHitList.size()); + this->SetClusterPositionAndError(nHitsInCluster, hitE, hitX, hitY, hitZ, p_Cluster, clusterPosition); + + if (!hasTrack) + { + clustersWeightedPosition += clusterPosition * clusterCorrectEnergy; + clustersTotalEnergy += clusterCorrectEnergy; + } + + edm4hep::ConstCluster p_ClusterCon = *p_Cluster; + pReconstructedParticle->addToClusters(p_ClusterCon); + } + + if (!hasTrack) + { + if (clustersTotalEnergy < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING PfoCreator::CreateParticleFlowObjects: invalid cluster energy " << clustersTotalEnergy << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = clustersWeightedPosition * (1.f / clustersTotalEnergy); + } + } + else + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CalculateTrackBasedReferencePoint(pPandoraPfo, referencePoint)); + } + + this->SetRecoParticleReferencePoint(referencePoint, pReconstructedParticle); + this->AddTracksToRecoParticle(pPandoraPfo, pReconstructedParticle); + this->SetRecoParticlePropertiesFromPFO(pPandoraPfo, pReconstructedParticle); + + edm4hep::Vertex pStartVertex0 = pStartVertexCollection->create(); + edm4hep::Vertex* pStartVertex = &pStartVertex0; + pStartVertex->setAlgorithmType(0); + const float ref_value[3] = {referencePoint.GetX(),referencePoint.GetY(),referencePoint.GetZ()}; + pStartVertex->setPosition(edm4hep::Vector3f(ref_value)); + pStartVertex->setAssociatedParticle(*pReconstructedParticle); + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::InitialiseSubDetectorNames(pandora::StringVector &subDetectorNames) const +{ + subDetectorNames.push_back("ecal"); + subDetectorNames.push_back("hcal"); + subDetectorNames.push_back("yoke"); + subDetectorNames.push_back("lcal"); + subDetectorNames.push_back("lhcal"); + subDetectorNames.push_back("bcal"); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterSubDetectorEnergies(const pandora::StringVector &subDetectorNames, edm4hep::Cluster *const p_Cluster, + const pandora::CaloHitList &pandoraCaloHitList, pandora::FloatVector &hitE, pandora::FloatVector &hitX, pandora::FloatVector &hitY, + pandora::FloatVector &hitZ) const +{ + for (pandora::CaloHitList::const_iterator hIter = pandoraCaloHitList.begin(), hIterEnd = pandoraCaloHitList.end(); hIter != hIterEnd; ++hIter) + { + const pandora::CaloHit *const pPandoraCaloHit(*hIter); + edm4hep::CalorimeterHit *const pCalorimeterHit0 = (edm4hep::CalorimeterHit*)(pPandoraCaloHit->GetParentAddress()); + const edm4hep::CalorimeterHit pCalorimeterHit = *pCalorimeterHit0; + + p_Cluster->addToHits(pCalorimeterHit); + + const float caloHitEnergy(pCalorimeterHit.getEnergy()); + hitE.push_back(caloHitEnergy); + hitX.push_back(pCalorimeterHit.getPosition()[0]); + hitY.push_back(pCalorimeterHit.getPosition()[1]); + hitZ.push_back(pCalorimeterHit.getPosition()[2]); + /*Can be added later + std::vector<float> &subDetectorEnergies = p_Cluster->subdetectorEnergies(); + subDetectorEnergies.resize(subDetectorNames.size()); + + switch (CHT(pCalorimeterHit->getType()).caloID()) + { + case CHT::ecal: subDetectorEnergies[ECAL_INDEX ] += caloHitEnergy; break; + case CHT::hcal: subDetectorEnergies[HCAL_INDEX ] += caloHitEnergy; break; + case CHT::yoke: subDetectorEnergies[YOKE_INDEX ] += caloHitEnergy; break; + case CHT::lcal: subDetectorEnergies[LCAL_INDEX ] += caloHitEnergy; break; + case CHT::lhcal: subDetectorEnergies[LHCAL_INDEX] += caloHitEnergy; break; + case CHT::bcal: subDetectorEnergies[BCAL_INDEX ] += caloHitEnergy; break; + default: streamlog_out(WARNING) << "PfoCreator::SetClusterSubDetectorEnergies: no subdetector found for hit with type: " << pCalorimeterHit->getType() << std::endl; + } + */ + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterEnergyAndError(const pandora::ParticleFlowObject *const pPandoraPfo, const pandora::Cluster *const pPandoraCluster, + edm4hep::Cluster *const p_Cluster, float &clusterCorrectEnergy) const +{ + const bool isEmShower((pandora::PHOTON == pPandoraPfo->GetParticleId()) || (pandora::E_MINUS == std::abs(pPandoraPfo->GetParticleId()))); + clusterCorrectEnergy = (isEmShower ? pPandoraCluster->GetCorrectedElectromagneticEnergy(*m_pPandora) : pPandoraCluster->GetCorrectedHadronicEnergy(*m_pPandora)); + + if (clusterCorrectEnergy < std::numeric_limits<float>::epsilon()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + + const float stochasticTerm(isEmShower ? m_settings.m_emStochasticTerm : m_settings.m_hadStochasticTerm); + const float constantTerm(isEmShower ? m_settings.m_emConstantTerm : m_settings.m_hadConstantTerm); + const float energyError(std::sqrt(stochasticTerm * stochasticTerm / clusterCorrectEnergy + constantTerm * constantTerm) * clusterCorrectEnergy); + + p_Cluster->setEnergy(clusterCorrectEnergy); + p_Cluster->setEnergyError(energyError); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterPositionAndError(const unsigned int nHitsInCluster, pandora::FloatVector &hitE, pandora::FloatVector &hitX, + pandora::FloatVector &hitY, pandora::FloatVector &hitZ, edm4hep::Cluster *const p_Cluster, pandora::CartesianVector &clusterPositionVec) const +{ + ClusterShapes *const pClusterShapes(new ClusterShapes(nHitsInCluster, hitE.data(), hitX.data(), hitY.data(), hitZ.data()));//this need GSL/1.14 + + try + { + p_Cluster->setPhi(std::atan2(pClusterShapes->getEigenVecInertia()[1], pClusterShapes->getEigenVecInertia()[0])); + p_Cluster->setITheta(std::acos(pClusterShapes->getEigenVecInertia()[2])); + p_Cluster->setPosition(pClusterShapes->getCentreOfGravity()); + clusterPositionVec.SetValues(pClusterShapes->getCentreOfGravity()[0], pClusterShapes->getCentreOfGravity()[1], pClusterShapes->getCentreOfGravity()[2]); + } + catch (...) + { + std::cout<<"WARNING PfoCreator::SetClusterPositionAndError: unidentified exception caught." << std::endl; + } + + delete pClusterShapes; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode PfoCreator::CalculateTrackBasedReferencePoint(const pandora::ParticleFlowObject *const pPandoraPfo, pandora::CartesianVector &referencePoint) const +{ + const pandora::TrackList &trackList(pPandoraPfo->GetTrackList()); + + float totalTrackMomentumAtDca(0.f), totalTrackMomentumAtStart(0.f); + pandora::CartesianVector referencePointAtDCAWeighted(0.f, 0.f, 0.f), referencePointAtStartWeighted(0.f, 0.f, 0.f); + + bool hasSiblings(false); + for (pandora::TrackList::const_iterator tIter = trackList.begin(), tIterEnd = trackList.end(); tIter != tIterEnd; ++tIter) + { + const pandora::Track *const pPandoraTrack(*tIter); + + if (!this->IsValidParentTrack(pPandoraTrack, trackList)) + continue; + + if (this->HasValidSiblingTrack(pPandoraTrack, trackList)) + { + // Presence of sibling tracks typically represents a conversion + const pandora::CartesianVector &trackStartPoint((pPandoraTrack->GetTrackStateAtStart()).GetPosition()); + const float trackStartMomentum(((pPandoraTrack->GetTrackStateAtStart()).GetMomentum()).GetMagnitude()); + referencePointAtStartWeighted += trackStartPoint * trackStartMomentum; + totalTrackMomentumAtStart += trackStartMomentum; + hasSiblings = true; + } + else + { + const edm4hep::Track *const pLcioTrack0 = (edm4hep::Track*)(pPandoraTrack->GetParentAddress()); + const edm4hep::Track pLcioTrack = *pLcioTrack0; + + const float z0(pPandoraTrack->GetZ0()); + pandora::CartesianVector intersectionPoint(0.f, 0.f, 0.f); + + if(pLcioTrack.trackStates_size()==0) throw "zero trackStates size find"; + intersectionPoint.SetValues(pLcioTrack.getTrackStates(0).D0 * std::cos(pLcioTrack.getTrackStates(0).phi), pLcioTrack.getTrackStates(0).D0 * std::sin(pLcioTrack.getTrackStates(0).phi), z0); + const float trackMomentumAtDca((pPandoraTrack->GetMomentumAtDca()).GetMagnitude()); + referencePointAtDCAWeighted += intersectionPoint * trackMomentumAtDca; + totalTrackMomentumAtDca += trackMomentumAtDca; + } + } + + if (hasSiblings) + { + if (totalTrackMomentumAtStart < std::numeric_limits<float>::epsilon()) + { + std::cout<<" WARNING PfoCreator::CalculateTrackBasedReferencePoint: invalid track momentum " << totalTrackMomentumAtStart << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = referencePointAtStartWeighted * (1.f / totalTrackMomentumAtStart); + } + } + else + { + if (totalTrackMomentumAtDca < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING PfoCreator::CalculateTrackBasedReferencePoint: invalid track momentum " << totalTrackMomentumAtDca << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = referencePointAtDCAWeighted * (1.f / totalTrackMomentumAtDca); + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::IsValidParentTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &parentTrackList(pPandoraTrack->GetParentList()); + + for (pandora::TrackList::const_iterator iter = parentTrackList.begin(), iterEnd = parentTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + continue; + + // ATTN This track must have a parent not in the all track list; still use it if it is the closest to the ip + std::cout<<"WARNING PfoCreator::IsValidParentTrack: mismatch in track relationship information, use information as available " << std::endl; + + if (this->IsClosestTrackToIP(pPandoraTrack, allTrackList)) + return true; + + return false; + } + + // Ideal case: All parents are associated to same pfo + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::HasValidSiblingTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &siblingTrackList(pPandoraTrack->GetSiblingList()); + + for (pandora::TrackList::const_iterator iter = siblingTrackList.begin(), iterEnd = siblingTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + continue; + + // ATTN This track must have a sibling not in the all track list; still use it if it has a second sibling that is in the list + std::cout<<"WARNING PfoCreator::HasValidSiblingTrack: mismatch in track relationship information, use information as available " << std::endl; + + if (this->AreAnyOtherSiblingsInList(pPandoraTrack, allTrackList)) + return true; + + return false; + } + + // Ideal case: All siblings associated to same pfo + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::IsClosestTrackToIP(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::Track *pClosestTrack(NULL); + float closestTrackDisplacement(std::numeric_limits<float>::max()); + + for (pandora::TrackList::const_iterator iter = allTrackList.begin(), iterEnd = allTrackList.end(); iter != iterEnd; ++iter) + { + const pandora::Track *const pTrack(*iter); + const float trialTrackDisplacement(pTrack->GetTrackStateAtStart().GetPosition().GetMagnitude()); + + if (trialTrackDisplacement < closestTrackDisplacement) + { + closestTrackDisplacement = trialTrackDisplacement; + pClosestTrack = pTrack; + } + } + + return (pPandoraTrack == pClosestTrack); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::AreAnyOtherSiblingsInList(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &siblingTrackList(pPandoraTrack->GetSiblingList()); + + for (pandora::TrackList::const_iterator iter = siblingTrackList.begin(), iterEnd = siblingTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + return true; + } + + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetRecoParticleReferencePoint(const pandora::CartesianVector &referencePoint, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const float referencePointArray[3] = {referencePoint.GetX(), referencePoint.GetY(), referencePoint.GetZ()}; + pReconstructedParticle->setReferencePoint(referencePointArray); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::AddTracksToRecoParticle(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const pandora::TrackList &trackList(pPandoraPfo->GetTrackList()); + + for (pandora::TrackList::const_iterator tIter = trackList.begin(), tIterEnd = trackList.end(); tIter != tIterEnd; ++tIter) + { + const pandora::Track *const pTrack(*tIter); + const edm4hep::Track *const pLcioTrack0 = (edm4hep::Track*)(pTrack->GetParentAddress()); + const edm4hep::Track pLcioTrack = *pLcioTrack0; + pReconstructedParticle->addToTracks(pLcioTrack); + + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetRecoParticlePropertiesFromPFO(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const float momentum[3] = {pPandoraPfo->GetMomentum().GetX(), pPandoraPfo->GetMomentum().GetY(), pPandoraPfo->GetMomentum().GetZ()}; + pReconstructedParticle->setMomentum(momentum); + pReconstructedParticle->setEnergy(pPandoraPfo->GetEnergy()); + pReconstructedParticle->setMass(pPandoraPfo->GetMass()); + pReconstructedParticle->setCharge(pPandoraPfo->GetCharge()); + pReconstructedParticle->setType(pPandoraPfo->GetParticleId()); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PfoCreator::Settings::Settings(): + m_emStochasticTerm(0.17f), + m_hadStochasticTerm(0.6f), + m_emConstantTerm(0.01f), + m_hadConstantTerm(0.03f) +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/TrackCreator.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/TrackCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8dc23c5725546cdb3626cbe3b4c1281648e4da8a --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/TrackCreator.cpp @@ -0,0 +1,948 @@ +/** + * + * @brief Implementation of the track creator class. + * + * $Log: $ + */ + + +//#include "UTIL/ILDConf.h" + +#include "edm4hep/Vertex.h" +#include "edm4hep/ReconstructedParticle.h" + +#include "gear/BField.h" +#include "gear/CalorimeterParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/TPCParameters.h" +#include "gear/FTDParameters.h" +#include "gear/FTDLayerLayout.h" + +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" +#include "PandoraPFAlg.h" + +#include "TrackCreator.h" +#include "Pandora/PdgTable.h" + +#include <algorithm> +#include <cmath> +#include <limits> + +TrackCreator::TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc) : + m_settings(settings), + m_pPandora(pPandora) +{ + + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + m_bField = (_GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z()); + m_tpcInnerR = (_GEAR->getTPCParameters().getPadLayout().getPlaneExtent()[0]); + m_tpcOuterR = (_GEAR->getTPCParameters().getPadLayout().getPlaneExtent()[1]); + m_tpcMaxRow = (_GEAR->getTPCParameters().getPadLayout().getNRows()); + m_tpcZmax = (_GEAR->getTPCParameters().getMaxDriftLength()); + m_eCalBarrelInnerSymmetry = (_GEAR->getEcalBarrelParameters().getSymmetryOrder()); + m_eCalBarrelInnerPhi0 = (_GEAR->getEcalBarrelParameters().getPhi0()); + m_eCalBarrelInnerR = (_GEAR->getEcalBarrelParameters().getExtent()[0]); + m_eCalEndCapInnerZ = (_GEAR->getEcalEndcapParameters().getExtent()[2]); + // fg: FTD description in GEAR has changed ... + try + { + m_ftdInnerRadii = _GEAR->getGearParameters("FTD").getDoubleVals("FTDInnerRadius"); + m_ftdOuterRadii = _GEAR->getGearParameters("FTD").getDoubleVals("FTDOuterRadius"); + m_ftdZPositions = _GEAR->getGearParameters("FTD").getDoubleVals("FTDZCoordinate"); + m_nFtdLayers = m_ftdZPositions.size(); + } + catch (gear::UnknownParameterException &) + { + const gear::FTDLayerLayout &ftdLayerLayout(_GEAR->getFTDParameters().getFTDLayerLayout()); + std::cout << " Filling FTD parameters from gear::FTDParameters - n layers: " << ftdLayerLayout.getNLayers() << std::endl; + + for(unsigned int i = 0, N = ftdLayerLayout.getNLayers(); i < N; ++i) + { + // Create a disk to represent even number petals front side + m_ftdInnerRadii.push_back(ftdLayerLayout.getSensitiveRinner(i)); + m_ftdOuterRadii.push_back(ftdLayerLayout.getMaxRadius(i)); + + // Take the mean z position of the staggered petals + const double zpos(ftdLayerLayout.getZposition(i)); + m_ftdZPositions.push_back(zpos); + std::cout << " layer " << i << " - mean z position = " << zpos << std::endl; + } + + m_nFtdLayers = m_ftdZPositions.size() ; + } + + // Check tpc parameters + if ((std::fabs(m_tpcZmax) < std::numeric_limits<float>::epsilon()) || (std::fabs(m_tpcInnerR) < std::numeric_limits<float>::epsilon()) + || (std::fabs(m_tpcOuterR - m_tpcInnerR) < std::numeric_limits<float>::epsilon())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + m_cosTpc = m_tpcZmax / std::sqrt(m_tpcZmax * m_tpcZmax + m_tpcInnerR * m_tpcInnerR); + + // Check ftd parameters + if ((0 == m_nFtdLayers) || (m_nFtdLayers != m_ftdInnerRadii.size()) || (m_nFtdLayers != m_ftdOuterRadii.size())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + for (unsigned int iFtdLayer = 0; iFtdLayer < m_nFtdLayers; ++iFtdLayer) + { + if ((std::fabs(m_ftdOuterRadii[iFtdLayer]) < std::numeric_limits<float>::epsilon()) || + (std::fabs(m_ftdInnerRadii[iFtdLayer]) < std::numeric_limits<float>::epsilon())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + } + + m_tanLambdaFtd = m_ftdZPositions[0] / m_ftdOuterRadii[0]; + + // Calculate etd and set parameters + // fg: make SET and ETD optional - as they might not be in the model ... + try + { + const DoubleVector &etdZPositions(_GEAR->getGearParameters("ETD").getDoubleVals("ETDLayerZ")); + const DoubleVector &setInnerRadii(_GEAR->getGearParameters("SET").getDoubleVals("SETLayerRadius")); + + if (etdZPositions.empty() || setInnerRadii.empty()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + + m_minEtdZPosition = *(std::min_element(etdZPositions.begin(), etdZPositions.end())); + m_minSetRadius = *(std::min_element(setInnerRadii.begin(), setInnerRadii.end())); + } + catch(gear::UnknownParameterException &) + { + std::cout << "Warnning, ETDLayerZ or SETLayerRadius parameters missing from GEAR parameters!" << std::endl + << " -> both will be set to " << std::numeric_limits<float>::quiet_NaN() << std::endl; + + //fg: Set them to NAN, so that they cannot be used to set trackParameters.m_reachesCalorimeter = true; + m_minEtdZPosition = std::numeric_limits<float>::quiet_NaN(); + m_minSetRadius = std::numeric_limits<float>::quiet_NaN(); + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +TrackCreator::~TrackCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::CreateTrackAssociations(const CollectionMaps& collectionMaps)//TODO, due to the lack of full Vertex information +{ +// TODO, because the Vertex.getAssociatedParticle() doesn't work for LCIO to plcio transfer +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractKinks(collectionMaps)); +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractProngsAndSplits(const CollectionMaps& collectionMaps)); +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractV0s(const CollectionMaps& collectionMaps)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode TrackCreator::ExtractKinks(const CollectionMaps& collectionMaps) +{ + std::cout<<"start TrackCreator::ExtractKinks:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_kinkVertexCollections.begin(), iterEnd = m_settings.m_kinkVertexCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.CollectionMap_Vertex.find(*iter) == collectionMaps.CollectionMap_Vertex.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const edm4hep::VertexCollection *pKinkCollection = (collectionMaps.CollectionMap_Vertex.find(*iter))->second; + + for (int i = 0, iMax = pKinkCollection->size(); i < iMax; ++i) + { + try + { + const edm4hep::Vertex pVertex0 = pKinkCollection->at(i); + const edm4hep::Vertex* pVertex = &(pVertex0); + + if (NULL == pVertex) throw ("Collection type mismatch"); + + std::cout<<"pVertex0 getChi2="<<pVertex0.getChi2()<<std::endl; + std::cout<<"pVertex getChi2="<<pVertex->getChi2()<<std::endl; + std::cout<<"Hi 0 "<<std::endl; + const plcio::ConstReconstructedParticle pReconstructedParticle0 = pVertex0.getAssociatedParticle(); + std::cout<<"Hi 1"<<std::endl; + //EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const plcio::ConstReconstructedParticle pReconstructedParticle = pVertex->getAssociatedParticle(); + std::cout<<"Hi 2:"<<&pReconstructedParticle<<std::endl; + //const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + //plcio::ConstTrack trackVec = pReconstructedParticle.getTracks(); + + std::cout<<"pReconstructedParticle0 en="<<pReconstructedParticle0.getEnergy()<<std::endl; + std::cout<<"pReconstructedParticle en="<<pReconstructedParticle.getEnergy()<<std::endl; + //if (this->IsConflictingRelationship(trackVec))continue; + if (this->IsConflictingRelationship(pReconstructedParticle))continue; + + //const int vertexPdgCode(pReconstructedParticle->getType()); + const int vertexPdgCode(pReconstructedParticle.getType()); + + // Extract the kink vertex information + //for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + //for (unsigned int iTrack = 0, nTracks = trackVec.tracks_size(); iTrack < nTracks; ++iTrack) + for (unsigned int iTrack = 0, nTracks = pReconstructedParticle.tracks_size(); iTrack < nTracks; ++iTrack) + { + //EVENT::Track *pTrack = trackVec[iTrack]; + //plcio::ConstTrack pTrack = trackVec.getTracks(iTrack); + plcio::ConstTrack pTrack = pReconstructedParticle.getTracks(iTrack); + //(0 == iTrack) ? m_parentTrackList.insert(pTrack) : m_daughterTrackList.insert(pTrack); + (0 == iTrack) ? m_parentTrackList.insert(pTrack.id()) : m_daughterTrackList.insert(pTrack.id()); + //std::cout << "KinkTrack " << iTrack << ", nHits " << pTrack.getTrackerHits().size() << std::endl; + std::cout << "KinkTrack " << iTrack << ", nHits " << pTrack.trackerHits_size() << std::endl; + + int trackPdgCode = pandora::UNKNOWN_PARTICLE_TYPE; + + if (0 == iTrack) + { + trackPdgCode = vertexPdgCode; + } + else + { + switch (vertexPdgCode) + { + case pandora::PI_PLUS : + case pandora::K_PLUS : + trackPdgCode = pandora::MU_PLUS; + break; + case pandora::PI_MINUS : + case pandora::K_MINUS : + trackPdgCode = pandora::MU_MINUS; + break; + case pandora::HYPERON_MINUS_BAR : + case pandora::SIGMA_PLUS : + trackPdgCode = pandora::PI_PLUS; + break; + case pandora::SIGMA_MINUS : + case pandora::HYPERON_MINUS : + trackPdgCode = pandora::PI_PLUS; + break; + default : + //(pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + (pTrack.getTrackStates(0).omega > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + } + } + + m_trackToPidMap.insert(TrackToPidMap::value_type(pTrack, trackPdgCode)); + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track parent-daughter relationships + if (0 == iTrack) + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, pTrack, trackVec[jTrack])); + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(trackVec.getTracks(jTrack).id()) ) ); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(pReconstructedParticle.getTracks(jTrack).id()) ) ); + } + } + + // Make track sibling relationships + else + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, pTrack, trackVec[jTrack])); + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(trackVec.getTracks(jTrack).id()) )); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(pReconstructedParticle.getTracks(jTrack).id()) )); + } + } + } + } + catch (...) + { + std::cout << "Failed to extract kink vertex: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract kink vertex collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode TrackCreator::ExtractProngsAndSplits(const EVENT::LCEvent *const pLCEvent) +{ + for (StringVector::const_iterator iter = m_settings.m_prongSplitVertexCollections.begin(), iterEnd = m_settings.m_prongSplitVertexCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pProngOrSplitCollection = pLCEvent->getCollection(*iter); + + for (int i = 0, iMax = pProngOrSplitCollection->getNumberOfElements(); i < iMax; ++i) + { + try + { + EVENT::Vertex *pVertex = dynamic_cast<Vertex*>(pProngOrSplitCollection->getElementAt(i)); + + if (NULL == pVertex) + throw EVENT::Exception("Collection type mismatch"); + + EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + + if (this->IsConflictingRelationship(trackVec)) + continue; + + // Extract the prong/split vertex information + for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + { + EVENT::Track *pTrack = trackVec[iTrack]; + (0 == iTrack) ? m_parentTrackList.insert(pTrack) : m_daughterTrackList.insert(pTrack); + streamlog_out(DEBUG) << "Prong or Split Track " << iTrack << ", nHits " << pTrack->getTrackerHits().size() << std::endl; + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track parent-daughter relationships + if (0 == iTrack) + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + + // Make track sibling relationships + else + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract prong/split vertex: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract prong/split vertex collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::ExtractV0s(const EVENT::LCEvent *const pLCEvent) +{ + for (StringVector::const_iterator iter = m_settings.m_v0VertexCollections.begin(), iterEnd = m_settings.m_v0VertexCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pV0Collection = pLCEvent->getCollection(*iter); + + for (int i = 0, iMax = pV0Collection->getNumberOfElements(); i < iMax; ++i) + { + try + { + EVENT::Vertex *pVertex = dynamic_cast<Vertex*>(pV0Collection->getElementAt(i)); + + if (NULL == pVertex) + throw EVENT::Exception("Collection type mismatch"); + + EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + + if (this->IsConflictingRelationship(trackVec)) + continue; + + // Extract the v0 vertex information + const int vertexPdgCode(pReconstructedParticle->getType()); + + for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + { + EVENT::Track *pTrack = trackVec[iTrack]; + m_v0TrackList.insert(pTrack); + streamlog_out(DEBUG) << "V0Track " << iTrack << ", nHits " << pTrack->getTrackerHits().size() << std::endl; + + int trackPdgCode = pandora::UNKNOWN_PARTICLE_TYPE; + + switch (vertexPdgCode) + { + case pandora::PHOTON : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::E_PLUS : trackPdgCode = pandora::E_MINUS; + break; + case pandora::LAMBDA : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PROTON : trackPdgCode = pandora::PI_MINUS; + break; + case pandora::LAMBDA_BAR : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PROTON_BAR; + break; + case pandora::K_SHORT : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + default : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + } + + m_trackToPidMap.insert(TrackToPidMap::value_type(pTrack, trackPdgCode)); + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track sibling relationships + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract v0 vertex: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract v0 vertex collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool TrackCreator::IsConflictingRelationship(const edm4hep::ConstReconstructedParticle &Particle) const +{ + for (unsigned int iTrack = 0, nTracks = Particle.tracks_size(); iTrack < nTracks; ++iTrack) + { + edm4hep::ConstTrack pTrack = Particle.getTracks(iTrack) ; + unsigned int pTrack_id = pTrack.id() ; + + if (this->IsDaughter(pTrack_id) || this->IsParent(pTrack_id) || this->IsV0(pTrack_id)) + return true; + } + + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::CreateTracks(const CollectionMaps& collectionMaps) +{ + std::cout<<"start TrackCreator::CreateTracks:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_trackCollections.begin(), iterEnd = m_settings.m_trackCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_Track.find(*iter) == collectionMaps.collectionMap_Track.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::Track>& pTrackCollection = (collectionMaps.collectionMap_Track.find(*iter))->second; + + for (int i = 0, iMax = pTrackCollection.size(); i < iMax; ++i) + { + try + { + const edm4hep::Track& pTrack0 = pTrackCollection.at(i); + const edm4hep::Track* pTrack = (const edm4hep::Track*)(&pTrack0); + + if (NULL == pTrack) throw ("Collection type mismatch"); + + int minTrackHits = m_settings.m_minTrackHits; + const float tanLambda(std::fabs(pTrack->getTrackStates(0).tanLambda)); + + if (tanLambda > m_tanLambdaFtd) + { + int expectedFtdHits(0); + + for (unsigned int iFtdLayer = 0; iFtdLayer < m_nFtdLayers; ++iFtdLayer) + { + if ((tanLambda > m_ftdZPositions[iFtdLayer] / m_ftdOuterRadii[iFtdLayer]) && + (tanLambda < m_ftdZPositions[iFtdLayer] / m_ftdInnerRadii[iFtdLayer])) + { + expectedFtdHits++; + } + } + + minTrackHits = std::max(m_settings.m_minFtdTrackHits, expectedFtdHits); + } + + const int nTrackHits(static_cast<int>(pTrack->trackerHits_size())); + + if ((nTrackHits < minTrackHits) || (nTrackHits > m_settings.m_maxTrackHits)) + continue; + + // Proceed to create the pandora track + PandoraApi::Track::Parameters trackParameters; + trackParameters.m_d0 = pTrack->getTrackStates(0).D0; + trackParameters.m_z0 = pTrack->getTrackStates(0).Z0; + trackParameters.m_pParentAddress = pTrack; + // By default, assume tracks are charged pions + const float signedCurvature(pTrack->getTrackStates(0).omega); + trackParameters.m_particleId = (signedCurvature > 0) ? pandora::PI_PLUS : pandora::PI_MINUS; + trackParameters.m_mass = pandora::PdgTable::GetParticleMass(pandora::PI_PLUS); + + // Use particle id information from V0 and Kink finders + TrackToPidMap::const_iterator iter_t = m_trackToPidMap.find(*pTrack); + + if(iter_t != m_trackToPidMap.end()) + { + trackParameters.m_particleId = (*iter_t).second; + trackParameters.m_mass = pandora::PdgTable::GetParticleMass((*iter_t).second); + } + + if (std::numeric_limits<float>::epsilon() < std::fabs(signedCurvature)) + trackParameters.m_charge = static_cast<int>(signedCurvature / std::fabs(signedCurvature)); + + this->GetTrackStates(pTrack, trackParameters); + this->TrackReachesECAL(pTrack, trackParameters); + this->DefineTrackPfoUsage(pTrack, trackParameters); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Track::Create(*m_pPandora, trackParameters)); + m_trackVector.push_back(pTrack); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"Failed to extract a track: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract a track "<< std::endl; + } + } + } + catch (...) + { + std::cout<<"Failed to extract track collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::GetTrackStates(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + edm4hep::TrackState pTrackState = pTrack->getTrackStates(1); // ref /cvmfs/cepcsw.ihep.ac.cn/prototype/LCIO/include/EVENT/TrackState.h + + const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState.omega)); + trackParameters.m_momentumAtDca = pandora::CartesianVector(std::cos(pTrackState.phi), std::sin(pTrackState.phi), pTrackState.tanLambda) * pt; + this->CopyTrackState(pTrack->getTrackStates(2), trackParameters.m_trackStateAtStart); + + auto pEndTrack = (pTrack->tracks_size() ==0 ) ? *pTrack : pTrack->getTracks(pTrack->tracks_size()-1); + + this->CopyTrackState(pEndTrack.getTrackStates(3), trackParameters.m_trackStateAtEnd); + //FIXME ? LCIO input only has 4 states, so 4 can't be used. + this->CopyTrackState(pEndTrack.getTrackStates(3), trackParameters.m_trackStateAtCalorimeter); + + + trackParameters.m_isProjectedToEndCap = ((std::fabs(trackParameters.m_trackStateAtCalorimeter.Get().GetPosition().GetZ()) < m_eCalEndCapInnerZ) ? false : true); + + // Convert generic time (length from reference point to intersection, divided by momentum) into nanoseconds + const float minGenericTime(this->CalculateTrackTimeAtCalorimeter(pTrack)); + const float particleMass(trackParameters.m_mass.Get()); + const float particleEnergy(std::sqrt(particleMass * particleMass + trackParameters.m_momentumAtDca.Get().GetMagnitudeSquared())); + trackParameters.m_timeAtCalorimeter = minGenericTime * particleEnergy / 299.792f; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +float TrackCreator::CalculateTrackTimeAtCalorimeter(const edm4hep::Track *const pTrack) const +{ + const pandora::Helix helix(pTrack->getTrackStates(0).phi, pTrack->getTrackStates(0).D0, pTrack->getTrackStates(0).Z0, pTrack->getTrackStates(0).omega, pTrack->getTrackStates(0).tanLambda, m_bField); + const pandora::CartesianVector &referencePoint(helix.GetReferencePoint()); + + // First project to endcap + float minGenericTime(std::numeric_limits<float>::max()); + + pandora::CartesianVector bestECalProjection(0.f, 0.f, 0.f); + const int signPz((helix.GetMomentum().GetZ() > 0.f) ? 1 : -1); + (void) helix.GetPointInZ(static_cast<float>(signPz) * m_eCalEndCapInnerZ, referencePoint, bestECalProjection, minGenericTime); + + // Then project to barrel surface(s) + pandora::CartesianVector barrelProjection(0.f, 0.f, 0.f); + if (m_eCalBarrelInnerSymmetry > 0) + { + // Polygon + float twopi_n = 2. * M_PI / (static_cast<float>(m_eCalBarrelInnerSymmetry)); + + for (int i = 0; i < m_eCalBarrelInnerSymmetry; ++i) + { + float genericTime(std::numeric_limits<float>::max()); + const float phi(twopi_n * static_cast<float>(i) + m_eCalBarrelInnerPhi0); + + const pandora::StatusCode statusCode(helix.GetPointInXY(m_eCalBarrelInnerR * std::cos(phi), m_eCalBarrelInnerR * std::sin(phi), + std::cos(phi + 0.5 * M_PI), std::sin(phi + 0.5 * M_PI), referencePoint, barrelProjection, genericTime)); + + if ((pandora::STATUS_CODE_SUCCESS == statusCode) && (genericTime < minGenericTime)) + { + minGenericTime = genericTime; + bestECalProjection = barrelProjection; + } + } + } + else + { + // Cylinder + float genericTime(std::numeric_limits<float>::max()); + const pandora::StatusCode statusCode(helix.GetPointOnCircle(m_eCalBarrelInnerR, referencePoint, barrelProjection, genericTime)); + + if ((pandora::STATUS_CODE_SUCCESS == statusCode) && (genericTime < minGenericTime)) + { + minGenericTime = genericTime; + bestECalProjection = barrelProjection; + } + } + + if (bestECalProjection.GetMagnitudeSquared() < std::numeric_limits<float>::epsilon()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + return minGenericTime; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::CopyTrackState(const edm4hep::TrackState & pTrackState, pandora::InputTrackState &inputTrackState) const +{ + const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState.omega)); + + const double px(pt * std::cos(pTrackState.phi)); + const double py(pt * std::sin(pTrackState.phi)); + const double pz(pt * pTrackState.tanLambda); + + const double xs(pTrackState.referencePoint[0]); + const double ys(pTrackState.referencePoint[1]); + const double zs(pTrackState.referencePoint[2]); + + inputTrackState = pandora::TrackState(xs, ys, zs, px, py, pz); +} + + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::TrackReachesECAL(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + + // Calculate hit position information + float hitZMin(std::numeric_limits<float>::max()); + float hitZMax(-std::numeric_limits<float>::max()); + float hitOuterR(-std::numeric_limits<float>::max()); + + int maxOccupiedFtdLayer=0; + + + const unsigned int nTrackHits(pTrack->trackerHits_size()); + for (unsigned int i = 0; i < nTrackHits; ++i) + { + + const edm4hep::ConstTrackerHit Hit ( pTrack->getTrackerHits(i) ); + const edm4hep::Vector3d pos = Hit.getPosition(); + + float x = float(pos[0]); + float y = float(pos[1]); + float z = float(pos[2]); + float r = std::sqrt(x * x + y * y); + + if (z > hitZMax) hitZMax = z; + + if (z < hitZMin) hitZMin = z; + + if (r > hitOuterR) hitOuterR = r; + + if ((r > m_tpcInnerR) && (r < m_tpcOuterR) && (std::fabs(z) <= m_tpcZmax)) continue; + + for (unsigned int j = 0; j < m_nFtdLayers; ++j) + { + if ((r > m_ftdInnerRadii[j]) && (r < m_ftdOuterRadii[j]) && + (std::fabs(z) - m_settings.m_reachesECalFtdZMaxDistance < m_ftdZPositions[j]) && + (std::fabs(z) + m_settings.m_reachesECalFtdZMaxDistance > m_ftdZPositions[j])) + { + if ( j > maxOccupiedFtdLayer) maxOccupiedFtdLayer = j; + break; + } + } + } + const int nTpcHits(this->GetNTpcHits(pTrack)); + const int nFtdHits(this->GetNFtdHits(pTrack)); + + // Look to see if there are hits in etd or set, implying track has reached edge of ecal + if ((hitOuterR > m_minSetRadius) || (hitZMax > m_minEtdZPosition)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + + // Require sufficient hits in tpc or ftd, then compare extremal hit positions with tracker dimensions + if ((nTpcHits >= m_settings.m_reachesECalNTpcHits) || (nFtdHits >= m_settings.m_reachesECalNFtdHits)) + { + if ((hitOuterR - m_tpcOuterR > m_settings.m_reachesECalTpcOuterDistance) || + (std::fabs(hitZMax) - m_tpcZmax > m_settings.m_reachesECalTpcZMaxDistance) || + (std::fabs(hitZMin) - m_tpcZmax > m_settings.m_reachesECalTpcZMaxDistance) || + (maxOccupiedFtdLayer >= m_settings.m_reachesECalMinFtdLayer)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + } + + // If track is lowpt, it may curl up and end inside tpc inner radius + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float cosAngleAtDca(std::fabs(momentumAtDca.GetZ()) / momentumAtDca.GetMagnitude()); + const float pX(momentumAtDca.GetX()), pY(momentumAtDca.GetY()); + const float pT(std::sqrt(pX * pX + pY * pY)); + + if ((cosAngleAtDca > m_cosTpc) || (pT < m_settings.m_curvatureToMomentumFactor * m_bField * m_tpcOuterR)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + + trackParameters.m_reachesCalorimeter = false; + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::DefineTrackPfoUsage(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + bool canFormPfo(false); + bool canFormClusterlessPfo(false); + + if (trackParameters.m_reachesCalorimeter.Get() && !this->IsParent(pTrack->id())) + { + const float d0(std::fabs(pTrack->getTrackStates(0).D0)), z0(std::fabs(pTrack->getTrackStates(0).Z0)); + + float rInner(std::numeric_limits<float>::max()), zMin(std::numeric_limits<float>::max()); + + for (std::vector<edm4hep::ConstTrackerHit>::const_iterator iter = pTrack->trackerHits_begin(), iterEnd = pTrack->trackerHits_end(); iter != iterEnd; ++iter) + { + const edm4hep::Vector3d pPosition = (*iter).getPosition(); + const float x(pPosition[0]), y(pPosition[1]), absoluteZ(std::fabs(pPosition[2])); + const float r(std::sqrt(x * x + y * y)); + + if (r < rInner) + rInner = r; + + if (absoluteZ < zMin) + zMin = absoluteZ; + } + + if (this->PassesQualityCuts(pTrack, trackParameters)) + { + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float pX(momentumAtDca.GetX()), pY(momentumAtDca.GetY()), pZ(momentumAtDca.GetZ()); + const float pT(std::sqrt(pX * pX + pY * pY)); + + const float zCutForNonVertexTracks(m_tpcInnerR * std::fabs(pZ / pT) + m_settings.m_zCutForNonVertexTracks); + const bool passRzQualityCuts((zMin < zCutForNonVertexTracks) && (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)); + + const bool isV0(this->IsV0(pTrack->id())); + const bool isDaughter(this->IsDaughter(pTrack->id())); + + // Decide whether track can be associated with a pandora cluster and used to form a charged PFO + if ((d0 < m_settings.m_d0TrackCut) && (z0 < m_settings.m_z0TrackCut) && (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)) + { + canFormPfo = true; + } + else if (passRzQualityCuts && (0 != m_settings.m_usingNonVertexTracks)) + { + canFormPfo = true; + } + else if (isV0 || isDaughter) + { + canFormPfo = true; + } + + // Decide whether track can be used to form a charged PFO, even if track fails to be associated with a pandora cluster + const float particleMass(trackParameters.m_mass.Get()); + const float trackEnergy(std::sqrt(momentumAtDca.GetMagnitudeSquared() + particleMass * particleMass)); + + if ((0 != m_settings.m_usingUnmatchedVertexTracks) && (trackEnergy < m_settings.m_unmatchedVertexTrackMaxEnergy)) + { + if ((d0 < m_settings.m_d0UnmatchedVertexTrackCut) && (z0 < m_settings.m_z0UnmatchedVertexTrackCut) && + (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)) + { + canFormClusterlessPfo = true; + } + else if (passRzQualityCuts && (0 != m_settings.m_usingNonVertexTracks) && (0 != m_settings.m_usingUnmatchedNonVertexTracks)) + { + canFormClusterlessPfo = true; + } + else if (isV0 || isDaughter) + { + canFormClusterlessPfo = true; + } + } + } + else if (this->IsDaughter(pTrack->id()) || this->IsV0(pTrack->id())) + { + std::cout<<"WARNING Recovering daughter or v0 track " << trackParameters.m_momentumAtDca.Get().GetMagnitude() << std::endl; + canFormPfo = true; + } + } + + trackParameters.m_canFormPfo = canFormPfo; + trackParameters.m_canFormClusterlessPfo = canFormClusterlessPfo; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool TrackCreator::PassesQualityCuts(const edm4hep::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const +{ + // First simple sanity checks + if (trackParameters.m_trackStateAtCalorimeter.Get().GetPosition().GetMagnitude() < m_settings.m_minTrackECalDistanceFromIp) + return false; + + if (std::fabs(pTrack->getTrackStates(0).omega) < std::numeric_limits<float>::epsilon()) + { + std::cout<<"ERROR Track has Omega = 0 " << std::endl; + return false; + } + + // Check momentum uncertainty is reasonable to use track + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float sigmaPOverP(std::sqrt(pTrack->getTrackStates(0).covMatrix[5]) / std::fabs(pTrack->getTrackStates(0).omega)); + + if (sigmaPOverP > m_settings.m_maxTrackSigmaPOverP) + { + std::cout<<"WARNING Dropping track : " << momentumAtDca.GetMagnitude() << "+-" << sigmaPOverP * (momentumAtDca.GetMagnitude()) + << " chi2 = " << pTrack->getChi2() << " " << pTrack->getNdf() + << " from " << pTrack->trackerHits_size() << std::endl; + return false; + } + + // Require reasonable number of TPC hits + if (momentumAtDca.GetMagnitude() > m_settings.m_minMomentumForTrackHitChecks) + { + const float pX(fabs(momentumAtDca.GetX())); + const float pY(fabs(momentumAtDca.GetY())); + const float pZ(fabs(momentumAtDca.GetZ())); + const float pT(std::sqrt(pX * pX + pY * pY)); + const float rInnermostHit(pTrack->getRadiusOfInnermostHit()); + + if ((std::numeric_limits<float>::epsilon() > std::fabs(pT)) || (std::numeric_limits<float>::epsilon() > std::fabs(pZ)) || (rInnermostHit == m_tpcOuterR)) + { + std::cout<<"ERROR Invalid track parameter, pT " << pT << ", pZ " << pZ << ", rInnermostHit " << rInnermostHit << std::endl; + return false; + } + + float nExpectedTpcHits(0.); + + if (pZ < m_tpcZmax / m_tpcOuterR * pT) + { + const float innerExpectedHitRadius(std::max(m_tpcInnerR, rInnermostHit)); + const float frac((m_tpcOuterR - innerExpectedHitRadius) / (m_tpcOuterR - m_tpcInnerR)); + nExpectedTpcHits = m_tpcMaxRow * frac; + } + + if ((pZ <= m_tpcZmax / m_tpcInnerR * pT) && (pZ >= m_tpcZmax / m_tpcOuterR * pT)) + { + const float innerExpectedHitRadius(std::max(m_tpcInnerR, rInnermostHit)); + const float frac((m_tpcZmax * pT / pZ - innerExpectedHitRadius) / (m_tpcOuterR - innerExpectedHitRadius)); + nExpectedTpcHits = frac * m_tpcMaxRow; + } + + // TODO Get TPC membrane information from GEAR when available + if (std::fabs(pZ) / momentumAtDca.GetMagnitude() < m_settings.m_tpcMembraneMaxZ / m_tpcInnerR) + nExpectedTpcHits = 0; + + const int nTpcHits(this->GetNTpcHits(pTrack)); + const int nFtdHits(this->GetNFtdHits(pTrack)); + + const int minTpcHits = static_cast<int>(nExpectedTpcHits * m_settings.m_minTpcHitFractionOfExpected); + + if ((nTpcHits < minTpcHits) && (nFtdHits < m_settings.m_minFtdHitsForTpcHitFraction)) + { + std::cout<<"WARNING Dropping track : " << momentumAtDca.GetMagnitude() << " Number of TPC hits = " << nTpcHits + << " < " << minTpcHits << " nftd = " << nFtdHits << std::endl; + return false; + } + } + + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int TrackCreator::GetNTpcHits(const edm4hep::Track *const pTrack) const +{ + // ATTN + //fg: hit numbers are now given in different order wrt LOI: + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 1 ] = hitsInFit ; + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 2 ] = hitCount ; + // ---- use hitsInFit : + //return pTrack->getSubdetectorHitNumbers()[ 2 * lcio::ILDDetID::TPC - 1 ]; + return pTrack->getSubDetectorHitNumbers(2 * 4 - 1);// lcio::ILDDetID::TPC=4, still use LCIO code now +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int TrackCreator::GetNFtdHits(const edm4hep::Track *const pTrack) const +{ + // ATTN + //fg: hit numbers are now given in different order wrt LOI: + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 1 ] = hitsInFit ; + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 2 ] = hitCount ; + // ---- use hitsInFit : + //return pTrack->getSubdetectorHitNumbers()[ 2 * lcio::ILDDetID::FTD - 1 ]; + return pTrack->getSubDetectorHitNumbers( 2 * 3 - 1 );// lcio::ILDDetID::FTD=3 +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +TrackCreator::Settings::Settings() : + m_shouldFormTrackRelationships(1), + m_minTrackHits(5), + m_minFtdTrackHits(0), + m_maxTrackHits(5000.f), + m_d0TrackCut(50.f), + m_z0TrackCut(50.f), + m_usingNonVertexTracks(1), + m_usingUnmatchedNonVertexTracks(0), + m_usingUnmatchedVertexTracks(1), + m_unmatchedVertexTrackMaxEnergy(5.f), + m_d0UnmatchedVertexTrackCut(5.f), + m_z0UnmatchedVertexTrackCut(5.f), + m_zCutForNonVertexTracks(250.f), + m_reachesECalNTpcHits(11), + m_reachesECalNFtdHits(4), + m_reachesECalTpcOuterDistance(-100.f), + m_reachesECalMinFtdLayer(9), + m_reachesECalTpcZMaxDistance(-50.f), + m_reachesECalFtdZMaxDistance(1.f), + m_curvatureToMomentumFactor(0.3f / 2000.f), + m_minTrackECalDistanceFromIp(100.f), + m_maxTrackSigmaPOverP(0.15f), + m_minMomentumForTrackHitChecks(1.f), + m_tpcMembraneMaxZ(10.f), + m_maxTpcInnerRDistance(50.f), + m_minTpcHitFractionOfExpected(0.2f), + m_minFtdHitsForTpcHitFraction(2) +{ +} diff --git a/Reconstruction/PFA/Pandora/GaudiPandora/src/Utility.cpp b/Reconstruction/PFA/Pandora/GaudiPandora/src/Utility.cpp new file mode 100644 index 0000000000000000000000000000000000000000..819fa15d4771c80d65e6437d22ebd46120d311de --- /dev/null +++ b/Reconstruction/PFA/Pandora/GaudiPandora/src/Utility.cpp @@ -0,0 +1,7 @@ +#include "Utility.h" + +std::string Convert (float number){ + std::ostringstream buff; + buff<<number; + return buff.str(); +} diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.cc b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.cc new file mode 100644 index 0000000000000000000000000000000000000000..e7e8d4fca32578d72ccad1c451164b2d441f7687 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.cc @@ -0,0 +1,2005 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +#include "ClusterShapes.h" + +#include <gsl/gsl_vector.h> +#include <gsl/gsl_matrix.h> +//#include <gsl/gsl_blas.h> +#include <gsl/gsl_linalg.h> +#include <gsl/gsl_eigen.h> +#include <gsl/gsl_multifit_nlin.h> +#include <gsl/gsl_sf_gamma.h> +#include <gsl/gsl_integration.h> +//#include <gsl/gsl_rng.h> +//#include <gsl/gsl_sf_pow_int.h> + + + +// ################################################# +// ##### ##### +// ##### Additional Structures and Functions ##### +// ##### ##### +// ################################################# +//============================================================================= + +struct data { + int n; + float* x; + float* y; + float* z; + float* ex; + float* ey; + float* ez; +}; + +//============================================================================= + +// Gammafunction +double G(double x) { + + return gsl_sf_gamma(x); + +} + +//============================================================================= + +// inverse Gammafunction +double invG(double x) { + + return gsl_sf_gammainv(x); + +} + +//============================================================================= + +// Integral needed for deriving the derivative of the Gammafunction +double Integral_G(double x, void* params) { + double a = *(double*)params; + double f = exp(-x) * pow(x,a-1) * log(x); + return f; +} + +//============================================================================= + +double DinvG(double x) { + + int workspace_size = 1000; + double abs_error = 0; + double rel_error = 1e-6; + double result = 0.0; + double error = 0.0; + int status = 0; + + gsl_integration_workspace* w = gsl_integration_workspace_alloc(workspace_size); + gsl_function F; + F.function = &Integral_G; + F.params = &x; + + status = gsl_integration_qagiu(&F,0,abs_error,rel_error,workspace_size,w, + &result,&error); + + // debug + /* + printf ("Numeric Integration : \n"); + printf ("parameter of integration = % .18f\n", x); + printf ("status of integration = %d \n" , status); + printf ("result = % .18f\n", result); + printf ("estimated error = % .18f\n", error); + printf ("intervals = %d\n\n", w->size); + */ + + double G2 = pow(gsl_sf_gamma(x),2); + double DG = result; + + gsl_integration_workspace_free(w); + + return -DG/G2; + +} + +//============================================================================= + +int ShapeFitFunct(const gsl_vector* par, void* d, gsl_vector* f) { + + // Used for shape fitting. Function to fit: + // + // a[i](t[i],s[i]) = + // + // E0 * b * 1/Gamma(a) * ( b * (t[i] - t0) )^(a-1) * exp(-b*(t[i] - t0)) * exp(-d*s[i]) + // + // Function to minimise: + // + // f0[i] = E0 * b * 1/Gamma(a) * + // ( b * (t[i] - t0) )^(a-1) * exp(-b*(t[i] - t0)) * exp(-d*s[i]) - a[i] + // + + + // float E0 = gsl_vector_get(par,0); + float A = gsl_vector_get(par,0); + float B = gsl_vector_get(par,1); + float D = gsl_vector_get(par,2); + float t0 = gsl_vector_get(par,3); + int n = ((struct data*)d)->n; + float* t = ((struct data*)d)->x; + float* s = ((struct data*)d)->y; + float* a = ((struct data*)d)->z; // amplitude stored in z[i] + float fi = 0.0; + + + for (int i(0); i < n; i++) { + fi = /*E0 * */ B * invG(A) * pow(B*(t[i]-t0),A-1) * exp(-B*(t[i]-t0)) * exp(-D*s[i]) + - a[i]; + gsl_vector_set(f,i,fi); + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int dShapeFitFunct(const gsl_vector* par, void* d, gsl_matrix* J) { + + // Used for shape fitting + //float E0 = gsl_vector_get(par,0); + float A = gsl_vector_get(par,0); + float B = gsl_vector_get(par,1); + float D = gsl_vector_get(par,2); + float t0 = gsl_vector_get(par,3); + int n = ((struct data*)d)->n; + float* t = ((struct data*)d)->x; + float* s = ((struct data*)d)->y; + + + // calculate Jacobi's matrix J[i][j] = dfi/dparj, but here only one dimension + + for (int i(0); i < n; i++) { + + /* + gsl_matrix_set(J,i,0,B * invG(A) * pow(B*(t[i]-t0),A-1) * exp(-B*(t[i]-t0)) + * exp(-D*s[i]) ); + */ + + gsl_matrix_set(J,i,0,( /* E0 * */ B * invG(A) * log(B*(t[i]-t0))*pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) + DinvG(A) * /* E0 * */ B * pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) + ) * exp(-D*s[i])); + + gsl_matrix_set(J,i,1,( /* E0 * */ invG(A) * pow(B*(t[i]-t0),A-1) * exp(-B*(t[i]-t0)) + + /* E0 * */ invG(A) * (A-1) * B * (t[i]-t0) * pow(B*(t[i]-t0),A-2) * + exp(-B*(t[i]-t0)) - + /* E0 * */ B * invG(A) * (t[i]-t0) * pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) + ) * exp(-D*s[i])); + + gsl_matrix_set(J,i,2,-/* E0 * */ B * invG(A) * s[i] * pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) * exp(-D*s[i])); + + gsl_matrix_set(J,i,3,(-/* E0 * */ pow(B,2) * invG(A) * (A-1) * pow(B*(t[i]-t0),A-2) * + exp(-B*(t[i]-t0)) + + /* E0 * */ pow(B,2) * invG(A) * pow(B*(t[i]-t0),A-1) * + exp(-B*(t[i]-t0)) + ) * exp(-D*s[i])); + + + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int fdfShapeFitFunct(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J) { + + // For helix fitting + ShapeFitFunct(par, d, f); + dShapeFitFunct(par, d, J); + + return GSL_SUCCESS; + +} + +//============================================================================= + +int signum(float x) { + + // computes the signum of x. Needed for the 3. parametrisation + + if ( x >= 0 ) return 1; // x == 0 is taken as positive + else return -1; + +} + +//============================================================================= + +int functParametrisation1(const gsl_vector* par, void* d, gsl_vector* f) { + + // For helix fitting + // calculate fit function f0[i] = + // ( (x0 + R*cos(b*z[i] + phi0)) - x[i] ) for i = 0 to n-1 + // and f1[i] = + // ( (y0 + R*sin(b*z[i] + phi0)) - y[i] ) for i = n to dim*n - 1 + // That means, minimise the two functions f0[i] and f1[i] + + float x0 = gsl_vector_get(par,0); + float y0 = gsl_vector_get(par,1); + float R = gsl_vector_get(par,2); + float b = gsl_vector_get(par,3); + float phi0 = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + float* z = ((struct data*)d)->z; +//float* ex = ((struct data*)d)->ex; +//float* ey = ((struct data*)d)->ey; +//float* ez = ((struct data*)d)->ez; + float fi = 0.0; + + // first dimension + for (int i(0); i < n; i++) { + fi = (x0 + R*cos(b*z[i] + phi0)) - x[i]; + // float err = sqrt(ex[i]*ex[i]+R*b*R*b*sin(b*z[i] + phi0)*R*b*R*b*sin(b*z[i] + phi0)*ez[i]*ez[i]); + // fi = fi/err; + gsl_vector_set(f,i,fi); + } + // second dimension + for (int i(0); i < n; i++) { + fi = (y0 + R*sin(b*z[i] + phi0)) - y[i]; + // float err = sqrt(ey[i]*ey[i]+R*b*R*b*cos(b*z[i] + phi0)*R*b*R*b*cos(b*z[i] + phi0)*ez[i]*ez[i]); + // fi = fi/err; + gsl_vector_set(f,i+n,fi); + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int dfunctParametrisation1(const gsl_vector* par, void* d, gsl_matrix* J) { + + // For helix fitting + float R = gsl_vector_get(par,2); + float b = gsl_vector_get(par,3); + float phi0 = gsl_vector_get(par,4); + + int n = ((struct data*)d)->n; + float* z = ((struct data*)d)->z; +//float* ex = ((struct data*)d)->ex; +//float* ey = ((struct data*)d)->ey; +//float* ez = ((struct data*)d)->ez; + + + // calculate Jacobi's matrix J[i][j] = dfi/dparj + + // part of Jacobi's matrix corresponding to first dimension + for (int i(0); i < n; i++) { + // float err = sqrt(ex[i]*ex[i]+R*b*R*b*sin(b*z[i] + phi0)*R*b*R*b*sin(b*z[i] + phi0)*ez[i]*ez[i]); + gsl_matrix_set(J,i,0,1); + gsl_matrix_set(J,i,1,0); + gsl_matrix_set(J,i,2,cos(b*z[i]+phi0)); + gsl_matrix_set(J,i,3,-z[i]*R*sin(b*z[i]+phi0)); + gsl_matrix_set(J,i,4,-R*sin(b*z[i]+phi0)); + + } + + // part of Jacobi's matrix corresponding to second dimension + for (int i(0); i < n; i++) { + // float err = sqrt(ey[i]*ey[i]+R*b*R*b*cos(b*z[i] + phi0)*R*b*R*b*cos(b*z[i] + phi0)*ez[i]*ez[i]); + gsl_matrix_set(J,i+n,0,0); + gsl_matrix_set(J,i+n,1,1); + gsl_matrix_set(J,i+n,2,sin(b*z[i]+phi0)); + gsl_matrix_set(J,i+n,3,z[i]*R*cos(b*z[i]+phi0)); + gsl_matrix_set(J,i+n,4,R*cos(b*z[i]+phi0)); + + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int fdfParametrisation1(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J) { + + // For helix fitting + functParametrisation1(par, d, f); + dfunctParametrisation1(par, d, J); + + return GSL_SUCCESS; + +} + +//============================================================================= + +int functParametrisation2(const gsl_vector* par, void* d, gsl_vector* f) { + + // For helix fitting + // calculate fit function f0[i] = + // ( (x0 + R*cos(phi)) - x[i] ) for i = 0 to n-1 + // f1[i] = + // ( (y0 + R*sin(phi)) - y[i] ) for i = n to dim*n - 1 + // and f2[i] = + // ( (z0 + b*phi ) - z[i] ) + // That means, minimise the three functions f0[i], f1[i] and f2[i] + + float x0 = gsl_vector_get(par,0); + float y0 = gsl_vector_get(par,1); + float z0 = gsl_vector_get(par,2); + float R = gsl_vector_get(par,3); + float b = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + float* z = ((struct data*)d)->z; + float fi = 0.0; + float phii = 0.0; + + // first dimension + for (int i(0); i < n; i++) { + phii = atan2( y[i]-y0, x[i]-x0 ); + fi = (x0 + R*cos(phii)) - x[i]; + gsl_vector_set(f,i,fi); + } + // second dimension + for (int i(0); i < n; i++) { + phii = atan2( y[i]-y0, x[i]-x0 ); + fi = (y0 + R*sin(phii)) - y[i]; + gsl_vector_set(f,i+n,fi); + } + // third dimension + for (int i(0); i < n; i++) { + phii = atan2( y[i]-y0, x[i]-x0 ); + fi = (z0 + b*phii) - z[i]; + gsl_vector_set(f,i+2*n,fi); + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int dfunctParametrisation2(const gsl_vector* par, void* d, gsl_matrix* J) { + + // For helix fitting + float x0 = gsl_vector_get(par,0); + float y0 = gsl_vector_get(par,1); + float R = gsl_vector_get(par,3); + float b = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + float phii = 0.0; + + // calculate Jacobi's matrix J[i][j] = dfi/dparj + + // part of Jacobi's matrix corresponding to first dimension + for (int i(0); i < n; i++) { + + phii = atan2( y[i]-y0, x[i]-x0 ); + + gsl_matrix_set(J,i,0,1 - R*sin(phii)* + ( (y[i]-y0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i,1,R*sin(phii)* + ( (x[i]-x0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i,2,0); + gsl_matrix_set(J,i,3,cos(phii)); + gsl_matrix_set(J,i,4,0); + + } + + // part of Jacobi's matrix corresponding to second dimension + for (int i(0); i < n; i++) { + + phii = atan2( y[i]-y0, x[i]-x0 ); + + gsl_matrix_set(J,i+n,0,R*cos(phii)* + ( (y[i]-y0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i+n,1,1 + R*cos(phii)* + ( (x[i]-x0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i+n,2,0); + gsl_matrix_set(J,i+n,3,sin(phii)); + gsl_matrix_set(J,i+n,4,0); + + } + + // part of Jacobi's matrix corresponding to third dimension + for (int i(0); i < n; i++) { + + phii = atan2( y[i]-y0, x[i]-x0 ); + + gsl_matrix_set(J,i+2*n,0,b* + ( (y[i]-y0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i+2*n,1,b* + ( (x[i]-x0)/( (x[i]-x0)*(x[i]-x0) + (y[i]-y0)*(y[i]-y0) ) ) ); + gsl_matrix_set(J,i+2*n,2,1); + gsl_matrix_set(J,i+2*n,3,0); + gsl_matrix_set(J,i+2*n,4,phii); + + } + + return GSL_SUCCESS; +} + +//============================================================================= + +int fdfParametrisation2(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J) { + + // For helix fitting + functParametrisation2(par, d, f); + dfunctParametrisation2(par, d, J); + + return GSL_SUCCESS; + +} + +//============================================================================= + +int functParametrisation3(const gsl_vector* par, void* d, gsl_vector* f) { + + // For helix fitting + // calculate fit function f0[i] = + // ( ( ( (1/omega) - d0 )*sin(Phi0) + ( 1/fabs(omega) )*cos( ( -omega/sqrt(1+tanL^2) )*s + Phi0 +( (omega*pi)/(2*fabs(omega)) ) ) ) - x[i] ) for i = 0 to n-1 + // f1[i] = + // ( ( (-1.0)*( (1/omega) - d0 )*cos(Phi0) + ( 1/fabs(omega) )*sin( ( -omega/sqrt(1+tanL^2) )*s + Phi0 +( (omega*pi)/(2*fabs(omega)) ) ) ) - y[i] ) for i = n to dim*n - 1 + // and f2[i] = + // ( ( z0 + (tanL/sqrt(1+tanL^2))*s ) - z[i] ) + // That means, minimise the three functions f0[i], f1[i] and f2[i] + + double z0 = gsl_vector_get(par,0); + double Phi0 = gsl_vector_get(par,1); + double omega = gsl_vector_get(par,2); + double d0 = gsl_vector_get(par,3); + double tanL = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + float* z = ((struct data*)d)->z; + double phii = 0.0; + double fi = 0.0; + double si = 0.0; + + // first dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + fi = ( ( (1/omega) - d0 )*sin(Phi0) + ( 1/fabs(omega) )*cos(phii) ) - ((double)x[i]); + gsl_vector_set(f,i,fi); + } + // second dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + fi = ( (-1.0)*( (1/omega) - d0 )*cos(Phi0) + ( 1/fabs(omega) )*sin(phii) ) - ((double)y[i]); + gsl_vector_set(f,i+n,fi); + } + // third dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + si = (-1.0)*( (sqrt(1+pow(tanL,2)))/omega )*(phii - Phi0 - (omega*M_PI)/(2*fabs(omega))); + fi = ( z0 + (tanL/sqrt(1+pow(tanL,2)))*si ) - ((double)z[i]); + gsl_vector_set(f,i+2*n,fi); + } + + return GSL_SUCCESS; + +} + +//============================================================================= + +int dfunctParametrisation3(const gsl_vector* par, void* d, gsl_matrix* J) { + + + // For helix fitting + // double z0 = gsl_vector_get(par,0); // not needed + double Phi0 = gsl_vector_get(par,1); + double omega = gsl_vector_get(par,2); + double d0 = gsl_vector_get(par,3); + double tanL = gsl_vector_get(par,4); + int n = ((struct data*)d)->n; + float* x = ((struct data*)d)->x; + float* y = ((struct data*)d)->y; + // float* z = ((struct data*)d)->z; // not needed + double phii = 0.0; + double si = 0.0; + + // calculate Jacobi's matrix J[i][j] = dfi/dparj + + // part of Jacobi's matrix corresponding to first dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 ) * cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + si = (-1.0)*( (sqrt(1+pow(tanL,2)))/omega )*(phii - Phi0 - (omega*M_PI)/(2*fabs(omega))); + + gsl_matrix_set(J,i,0,0); + gsl_matrix_set(J,i,1,((1/omega) - d0) * cos(Phi0) - (1/fabs(omega)) * sin(phii) ); + gsl_matrix_set(J,i,2,((-1.0)*sin(Phi0))/pow(omega,2) - ( (signum(omega))/(pow(fabs(omega),2)) ) * cos(phii) - + (1/fabs(omega)) * sin(phii) * ( ( ((-1.0)/sqrt(1+pow(tanL,2)))*si) + (M_PI)/(2*fabs(omega)) - (signum(omega)*omega*M_PI)/(2*pow(fabs(omega),2)) ) ); + gsl_matrix_set(J,i,3,(-1.0)*sin(Phi0)); + gsl_matrix_set(J,i,4,((-1.0)/fabs(omega))*sin(phii) * ( (omega*tanL*si)/sqrt(pow(1+pow(tanL,2),3)) ) ); + + } + + // part of Jacobi's matrix corresponding to second dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + si = (-1.0)*( (sqrt(1+pow(tanL,2)))/omega )*(phii - Phi0 - (omega*M_PI)/(2*fabs(omega))); + + gsl_matrix_set(J,i+n,0,0); + gsl_matrix_set(J,i+n,1,((1/omega) - d0)*sin(Phi0) + (1/fabs(omega)) * cos(phii) ); + gsl_matrix_set(J,i+n,2,cos(Phi0)/pow(omega,2) + ( (signum(omega))/(pow(fabs(omega),2)) ) * sin(phii) + + (1/fabs(omega))*cos(phii) * ( ( ((-1.0)/sqrt(1+pow(tanL,2)))*si) + (M_PI)/(2*fabs(omega)) - (signum(omega)*omega*M_PI)/(2*pow(fabs(omega),2)) ) ); + gsl_matrix_set(J,i+n,3,cos(Phi0)); + gsl_matrix_set(J,i+n,4,(1/fabs(omega))*cos(phii) * ( (omega*tanL*si)/sqrt(pow(1+pow(tanL,2),3)) ) ); + + } + + // part of Jacobi's matrix corresponding to third dimension + for (int i(0); i < n; i++) { + phii = atan2( ( ((double)y[i]) + ((1/omega) - d0 )*cos(Phi0) ), ( ((double)x[i]) - ((1/omega) - d0 )*sin(Phi0) ) ); + si = (-1.0)*( (sqrt(1+pow(tanL,2)))/omega )*(phii - Phi0 - (omega*M_PI)/(2*fabs(omega))); + + gsl_matrix_set(J,i+2*n,0,1.0); + gsl_matrix_set(J,i+2*n,1,0); + gsl_matrix_set(J,i+2*n,2,0); + gsl_matrix_set(J,i+2*n,3,0); + gsl_matrix_set(J,i+2*n,4,si/sqrt(1+pow(tanL,2)) - (pow(tanL,2)*si)/sqrt(pow(1+pow(tanL,2),3)) ); + + } + + return GSL_SUCCESS; + +} + +//============================================================================= + +int fdfParametrisation3(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J) { + + // For helix fitting + functParametrisation3(par, d, f); + dfunctParametrisation3(par, d, J); + + return GSL_SUCCESS; + +} + +//============================================================================= + + + + +// ########################################## +// ##### ##### +// ##### Constructor and Destructor ##### +// ##### ##### +// ########################################## + +//============================================================================= + +ClusterShapes::ClusterShapes(int nhits, float* a, float* x, float* y, float* z){ + + _nHits = nhits; + _aHit = new float[_nHits]; + _xHit = new float[_nHits]; + _yHit = new float[_nHits]; + _zHit = new float[_nHits]; + _exHit = new float[_nHits]; + _eyHit = new float[_nHits]; + _ezHit = new float[_nHits]; + _types = new int[_nHits]; + + _xl = new float[_nHits]; + _xt = new float[_nHits]; + + _t = new float[_nHits]; + _s = new float[_nHits]; + + for (int i(0); i < nhits; ++i) { + _aHit[i] = a[i]; + _xHit[i] = x[i]; + _yHit[i] = y[i]; + _zHit[i] = z[i]; + _exHit[i] = 1.0; + _eyHit[i] = 1.0; + _ezHit[i] = 1.0; + _types[i] = 1; // all hits are assumed to be "cyllindrical" + } + + _ifNotGravity = 1; + _ifNotWidth = 1; + _ifNotInertia = 1; + _ifNotEigensystem = 1; + +} + + +//============================================================================= + +ClusterShapes::~ClusterShapes() { + + delete[] _aHit; + delete[] _xHit; + delete[] _yHit; + delete[] _zHit; + delete[] _exHit; + delete[] _eyHit; + delete[] _ezHit; + delete[] _types; + delete[] _xl; + delete[] _xt; + delete[] _t; + delete[] _s; +} + +//============================================================================= + +void ClusterShapes::setErrors(float *ex, float *ey, float *ez) { + + for (int i=0; i<_nHits; ++i) { + _exHit[i] = ex[i]; + _eyHit[i] = ey[i]; + _ezHit[i] = ez[i]; + } + +} + +void ClusterShapes::setHitTypes(int* typ) { + for (int i=0; i<_nHits; ++i) { + _types[i] = typ[i]; + + } + +} + + + +// ########################################## +// ##### ##### +// ##### public methods ##### +// ##### ##### +// ########################################## + +//============================================================================= + +int ClusterShapes::getNumberOfHits() { + return _nHits; +} + +//============================================================================= + +float ClusterShapes::getTotalAmplitude() { + if (_ifNotGravity == 1) findGravity(); + return _totAmpl; +} + +//============================================================================= + +float* ClusterShapes::getCentreOfGravity() { + if (_ifNotGravity == 1) findGravity() ; + return &_analogGravity[0] ; +} + +//============================================================================= + +float* ClusterShapes::getEigenValInertia() { + if (_ifNotInertia == 1) findInertia(); + return &_ValAnalogInertia[0] ; +} + +//============================================================================= + +float* ClusterShapes::getEigenVecInertia() { + if (_ifNotInertia == 1) findInertia(); + return &_VecAnalogInertia[0] ; +} + +//============================================================================= + +float ClusterShapes::getWidth() { + if (_ifNotWidth == 1) findWidth(); + return _analogWidth; +} + +//============================================================================= + +int ClusterShapes::getEigenSytemCoordinates(float* xlong, float* xtrans) { + + float xStart[3]; + int index_xStart; + + + // NOT SAVE, change to class variables !!!!! + float X0 = 7.0; + float Rm = 13.5; + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + for (int i = 0; i < _nHits; ++i) { + xlong[i] = _xl[i]; + xtrans[i] = _xt[i]; + } + + return 0; // no error messages at the moment + +} + +//============================================================================= + +int ClusterShapes::getEigenSytemCoordinates(float* xlong, float* xtrans, float* a) { + + float xStart[3]; + int index_xStart; + + // NOT SAVE, change to class variables !!!!! + float X0 = 7.0; + float Rm = 13.5; + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + for (int i = 0; i < _nHits; ++i) { + xlong[i] = _xl[i]; + xtrans[i] = _xt[i]; + a[i] = _aHit[i]; + } + + return 0; // no error messages at the moment + +} + +//============================================================================= + +int ClusterShapes::fit3DProfile(float& chi2, float& E0, float& A, float& B, float& D, + float& xl0, float* xStart, int& index_xStart, + float X0, float Rm) { + + const int npar = 4; + + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + float* E = new float[_nHits]; + + + double par_init[npar]; + for (int i = 0; i < npar; ++i) par_init[i] = 0.0; // initialise + + float E0_init = 0.0; + float A_init = 0.0; + float B_init = 0.5; // empirically + float D_init = 0.5; // empirically + float t0_init = -10.0/X0; // shift xl0_ini is assumed to be -10.0 without a reason ???? + + float E0_tmp = 0.0; + int i_max = 0; + float t_max = 0.0; + for (int i = 0; i < _nHits; ++i) { + if (E0_tmp < _aHit[i]) { + E0_tmp = _aHit[i]; + i_max = i; + } + E0_init += _aHit[i]; + } + + // first definition + //t_max = _xl[i_max]/X0; + //A_init = t_max*B_init + 1.0; + + // second definition + //t_max = (1.0/3.0) * (t[_nHits-1] - t[0]); + //A_init = t_max*B_init + 1.0; + + // third definition + float Ec = X0 * 0.021/Rm; + A_init = B_init * log(E0_init/Ec) + 0.5 * B_init + 1.0; // (+0.5 for Photons initiated showers) + + + + // par_init[0] = E0_init; + E0 = E0_init; + for (int i = 0; i < _nHits; ++i) E[i] = _aHit[i]/E0_init; + par_init[0] = A_init; // 2.0 + par_init[1] = B_init; + par_init[2] = D_init; + par_init[3] = t0_init; + + // debug + + std::cout << "E0_init : " << E0_init << "\t" << "A_init : " << A_init << "\t" + << "B_init : " << B_init << "\t" << "D_init : " << D_init << "\t" + << "xl0_init : " << t0_init*X0 << "\t" << "X0 : " << X0 + << "\t" << "t_max : " << t_max << std::endl << std::endl; + + + double t0 = xl0/X0; + double par[npar]; + par[0] = A; + par[1] = B; + par[2] = D; + par[3] = t0; + + fit3DProfileAdvanced(chi2,par_init,par,npar,_t,_s,E,E0); + + A = par[0]; + B = par[1]; + D = par[2]; + xl0 = par[3] * X0; + + delete[] E; + + int result = 0; // no error handling at the moment + return result; +} + +//============================================================================= + +float ClusterShapes::getChi2Fit3DProfileSimple(float a, float b, float c, float d, + float X0, float Rm) { + + float chi2 = 0.0; + + float xStart[3]; + int index_xStart; + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + chi2 = calculateChi2Fit3DProfileSimple(a,b,c,d); + + return chi2; + +} + +//============================================================================= + +float ClusterShapes::getChi2Fit3DProfileAdvanced(float E0, float a, float b, float d, + float t0, float X0, float Rm) { + + float chi2 = 0.0; + + float xStart[3]; + int index_xStart; + + if (_ifNotEigensystem == 1) transformToEigensystem(xStart,index_xStart,X0,Rm); + + chi2 = calculateChi2Fit3DProfileAdvanced(E0,a,b,d,t0); + + return chi2; + +} + +//============================================================================= + +int ClusterShapes::FitHelix(int max_iter, int status_out, int parametrisation, + float* parameter, float* dparameter, float& chi2, + float& distmax, int direction) { + + + // Modified by Hengne Li @ LAL + + double parameterdb[5]; + double dparameterdb[5]; + double chi2db; + double distmaxdb; + for ( int i=0; i<5; i++ ){ + parameterdb[i] = double(parameter[i]); + dparameterdb[i] = double(dparameter[i]); + } + chi2db = double(chi2); + distmaxdb = double(distmax); + + int returnvalue = FitHelix(max_iter,status_out,parametrisation,parameterdb,dparameterdb,chi2db,distmaxdb,direction); + + for ( int i=0; i<5; i++ ){ + parameter[i] = float(parameterdb[i]); + dparameter[i] = float(dparameterdb[i]); + } + chi2 = float(chi2db); + distmax = float(distmaxdb); + + return returnvalue ; + +} + +//============================================================================= + +int ClusterShapes::FitHelix(int max_iter, int status_out, int parametrisation, + double* parameter, double* dparameter, double& chi2, + double& distmax, int direction) { + + // FIXME: version with double typed parameters needed 2006/06/10 OW + + if (_nHits < 3) { + std::cout << "ClusterShapes : helix fit impossible, two few points" ; + std::cout << std::endl; + for (int i = 0; i < 5; ++i) { + parameter[i] = 0.0; + dparameter[i] = 0.0; + } + return 1; + } + + // find initial parameters + + double Rmin = 1.0e+10; + double Rmax = -1.0; + int i1 = -1; + + // 1st loop + for (int i(0); i < _nHits; ++i) { + double Rz = sqrt(_xHit[i]*_xHit[i] + _yHit[i]*_yHit[i]); + if (Rz < Rmin) { + Rmin = Rz; + i1 = i; + } + if (Rz > Rmax) { + Rmax = Rz; + } + + } + + + + // debug + /* + for (int i(0); i < _nHits; ++i) std::cout << i << " " << _xHit[i] << " " << _yHit[i] << " " << _zHit[i] << std::endl; + std::cout << std::endl << Rmin << " " << Rmax << " " << i1 << std::endl; + */ + + + + + + // 2nd loop + double Upper = Rmin + 1.1*(Rmax-Rmin); + double Lower = Rmin + 0.9*(Rmax-Rmin); + double dZmin = 1.0e+20; + + int i3 = -1 ; + + for (int i(0); i < _nHits; ++i) { + double Rz = sqrt(_xHit[i]*_xHit[i] + _yHit[i]*_yHit[i]); + if ((Rz > Lower) && (Rz < Upper)) { + double dZ = fabs(_zHit[i]-_zHit[i1]); + if (dZ < dZmin) { + dZmin = dZ; + i3 = i; + } + } + } + + // debug + //std::cout << std::endl << Upper << " " << Lower << " " << dZmin << " " << i3 << std::endl; + + + + + double z1 = std::min(_zHit[i1],_zHit[i3]); + double z3 = std::max(_zHit[i1],_zHit[i3]); + + + int i2 = -1; + double dRmin = 1.0e+20; + double Rref = 0.5 * ( Rmax + Rmin ); + + // 3d loop + + for (int i(0); i < _nHits; ++i) { + if (_zHit[i] >= z1 && _zHit[i] <= z3) { + double Rz = sqrt(_xHit[i]*_xHit[i] + _yHit[i]*_yHit[i]); + double dRz = fabs(Rz - Rref); + if (dRz < dRmin) { + i2 = i; + dRmin = dRz; + } + } + } + + int problematic = 0; + + if (i2 < 0 || i2 == i1 || i2 == i3) { + problematic = 1; + // std::cout << "here we are " << std::endl; + for (int i(0); i < _nHits; ++i) { + if (i != i1 && i != i3) { + i2 = i; + if (_zHit[i2] < z1) { + int itemp = i1; + i1 = i2; + i2 = itemp; + } + else if (_zHit[i2] > z3) { + int itemp = i3; + i3 = i2; + i2 = itemp; + } + break; + } + } + // std::cout << i1 << " " << i2 << " " << i3 << std::endl; + } + + + double x0 = 0.5*(_xHit[i2]+_xHit[i1]); + double y0 = 0.5*(_yHit[i2]+_yHit[i1]); + double x0p = 0.5*(_xHit[i3]+_xHit[i2]); + double y0p = 0.5*(_yHit[i3]+_yHit[i2]); + double ax = _yHit[i2] - _yHit[i1]; + double ay = _xHit[i1] - _xHit[i2]; + double axp = _yHit[i3] - _yHit[i2]; + double ayp = _xHit[i2] - _xHit[i3]; + double det = ax * ayp - axp * ay; + double time; + + if (det == 0.) { + time = 500.; + } + else { + gsl_matrix* A = gsl_matrix_alloc(2,2); + gsl_vector* B = gsl_vector_alloc(2); + gsl_vector* T = gsl_vector_alloc(2); + gsl_matrix_set(A,0,0,ax); + gsl_matrix_set(A,0,1,-axp); + gsl_matrix_set(A,1,0,ay); + gsl_matrix_set(A,1,1,-ayp); + gsl_vector_set(B,0,x0p-x0); + gsl_vector_set(B,1,y0p-y0); + gsl_linalg_HH_solve(A,B,T); + time = gsl_vector_get(T,0); + gsl_matrix_free(A); + gsl_vector_free(B); + gsl_vector_free(T); + } + + double X0 = x0 + ax*time; + double Y0 = y0 + ay*time; + + double dX = _xHit[i1] - X0; + double dY = _yHit[i1] - Y0; + + double R0 = sqrt(dX*dX + dY*dY); + + /* + if (problematic == 1) { + std::cout << i1 << " " << i2 << " " << i3 << std::endl; + std::cout << _xHit[i1] << " " << _yHit[i1] << " " << _zHit[i1] << std::endl; + std::cout << _xHit[i2] << " " << _yHit[i2] << " " << _zHit[i2] << std::endl; + std::cout << _xHit[i3] << " " << _yHit[i3] << " " << _zHit[i3] << std::endl; + std::cout << "R0 = " << R0 << std::endl; + } + */ + + double phi1 = (double)atan2(_yHit[i1]-Y0,_xHit[i1]-X0); + double phi2 = (double)atan2(_yHit[i2]-Y0,_xHit[i2]-X0); + double phi3 = (double)atan2(_yHit[i3]-Y0,_xHit[i3]-X0); + +// testing bz > 0 hypothesis + + if ( phi1 > phi2 ) + phi2 = phi2 + 2.0*M_PI; + if ( phi1 > phi3 ) + phi3 = phi3 + 2.0*M_PI; + if ( phi2 > phi3 ) + phi3 = phi3 + 2.0*M_PI; + + double bz_plus = (phi3 - phi1) / (_zHit[i3]-_zHit[i1]); + double phi0_plus = phi1 - bz_plus * _zHit[i1]; + double dphi_plus = fabs( bz_plus * _zHit[i2] + phi0_plus - phi2 ); + +// testing bz < 0 hypothesis + + phi1 = (double)atan2(_yHit[i1]-Y0,_xHit[i1]-X0); + phi2 = (double)atan2(_yHit[i2]-Y0,_xHit[i2]-X0); + phi3 = (double)atan2(_yHit[i3]-Y0,_xHit[i3]-X0); + + if ( phi1 < phi2 ) + phi2 = phi2 - 2.0*M_PI; + if ( phi1 < phi3 ) + phi3 = phi3 - 2.0*M_PI; + if ( phi2 < phi3 ) + phi3 = phi3 - 2.0*M_PI; + + double bz_minus = (phi3 - phi1) / (_zHit[i3]-_zHit[i1]); + double phi0_minus = phi1 - bz_minus * _zHit[i1]; + double dphi_minus = fabs( bz_minus * _zHit[i2] + phi0_minus - phi2 ); + + double bz; + double phi0; + + if (dphi_plus < dphi_minus) { + bz = bz_plus; + phi0 = phi0_plus; + } + else { + bz = bz_minus; + phi0 = phi0_minus; + + } + + double par_init[5]; + + if (parametrisation == 1) { + par_init[0] = (double)X0; + par_init[1] = (double)Y0; + par_init[2] = (double)R0; + par_init[3] = (double)bz; + par_init[4] = (double)phi0; + } + else if (parametrisation == 2) { + par_init[0] = (double)X0; + par_init[1] = (double)Y0; + par_init[2] = (double)(-phi0/bz); + par_init[3] = (double)R0; + par_init[4] = (double)(1/bz); + } + + else if (parametrisation == 3) { // parameter vector: (z0,Phi0,omega,d0,tanL) + + // debug + // std::cout << std::setprecision(6) << "InitFit (X0,Y0,R0,bz,phi0) = " << "(" << X0 << "," << Y0 << "," << R0 << "," << bz << "," << phi0 << ")" << std::endl; + + + // debug + /* + X0 = -1205.28; + Y0 = 175.317; + R0 = 1217.97; + bz = 0.00326074; + phi0 = -0.144444; + */ + + + // debug + // std::cout << std::setprecision(6) << "InitUsed (X0,Y0,R0,bz,phi0) = " << "(" << X0 << "," << Y0 << "," << R0 << "," << bz << "," << phi0 << ")" << std::endl; + + double omega = 1/R0*direction; + double tanL = (-1.0)*omega/bz; + + double Phi0 = (-1.0)*atan2(X0,Y0); + + if (direction == 1) { + + if (tanL >= 0.0) Phi0 += M_PI; // add pi (see LC-DET-2006-004) // >= or > ? + else Phi0 -= M_PI; // < or <= ? + + } + + //double d0 = R0 - X0/sin(Phi0); + //double d0 = R0 + Y0/cos(Phi0); + + double d0 = 0.0; + if (true /*direction != 1*/) d0 = R0 - sqrt(X0*X0 + Y0*Y0); + // else d0 = R0 + sqrt(X0*X0 + Y0*Y0); + + + + // double d0 = R0 - ( (X0-Y0)/(sqrt(2.0)*cos(pi/4 - Phi0)) ); + // double d0 = R0 - ((X0-Y0)/(sin(Phi0)+cos(Phi0))); + + // double Phi0 = asin(X0/(R0-d0)); + + + double z0 = (1/bz)*((-1.0)*phi0+Phi0+(omega*M_PI)/(2.0*fabs(omega))); + + + // debug + /* + std::cout << std::setprecision(6) << "InitFitCalculated (d0,z0,phi0,omega,tanL) = " << "(" << d0 << "," << z0 << "," << Phi0 << "," << omega << "," << tanL << ")" + << " " << "sign(omega) = " << direction << std::endl; + */ + + // debug + /* + d0 = 0.00016512; + z0 = 0.000853511; + Phi0 = 1.11974; + omega = -4.22171e-05; + tanL = -0.33436; + */ + + + + + // debug + // std::cout << std::setprecision(6) << "InitFitUsed (d0,z0,phi0,omega,tanL) = " << "(" << d0 << "," << z0 << "," << Phi0 << "," << omega << "," << tanL << ")" << std::endl; + + par_init[0] = z0; + par_init[1] = Phi0; + par_init[2] = omega; + par_init[3] = d0; + par_init[4] = tanL; + } + else return 1; + + + // local variables + int status = 0; + int iter = 0; + + int npar = 5; // five parameters to fit + int ndim = 0; + if (parametrisation == 1) ndim = 2; // two dependent dimensions + else if (parametrisation == 2) ndim = 3; // three dependent dimensions + else if (parametrisation == 3) ndim = 3; // three dependent dimensions + + else return 1; + + + + double chi2_nofit = 0.0; + int iFirst = 1; + for (int ipoint(0); ipoint < _nHits; ipoint++) { + double distRPZ[2]; + double Dist = DistanceHelix(_xHit[ipoint],_yHit[ipoint],_zHit[ipoint], + X0,Y0,R0,bz,phi0,distRPZ); + double chi2rphi = distRPZ[0]/_exHit[ipoint]; + chi2rphi = chi2rphi*chi2rphi; + double chi2z = distRPZ[1]/_ezHit[ipoint]; + chi2z = chi2z*chi2z; + chi2_nofit = chi2_nofit + chi2rphi + chi2z; + if (Dist > distmax || iFirst == 1) { + distmax = Dist; + iFirst = 0; + } + } + chi2_nofit = chi2_nofit/double(_nHits); + + if ( status_out == 1 ) { + for (int i(0); i < 5; ++i) { + parameter[i] = (double)par_init[i]; + dparameter[i] = 0.0; + } + chi2 = chi2_nofit; + return 0; + } + + // converging criteria + const double abs_error = 1e-4; + const double rel_error = 1e-4; + + gsl_multifit_function_fdf fitfunct; + + const gsl_multifit_fdfsolver_type* T = gsl_multifit_fdfsolver_lmsder; + + gsl_multifit_fdfsolver* s = gsl_multifit_fdfsolver_alloc(T,ndim*_nHits,npar); + + gsl_matrix* covar = gsl_matrix_alloc(npar,npar); // covariance matrix + + data d; + d.n = _nHits; + d.x = &_xHit[0]; + d.y = &_yHit[0]; + d.z = &_zHit[0]; + d.ex = &_exHit[0]; + d.ey = &_eyHit[0]; + d.ez = &_ezHit[0]; + + + if (parametrisation == 1) { + fitfunct.f = &functParametrisation1; + fitfunct.df = &dfunctParametrisation1; + fitfunct.fdf = &fdfParametrisation1; + fitfunct.n = ndim*_nHits; + fitfunct.p = npar; + fitfunct.params = &d; + } + else if (parametrisation == 2) { + fitfunct.f = &functParametrisation2; + fitfunct.df = &dfunctParametrisation2; + fitfunct.fdf = &fdfParametrisation2; + fitfunct.n = ndim*_nHits; + fitfunct.p = npar; + fitfunct.params = &d; + } + else if (parametrisation == 3) { + fitfunct.f = &functParametrisation3; + fitfunct.df = &dfunctParametrisation3; + fitfunct.fdf = &fdfParametrisation3; + fitfunct.n = ndim*_nHits; + fitfunct.p = npar; + fitfunct.params = &d; + } + else return 1; + + gsl_vector_view pinit = gsl_vector_view_array(par_init,npar); + gsl_multifit_fdfsolver_set(s,&fitfunct,&pinit.vector); + + // perform fit + do { + iter++; + status = gsl_multifit_fdfsolver_iterate(s); + + if (status) break; + status = gsl_multifit_test_delta (s->dx, s->x,abs_error,rel_error); + + } while ( status==GSL_CONTINUE && iter < max_iter); + + gsl_multifit_covar (s->J, rel_error, covar); + + + + chi2 = 0.0; + + if (parametrisation == 1) { + X0 = (double)gsl_vector_get(s->x,0); + Y0 = (double)gsl_vector_get(s->x,1); + R0 = (double)gsl_vector_get(s->x,2); + bz = (double)gsl_vector_get(s->x,3); + phi0 = (double)gsl_vector_get(s->x,4); + } + else if (parametrisation == 2) { + X0 = (double)gsl_vector_get(s->x,0); + Y0 = (double)gsl_vector_get(s->x,1); + R0 = (double)gsl_vector_get(s->x,3); + bz = (double)(1/gsl_vector_get(s->x,4)); + phi0 = (double)(-gsl_vector_get(s->x,2)/gsl_vector_get(s->x,4)); + } + else if (parametrisation == 3) { // (parameter vector: (z0,phi0,omega,d0,tanL) + + double z0 = gsl_vector_get(s->x,0); + double Phi0 = gsl_vector_get(s->x,1); + double omega = gsl_vector_get(s->x,2); + double d0 = gsl_vector_get(s->x,3); + double tanL = gsl_vector_get(s->x,4); + + X0 = (double)( ( (1/omega) - d0 )*sin(Phi0) ); + Y0 = (double)( (-1)*( (1/omega) - d0 )*cos(Phi0) ); + R0 = (double)( 1/fabs(omega) ); + bz = (double)( (-1)*(omega/tanL) ); + phi0 = (double)( ( (z0*omega)/tanL ) + Phi0 + ( (omega*M_PI)/(2*fabs(omega)) ) ); + } + else return 1; + + iFirst = 1; + double ddmax = 0.0; + for (int ipoint(0); ipoint < _nHits; ipoint++) { + double distRPZ[2]; + double Dist = DistanceHelix(_xHit[ipoint],_yHit[ipoint],_zHit[ipoint], + X0,Y0,R0,bz,phi0,distRPZ); + double chi2rphi = distRPZ[0]/_exHit[ipoint]; + chi2rphi = chi2rphi*chi2rphi; + double chi2z = distRPZ[1]/_ezHit[ipoint]; + chi2z = chi2z*chi2z; + chi2 = chi2 + chi2rphi + chi2z; + if (Dist > ddmax || iFirst == 1) { + iFirst = 0; + ddmax = Dist; + } + } + + + chi2 = chi2/double(_nHits); + if (chi2 < chi2_nofit) { + for (int i = 0; i < npar; i++) { + parameter[i] = gsl_vector_get(s->x,i); + dparameter[i] = sqrt(gsl_matrix_get(covar,i,i)); + } + distmax = ddmax; + } + else { + chi2 = chi2_nofit; + for (int i = 0; i < npar; i++) { + parameter[i] = (double)par_init[i]; + dparameter[i] = 0.0; + } + } + + // if (problematic == 1) + // std::cout << "chi2 = " << chi2 << std::endl; + + gsl_multifit_fdfsolver_free(s); + gsl_matrix_free(covar); + return 0; + +} + + + +// ########################################## +// ##### ##### +// ##### private methods ##### +// ##### ##### +// ########################################## + +//============================================================================= + +void ClusterShapes::findElipsoid() { + + /** Elipsoid parameter calculations see cluster_proper.f */ + float cx,cy,cz ; + float dx,dy,dz ; + float r_hit_max, d_begn, d_last, r_max, proj; + if (_ifNotInertia == 1) findInertia() ; + // Normalize the eigen values of inertia tensor + float wr1 = sqrt(_ValAnalogInertia[0]/_totAmpl); + float wr2 = sqrt(_ValAnalogInertia[1]/_totAmpl); + float wr3 = sqrt(_ValAnalogInertia[2]/_totAmpl); + _r1 = sqrt(wr2*wr3); // spatial axis length -- the largest + _r2 = sqrt(wr1*wr3); // spatial axis length -- less + _r3 = sqrt(wr1*wr2); // spatial axis length -- even more less + _vol = 4.*M_PI*_r1*_r2*_r3/3.; // ellipsoid volume + _r_ave = pow(_vol,1/3); // average radius (quibc root) + _density = _totAmpl/_vol; // density + // _eccentricity = _r_ave/_r1; // Cluster Eccentricity + _eccentricity =_analogWidth/_r1; // Cluster Eccentricity + + // Find Minumal and Maximal Lenght for Principal axis + r_hit_max = -100000.; + d_begn = 100000.; + d_last = -100000.; + cx = _VecAnalogInertia[0] ; + cy = _VecAnalogInertia[1] ; + cz = _VecAnalogInertia[2] ; + for (int i(0); i < _nHits; ++i) { + dx = _xHit[i] - _xgr; + dy = _yHit[i] - _ygr; + dz = _zHit[i] - _zgr; + r_max = sqrt(dx*dx + dy*dy + dz*dz);; + if(r_max > r_hit_max) r_hit_max = r_max; + proj = dx*cx + dy*cy + dz*cz; + if(proj < d_begn) + d_begn = proj; + // lad_begn = ladc(L) + if(proj > d_last) + d_last = proj; + // lad_last = ladc(L) + } + // if (r_hit_max > 0.0) + // _r1 = 1.05*r_hit_max; // + 5% of length + _r1_forw = fabs(d_last); + _r1_back = fabs(d_begn); +} + +//============================================================================= + +void ClusterShapes::findGravity() { + + _totAmpl = 0. ; + for (int i(0); i < 3; ++i) { + _analogGravity[i] = 0.0 ; + } + for (int i(0); i < _nHits; ++i) { + _totAmpl+=_aHit[i] ; + _analogGravity[0]+=_aHit[i]*_xHit[i] ; + _analogGravity[1]+=_aHit[i]*_yHit[i] ; + _analogGravity[2]+=_aHit[i]*_zHit[i] ; + } + for (int i(0); i < 3; ++i) { + _analogGravity[i]/=_totAmpl ; + } + _xgr = _analogGravity[0]; + _ygr = _analogGravity[1]; + _zgr = _analogGravity[2]; + _ifNotGravity = 0; +} + +//============================================================================= + +void ClusterShapes::findInertia() { + + double aIne[3][3]; + // float radius1; + float radius2 = 0.0; + + findGravity(); + + for (int i(0); i < 3; ++i) { + for (int j(0); j < 3; ++j) { + aIne[i][j] = 0.0; + } + } + + for (int i(0); i < _nHits; ++i) { + float dX = _xHit[i] - _analogGravity[0]; + float dY = _yHit[i] - _analogGravity[1]; + float dZ = _zHit[i] - _analogGravity[2]; + aIne[0][0] += _aHit[i]*(dY*dY+dZ*dZ); + aIne[1][1] += _aHit[i]*(dX*dX+dZ*dZ); + aIne[2][2] += _aHit[i]*(dX*dX+dY*dY); + aIne[0][1] -= _aHit[i]*dX*dY; + aIne[0][2] -= _aHit[i]*dX*dZ; + aIne[1][2] -= _aHit[i]*dY*dZ; + } + + for (int i(0); i < 2; ++i) { + for (int j = i+1; j < 3; ++j) { + aIne[j][i] = aIne[i][j]; + } + } + //**************************************** + // analog Inertia + //**************************************** + + gsl_matrix_view aMatrix = gsl_matrix_view_array((double*)aIne,3,3); + gsl_vector* aVector = gsl_vector_alloc(3); + gsl_matrix* aEigenVec = gsl_matrix_alloc(3,3); + gsl_eigen_symmv_workspace* wa = gsl_eigen_symmv_alloc(3); + gsl_eigen_symmv(&aMatrix.matrix,aVector,aEigenVec,wa); + gsl_eigen_symmv_free(wa); + gsl_eigen_symmv_sort(aVector,aEigenVec,GSL_EIGEN_SORT_ABS_ASC); + + for (int i(0); i < 3; i++) { + _ValAnalogInertia[i] = gsl_vector_get(aVector,i); + for (int j(0); j < 3; j++) { + _VecAnalogInertia[i+3*j] = gsl_matrix_get(aEigenVec,i,j); + } + } + + // Main principal points away from IP + + _radius = 0.; + radius2 = 0.; + + for (int i(0); i < 3; ++i) { + _radius += _analogGravity[i]*_analogGravity[i]; + radius2 += (_analogGravity[i]+_VecAnalogInertia[i])*(_analogGravity[i]+_VecAnalogInertia[i]); + } + + if ( radius2 < _radius) { + for (int i(0); i < 3; ++i) + _VecAnalogInertia[i] = - _VecAnalogInertia[i]; + } + + _radius = sqrt(_radius); + _ifNotInertia = 0; + + // The final job + findWidth(); + findElipsoid(); + + gsl_vector_free(aVector); + gsl_matrix_free(aEigenVec); + +} + +//============================================================================= + +void ClusterShapes::findWidth() { + + float dist = 0.0; + if (_ifNotInertia == 1) findInertia() ; + _analogWidth = 0.0 ; + for (int i(0); i < _nHits; ++i) { + dist = findDistance(i) ; + _analogWidth+=_aHit[i]*dist*dist ; + } + _analogWidth = sqrt(_analogWidth / _totAmpl) ; + _ifNotWidth = 0 ; +} + +//============================================================================= + +float ClusterShapes::findDistance(int i) { + + float cx = 0.0; + float cy = 0.0; + float cz = 0.0; + float dx = 0.0; + float dy = 0.0; + float dz = 0.0; + cx = _VecAnalogInertia[0] ; + cy = _VecAnalogInertia[1] ; + cz = _VecAnalogInertia[2] ; + dx = _analogGravity[0] - _xHit[i] ; + dy = _analogGravity[1] - _yHit[i] ; + dz = _analogGravity[2] - _zHit[i] ; + float tx = cy*dz - cz*dy ; + float ty = cz*dx - cx*dz ; + float tz = cx*dy - cy*dx ; + float tt = sqrt(tx*tx+ty*ty+tz*tz) ; + float ti = sqrt(cx*cx+cy*cy+cz*cz) ; + float f = tt / ti ; + return f ; +} +/** + Function sdist(xp,yp,zp,cx,cy,cz,xv,yv,zv) +c---------------------------------------------------------------------- +c Distance from line to point +c xp, yp, zp -- point is at the line +c xv, yv, zv -- point is out of line +******************************************************************** +* Last update V.L.Morgunov 08-Apr-2002 * +******************************************************************** + real xp,yp,zp,cx,cy,cz,xv,yv,zv,t1,t2,t3,tt,sdist + + t1 = cy*(zp-zv)-cz*(yp-yv) + t2 = cz*(xp-xv)-cx*(zp-zv) + t3 = cx*(yp-yv)-cy*(xp-xv) + tt = sqrt(cx**2+cy**2+cz**2) + sdist = sqrt(t1**2+t2**2+t3**2)/tt + + return + end +*/ + +//============================================================================= + +float ClusterShapes::vecProduct(float * x1, float * x2) { + + float x1abs(0.); + float x2abs(0.); + float prod(0.); + + for (int i(0); i < 3; ++i) { + x1abs += x1[i]*x1[i]; + x2abs += x2[i]*x2[i]; + prod += x1[i]*x2[i]; + } + + + x1abs = sqrt(x1abs); + x2abs = sqrt(x2abs); + + if (x1abs > 0.0 && x2abs > 0.0) { + prod = prod/(x1abs*x2abs); + } + else { + prod = 0.; + } + + return prod; + +} + +//============================================================================= + +float ClusterShapes::vecProject(float * x, float * axis) { + float axisabs(0.); + float prod(0.); + for (int i(0); i < 3; ++i) { + axisabs += axis[i]*axis[i]; + prod += x[i]*axis[i]; + } + axisabs = sqrt(axisabs); + if (axisabs > 0.0 ) { + prod = prod/axisabs; + } + else { + prod = 0.; + } + return prod; +} + +//============================================================================= + +double ClusterShapes::DistanceHelix(double x, double y, double z, double X0, double Y0, + double R0, double bz, double phi0, double * distRPZ) { + + double phi = atan2(y-Y0,x-X0); + double R = sqrt( (y-Y0)*(y-Y0) + (x-X0)*(x-X0) ); + double dXY2 = (R-R0)*(R-R0); + double _const_2pi = 2.0*M_PI; + double xN = (bz*z + phi0 - phi)/_const_2pi; + + int n1 = 0; + int n2 = 0; + int nSpirals = 0; + + if (xN > 0) { + n1 = (int)xN; + n2 = n1 + 1; + } + else { + n1 = (int)xN - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xN) < fabs(n2-xN)) { + nSpirals = n1; + } + else { + nSpirals = n2; + } + + double dZ = (phi + _const_2pi*nSpirals - phi0)/bz - z; + double dZ2 = dZ*dZ; + + distRPZ[0] = sqrt(dXY2); + distRPZ[1] = sqrt(dZ2); + + return sqrt(dXY2 + dZ2); + +} + +//============================================================================= + +int ClusterShapes::transformToEigensystem(float* xStart, int& index_xStart, float X0, + float Rm) { + + if (_ifNotInertia == 1) findInertia(); + + float MainAxis[3]; + float MainCentre[3]; + + + MainAxis[0] = _VecAnalogInertia[0]; + MainAxis[1] = _VecAnalogInertia[1]; + MainAxis[2] = _VecAnalogInertia[2]; + MainCentre[0] = _analogGravity[0]; + MainCentre[1] = _analogGravity[1]; + MainCentre[2] = _analogGravity[2]; + + int ifirst = 0; + float xx[3]; + float prodmin = 0.0; + int index = 0; + + for (int i(0); i < _nHits; ++i) { + xx[0] = _xHit[i] - MainCentre[0]; + xx[1] = _yHit[i] - MainCentre[1]; + xx[2] = _zHit[i] - MainCentre[2]; + float prod = vecProject(xx,MainAxis); + if (ifirst == 0 || prod < prodmin) { + ifirst = 1; + prodmin = prod; + index = i; + } + } + xStart[0] = MainCentre[0] + prodmin*MainAxis[0]; + xStart[1] = MainCentre[1] + prodmin*MainAxis[1]; + xStart[2] = MainCentre[2] + prodmin*MainAxis[2]; + index_xStart = index; + + for (int i(0); i < _nHits; ++i) { + xx[0] = _xHit[i] - xStart[0]; + xx[1] = _yHit[i] - xStart[1]; + xx[2] = _zHit[i] - xStart[2]; + float xx2(0.); + for (int j(0); j < 3; ++j) xx2 += xx[j]*xx[j]; + + _xl[i] = 0.001 + vecProject(xx,MainAxis); + _xt[i] = sqrt(std::max(0.0,xx2 + 0.1 - _xl[i]*_xl[i])); + // std::cout << i << " " << _xl[i] << " " << _xt[i] << " " << _aHit[i] << " " + // << std::endl; + } + + for (int i = 0; i < _nHits; ++i) { + _t[i] = _xl[i]/X0; + _s[i] = _xt[i]/Rm; + } + + _ifNotEigensystem = 0; + + return 0; // no error messages at the moment + +} + +//============================================================================= + +float ClusterShapes::calculateChi2Fit3DProfileSimple(float a, float b, float c, + float d) { + + // ClusterShapes::transformToEigensystem needs to be executed before + + float chi2 = 0.0; + float Ampl = 0.0; + + for (int i(0); i < _nHits; ++i) { + // old definition of Ampl and chi2 + //Ampl = a*(float)pow(_xl[i],b)*exp(-c*_xl[i]-d*_xt[i]); + //chi2 += ((Ampl - _aHit[i])*(Ampl - _aHit[i]))/(_aHit[i]*_aHit[i]); + + Ampl = a*(float)pow(_xl[i],b)*exp(-c*_xl[i]-d*_xt[i]); + chi2 += (log(_aHit[i]) - log(Ampl))*(log(_aHit[i]) - log(Ampl)); + } + + chi2 = chi2/std::max((float)1.0,(float)(_nHits - 4)); + + return chi2; + +} + +//============================================================================= + +float ClusterShapes::calculateChi2Fit3DProfileAdvanced(float E0, float a, float b, + float d, float t0) { + + // ClusterShapes::transformToEigensystem needs to be executed before + + float chi2 = 0.0; + float Ampl = 0.0; + float shift = 0.0; + + for (int i(0); i < _nHits; ++i) { + + shift = _t[i]-t0; + + if (shift <= 0) Ampl = 0.0; + else { + Ampl = E0 * b * invG(a) * pow(b*(shift),a-1) + * exp(-b*(shift)) * exp(-d*_s[i]); + } + + // debug + /* + std::cout << "OUT : " << Ampl << " " << E0 << " " << a << " " << b << " " + << d << " " << t0 << " " << _t[i] << " " << invG(a) << " " + << pow(b*(_t[i]-t0),a-1) << " " << exp(-b*(_t[i]-t0)) << " " + << exp(-d*_s[i]) + << std::endl; + */ + + chi2 += ((Ampl - _aHit[i])*(Ampl - _aHit[i]))/(_aHit[i]*_aHit[i]); + //chi2 += (log(_aHit[i]) - log(Ampl))*(log(_aHit[i]) - log(Ampl)); + //chi2 += log((Ampl - _aHit[i])*(Ampl - _aHit[i]))/log(_aHit[i]*_aHit[i]); + + } + chi2 = chi2/std::max((float)1.0,(float)(_nHits - 4)); + + return chi2; + +} + +//============================================================================= + +int ClusterShapes::fit3DProfileSimple(float& chi2, float& a, float& b, float& c, + float& d) { + + // Fit function: _aHit[i] = a * pow(_xl[i],b) * exp(-c*_xl[i]) * exp(-d*_xt[i]) + + float Slnxl(0.); + float Sxl(0.); + float Sxt(0.); + float Sln2xl(0.); + float Sxllnxl(0.); + float Sxtlnxl(0.); + float Sxlxl(0.); + float Sxlxt(0.); + float Sxtxt(0.); + float SlnA(0.); + float SlnAlnxl(0.); + float SlnAxl(0.); + float SlnAxt(0.); + + // for a quadratic matrix + for (int i = 0; i < _nHits; i++) { + Slnxl += log(_xl[i]); + Sxl += _xl[i]; + Sxt += _xt[i]; + Sln2xl += log(_xl[i])*log(_xl[i]); + Sxllnxl += _xl[i]*log(_xl[i]); + Sxtlnxl += _xt[i]*log(_xl[i]); + Sxlxl += _xl[i]*_xl[i]; + Sxlxt += _xl[i]*_xt[i]; + Sxtxt += _xt[i]*_xt[i]; + SlnA += log(_aHit[i]); + SlnAlnxl += log(_aHit[i])*log(_xl[i]); + SlnAxl += log(_aHit[i])*_xl[i]; + SlnAxt += log(_aHit[i])*_xt[i]; + } + // create system of linear equations, written as Ae = z + + gsl_matrix* A = gsl_matrix_alloc(4,4); + gsl_vector* z = gsl_vector_alloc(4); + gsl_vector* e = gsl_vector_alloc(4); + + // initialise matrix and vectors + + gsl_matrix_set(A,0,0,_nHits); + gsl_matrix_set(A,0,1,Slnxl); + gsl_matrix_set(A,0,2,-Sxl); + gsl_matrix_set(A,0,3,-Sxt); + + gsl_matrix_set(A,1,0,Slnxl); + gsl_matrix_set(A,1,1,Sln2xl); + gsl_matrix_set(A,1,2,-Sxllnxl); + gsl_matrix_set(A,1,3,-Sxtlnxl); + + gsl_matrix_set(A,2,0,-Sxl); + gsl_matrix_set(A,2,1,-Sxllnxl); + gsl_matrix_set(A,2,2,Sxlxl); + gsl_matrix_set(A,2,3,Sxlxt); + + gsl_matrix_set(A,3,0,-Sxt); + gsl_matrix_set(A,3,1,-Sxtlnxl); + gsl_matrix_set(A,3,2,Sxlxt); + gsl_matrix_set(A,3,3,Sxtxt); + + gsl_vector_set(z,0,SlnA); + gsl_vector_set(z,1,SlnAlnxl); + gsl_vector_set(z,2,-SlnAxl); + gsl_vector_set(z,3,-SlnAxt); + + gsl_linalg_HH_solve(A,z,e); + + a = exp(gsl_vector_get(e,0)); + b = gsl_vector_get(e,1); + c = gsl_vector_get(e,2); + d = gsl_vector_get(e,3); + + chi2 = calculateChi2Fit3DProfileSimple(a,b,c,d); + + gsl_matrix_free(A); + gsl_vector_free(z); + gsl_vector_free(e); + + int result = 0; // no error handling at the moment + return result; + +} + +//============================================================================= + +int ClusterShapes::fit3DProfileAdvanced(float& chi2, double* par_init, double* par, + int npar, float* t, float* s, float* E, + float E0) { + + // local variables + int status = 0; + int iter = 0; + int max_iter = 1000; + + + // converging criteria + const double abs_error = 0.0; + const double rel_error = 1e-1; + + + + gsl_multifit_function_fdf fitfunct; + + const gsl_multifit_fdfsolver_type* T = gsl_multifit_fdfsolver_lmsder; + + gsl_multifit_fdfsolver* Solver = gsl_multifit_fdfsolver_alloc(T,_nHits,npar); + + gsl_matrix* covar = gsl_matrix_alloc(npar,npar); // covariance matrix + + data DataSet; + DataSet.n = _nHits; + DataSet.x = &t[0]; + DataSet.y = &s[0]; + DataSet.z = &E[0]; // _aHit[0]; // ???? normalise per volume ???? + + + fitfunct.f = &ShapeFitFunct; + fitfunct.df = &dShapeFitFunct; + fitfunct.fdf = &fdfShapeFitFunct; + fitfunct.n = _nHits; + fitfunct.p = npar; + fitfunct.params = &DataSet; + + gsl_vector_view pinit = gsl_vector_view_array(par_init,npar); + gsl_multifit_fdfsolver_set(Solver,&fitfunct,&pinit.vector); + + gsl_set_error_handler_off(); + + // perform fit + do { + iter++; + std::cout << "Multidimensional Fit Iteration started ... ... "; + status = gsl_multifit_fdfsolver_iterate(Solver); + std::cout << "--- DONE ---" << std::endl; + + if (status) break; + status = gsl_multifit_test_delta (Solver->dx,Solver->x,abs_error,rel_error); + + // debug + /* + // E0 = (float)gsl_vector_get(Solver->x,0); + par[0] = (float)gsl_vector_get(Solver->x,0); + par[1] = (float)gsl_vector_get(Solver->x,1); + par[2] = (float)gsl_vector_get(Solver->x,2); + par[3] = (float)gsl_vector_get(Solver->x,3); + + std::cout << "Status of multidimensional fit : " << status << " " + << "Iterations : " << iter << std::endl; + std::cout << "E0 : " << "FIXED" << "\t" << "A : " << par[0] << "\t" << "B : " + << par[1] << "\t" << "D : " << par[2] << "\t" << "t0 : " << par[3] + << std::endl << std::endl; + */ + + } while ( status==GSL_CONTINUE && iter < max_iter); + + gsl_multifit_covar (Solver->J,rel_error,covar); + + // E0 = (float)gsl_vector_get(Solver->x,0); + par[0] = (float)gsl_vector_get(Solver->x,0); // A + par[1] = (float)gsl_vector_get(Solver->x,1); // B + par[2] = (float)gsl_vector_get(Solver->x,2); // D + par[3] = (float)gsl_vector_get(Solver->x,3); // t0 + + gsl_multifit_fdfsolver_free(Solver); + gsl_matrix_free(covar); + + chi2 = calculateChi2Fit3DProfileAdvanced(E0,par[0],par[1],par[2],par[3]); + if (status) chi2 = -1.0; + + int result = 0; // no error handling at the moment + return result; + +} + +//============================================================================= + diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.h b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.h new file mode 100644 index 0000000000000000000000000000000000000000..2b97b685cf3c2604caaced1a9fb0f44dc17ff6af --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/ClusterShapes.h @@ -0,0 +1,356 @@ +#ifndef ClusterShapes_h +#define ClusterShapes_h + + +#include <stdio.h> +#include <iostream> +#include <iomanip> +#include <string> +#include <sstream> +#include <cstdlib> +#include "HelixClass.h" +#include <math.h> + + +/** + * Utility class to derive properties of clusters, such as centre of gravity, + * axes of inertia, fits of the cluster shape and so on. All the details are + * explained in the documentation of the methods. Several classes of the GSL + * (GNU Scientific Library) are needed in this class. + * + * @authors V. Morgunov (ITEP/DESY), A. Raspereza (DESY), O. Wendt (DESY) + * @version $Id: ClusterShapes.h,v 1.14 2007-04-27 13:56:53 owendt Exp $ + * + */ +class ClusterShapes { + + public: + + /** + * Constructor + * @param nhits : number of hits in the cluster + * @param a : amplitudes of elements ('cells') of the cluster. Stored in + * an array, with one entry for each element ('cell'). Each entry + * is depending on coordinates x,y,z (Cartesian), which are stored + * in the arrays x,y,z. + * @param x,y,z : array of coordinates corresponding to the array of amplitudes a. + * + * + */ + ClusterShapes(int nhits, float* a, float* x, float* y, float* z); + + + /** + * Destructor + */ + ~ClusterShapes(); + + /** + * Defining errors for Helix Fit + */ + void setErrors(float *ex, float* ey, float *ez); + + /** + * Defining hit types for Helix Fit : + * type 1 - cyllindrical detector + * type 2 - Z disk detector + */ + void setHitTypes(int *ityp); + + + /** + * returns the number of elements of the cluster + */ + int getNumberOfHits(); + + /** + * returns the accumulated amplitude for the whole cluster (just the sum of the + * energy in all the entries of the cluster) + */ + float getTotalAmplitude(); + + /** + * returns an array, which represents a vector from the origin of the + * coordiante system, i.\ e.\ IP, to the centre of gravity of the cluster. The centre + * of gravity is calculated with the energy of the entries of the cluster. + */ + float* getCentreOfGravity(); + + /** US spelling of getCentreOfGravity */ + inline float* getCenterOfGravity() { return getCentreOfGravity() ; } + + /** + * array of the inertias of mass (i.\ e.\ energy) corresponding to the three main axes + * of inertia. The array is sorted in ascending order. + */ + float* getEigenValInertia(); + + /** + * array of the three main axes of inertia (9 entries) starting + * with the axis corresponding to the smallest inertia of mass + * (main principal axis). All axes are normalised to a length + * of 1. + */ + float* getEigenVecInertia(); + + /** + * 'mean' width of the cluster perpendicular to the main + * principal axis, defined as: + * width := sqrt( 1/TotalAmplitude * Sum(a[i]*d[i]*d[i]) ), + * where d[i] is the distance of the i-th point to the main + * principal axis. + */ + float getWidth(); + + /** + * returns the coordinates of the cluster transformed into + * the CoG-System. + * @param xlong : pointer to an array, where the calculated longitudinal coordiantes + * are stored in. + * @param xtrans : pointer to an array, where the calculated transversal coordiantes + * are stored in. + */ + int getEigenSytemCoordinates(float* xlong, float* xtrans); + + /** + * returns the coordinates and the amplitudes of the cluster + * transformed into the CoG-System. + * @param xlong : pointer to an array, where the calculated longitudinal coordiantes + * are stored in. + * @param xtrans : pointer to an array, where the calculated transversal coordiantes + * are stored in. + * @param a : pointer to an array, where the amplitudes corresponding to the + * longitudinal and transversal coordiantes are stored in. + */ + int getEigenSytemCoordinates(float* xlong, float* xtrans, float* a); + + /** + * performs a least square fit on the shape of an electro- + * magnetic-shower, which is defined as: + * A[i] = a * (xl[i]-xl0)^b * exp(-c*(xl[i]-xl0)) * exp(-d*xt[i]), + * where A[i] is the array of amplitudes, xl[i] is the + * coordinate of the actual point along the main principal + * axis and xt[i] the coordinate perpendicular to it. The return value + * of the method itself is not used at the moment (always returns 0). + * @param a,b,c,d,xl0 : references to the parameters, which are fitted. + * @param chi2 : reference to the chi2 of the fit + * @param xStart : pointer to the 'initial hit' of the cluster. It is defined + * as the point with the largest distance to the CoG measured + * in the direction towards the IP. + * @param index_xStart : index of the point in the cluster corresponding to xStart + * @param X0 : radiation length of the detector material. For a composite + * detector this is meant to be the 'mean' radiation length. + * @param Rm : Moliere radius of the the detector material. For a composite + * detector this is meant to be the 'mean' Moliere radius. + */ + int fit3DProfile(float& chi2, float& a, float& b, float& c, float& d, float& xl0, + float * xStart, int& index_xStart, float X0, float Rm); + + /** + * returns the chi2 of the fit in the method Fit3DProfile (if simple + * parametrisation is used)for a given set of parameters a,b,c,d + * @param a,b,c,d,xl0 : fitted parameters, which have been calculated before + * @param X0 : radiation length of the detector material. For a composite + * detector this is meant to be the 'mean' radiation length. + * @param Rm : Moliere radius of the the detector material. For a composite + * detector this is meant to be the 'mean' Moliere radius. + */ + float getChi2Fit3DProfileSimple(float a, float b, float c, float d, float X0, + float Rm); + + /** + * returns the chi2 of the fit in the method Fit3DProfile (if advanced + * parametrisation is used) for a given set of parameters E0,a,b,d,t0 + * @param E0,a,b,d,t0 : fitted parameters, which have been calculated before + * @param X0 : radiation length of the detector material. For a composite + * detector this is meant to be the 'mean' radiation length. + * @param Rm : Moliere radius of the the detector material. For a composite + * detector this is meant to be the 'mean' Moliere radius. + */ + float getChi2Fit3DProfileAdvanced(float E0, float a, float b, float d, float t0, + float X0, float Rm); + + /** + * performs a least square fit on a helix path in space, which + * which is defined as (Cartesian coordiantes): + * + * 1. parametrisation: + * x[i] = x0 + R*cos(b*z[i] + phi0) + * y[i] = y0 + R*sin(b*z[i] + phi0) + * z[i] = z[i], + * where x0,y0,R,b and phi0 are the parameters to be fitted and + * x[i],y[i],z[i] are the (Cartesian) coordiantes of the space + * points. + * + * 2. parametrisation: + * x[i] = x0 + R*cos(phi) + * y[i] = y0 + R*sin(phi) + * z[i] = z0 + b*phi + * and phi = atan2( y[i]-y0 , x[i]-x0 ), + * where x0,y0,z0,R and b are the parameters to be fitted and + * x[i],y[i],z[i] are the (Cartesian) coordiantes of the space + * points. + * + * The method returns 1 if an error occured and 0 if not. + * + * The following output/input parameters are returned/needed: + * + * OUTPUTS: + * @param parameter : array of parameters to be fitted. + * For parametrisation 1: parameter[5] = {x0,y0,R,b,phi0} + * For parametrisation 2: parameter[5] = {x0,y0,z0,R,b} + * @param dparameter : error on the parameters, that means: + * dparameter[i] = sqrt( CovarMatrix[i][i] ) + * @param chi2 : chi2 of the fit + * @param distmax : maximal distance between the points x[i],y[i] + * z[i] and the fitted function + * + * INPUTS: + * @param parametrisation : 1 for first and 2 for second parametrisation (see above) + * @param max_iter : maximal number of iterations, before fit cancels + * @param status_out : if set to 1, only the initial parameters of + * the fit are calculated and are stored in + * parameter. The entries of dparameter are + * set to 0.0 + */ + int FitHelix(int max_iter, int status_out, int parametrisation, + double* parameter, double* dparameter, double& chi2, double& distmax, int direction=1); + + + int FitHelix(int max_iter, int status_out, int parametrisation, + float* parameter, float* dparameter, float& chi2, float& distmax, int direction=1); + + /** + * distance to the centre of gravity measured from IP + * (absolut value of the vector to the centre of gravity) + */ + inline float radius() { return _radius; } + + /** + * largest spatial axis length of the ellipsoid derived + * by the inertia tensor (by their eigenvalues and eigen- + * vectors) + */ + inline float getElipsoid_r1() { return _r1; } + + /** + * medium spatial axis length of the ellipsoid derived + * by the inertia tensor (by their eigenvalues and eigen- + * vectors) + */ + inline float getElipsoid_r2() { return _r2; } + + /** + * smallest spatial axis length of the ellipsoid derived + * by the inertia tensor (by their eigenvalues and eigen- + * vectors) + */ + inline float getElipsoid_r3() { return _r3; } + + /** + * volume of the ellipsoid + */ + inline float getElipsoid_vol() { return _vol; } + + /** + * average radius of the ellipsoid (qubic root of volume) + */ + inline float getElipsoid_r_ave() { return _r_ave; } + + /** + * density of the ellipsoid defined by: totAmpl/vol + */ + inline float getElipsoid_density() { return _density; } + + /** + * eccentricity of the ellipsoid defined by: + * Width/r1 + */ + inline float getElipsoid_eccentricity() { return _eccentricity; } + + /** + * distance from centre of gravity to the point most far + * away from IP projected on the main principal axis + */ + inline float getElipsoid_r_forw() { return _r1_forw; } + + /** + * distance from centre of gravity to the point nearest + * to IP projected on the main principal axis + */ + inline float getElipsoid_r_back() { return _r1_back; } + + + + + + private: + + int _nHits; + + float* _aHit; + float* _xHit; + float* _yHit; + float* _zHit; + float* _exHit; + float* _eyHit; + float* _ezHit; + int* _types; + float* _xl; + float* _xt; + float* _t; + float* _s; + + int _ifNotGravity; + float _totAmpl; + float _radius; + float _xgr; + float _ygr; + float _zgr; + float _analogGravity[3]; + + int _ifNotWidth; + float _analogWidth; + + int _ifNotInertia; + float _ValAnalogInertia[3]; + float _VecAnalogInertia[9]; + + int _ifNotEigensystem; + + int _ifNotElipsoid; + float _r1 ; // Cluster spatial axis length -- the largest + float _r2 ; // Cluster spatial axis length -- less + float _r3 ; // Cluster spatial axis length -- less + float _vol ; // Cluster ellipsoid volume + float _r_ave ; // Cluster average radius (qubic root) + float _density ; // Cluster density + float _eccentricity ; // Cluster Eccentricity + float _r1_forw ; + float _r1_back ; + + void findElipsoid(); + void findGravity(); + void findInertia(); + void findWidth(); + float findDistance(int i); + float vecProduct(float * x1, float * x2); + float vecProject(float * x, float * axis); + double DistanceHelix(double x, double y, double z, double X0, double Y0, double R0, double bz, + double phi0, double * distRPhiZ); + int transformToEigensystem(float* xStart, int& index_xStart, float X0, float Xm); + float calculateChi2Fit3DProfileSimple(float a, float b, float c, float d); + float calculateChi2Fit3DProfileAdvanced(float E0, float a, float b, float d, float t0); + int fit3DProfileSimple(float& chi2, float& a, float& b, float& c, float& d); + int fit3DProfileAdvanced(float& chi2, double* par_init, double* par, int npar, + float* t, float* s, float* E, float E0); + + // private methods for non-linear, multidim. fitting (helix) + // static int functParametrisation1(const gsl_vector* par, void* data, gsl_vector* f); + // static int dfunctParametrisation1(const gsl_vector* par, void* d, gsl_matrix* J); + // static int fdfParametrisation1(const gsl_vector* par, void* d, gsl_vector* f, gsl_matrix* J); + + +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.cc b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.cc new file mode 100644 index 0000000000000000000000000000000000000000..6582e17e49d105cd27dcef084b14e5e0c851f2fc --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.cc @@ -0,0 +1,768 @@ +#include "HelixClass.h" +#include <math.h> +#include <stdlib.h> +#include <iostream> +#include "ced_cli.h" + +HelixClass::HelixClass() { + _const_2pi = 2.0*M_PI; + _const_pi2 = 0.5*M_PI; + _FCT = 2.99792458E-4; +} + +HelixClass::~HelixClass() {} + +void HelixClass::Initialize_VP(float * pos, float * mom, float q, float B) { + _referencePoint[0] = pos[0]; + _referencePoint[1] = pos[1]; + _referencePoint[2] = pos[2]; + _momentum[0] = mom[0]; + _momentum[1] = mom[1]; + _momentum[2] = mom[2]; + _charge = q; + _bField = B; + _pxy = sqrt(mom[0]*mom[0]+mom[1]*mom[1]); + _radius = _pxy / (_FCT*B); + _omega = q/_radius; + _tanLambda = mom[2]/_pxy; + _phiMomRefPoint = atan2(mom[1],mom[0]); + _xCentre = pos[0] + _radius*cos(_phiMomRefPoint-_const_pi2*q); + _yCentre = pos[1] + _radius*sin(_phiMomRefPoint-_const_pi2*q); + _phiRefPoint = atan2(pos[1]-_yCentre,pos[0]-_xCentre); + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phi0 = -_const_pi2*q + _phiAtPCA; + while (_phi0<0) _phi0+=_const_2pi; + while (_phi0>=_const_2pi) _phi0-=_const_2pi; + _xAtPCA = _xCentre + _radius*cos(_phiAtPCA); + _yAtPCA = _yCentre + _radius*sin(_phiAtPCA); + // _d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0); + double pxy = double(_pxy); + double radius = pxy/double(_FCT*B); + double xCentre = double(pos[0]) + radius*double(cos(_phiMomRefPoint-_const_pi2*q)); + double yCentre = double(pos[1]) + radius*double(sin(_phiMomRefPoint-_const_pi2*q)); + + double d0; + + if (q>0) { + d0 = double(q)*radius - double(sqrt(xCentre*xCentre+yCentre*yCentre)); + } + else { + d0 = double(q)*radius + double(sqrt(xCentre*xCentre+yCentre*yCentre)); + } + + _d0 = float(d0); + +// if (fabs(_d0)>0.001 ) { +// std::cout << "New helix : " << std::endl; +// std::cout << " Position : " << pos[0] +// << " " << pos[1] +// << " " << pos[2] << std::endl; +// std::cout << " Radius = " << _radius << std::endl; +// std::cout << " RC = " << sqrt(_xCentre*_xCentre+_yCentre*_yCentre) << std::endl; +// std::cout << " D0 = " << _d0 << std::endl; +// } + + _pxAtPCA = _pxy*cos(_phi0); + _pyAtPCA = _pxy*sin(_phi0); + float deltaPhi = _phiRefPoint - _phiAtPCA; + float xCircles = -pos[2]*q/(_radius*_tanLambda) - deltaPhi; + xCircles = xCircles/_const_2pi; + int nCircles; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + _z0 = pos[2] + _radius*_tanLambda*q*(deltaPhi + _const_2pi*nCircles); + +} + +void HelixClass::Initialize_Canonical(float phi0, float d0, float z0, + float omega, float tanLambda, float B) { + _omega = omega; + _d0 = d0; + _phi0 = phi0; + _z0 = z0; + _tanLambda = tanLambda; + _charge = omega/fabs(omega); + _radius = 1./fabs(omega); + _xAtPCA = -_d0*sin(_phi0); + _yAtPCA = _d0*cos(_phi0); + _referencePoint[0] = _xAtPCA; + _referencePoint[1] = _yAtPCA; + _referencePoint[2] = _z0; + _pxy = _FCT*B*_radius; + _momentum[0] = _pxy*cos(_phi0); + _momentum[1] = _pxy*sin(_phi0); + _momentum[2] = _tanLambda * _pxy; + _pxAtPCA = _momentum[0]; + _pyAtPCA = _momentum[1]; + _phiMomRefPoint = atan2(_momentum[1],_momentum[0]); + _xCentre = _referencePoint[0] + + _radius*cos(_phi0-_const_pi2*_charge); + _yCentre = _referencePoint[1] + + _radius*sin(_phi0-_const_pi2*_charge); + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phiRefPoint = _phiAtPCA ; + _bField = B; +} + + +void HelixClass::Initialize_BZ(float xCentre, float yCentre, float radius, + float bZ, float phi0, float B, float signPz, + float zBegin) { + + _radius = radius; + _pxy = _FCT*B*_radius; + _charge = -(bZ*signPz)/fabs(bZ*signPz); + _momentum[2] = -_charge*_pxy/(bZ*_radius); + _xCentre = xCentre; + _yCentre = yCentre; + _omega = _charge/radius; + _phiAtPCA = atan2(-_yCentre,-_xCentre); + _phi0 = -_const_pi2*_charge + _phiAtPCA; + while (_phi0<0) _phi0+=_const_2pi; + while (_phi0>=_const_2pi) _phi0-=_const_2pi; + _xAtPCA = _xCentre + _radius*cos(_phiAtPCA); + _yAtPCA = _yCentre + _radius*sin(_phiAtPCA); + _d0 = -_xAtPCA*sin(_phi0) + _yAtPCA*cos(_phi0); + _pxAtPCA = _pxy*cos(_phi0); + _pyAtPCA = _pxy*sin(_phi0); + _referencePoint[2] = zBegin; + _referencePoint[0] = xCentre + radius*cos(bZ*zBegin+phi0); + _referencePoint[1] = yCentre + radius*sin(bZ*zBegin+phi0); + _phiRefPoint = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + _phiMomRefPoint = -_const_pi2*_charge + _phiRefPoint; + _tanLambda = _momentum[2]/_pxy; + _momentum[0] = _pxy*cos(_phiMomRefPoint); + _momentum[1] = _pxy*sin(_phiMomRefPoint); + + float deltaPhi = _phiRefPoint - _phiAtPCA; + float xCircles = bZ*_referencePoint[2] - deltaPhi; + xCircles = xCircles/_const_2pi; + int nCircles; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + _z0 = _referencePoint[2] - (deltaPhi + _const_2pi*nCircles)/bZ; + _bField = B; + +} + +const float * HelixClass::getMomentum() { + return _momentum; +} +const float * HelixClass::getReferencePoint() { + return _referencePoint; +} +float HelixClass::getPhi0() { + if (_phi0<0.0) + _phi0 += 2*M_PI; + return _phi0; +} +float HelixClass::getD0() { + return _d0; +} +float HelixClass::getZ0() { + return _z0; +} +float HelixClass::getOmega() { + return _omega; +} +float HelixClass::getTanLambda() { + return _tanLambda; +} +float HelixClass::getPXY() { + return _pxy; +} +float HelixClass::getXC() { + return _xCentre; +} + +float HelixClass::getYC() { + return _yCentre; +} + +float HelixClass::getRadius() { + return _radius; +} + +float HelixClass::getBz() { + return _bZ; +} + +float HelixClass::getPhiZ() { + return _phiZ; +} + +float HelixClass::getCharge() { + return _charge; +} + +float HelixClass::getPointInXY(float x0, float y0, float ax, float ay, + float * ref , float * point) { + + float time; + + float AA = sqrt(ax*ax+ay*ay); + + + if (AA <= 0) { + time = -1.0e+20; + return time; + } + + + float BB = ax*(x0-_xCentre) + ay*(y0-_yCentre); + BB = BB / AA; + + float CC = (x0-_xCentre)*(x0-_xCentre) + + (y0-_yCentre)*(y0-_yCentre) - _radius*_radius; + + CC = CC / AA; + + float DET = BB*BB - CC; + float tt1 = 0.; + float tt2 = 0.; + float xx1,xx2,yy1,yy2; + + + if (DET < 0 ) { + time = 1.0e+10; + point[0]=0.0; + point[1]=0.0; + point[2]=0.0; + return time; + } + + + tt1 = - BB + sqrt(DET); + tt2 = - BB - sqrt(DET); + + xx1 = x0 + tt1*ax; + yy1 = y0 + tt1*ay; + xx2 = x0 + tt2*ax; + yy2 = y0 + tt2*ay; + + float phi1 = atan2(yy1-_yCentre,xx1-_xCentre); + float phi2 = atan2(yy2-_yCentre,xx2-_xCentre); + float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre); + + float dphi1 = phi1 - phi0; + float dphi2 = phi2 - phi0; + + if (dphi1 < 0 && _charge < 0) { + dphi1 = dphi1 + _const_2pi; + } + else if (dphi1 > 0 && _charge > 0) { + dphi1 = dphi1 - _const_2pi; + } + + if (dphi2 < 0 && _charge < 0) { + dphi2 = dphi2 + _const_2pi; + } + else if (dphi2 > 0 && _charge > 0) { + dphi2 = dphi2 - _const_2pi; + } + + // Times + tt1 = -_charge*dphi1*_radius/_pxy; + tt2 = -_charge*dphi2*_radius/_pxy; + + if (tt1 < 0. ) + std::cout << "WARNING " << tt1 << std::endl; + if (tt2 < 0. ) + std::cout << "WARNING " << tt2 << std::endl; + + + if (tt1 < tt2) { + point[0] = xx1; + point[1] = yy1; + time = tt1; + } + else { + point[0] = xx2; + point[1] = yy2; + time = tt2; + } + + point[2] = ref[2]+time*_momentum[2]; + + + + return time; + +} + + +float HelixClass::getPointOnCircle(float Radius, float * ref, float * point) { + + float distCenterToIP = sqrt(_xCentre*_xCentre + _yCentre*_yCentre); + + point[0] = 0.0; + point[1] = 0.0; + point[2] = 0.0; + + if ((distCenterToIP+_radius)<Radius) { + float xx = -1.0e+20; + return xx; + } + + if ((_radius+Radius)<distCenterToIP) { + float xx = -1.0e+20; + return xx; + } + + float phiCentre = atan2(_yCentre,_xCentre); + float phiStar = Radius*Radius + distCenterToIP*distCenterToIP + - _radius*_radius; + + phiStar = 0.5*phiStar/fmax(1.0e-20,Radius*distCenterToIP); + + if (phiStar > 1.0) + phiStar = 0.9999999; + + if (phiStar < -1.0) + phiStar = -0.9999999; + + phiStar = acos(phiStar); + + float tt1,tt2,time; + + float xx1 = Radius*cos(phiCentre+phiStar); + float yy1 = Radius*sin(phiCentre+phiStar); + + float xx2 = Radius*cos(phiCentre-phiStar); + float yy2 = Radius*sin(phiCentre-phiStar); + + + float phi1 = atan2(yy1-_yCentre,xx1-_xCentre); + float phi2 = atan2(yy2-_yCentre,xx2-_xCentre); + float phi0 = atan2(ref[1]-_yCentre,ref[0]-_xCentre); + + float dphi1 = phi1 - phi0; + float dphi2 = phi2 - phi0; + + if (dphi1 < 0 && _charge < 0) { + dphi1 = dphi1 + _const_2pi; + } + else if (dphi1 > 0 && _charge > 0) { + dphi1 = dphi1 - _const_2pi; + } + + if (dphi2 < 0 && _charge < 0) { + dphi2 = dphi2 + _const_2pi; + } + else if (dphi2 > 0 && _charge > 0) { + dphi2 = dphi2 - _const_2pi; + } + + // Times + tt1 = -_charge*dphi1*_radius/_pxy; + tt2 = -_charge*dphi2*_radius/_pxy; + + if (tt1 < 0. ) + std::cout << "WARNING " << tt1 << std::endl; + if (tt2 < 0. ) + std::cout << "WARNING " << tt2 << std::endl; + + + float time2; + if (tt1 < tt2) { + point[0] = xx1; + point[1] = yy1; + point[3] = xx2; + point[4] = yy2; + time = tt1; + time2 = tt2; + } + else { + point[0] = xx2; + point[1] = yy2; + point[3] = xx1; + point[4] = yy1; + time = tt2; + time2 = tt1; + } + + point[2] = ref[2]+time*_momentum[2]; + point[5] = ref[2]+time2*_momentum[2]; + + + return time; + +} + + +float HelixClass::getPointInZ(float zLine, float * ref, float * point) { + + float time = zLine - ref[2]; + + if (_momentum[2] == 0.) { + time = -1.0e+20; + point[0] = 0.; + point[1] = 0.; + point[2] = 0.; + return time; + } + + time = time/_momentum[2]; + + float phi0 = atan2(ref[1] - _yCentre , ref[0] - _xCentre); + float phi = phi0 - _charge*_pxy*time/_radius; + float xx = _xCentre + _radius*cos(phi); + float yy = _yCentre + _radius*sin(phi); + + point[0] = xx; + point[1] = yy; + point[2] = zLine; + + return time; + + +} + +float HelixClass::getDistanceToPoint(float * xPoint, float * Distance) { + + float zOnHelix; + float phi = atan2(xPoint[1]-_yCentre,xPoint[0]-_xCentre); + float phi0 = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + //calculate distance to XYprojected centre of Helix, comparing this with distance to radius around centre gives DistXY + float DistXY = (_xCentre-xPoint[0])*(_xCentre-xPoint[0]) + (_yCentre-xPoint[1])*(_yCentre-xPoint[1]); + DistXY = sqrt(DistXY); + DistXY = fabs(DistXY - _radius); + + int nCircles = 0; + + if (fabs(_tanLambda*_radius)>1.0e-20) { + float xCircles = phi0 - phi -_charge*(xPoint[2]-_referencePoint[2])/(_tanLambda*_radius); + xCircles = xCircles/_const_2pi; + int n1,n2; + + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + + } + + float DPhi = _const_2pi*((float)nCircles) + phi - phi0; + + zOnHelix = _referencePoint[2] - _charge*_radius*_tanLambda*DPhi; + + float DistZ = fabs(zOnHelix - xPoint[2]); + float Time; + + if (fabs(_momentum[2]) > 1.0e-20) { + Time = (zOnHelix - _referencePoint[2])/_momentum[2]; + } + else { + Time = _charge*_radius*DPhi/_pxy; + } + + Distance[0] = DistXY; + Distance[1] = DistZ; + Distance[2] = sqrt(DistXY*DistXY+DistZ*DistZ); + + return Time; + + +} + +//When we are not interested in the exact distance, we can check if we are +//already far enough away in XY, before we start calculating in Z as the +//distance will only increase +float HelixClass::getDistanceToPoint(const std::vector<float>& xPoint, float distCut) { + //calculate distance to XYprojected centre of Helix, comparing this with distance to radius around centre gives DistXY + float tempx = xPoint[0]-_xCentre; + float tempy = xPoint[1]-_yCentre; + float tempsq = sqrt(tempx*tempx + tempy*tempy); + float tempdf = tempsq - _radius; + float DistXY = fabs( tempdf ); + //If this is bigger than distCut, we dont have to know how much bigger this is + if( DistXY > distCut) { + return DistXY; + } + + int nCircles = 0; + float phi = atan2(tempy,tempx); + float phi0 = atan2(_referencePoint[1]-_yCentre,_referencePoint[0]-_xCentre); + float phidiff = phi0-phi; + float tempz = xPoint[2] - _referencePoint[2];//Yes referencePoint + float tanradius = _tanLambda*_radius; + if (fabs(tanradius)>1.0e-20) { + float xCircles = (phidiff -_charge*tempz/tanradius)/_const_2pi; + int n1,n2; + if (xCircles >= 0.) { + n1 = int(xCircles); + n2 = n1 + 1; + } + else { + n1 = int(xCircles) - 1; + n2 = n1 + 1; + } + if (fabs(n1-xCircles) < fabs(n2-xCircles)) { + nCircles = n1; + } + else { + nCircles = n2; + } + } + float DistZ = - tempz - _charge*tanradius*(_const_2pi*((float)nCircles) - phidiff); + return sqrt(DistXY*DistXY+DistZ*DistZ); +}//getDistanceToPoint(vector,float) + +float HelixClass::getDistanceToPoint(const float* xPoint, float distCut) { + std::vector<float> xPosition(xPoint, xPoint + 3 );//We are expecting three coordinates, must be +3, last element is excluded! + return getDistanceToPoint(xPosition, distCut); +}//getDistanceToPoint(float*,float) + + + +void HelixClass::setHelixEdges(float * xStart, float * xEnd) { + for (int i=0; i<3; ++i) { + _xStart[i] = xStart[i]; + _xEnd[i] = xEnd[i]; + } + +} + +float HelixClass::getDistanceToHelix(HelixClass * helix, float * pos, float * mom) { + + float x01 = getXC(); + float y01 = getYC(); + + float x02 = helix->getXC(); + float y02 = helix->getYC(); + + float rad1 = getRadius(); + float rad2 = helix->getRadius(); + + float distance = sqrt((x01-x02)*(x01-x02)+(y01-y02)*(y01-y02)); + + bool singlePoint = true; + + float phi1 = 0; + float phi2 = 0; + + if (rad1+rad2<distance) { + phi1 = atan2(y02-y01,x02-x01); + phi2 = atan2(y01-y02,x01-x02); + } + else if (distance+rad2<rad1) { + phi1 = atan2(y02-y01,x02-x01); + phi2 = phi1; + } + else if (distance+rad1<rad2) { + phi1 = atan2(y01-y02,x01-x02); + phi2 = phi1; + } + else { + singlePoint = false; + float cosAlpha = 0.5*(distance*distance+rad2*rad2-rad1*rad1)/(distance*rad2); + float alpha = acos(cosAlpha); + float phi0 = atan2(y01-y02,x01-x02); + phi1 = phi0 + alpha; + phi2 = phi0 - alpha; + } + + + float ref1[3]; + float ref2[3]; + for (int i=0;i<3;++i) { + ref1[i]=_referencePoint[i]; + ref2[i]=helix->getReferencePoint()[i]; + } + + float pos1[3]; + float pos2[3]; + float mom1[3]; + float mom2[3]; + + + if (singlePoint ) { + + float xSect1 = x01 + rad1*cos(phi1); + float ySect1 = y01 + rad1*sin(phi1); + float xSect2 = x02 + rad2*cos(phi2); + float ySect2 = y02 + rad2*sin(phi2); + float R1 = sqrt(xSect1*xSect1+ySect1*ySect1); + float R2 = sqrt(xSect2*xSect2+ySect2*ySect2); + + getPointOnCircle(R1,ref1,pos1); + helix->getPointOnCircle(R2,ref2,pos2); + + } + else { + + float xSect1 = x02 + rad2*cos(phi1); + float ySect1 = y02 + rad2*sin(phi1); + float xSect2 = x02 + rad2*cos(phi2); + float ySect2 = y02 + rad2*sin(phi2); + +// std::cout << "(xSect1,ySect1)=(" << xSect1 << "," << ySect1 << ")" << std::endl; +// std::cout << "(xSect2,ySect2)=(" << xSect2 << "," << ySect2 << ")" << std::endl; + + float temp21[3]; + float temp22[3]; + + float phiI2 = atan2(ref2[1]-y02,ref2[0]-x02); + float phiF21 = atan2(ySect1-y02,xSect1-x02); + float phiF22 = atan2(ySect2-y02,xSect2-x02); + float deltaPhi21 = phiF21 - phiI2; + float deltaPhi22 = phiF22 - phiI2; + float charge2 = helix->getCharge(); + float pxy2 = helix->getPXY(); + float pz2 = helix->getMomentum()[2]; + if (deltaPhi21 < 0 && charge2 < 0) { + deltaPhi21 += _const_2pi; + } + else if (deltaPhi21 > 0 && charge2 > 0) { + deltaPhi21 -= _const_2pi; + } + + if (deltaPhi22 < 0 && charge2 < 0) { + deltaPhi22 += _const_2pi; + } + else if (deltaPhi22 > 0 && charge2 > 0) { + deltaPhi22 -= _const_2pi; + } + + float time21 = -charge2*deltaPhi21*rad2/pxy2; + float time22 = -charge2*deltaPhi22*rad2/pxy2; + + float Z21 = ref2[2] + time21*pz2; + float Z22 = ref2[2] + time22*pz2; + + temp21[0] = xSect1; temp21[1] = ySect1; temp21[2] = Z21; + temp22[0] = xSect2; temp22[1] = ySect2; temp22[2] = Z22; + + +// std::cout << "temp21 = " << temp21[0] << " " << temp21[1] << " " << temp21[2] << std::endl; +// std::cout << "temp22 = " << temp22[0] << " " << temp22[1] << " " << temp22[2] << std::endl; + + + float temp11[3]; + float temp12[3]; + + float phiI1 = atan2(ref1[1]-y01,ref1[0]-x01); + float phiF11 = atan2(ySect1-y01,xSect1-x01); + float phiF12 = atan2(ySect2-y01,xSect2-x01); + float deltaPhi11 = phiF11 - phiI1; + float deltaPhi12 = phiF12 - phiI1; + float charge1 = _charge; + float pxy1 = _pxy; + float pz1 = _momentum[2]; + if (deltaPhi11 < 0 && charge1 < 0) { + deltaPhi11 += _const_2pi; + } + else if (deltaPhi11 > 0 && charge1 > 0) { + deltaPhi11 -= _const_2pi; + } + + if (deltaPhi12 < 0 && charge1 < 0) { + deltaPhi12 += _const_2pi; + } + else if (deltaPhi12 > 0 && charge1 > 0) { + deltaPhi12 -= _const_2pi; + } + + float time11 = -charge1*deltaPhi11*rad1/pxy1; + float time12 = -charge1*deltaPhi12*rad1/pxy1; + + float Z11 = ref1[2] + time11*pz1; + float Z12 = ref1[2] + time12*pz1; + + temp11[0] = xSect1; temp11[1] = ySect1; temp11[2] = Z11; + temp12[0] = xSect2; temp12[1] = ySect2; temp12[2] = Z12; + +// std::cout << "temp11 = " << temp11[0] << " " << temp11[1] << " " << temp11[2] << std::endl; +// std::cout << "temp12 = " << temp12[0] << " " << temp12[1] << " " << temp12[2] << std::endl; + + float Dist1 = 0; + float Dist2 = 0; + + for (int j=0;j<3;++j) { + Dist1 += (temp11[j]-temp21[j])*(temp11[j]-temp21[j]); + Dist2 += (temp12[j]-temp22[j])*(temp12[j]-temp22[j]); + } + + if (Dist1<Dist2) { + for (int l=0;l<3;++l) { + pos1[l] = temp11[l]; + pos2[l] = temp21[l]; + } + } + else { + for (int l=0;l<3;++l) { + pos1[l] = temp12[l]; + pos2[l] = temp22[l]; + } + } + + } + + getExtrapolatedMomentum(pos1,mom1); + helix->getExtrapolatedMomentum(pos2,mom2); + + float helixDistance = 0; + + for (int i=0;i<3;++i) { + helixDistance += (pos1[i] - pos2[i])*(pos1[i] - pos2[i]); + pos[i] = 0.5*(pos1[i]+pos2[i]); + mom[i] = mom1[i]+mom2[i]; + } + helixDistance = sqrt(helixDistance); + + return helixDistance; + +} + +void HelixClass::getExtrapolatedMomentum(float * pos, float * momentum) { + + float phi = atan2(pos[1]-_yCentre,pos[0]-_xCentre); + if (phi <0.) phi += _const_2pi; + phi = phi - _phiAtPCA + _phi0; + momentum[0] = _pxy*cos(phi); + momentum[1] = _pxy*sin(phi); + momentum[2] = _momentum[2]; + + +} diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.h b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.h new file mode 100644 index 0000000000000000000000000000000000000000..794f8158652a637180cb99de38e35a249c2142d9 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/HelixClass.h @@ -0,0 +1,302 @@ +#ifndef HELIXAR_H +#define HELIXAR_H 1 +#include <vector> +/** + * Utility class to manipulate with different parameterisations <br> + * of helix. Helix can be initialized in a three different <br> + * ways using the following public methods : <br> + * 1) Initialize_VP(float * pos, float * mom, float q, float B) : <br> + * initialization of helix is done using <br> + * - position of the reference point : pos[3]; <br> + * - momentum vector at the reference point : mom[3];<br> + * - particle charge : q;<br> + * - magnetic field (in Tesla) : B;<br> + * 2) Initialize_BZ(float xCentre, float yCentre, float radius, <br> + * float bZ, float phi0, float B, float signPz,<br> + * float zBegin):<br> + * initialization of helix is done according to the following<br> + * parameterization<br> + * x = xCentre + radius*cos(bZ*z + phi0)<br> + * y = yCentre + radius*sin(bZ*z + phi0)<br> + * where (x,y,z) - position of point on the helix<br> + * - (xCentre,yCentre) is the centre of circumference in R-Phi plane<br> + * - radius is the radius of circumference<br> + * - bZ is the helix slope parameter<br> + * - phi0 is the initial phase of circumference<br> + * - B is the magnetic field (in Tesla)<br> + * - signPz is the sign of the z component of momentum vector<br> + * - zBegin is the z coordinate of the reference point;<br> + * 3) void Initialize_Canonical(float phi0, float d0, float z0, float omega,<br> + * float tanlambda, float B) :<br> + * canonical (LEP-wise) parameterisation with the following parameters<br> + * - phi0 - Phi angle of momentum vector at the point of<br> + * closest approach to IP in R-Phi plane; + * - d0 - signed distance of closest approach to IP in R-Phi plane;<br> + * - z0 - z coordinate of the point of closest approach in R-Phi plane;<br> + * - omega - signed curvature;<br> + * - tanlambda - tangent of dip angle;<br> + * - B - magnetic field (in Tesla);<br> + * A set of public methods (getters) provide access to <br> + * various parameters associated with helix. Helix Class contains<br> + * also several utility methods, allowing for calculation of helix<br> + * intersection points with planes parallel and perpendicular to <br> + * z (beam) axis and determination of the distance of closest approach<br> + * from arbitrary 3D point to the helix. <br> + * @author A. Raspereza (DESY)<br> + * @version $Id: HelixClass.h,v 1.16 2008-06-05 13:47:18 rasp Exp $<br> + * + */ + +#include "LineClass.h" +class HelixClass; + +class HelixClass { + public: + +/** + * Constructor. Initializations of constants which are used + * to calculate various parameters associated with helix. + */ + HelixClass(); +/** + * Destructor. + */ + ~HelixClass(); +/** + * Initialization of helix using <br> + * - position of the reference point : pos[3]; <br> + * - momentum vector at the reference point : mom[3];<br> + * - particle charge : q;<br> + * - magnetic field (in Tesla) : B<br> + */ + void Initialize_VP(float * pos, float * mom, float q, float B); + +/** + * Initialization of helix according to the following<br> + * parameterization<br> + * x = xCentre + radius*cos(bZ*z + phi0)<br> + * y = yCentre + radius*sin(bZ*z + phi0)<br> + * where (x,y,z) - position of point on the helix<br> + * - (xCentre,yCentre) is the centre of circumference in R-Phi plane<br> + * - radius is the radius of circumference<br> + * - bZ is the helix slope parameter<br> + * - phi0 is the initial phase of circumference<br> + * - B is the magnetic field (in Tesla)<br> + * - signPz is the sign of the z component of momentum vector<br> + * - zBegin is the z coordinate of the reference point<br> + */ + void Initialize_BZ(float xCentre, float yCentre, float radius, + float bZ, float phi0, float B, float signPz, + float zBegin); +/** + * Canonical (LEP-wise) parameterisation with the following parameters<br> + * - phi0 - Phi angle of momentum vector at the point of<br> + * closest approach to IP in R-Phi plane; + * - d0 - signed distance of closest approach in R-Phi plane;<br> + * - z0 - z coordinate of the point of closest approach to IP + * in R-Phi plane;<br> + * - omega - signed curvature;<br> + * - tanlambda - tangent of dip angle;<br> + * - B - magnetic field (in Tesla)<br> + */ + void Initialize_Canonical(float phi0, float d0, float z0, float omega, + float tanlambda, float B); + /** + * Returns momentum of particle at the point of closest approach <br> + * to IP <br> + */ + const float * getMomentum(); + + /** + * Returns reference point of track <br> + */ + const float * getReferencePoint(); + + /** + * Returns Phi angle of the momentum vector <br> + * at the point of closest approach to IP <br> + */ + float getPhi0(); + + /** + * Returns signed distance of closest approach <br> + * to IP in the R-Phi plane <br> + */ + float getD0(); + + /** + * Returns z coordinate of the point of closest + * approach to IP in the R-Phi plane <br> + */ + float getZ0(); + + /** + * Returns signed curvature of the track <br> + */ + float getOmega(); + + /** + * Returns tangent of dip angle of the track <br> + */ + float getTanLambda(); + + /** + * Returns transverse momentum of the track <br> + */ + float getPXY(); + + + /** + * Returns x coordinate of circumference + */ + float getXC(); + + /** + * Returns y coordinate of circumference + */ + float getYC(); + + + /** + * Returns radius of circumference + */ + float getRadius(); + + + /** + * Returns helix intersection point with the plane <br> + * parallel to z axis. Plane is defined by two coordinates <br> + * of the point belonging to the plane (x0,y0) and normal <br> + * vector (ax,ay). ref[3] is the reference point of the helix. <br> + * point[3] - returned vector holding the coordinates of <br> + * intersection point <br> + */ + float getPointInXY(float x0, float y0, float ax, float ay, + float * ref , float * point); + + /** + * Returns helix intersection point with the plane <br> + * perpendicular to z axis. Plane is defined by z coordinate <br> + * of the plane. ref[3] is the reference point of the helix. <br> + * point[3] - returned vector holding the coordinates of <br> + * intersection point <br> + */ + float getPointInZ(float zLine, float * ref, float * point); + + /** + * Return distance of the closest approach of the helix to <br> + * arbitrary 3D point in space. xPoint[3] - coordinates of <br> + * space point. Distance[3] - vector of distances of helix to <br> + * a given point in various projections : <br> + * Distance[0] - distance in R-Phi plane <br> + * Distance[1] - distance along Z axis <br> + * Distance[2] - 3D distance <br> + */ + float getDistanceToPoint(float * xPoint, float * Distance); + + /** + * Return distance of the closest approach of the helix to <br> + * arbitrary 3D point in space. xPoint[3] - coordinates of <br> + * space point. distCut - limit on the distance between helix <br> + * and the point to reduce calculation time <br> + * If R-Phi is found to be greater than distCut, rPhi distance is returned <br> + * If the R-Phi distance is not too big, than the exact 3D distance is returned <br> + * This function can be used, if the exact distance is not always needed <br> + */ + float getDistanceToPoint(const float* xPoint, float distCut); + float getDistanceToPoint(const std::vector<float>& xPoint, float distCut); + + /** + * This method calculates coordinates of both intersection <br> + * of the helix with a cylinder. <br> + * Rotational symmetry with respect to z axis is assumed, <br> + * meaning that cylinder axis corresponds to the z axis <br> + * of reference frame. <br> + * Inputs : <br> + * Radius - radius of cylinder. <br> + * ref[3] - point of closest approach to the origin of the helix. <br> + * Output : <br> + * point[6] - coordinates of intersection point. <br> + * Method returns also generic time, defined as the <br> + * ratio of helix length from reference point to the intersection <br> + * point to the particle momentum <br> + */ + float getPointOnCircle(float Radius, float * ref, float * point); + + /** Returns distance between two helixes <br> + * Output : <br> + * pos[3] - position of the point of closest approach <br> + * mom[3] - momentum of V0 <br> + */ + float getDistanceToHelix(HelixClass * helix, float * pos, float * mom); + + /** + * Set Edges of helix + */ + void setHelixEdges(float * xStart, float * xEnd); + + /** + * Returns starting point of helix + */ + float * getStartingPoint() {return _xStart;} + + /** + * Returns endpoint of helix + */ + float * getEndPoint() {return _xEnd;} + + /** + * Returns BZ for the second parameterization + */ + float getBz(); + + /** + * Returns Phi for the second parameterization + */ + float getPhiZ(); + + /** + * Returns extrapolated momentum + */ + void getExtrapolatedMomentum(float * pos, float * momentum); + + /** + * Returns charge + */ + float getCharge(); + + private: + float _momentum[3]; // momentum @ ref point + float _referencePoint[3]; // coordinates @ ref point + float _phi0; // phi0 in canonical parameterization + float _d0; // d0 in canonical parameterisation + float _z0; // z0 in canonical parameterisation + float _omega; // signed curvuture in canonical parameterisation + float _tanLambda; // TanLambda + float _pxy; // Transverse momentum + float _charge; // Particle Charge + float _bField; // Magnetic field (assumed to point to Z>0) + float _radius; // radius of circle in XY plane + float _xCentre; // X of circle centre + float _yCentre; // Y of circle centre + float _phiRefPoint; // Phi w.r.t. (X0,Y0) of circle @ ref point + float _phiAtPCA; // Phi w.r.t. (X0,Y0) of circle @ PCA + float _xAtPCA; // X @ PCA + float _yAtPCA; // Y @ PCA + float _pxAtPCA; // PX @ PCA + float _pyAtPCA; // PY @ PCA + float _phiMomRefPoint; // Phi of Momentum vector @ ref point + float _const_pi; // PI + float _const_2pi; // 2*PI + float _const_pi2; // PI/2 + float _FCT; // 2.99792458E-4 + float _xStart[3]; // Starting point of track segment + float _xEnd[3]; // Ending point of track segment + + float _bZ; + float _phiZ; + +}; + + +#endif diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.cc b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.cc new file mode 100644 index 0000000000000000000000000000000000000000..e23db1fa3f46982b8fff4a5ecb27a0264896f97d --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.cc @@ -0,0 +1,73 @@ +#include "LineClass.h" +#include <math.h> + +/* + * Constructor + */ + +LineClass::LineClass(float x0, + float y0, + float z0, + float ax, + float ay, + float az) { + _x0[0] = x0; + _x0[1] = y0; + _x0[2] = z0; + _ax[0] = ax; + _ax[1] = ay; + _ax[2] = az; +} + +LineClass::LineClass(float *x0, + float *ax) { + + for (int i=0; i<3; ++i) { + _x0[i] = x0[i]; + _ax[i] = ax[i]; + } +} + +float * LineClass::getReferencePoint() { + return _x0; +} + +float * LineClass::getDirectionalVector() { + return _ax; +} + +void LineClass::setReferencePoint(float *x0) { + for (int i=0; i<3; ++i) + _x0[i] = x0[i]; +} + +void LineClass::setDirectionalVector(float *ax) { + for (int i=0; i<3; ++i) + _ax[i] = ax[i]; + +} + +float LineClass::getDistanceToPoint(float * xpoint, float * pos) { + + float dif[3]; + float prod = 0; + float den = 0; + for (int i=0; i<3; ++i) { + dif[i] = xpoint[i] - _x0[i]; + prod += _ax[i]*dif[i]; + den += _ax[i]*_ax[i]; + } + float time = prod/fmax(1e-10,den); + + float dist = 0.0; + for (int i=0; i<3; ++i) { + pos[i] = _x0[i] + _ax[i]*time; + dist += (xpoint[i]-pos[i])*(xpoint[i]-pos[i]); + } + dist = sqrt(dist); + + return dist; + + + +} diff --git a/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.h b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.h new file mode 100644 index 0000000000000000000000000000000000000000..98970a263225b5a53ccfded69f33c92ae517d182 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MarlinUtil/01-08/source/LineClass.h @@ -0,0 +1,32 @@ +#ifndef LINECLASS_H +#define LINECLASS_H +class LineClass { + + public: + LineClass(float x0, + float y0, + float z0, + float ax, + float ay, + float az); + + LineClass(float *x0, + float *ax); + + ~LineClass(); + + float * getReferencePoint(); + void setReferencePoint(float *x0); + float * getDirectionalVector(); + void setDirectionalVector(float *ax); + float getDistanceToPoint(float * xpoint, float * pos); + + private: + + float _x0[3]; + float _ax[3]; + + +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/CMakeLists.txt b/Reconstruction/PFA/Pandora/MatrixPandora/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..73dc84e3d20f447bdf73fba3060bf1ae6e27c887 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/CMakeLists.txt @@ -0,0 +1,60 @@ +gaudi_subdir(MatrixPandora v0r0) + +find_package(DD4hep COMPONENTS DDG4 REQUIRED) +find_package(CLHEP REQUIRED) +find_package(GSL REQUIRED )##don't use this, use CEPC LCIO version one , due to the ClusterShape.cc file which is from LCIO +message("GSL: ${GSL_LIBRARIES} ") +set (gsl_include "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/include") +set (gsl_lib1 "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/lib/libgsl.so") +set (gsl_lib2 "/cvmfs/cepc.ihep.ac.cn/software/cepcsoft/x86_64-sl6-gcc49/external/GSL/1.14/install/lib/libgslcblas.so") +find_package(LCIO REQUIRED ) +find_package(GEAR REQUIRED) +#message("ENV GEAR: $ENV{GEAR}") +find_package(EDM4HEP REQUIRED ) +#message("EDM4HEP_INCLUDE_DIRS: ${EDM4HEP_INCLUDE_DIR}") +#message("EDM4HEP_LIB: ${EDM4HEP_LIBRARIES}") +include_directories(${EDM4HEP_INCLUDE_DIR}) + +find_package(PandoraSDK REQUIRED ) +#message("PandoraSDK_INCLUDE_DIRS: ${PandoraSDK_INCLUDE_DIRS}") +#message("PandoraSDK_LIB: ${PandoraSDK_LIBRARIES}") +find_package(LCContent REQUIRED ) +#message("LCContent_INCLUDE_DIRS: ${LCContent_INCLUDE_DIRS}") +#message("LCContent_LIB: ${LCContent_LIBRARIES}") +include_directories(${PandoraSDK_INCLUDE_DIRS}) +link_libraries(${PandoraSDK_LIBRARIES}) +include_directories(${LCContent_INCLUDE_DIRS}) +link_libraries(${LCContent_LIBRARIES}) + + +list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") +find_package(ROOT 5.26.00 REQUIRED COMPONENTS Eve Geom RGL EG) + +include_directories("../CED/CED/") +include_directories("../MarlinUtil/01-08/source/") + +gaudi_depends_on_subdirs( + Service/EventSeeder + Service/GearSvc + Detector/DetInterface +) + +set(dir_srcs + src/PandoraMatrixAlg.cpp + src/MCParticleCreator.cpp + src/GeometryCreator.cpp + src/CaloHitCreator.cpp + src/TrackCreator.cpp + src/PfoCreator.cpp + ../CED/CED/*.cc + ../MarlinUtil/01-08/source/*.cc +) +set(dir_include include) +# Modules +gaudi_add_module(MatrixPandora ${dir_srcs} + INCLUDE_DIRS ${gsl_include} ${dir_include} GaudiKernel FWCore CLHEP ${LCIO_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} gear DD4hep + LINK_LIBRARIES ${gsl_lib1} ${gsl_lib2} GaudiKernel FWCore CLHEP ROOT ${LCIO_LIBRARIES} $ENV{GEAR}/lib/libgear.so $ENV{GEAR}/lib/libgearxml.so DD4hep ${DD4hep_COMPONENT_LIBRARIES} DDRec + -Wl,--no-as-needed + EDM4HEP::edm4hep EDM4HEP::edm4hepDict + -Wl,--as-needed +) diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/CaloHitCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/CaloHitCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..c7714205c558c0df913d3f28b2198204aec59f58 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/CaloHitCreator.h @@ -0,0 +1,298 @@ +/** + * @file MarlinPandora/include/CaloHitCreator.h + * + * @brief Header file for the calo hit creator class. + * + * $Log: $ + */ + +#ifndef CALO_HIT_CREATOR_H +#define CALO_HIT_CREATOR_H 1 + +#include "GaudiKernel/ISvcLocator.h" +#include "edm4hep/CalorimeterHit.h" + +#include "gear/LayerLayout.h" + +#include "Api/PandoraApi.h" + +#include "DetInterface/IGeoSvc.h" +#include "DD4hep/DD4hepUnits.h" +#include "DD4hep/Detector.h" +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> +#include "DD4hep/BitFieldCoder.h" + + +#include <string> + +typedef std::vector<edm4hep::CalorimeterHit *> CalorimeterHitVector; + +namespace gear { class GearMgr; } + +class CollectionMaps; +/** + * @brief CaloHitCreator class + */ +class CaloHitCreator +{ +public: + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_eCalCaloHitCollections; ///< The ecal calorimeter hit collections + StringVector m_hCalCaloHitCollections; ///< The hcal calorimeter hit collections + StringVector m_lCalCaloHitCollections; ///< The lcal calorimeter hit collections + StringVector m_lHCalCaloHitCollections; ///< The lhcal calorimeter hit collections + StringVector m_muonCaloHitCollections; ///< The muon calorimeter hit collections + + float m_absorberRadLengthECal; ///< The absorber radiation length in the ECal + float m_absorberIntLengthECal; ///< The absorber interaction length in the ECal + float m_absorberRadLengthHCal; ///< The absorber radiation length in the HCal + float m_absorberIntLengthHCal; ///< The absorber interaction length in the HCal + float m_absorberRadLengthOther; ///< The absorber radiation length in other detector regions + float m_absorberIntLengthOther; ///< The absorber interaction length in other detector regions + + float m_eCalToMip; ///< The calibration from deposited ECal energy to mip + float m_hCalToMip; ///< The calibration from deposited HCal energy to mip + float m_muonToMip; ///< The calibration from deposited Muon energy to mip + float m_eCalMipThreshold; ///< Threshold for creating calo hits in the ECal, units mip + float m_hCalMipThreshold; ///< Threshold for creating calo hits in the HCal, units mip + float m_muonMipThreshold; ///< Threshold for creating calo hits in the HCal, units mip + + float m_eCalToEMGeV; ///< The calibration from deposited ECal energy to EM energy + float m_eCalToHadGeVBarrel; ///< The calibration from deposited ECal barrel energy to hadronic energy + float m_eCalToHadGeVEndCap; ///< The calibration from deposited ECal endcap energy to hadronic energy + float m_hCalToEMGeV; ///< The calibration from deposited HCal energy to EM energy + float m_hCalToHadGeV; ///< The calibration from deposited HCal energy to hadronic energy + int m_muonDigitalHits; ///< Muon hits are treated as digital (energy from hit count) + float m_muonHitEnergy; ///< The energy for a digital muon calorimeter hit, units GeV + + float m_maxHCalHitHadronicEnergy; ///< The maximum hadronic energy allowed for a single hcal hit + int m_nOuterSamplingLayers; ///< Number of layers from edge for hit to be flagged as an outer layer hit + float m_layersFromEdgeMaxRearDistance; ///< Maximum number of layers from candidate outer layer hit to rear of detector + + int m_hCalEndCapInnerSymmetryOrder; ///< HCal end cap inner symmetry order (missing from ILD00 gear file) + float m_hCalEndCapInnerPhiCoordinate; ///< HCal end cap inner phi coordinate (missing from ILD00 gear file) + + // For Strip Splitting method and hybrid ECAL. + int m_stripSplittingOn; ///< To use SSA, this should be true (default is false) + int m_useEcalScLayers; ///< To use scintillator layers ~ hybrid ECAL, this should be true (default is false) + float m_eCalSiToMip; ///< The calibration from deposited Si-layer energy to mip + float m_eCalScToMip; ///< The calibration from deposited Sc-layer energy to mip + float m_eCalSiMipThreshold; ///< Threshold for creating calo hits in the Si-layers of ECAL, units mip + float m_eCalScMipThreshold; ///< Threshold for creating calo hits in the Sc-layers of ECAL, units mip + float m_eCalSiToEMGeV; ///< The calibration from deposited Si-layer energy to EM energy + float m_eCalScToEMGeV; ///< The calibration from deposited Sc-layer energy to EM energy + float m_eCalSiToHadGeVBarrel; ///< The calibration from deposited Si-layer energy on the enecaps to hadronic energy + float m_eCalScToHadGeVBarrel; ///< The calibration from deposited Sc-layer energy on the endcaps to hadronic energy + float m_eCalSiToHadGeVEndCap; ///< The calibration from deposited Si-layer energy on the enecaps to hadronic energy + float m_eCalScToHadGeVEndCap; ///< The calibration from deposited Sc-layer energy on the endcaps to hadronic energy + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc, bool encoder_style); + + /** + * @brief Destructor + */ + ~CaloHitCreator(); + + /** + * @brief Create calo hits + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateCaloHits(const LCEvent *const pLCEvent); + pandora::StatusCode CreateCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Get the calorimeter hit vector + * + * @return The calorimeter hit vector + */ + const CalorimeterHitVector &GetCalorimeterHitVector() const; + + /** + * @brief Reset the calo hit creator + */ + void Reset(); + +private: + /** + * @brief Create ecal calo hits + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateECalCaloHits(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode CreateECalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create hcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateHCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create muon calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateMuonCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create lcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateLCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Create lhcal calo hits + * + * @param pLCEvent the lcio event + */ + pandora::StatusCode CreateLHCalCaloHits(const CollectionMaps& collectionMaps); + + /** + * @brief Get common calo hit properties: position, parent address, input energy and time + * + * @param pCaloHit the lcio calorimeter hit + * @param caloHitParameters the calo hit parameters to populate + */ + void GetCommonCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const; + + /** + * @brief Get end cap specific calo hit properties: cell size, absorber radiation and interaction lengths, normal vector + * + * @param pCaloHit the lcio calorimeter hit + * @param layerLayout the gear end cap layer layout + * @param caloHitParameters the calo hit parameters to populate + * @param absorberCorrection to receive the absorber thickness correction for the mip equivalent energy + */ + void GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const; + + /** + * @brief Get barrel specific calo hit properties: cell size, absorber radiation and interaction lengths, normal vector + * + * @param pCaloHit the lcio calorimeter hit + * @param layerLayout the gear barrel layer layout + * @param barrelSymmetryOrder the barrel order of symmetry + * @param barrelPhi0 the barrel orientation + * @param staveNumber the stave number + * @param caloHitParameters the calo hit parameters to populate + * @param absorberCorrection to receive the absorber thickness correction for the mip equivalent energy + */ + void GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const; + + void GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer> &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const; + /** + * @brief Get number of active layers from position of a calo hit to the edge of the detector + * + * @param pCaloHit the lcio calorimeter hit + */ + int GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCaloHit) const; + + /** + * @brief Get the maximum radius of a calo hit in a polygonal detector structure + * + * @param pCaloHit the lcio calorimeter hit + * @param symmetryOrder the symmetry order + * @param phi0 the angular orientation + * + * @return the maximum radius + */ + float GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const; + + void GetCoding(const edm4hep::CalorimeterHit* pCaloHit, long& sys, long& x, long& y, long& z) const ; + int GetBarrelLayer(const edm4hep::CalorimeterHit *const pCaloHit, const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer> &layerLayout) const; + /** + * @brief Get the layer coding string from the provided cell id encoding string + * + * @param encodingString the cell id encoding string + * + * @return the layer coding string + */ + std::string GetLayerCoding(const std::string &encodingString) const; + + /** + * @brief Get the stave coding string from the provided cell id encoding string + * + * @param encodingString the cell id encoding string + * + * @return the stave coding string + */ + std::string GetStaveCoding(const std::string &encodingString) const; + + const Settings m_settings; ///< The calo hit creator settings + + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create calo hits + + float m_eCalBarrelOuterZ; ///< ECal barrel outer z coordinate + float m_hCalBarrelOuterZ; ///< HCal barrel outer z coordinate + float m_muonBarrelOuterZ; ///< Muon barrel outer z coordinate + float m_coilOuterR; ///< Coil outer r coordinate + + float m_eCalBarrelInnerPhi0; ///< ECal barrel inner phi0 coordinate + unsigned int m_eCalBarrelInnerSymmetry; ///< ECal barrel inner symmetry order + float m_hCalBarrelInnerPhi0; ///< HCal barrel inner phi0 coordinate + unsigned int m_hCalBarrelInnerSymmetry; ///< HCal barrel inner symmetry order + float m_muonBarrelInnerPhi0; ///< Muon barrel inner phi0 coordinate + unsigned int m_muonBarrelInnerSymmetry; ///< Muon barrel inner symmetry order + + float m_hCalEndCapOuterR; ///< HCal endcap outer r coordinate + float m_hCalEndCapOuterZ; ///< HCal endcap outer z coordinate + float m_hCalBarrelOuterR; ///< HCal barrel outer r coordinate + float m_hCalBarrelOuterPhi0; ///< HCal barrel outer phi0 coordinate + unsigned int m_hCalBarrelOuterSymmetry; ///< HCal barrel outer symmetry order + + float m_hCalBarrelLayerThickness; ///< HCal barrel layer thickness + float m_hCalEndCapLayerThickness; ///< HCal endcap layer thickness + + CalorimeterHitVector m_calorimeterHitVector; ///< The calorimeter hit vector + std::string m_encoder_str; + std::string m_encoder_str_MUON ; + std::string m_encoder_str_LCal ; + std::string m_encoder_str_LHCal; + gear::GearMgr* _GEAR; + dd4hep::Detector* m_dd4hep; + dd4hep::rec::CellIDPositionConverter* m_cellIDConverter; + std::string m_compact ; +}; + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline const CalorimeterHitVector &CaloHitCreator::GetCalorimeterHitVector() const +{ + return m_calorimeterHitVector; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline void CaloHitCreator::Reset() +{ + m_calorimeterHitVector.clear(); +} + +#endif // #ifndef CALO_HIT_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/GeometryCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/GeometryCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..0a0c1ae2d6953e7d1b066e4107fda52c55396ff1 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/GeometryCreator.h @@ -0,0 +1,166 @@ +/** + * @file MarlinPandora/include/GeometryCreator.h + * + * @brief Header file for the geometry creator class. + * + * $Log: $ + */ + +#ifndef GEOMETRY_CREATOR_H +#define GEOMETRY_CREATOR_H 1 + +#include "Api/PandoraApi.h" + +#include "GaudiKernel/ISvcLocator.h" + +#include "DetInterface/IGeoSvc.h" +#include "DD4hep/DD4hepUnits.h" +#include "DD4hep/Detector.h" + +namespace gear { class CalorimeterParameters; class GearMgr; } + +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief GeometryCreator class + */ +class GeometryCreator +{ +public: + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + float m_absorberRadLengthECal; ///< The absorber radiation length in the ECal + float m_absorberIntLengthECal; ///< The absorber interaction length in the ECal + float m_absorberRadLengthHCal; ///< The absorber radiation length in the HCal + float m_absorberIntLengthHCal; ///< The absorber interaction length in the HCal + float m_absorberRadLengthOther; ///< The absorber radiation length in other detector regions + float m_absorberIntLengthOther; ///< The absorber interaction length in other detector regions + + int m_eCalEndCapInnerSymmetryOrder; ///< ECal end cap inner symmetry order (missing from ILD gear files) + float m_eCalEndCapInnerPhiCoordinate; ///< ECal end cap inner phi coordinate (missing from ILD gear files) + int m_eCalEndCapOuterSymmetryOrder; ///< ECal end cap outer symmetry order (missing from ILD gear files) + float m_eCalEndCapOuterPhiCoordinate; ///< ECal end cap outer phi coordinate (missing from ILD gear files) + + int m_hCalEndCapInnerSymmetryOrder; ///< HCal end cap inner symmetry order (missing from ILD gear files) + float m_hCalEndCapInnerPhiCoordinate; ///< HCal end cap inner phi coordinate (missing from ILD gear files) + int m_hCalEndCapOuterSymmetryOrder; ///< HCal end cap outer symmetry order (missing from ILD gear files) + float m_hCalEndCapOuterPhiCoordinate; ///< HCal end cap outer phi coordinate (missing from ILD gear files) + + int m_hCalRingInnerSymmetryOrder; ///< HCal ring inner symmetry order (missing from ILD gear files) + float m_hCalRingInnerPhiCoordinate; ///< HCal ring inner phi coordinate (missing from ILD gear files) + int m_hCalRingOuterSymmetryOrder; ///< HCal ring outer symmetry order (missing from ILD gear files) + float m_hCalRingOuterPhiCoordinate; ///< HCal ring outer phi coordinate (missing from ILD gear files) + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + GeometryCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~GeometryCreator(); + + /** + * @brief Create geometry + */ + //pandora::StatusCode CreateGeometry() const; + pandora::StatusCode CreateGeometry(ISvcLocator* svcloc); + +private: + typedef std::map<pandora::SubDetectorType, PandoraApi::Geometry::SubDetector::Parameters> SubDetectorTypeMap; + typedef std::map<std::string, PandoraApi::Geometry::SubDetector::Parameters> SubDetectorNameMap; + + /** + * @brief Set mandatory sub detector parameters + * + * @param subDetectorTypeMap the sub detector type map + */ + void SetMandatorySubDetectorParameters(SubDetectorTypeMap &subDetectorTypeMap) const; + + /** + * @brief Set additional sub detector parameters + * + * @param subDetectorNameMap the sub detector name map (for smaller sub detectors, identified uniquely only by name) + */ + void SetAdditionalSubDetectorParameters(SubDetectorNameMap &subDetectorNameMap) const; + + /** + * @brief Set sub detector parameters to their gear default values + * + * @param inputParameters input parameters, from gear + * @param subDetectorName the sub detector name + * @param subDetectorType the sub detector type + * @param parameters the sub detector parameters + */ + void SetDefaultSubDetectorParameters(const gear::CalorimeterParameters &inputParameters, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const; + + void SetDefaultSubDetectorParameters(const dd4hep::Detector* theDetector, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const; + + /** + * @brief Set positions of gaps in ILD detector and add information missing from GEAR parameters file + * + * @param subDetectorTypeMap the sub detector type map + * @param subDetectorNameMap the sub detector name map (for smaller sub detectors, identified uniquely only by name) + */ + pandora::StatusCode SetILDSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap, SubDetectorNameMap &subDetectorNameMap) const; + + /** + * @brief Add information missing from GEAR parameters file for ILD SDHCAL detector + * + * @param subDetectorTypeMap the sub detector type map + */ + pandora::StatusCode SetILD_SDHCALSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap) const; + + /** + * @brief Specify positions of hcal barrel box gaps - ILD specific + */ + pandora::StatusCode CreateHCalBarrelBoxGaps() const; + + /** + * @brief Specify positions of hcal end cap box gaps - ILD specific + */ + pandora::StatusCode CreateHCalEndCapBoxGaps() const; + + /** + * @brief Specify positions of hcal barrel concentric polygon gaps - ILD specific + */ + pandora::StatusCode CreateHCalBarrelConcentricGaps() const; + + /** + * @brief Create box gaps at regular positions on polygonal prism, oriented along main z axis - ILD specific + * + * @param symmetryOrder the pandora geometry parameters + * @param phi0 the phi coordinate + * @param innerRadius the inner r coordinate + * @param outerRadius the outer r coordinate + * @param minZ the minimum z coordinate + * @param maxZ the maximum z coordinate + * @param gapWidth the gap width + * @param vertexOffset position offset for vertex that doesn't point back to origin of xy plane + */ + pandora::StatusCode CreateRegularBoxGaps(unsigned int symmetryOrder, float phi0, float innerRadius, float outerRadius, float minZ, + float maxZ, float gapWidth, pandora::CartesianVector vertexOffset = pandora::CartesianVector(0, 0, 0)) const; + + const Settings m_settings; ///< The geometry creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create the geometry + gear::GearMgr* _GEAR; + dd4hep::Detector* m_dd4hep; +}; + +#endif // #ifndef GEOMETRY_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/MCParticleCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/MCParticleCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..4ad9f27553b03b7c795d6fc457fa6ecddaa46463 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/MCParticleCreator.h @@ -0,0 +1,98 @@ +/** + * @file MarlinPandora/include/MCParticleCreator.h + * + * @brief Header file for the mc particle creator class. + * + * $Log: $ + */ + +#ifndef MC_PARTICLE_CREATOR_H +#define MC_PARTICLE_CREATOR_H 1 + +#include "edm4hep/MCParticle.h" +#include "Api/PandoraApi.h" + +#include "CaloHitCreator.h" +#include "TrackCreator.h" +/** + * @brief MCParticleCreator class + */ + +class CollectionMaps; + +class MCParticleCreator +{ +public: + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_mcParticleCollections; ///< The mc particle collections + StringVector m_CaloHitRelationCollections; ///< The SimCaloHit to CaloHit particle relations + StringVector m_TrackRelationCollections; ///< The SimTrackerHit to TrackerHit particle relations + float m_bField; ///< m_bField + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + MCParticleCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~MCParticleCreator(); + + /** + * @brief Create MCParticles + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateMCParticles(const EVENT::LCEvent *const pLCEvent) const; + //pandora::StatusCode CreateMCParticles(const std::map<std::string, const podio::CollectionBase*>& collectionMap ) const; + pandora::StatusCode CreateMCParticles(const CollectionMaps& collectionMaps ) const; + + /** + * @brief Create Track to mc particle relationships + * + * @param pLCEvent the lcio event + * @param trackVector the vector containing all tracks successfully passed to pandora + */ + // pandora::StatusCode CreateTrackToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const TrackVector &trackVector) const; + pandora::StatusCode CreateTrackToMCParticleRelationships(const CollectionMaps& collectionMaps, const TrackVector &trackVector) const; + + void Reset(); + /** + * @brief Create calo hit to mc particle relationships + * + * @param pLCEvent the lcio event + * @param calorimeterHitVector the vector containing all calorimeter hits successfully passed to pandora + */ +// pandora::StatusCode CreateCaloHitToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const CalorimeterHitVector &calorimeterHitVector) const; + pandora::StatusCode CreateCaloHitToMCParticleRelationships(const CollectionMaps& collectionMaps, const CalorimeterHitVector &calorimeterHitVector) const; + +private: + const Settings m_settings; ///< The mc particle creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create the mc particles + const float m_bField; ///< The bfield + std::map<unsigned int, const edm4hep::MCParticle*>* m_id_pMC_map; +}; + +inline void MCParticleCreator::Reset() +{ + m_id_pMC_map->clear(); +} + +#endif // #ifndef MC_PARTICLE_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/PandoraMatrixAlg.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/PandoraMatrixAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..63210760fdcfe3b7b4e08697ce340639dee6edf3 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/PandoraMatrixAlg.h @@ -0,0 +1,327 @@ +#ifndef PandoraMatrixAlg_H +#define PandoraMatrixAlg_H + +#include "FWCore/DataHandle.h" +#include "GaudiAlg/GaudiAlgorithm.h" +#include <gsl/gsl_rng.h> +#include "edm4hep/ClusterCollection.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/VertexCollection.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/MCRecoCaloAssociation.h" +#include "edm4hep/MCRecoTrackerAssociation.h" +#include "edm4hep/MCRecoTrackerAssociationCollection.h" +#include "edm4hep/MCRecoCaloAssociationCollection.h" +#include "edm4hep/MCRecoParticleAssociation.h" +#include "edm4hep/MCRecoParticleAssociationCollection.h" + +#include "Api/PandoraApi.h" + +#ifdef MONITORING +#include "TApplication.h" +#endif + +#include <iostream> +#include <random> +#include <string> +#include <unistd.h> + + +#include "CaloHitCreator.h" +#include "GeometryCreator.h" +#include "MCParticleCreator.h" +#include "PfoCreator.h" +#include "TrackCreator.h" + +#include "TROOT.h" +#include "TTree.h" +#include "TFile.h" + + +/* PandoraMatrixAlg ========== <br> + * + */ +namespace pandora {class Pandora;} + +class IEventSeeder; + +class CollectionMaps +{ +public: + /** + * @brief Default constructor + */ + CollectionMaps(); + void clear(); + std::map<std::string, const edm4hep::MCParticleCollection*> CollectionMap_MC; + std::map<std::string, const edm4hep::CalorimeterHitCollection*> CollectionMap_CaloHit; + std::map<std::string, const edm4hep::VertexCollection*> CollectionMap_Vertex; + std::map<std::string, const edm4hep::TrackCollection*> CollectionMap_Track; + + std::map<std::string, std::vector<edm4hep::MCParticle> > collectionMap_MC; + std::map<std::string, std::vector<edm4hep::CalorimeterHit> > collectionMap_CaloHit; + std::map<std::string, std::vector<edm4hep::Vertex> > collectionMap_Vertex; + std::map<std::string, std::vector<edm4hep::Track> > collectionMap_Track; + std::map<std::string, std::vector<edm4hep::MCRecoCaloAssociation> > collectionMap_CaloRel; + std::map<std::string, std::vector<edm4hep::MCRecoTrackerAssociation> > collectionMap_TrkRel; +}; + + + +class PandoraMatrixAlg : public GaudiAlgorithm +{ + //friend class AlgFactory<PandoraMatrixAlg>;//gives error in 97 version + +public: + + PandoraMatrixAlg(const std::string& name, ISvcLocator* svcLoc); + + /** Called at the begin of the job before anything is read. + * Use to initialize the processor, e.g. book histograms. + */ + virtual StatusCode initialize() ; + + /** Called for every event - the working horse. + */ + virtual StatusCode execute() ; + + /** Called after data processing for clean up. + */ + virtual StatusCode finalize() ; + + //void FinaliseSteeringParameters(); + void FinaliseSteeringParameters(ISvcLocator* svcloc); + pandora::StatusCode RegisterUserComponents() const; + void Reset(); + typedef std::vector<float> FloatVector; + typedef std::vector<std::string> StringVector; + + + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + std::string m_pandoraSettingsXmlFile; ///< The pandora settings xml file + + float m_innerBField; ///< The bfield in the main tracker, ecal and hcal, units Tesla + float m_muonBarrelBField; ///< The bfield in the muon barrel, units Tesla + float m_muonEndCapBField; ///< The bfield in the muon endcap, units Tesla + + FloatVector m_inputEnergyCorrectionPoints; ///< The input energy points for non-linearity energy correction + FloatVector m_outputEnergyCorrectionPoints; ///< The output energy points for non-linearity energy correction + }; + + + /** + * @brief Get address of the pandora instance + * + * @return address of the pandora instance + */ + const pandora::Pandora *GetPandora() const; + StatusCode updateMap(); + StatusCode updateMap(CollectionMaps & tmp_map); + StatusCode Ana(); + StatusCode CreateMCRecoParticleAssociation(); + //StatusCode Create_MC(); +protected: + + typedef std::vector<float> FloatVec; + + int _nEvt ; + + IEventSeeder * _SEEDER; + + + Gaudi::Property< std::string > m_PandoraSettingsXmlFile { this, "PandoraSettingsDefault_xml", "/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraSettingsDefault_wx.xml" }; + Gaudi::Property<int> m_NEventsToSkip { this, "NEventsToSkip", 0 }; + + Gaudi::Property< std::vector<std::string> > m_TrackCollections{ this, "TrackCollections", {"MarlinTrkTracks"} }; + Gaudi::Property< std::vector<std::string> > m_ECalCaloHitCollections{ this, "ECalCaloHitCollections", {"ECALBarrel","ECALEndcap","ECALOther"} }; + Gaudi::Property< std::vector<std::string> > m_HCalCaloHitCollections{ this, "HCalCaloHitCollections", {"HCALBarrel","HCALEndcap","HCALOther"} }; + Gaudi::Property< std::vector<std::string> > m_LCalCaloHitCollections{ this, "LCalCaloHitCollections", {"LCAL"} }; + Gaudi::Property< std::vector<std::string> > m_LHCalCaloHitCollections{ this, "LHCalCaloHitCollections", {"LHCAL"} }; + Gaudi::Property< std::vector<std::string> > m_MuonCaloHitCollections{ this, "MuonCaloHitCollections", {"MUON"} }; + Gaudi::Property< std::vector<std::string> > m_MCParticleCollections{ this, "MCParticleCollections", {"MCParticle"} }; + Gaudi::Property< std::vector<std::string> > m_RelCaloHitCollections{ this, "RelCaloHitCollections", {"RelationCaloHit","RelationMuonHit"} }; + Gaudi::Property< std::vector<std::string> > m_RelTrackCollections{ this, "RelTrackCollections", {"MarlinTrkTracksMCTruthLink"} }; + Gaudi::Property< std::vector<std::string> > m_KinkVertexCollections{ this, "KinkVertexCollections", {"KinkVertices"} }; + Gaudi::Property< std::vector<std::string> > m_ProngVertexCollections{ this, "ProngVertexCollections", {"ProngVertices"} }; + Gaudi::Property< std::vector<std::string> > m_SplitVertexCollections{ this, "SplitVertexCollections", {"SplitVertices"} }; + Gaudi::Property< std::vector<std::string> > m_V0VertexCollections{ this, "V0VertexCollections", {"V0Vertices"} }; + Gaudi::Property< std::string > m_ClusterCollectionName { this, "ClusterCollectionName", "PandoraClusters" }; + Gaudi::Property< std::string > m_PFOCollectionName { this, "PFOCollectionName", "PandoraPFOs" }; + Gaudi::Property<float> m_ECalToMipCalibration{ this, "ECalToMipCalibration", 160.0 }; + Gaudi::Property<float> m_HCalToMipCalibration{ this, "HCalToMipCalibration", 34.8 }; + Gaudi::Property<float> m_ECalMipThreshold{ this, "ECalMipThreshold", 0.5 }; + Gaudi::Property<float> m_HCalMipThreshold{ this, "HCalMipThreshold", 0.3 }; + Gaudi::Property<float> m_ECalToEMGeVCalibration{ this, "ECalToEMGeVCalibration", 1.007 }; + Gaudi::Property<float> m_HCalToEMGeVCalibration{ this, "HCalToEMGeVCalibration", 1.007 }; + Gaudi::Property<float> m_ECalToHadGeVCalibrationBarrel{ this, "ECalToHadGeVCalibrationBarrel", 1.12 }; + Gaudi::Property<float> m_ECalToHadGeVCalibrationEndCap{ this, "ECalToHadGeVCalibrationEndCap", 1.12 }; + Gaudi::Property<float> m_HCalToHadGeVCalibration{ this, "HCalToHadGeVCalibration", 1.07 }; + Gaudi::Property<float> m_MuonToMipCalibration{ this, "MuonToMipCalibration", 10.0 }; + Gaudi::Property<int> m_DigitalMuonHits{ this, "DigitalMuonHits", 0 }; + Gaudi::Property<float> m_MaxHCalHitHadronicEnergy{ this, "MaxHCalHitHadronicEnergy", 1.0 }; + Gaudi::Property<int> m_UseOldTrackStateCalculation{ this, "UseOldTrackStateCalculation", 0 }; + + + Gaudi::Property<float> m_AbsorberRadLengthECal{ this, "AbsorberRadLengthECal", 0.2854 }; + Gaudi::Property<float> m_AbsorberIntLengthECal{ this, "AbsorberIntLengthECal", 0.0101 }; + Gaudi::Property<float> m_AbsorberRadLengthHCal{ this, "AbsorberRadLengthHCal", 0.0569 }; + Gaudi::Property<float> m_AbsorberIntLengthHCal{ this, "AbsorberIntLengthHCal", 0.006 }; + Gaudi::Property<float> m_AbsorberRadLengthOther{ this, "AbsorberRadLengthOther", 0.0569 }; + Gaudi::Property<float> m_AbsorberIntLengthOther{ this, "AbsorberIntLengthOther", 0.006 }; + Gaudi::Property< std::string > m_StartVertexCollectionName { this, "StartVertexCollectionName", "PandoraPFANewStartVertices" }; + Gaudi::Property< std::string > m_StartVertexAlgorithmName { this, "StartVertexAlgorithmName", "PandoraPFANew" }; + Gaudi::Property<float> m_EMStochasticTerm{ this, "EMStochasticTerm", 0.17 }; + Gaudi::Property<float> m_HadStochasticTerm{ this, "HadStochasticTerm", 0.6 }; + Gaudi::Property<float> m_EMConstantTerm{ this, "EMConstantTerm", 0.01 }; + Gaudi::Property<float> m_HadConstantTerm{ this, "HadConstantTerm", 0.03 }; + Gaudi::Property<float> m_MuonHitEnergy{ this, "MuonHitEnergy", 0.5 }; + Gaudi::Property<int> m_NOuterSamplingLayers{ this, "NOuterSamplingLayers", 3 }; + Gaudi::Property<float> m_LayersFromEdgeMaxRearDistance{ this, "LayersFromEdgeMaxRearDistance", 250.f }; + Gaudi::Property<float> m_MuonBarrelBField{ this, "MuonBarrelBField", -1.5f }; + Gaudi::Property<float> m_MuonEndCapBField{ this, "MuonEndCapBField", 0.01f }; + Gaudi::Property<int> m_ShouldFormTrackRelationships{ this, "ShouldFormTrackRelationships", 1 }; + Gaudi::Property<int> m_MinTrackHits{ this, "MinTrackHits", 5 }; + Gaudi::Property<int> m_MinFtdTrackHits{ this, "MinFtdTrackHits", 0 }; + Gaudi::Property<int> m_MaxTrackHits{ this, "MaxTrackHits", 5000 }; + Gaudi::Property<float> m_D0TrackCut{ this, "D0TrackCut", 50. }; + Gaudi::Property<float> m_Z0TrackCut{ this, "Z0TrackCut", 50. }; + Gaudi::Property<int> m_UseNonVertexTracks{ this, "UseNonVertexTracks", 1 }; + Gaudi::Property<int> m_UseUnmatchedNonVertexTracks{ this, "UseUnmatchedNonVertexTracks", 0 }; + Gaudi::Property<int> m_UseUnmatchedVertexTracks{ this, "UseUnmatchedVertexTracks", 1 }; + Gaudi::Property<float> m_UnmatchedVertexTrackMaxEnergy{ this, "UnmatchedVertexTrackMaxEnergy", 5. }; + Gaudi::Property<float> m_D0UnmatchedVertexTrackCut{ this, "D0UnmatchedVertexTrackCut", 5. }; + Gaudi::Property<float> m_Z0UnmatchedVertexTrackCut{ this, "Z0UnmatchedVertexTrackCut", 5. }; + Gaudi::Property<float> m_ZCutForNonVertexTracks{ this, "ZCutForNonVertexTracks", 250. }; + Gaudi::Property<int> m_ReachesECalNTpcHits{ this, "ReachesECalNTpcHits", 11 }; + Gaudi::Property<int> m_ReachesECalNFtdHits{ this, "ReachesECalNFtdHits", 4 }; + Gaudi::Property<float> m_ReachesECalTpcOuterDistance{ this, "ReachesECalTpcOuterDistance", -100. }; + Gaudi::Property<int> m_ReachesECalMinFtdLayer{ this, "ReachesECalMinFtdLayer", 9 }; + Gaudi::Property<float> m_ReachesECalTpcZMaxDistance{ this, "ReachesECalTpcZMaxDistance", -50. }; + Gaudi::Property<float> m_ReachesECalFtdZMaxDistance{ this, "ReachesECalFtdZMaxDistance", -1. }; + Gaudi::Property<float> m_CurvatureToMomentumFactor{ this, "CurvatureToMomentumFactor", 0.3 / 2000. }; + Gaudi::Property<float> m_MinTrackECalDistanceFromIp{ this, "MinTrackECalDistanceFromIp", 100. }; + + Gaudi::Property<float> m_MaxTrackSigmaPOverP { this, "MaxTrackSigmaPOverP", 0.15 }; + Gaudi::Property<float> m_MinMomentumForTrackHitChecks { this, "MinMomentumForTrackHitChecks", 1. }; + Gaudi::Property<float> m_TpcMembraneMaxZ { this, "TpcMembraneMaxZ", 10. }; + Gaudi::Property<float> m_MinTpcHitFractionOfExpected { this, "MinTpcHitFractionOfExpected", 0.20 }; + Gaudi::Property<int> m_MinFtdHitsForTpcHitFraction { this, "MinFtdHitsForTpcHitFraction", 2 }; + Gaudi::Property<float> m_MaxTpcInnerRDistance { this, "MaxTpcInnerRDistance", 50.0 }; + Gaudi::Property<int> m_ECalEndCapInnerSymmetryOrder { this, "ECalEndCapInnerSymmetryOrder", 4 }; + Gaudi::Property<float> m_ECalEndCapInnerPhiCoordinate { this, "ECalEndCapInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_ECalEndCapOuterSymmetryOrder { this, "ECalEndCapOuterSymmetryOrder", 8 }; + Gaudi::Property<float> m_ECalEndCapOuterPhiCoordinate { this, "ECalEndCapOuterPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalEndCapInnerSymmetryOrder { this, "HCalEndCapInnerSymmetryOrder", 4 }; + Gaudi::Property<float> m_HCalEndCapInnerPhiCoordinate { this, "HCalEndCapInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalEndCapOuterSymmetryOrder { this, "HCalEndCapOuterSymmetryOrder", 16 }; + Gaudi::Property<float> m_HCalEndCapOuterPhiCoordinate { this, "HCalEndCapOuterPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalRingInnerSymmetryOrder { this, "HCalRingInnerSymmetryOrder", 8 }; + Gaudi::Property<float> m_HCalRingInnerPhiCoordinate { this, "HCalRingInnerPhiCoordinate", 0. }; + Gaudi::Property<int> m_HCalRingOuterSymmetryOrder { this, "HCalRingOuterSymmetryOrder", 16 }; + Gaudi::Property<float> m_HCalRingOuterPhiCoordinate { this, "HCalRingOuterPhiCoordinate", 0. }; + Gaudi::Property<bool> m_StripSplittingOn { this, "StripSplittingOn", false }; + Gaudi::Property<bool> m_UseEcalScLayers { this, "UseEcalScLayers", false }; + Gaudi::Property<float> m_ECalSiToMipCalibration { this, "ECalSiToMipCalibration", 1. }; + Gaudi::Property<float> m_ECalScToMipCalibration { this, "ECalScToMipCalibration", 1. }; + Gaudi::Property<float> m_ECalSiMipThreshold { this, "ECalSiMipThreshold", 0. }; + Gaudi::Property<float> m_ECalScMipThreshold { this, "ECalScMipThreshold", 0. }; + Gaudi::Property<float> m_ECalSiToEMGeVCalibration { this, "ECalSiToEMGeVCalibration", 1. }; + Gaudi::Property<float> m_ECalScToEMGeVCalibration { this, "ECalScToEMGeVCalibration", 1. }; + Gaudi::Property<float> m_ECalSiToHadGeVCalibrationEndCap { this, "ECalSiToHadGeVCalibrationEndCap", 1. }; + Gaudi::Property<float> m_ECalScToHadGeVCalibrationEndCap { this, "ECalScToHadGeVCalibrationEndCap", 1. }; + Gaudi::Property<float> m_ECalSiToHadGeVCalibrationBarrel { this, "ECalSiToHadGeVCalibrationBarrel", 1. }; + Gaudi::Property<float> m_ECalScToHadGeVCalibrationBarrel { this, "ECalScToHadGeVCalibrationBarrel", 1. }; + + Gaudi::Property<FloatVector> m_InputEnergyCorrectionPoints { this, "InputEnergyCorrectionPoints", {} }; + Gaudi::Property<FloatVector> m_OutputEnergyCorrectionPoints { this, "OutputEnergyCorrectionPoints", {} }; + + + static pandora::Pandora *m_pPandora; + GeometryCreator *m_pGeometryCreator; ///< The geometry creator + CaloHitCreator *m_pCaloHitCreator; ///< The calo hit creator + TrackCreator *m_pTrackCreator; ///< The track creator + MCParticleCreator *m_pMCParticleCreator; ///< The mc particle creator + PfoCreator *m_pPfoCreator; ///< The pfo creator + + Settings m_settings; ///< The settings for the pandora pfa new algo + CollectionMaps *m_CollectionMaps; ///< The settings for the pandora pfa new algo + GeometryCreator::Settings m_geometryCreatorSettings; ///< The geometry creator settings + TrackCreator::Settings m_trackCreatorSettings; ///< The track creator settings + CaloHitCreator::Settings m_caloHitCreatorSettings; ///< The calo hit creator settings + MCParticleCreator::Settings m_mcParticleCreatorSettings; ///< The mc particle creator settings + PfoCreator::Settings m_pfoCreatorSettings; ///< The pfo creator settings + + std::string m_detectorName; ///< The detector name + unsigned int m_nRun; ///< The run number + unsigned int m_nEvent; ///< The event number + //### For Ana ################# + TFile* m_fout; + TTree* m_tree; + std::vector< std::vector<int> > m_pReco_mc_id; + std::vector< std::vector<float> > m_pReco_mc_weight; + std::vector<int > m_pReco_PID; + std::vector<float> m_pReco_mass; + std::vector<float> m_pReco_energy; + std::vector<float> m_pReco_px; + std::vector<float> m_pReco_py; + std::vector<float> m_pReco_pz; + std::vector<float> m_pReco_charge; + + std::vector<int> m_mc_id; + std::vector<int> m_mc_p_size; + std::vector<int> m_mc_pid ; + std::vector<float> m_mc_mass ; + std::vector<float> m_mc_px ; + std::vector<float> m_mc_py ; + std::vector<float> m_mc_pz ; + std::vector<float> m_mc_charge; + int m_hasConversion; + std::vector<float> m_hits_x ; + std::vector<float> m_hits_y ; + std::vector<float> m_hits_z ; + std::vector<float> m_hits_E ; + + Gaudi::Property< std::string > m_AnaOutput{ this, "AnaOutput", "/junofs/users/wxfang/MyGit/CEPCSW/Reconstruction/PFA/Pandora/GaudiPandora/Ana.root" }; + //###################### + + DataHandle<edm4hep::MCParticleCollection> m_mcParCol_r {"MCParticle", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALBarrel_r{"ECALBarrel", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALEndcap_r{"ECALEndcap", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_ECALOther_r {"ECALOther", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALBarrel_r{"HCALBarrel", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALEndcap_r{"HCALEndcap", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_HCALOther_r {"HCALOther", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_MUON_r {"MUON", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_LCAL_r {"LCAL", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_LHCAL_r {"LHCAL", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::CalorimeterHitCollection> m_BCAL_r {"BCAL", Gaudi::DataHandle::Reader, this}; + + DataHandle<edm4hep::VertexCollection> m_KinkVertices_r {"KinkVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_ProngVertices_r {"ProngVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_SplitVertices_r {"SplitVertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::VertexCollection> m_V0Vertices_r {"V0Vertices",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::TrackCollection> m_MarlinTrkTracks_r {"MarlinTrkTracks",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoCaloAssociationCollection> m_MCRecoCaloAssociation_r {"MCRecoCaloAssociation",Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCRecoTrackerAssociationCollection> m_MCRecoTrackerAssociation_r {"MCRecoTrackerAssociation",Gaudi::DataHandle::Reader, this}; + + DataHandle<edm4hep::ClusterCollection> m_ClusterCollection_w {"PandoraClusters",Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::ReconstructedParticleCollection> m_ReconstructedParticleCollection_w {"PandoraPFOs" ,Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::VertexCollection> m_VertexCollection_w {"PandoraPFANewStartVertices",Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::MCRecoParticleAssociationCollection> m_MCRecoParticleAssociation_w {"pfoMCRecoParticleAssociation",Gaudi::DataHandle::Writer, this}; + +}; + +#endif diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/PfoCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/PfoCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..83c6e14932bb00178cfc70453b478dced3a72f90 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/PfoCreator.h @@ -0,0 +1,219 @@ +/** + * @file MarlinPandora/include/PfoCreator.h + * + * @brief Header file for the pfo creator class. + * + * $Log: $ + */ + +#ifndef PFO_CREATOR_H +#define PFO_CREATOR_H 1 + +#include "FWCore/DataHandle.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/ClusterCollection.h" +#include "edm4hep/Cluster.h" +#include "edm4hep/ReconstructedParticleCollection.h" +#include "edm4hep/ReconstructedParticle.h" +#include "edm4hep/VertexCollection.h" +#include "edm4hep/Vertex.h" +#include "edm4hep/TrackCollection.h" +#include "edm4hep/Track.h" +#include "edm4hep/CalorimeterHitCollection.h" +#include "edm4hep/CalorimeterHit.h" + +#include "ClusterShapes.h" +#include "Api/PandoraApi.h" + +class CollectionMaps; +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief PfoCreator class + */ +class PfoCreator +{ +public: + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + std::string m_clusterCollectionName; ///< The name of the cluster output collection + std::string m_pfoCollectionName; ///< The name of the pfo output collection + std::string m_startVertexCollectionName; ///< The name of the start vertex output collection + std::string m_startVertexAlgName; ///< The name of the algorithm to fill the start vertex output collection + float m_emStochasticTerm; ///< The stochastic term for EM shower energy resolution + float m_hadStochasticTerm; ///< The stochastic term for Hadronic shower energy resolution + float m_emConstantTerm; ///< The constant term for EM shower energy resolution + float m_hadConstantTerm; ///< The constant term for Hadronic shower energy resolution + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + PfoCreator(const Settings &settings, const pandora::Pandora *const pPandora); + + /** + * @brief Destructor + */ + ~PfoCreator(); + + /** + * @brief Create particle flow objects + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateParticleFlowObjects(EVENT::LCEvent *pLCEvent); + //pandora::StatusCode CreateParticleFlowObjects(const CollectionMaps& collectionMaps); + pandora::StatusCode CreateParticleFlowObjects(CollectionMaps& collectionMaps, DataHandle<edm4hep::ClusterCollection>& _pClusterCollection, DataHandle<edm4hep::ReconstructedParticleCollection>& _pReconstructedParticleCollection, DataHandle<edm4hep::VertexCollection>& _pStartVertexCollection); + + CollectionMaps* m_collectionMaps; + +private: + /** + * @brief index for the subdetector + */ + enum Index + { + ECAL_INDEX = 0, + HCAL_INDEX = 1, + YOKE_INDEX = 2, + LCAL_INDEX = 3, + LHCAL_INDEX = 4, + BCAL_INDEX = 5 + }; + + /** + * @brief initialise sub detector name strings + * + * @param subDetectorNames to receive the list of sub detector names + */ + void InitialiseSubDetectorNames(pandora::StringVector &subDetectorNames) const; + + /** + * @brief Set sub detector energies for a cluster + * + * @param subDetectorNames the list of sub detector names + * @param pLcioCluster the address of the lcio cluster to be set sub detector energies + * @param pandoraCaloHitList the pandora calorimeter hit list + * @param hitE the vector to receive the energy of hits + * @param hitX the vector to receive the x position of hits + * @param hitY the vector to receive the y position of hits + * @param hitZ the vector to receive the z position of hits + */ + void SetClusterSubDetectorEnergies(const pandora::StringVector &subDetectorNames, edm4hep::Cluster *const pLcioCluster, + const pandora::CaloHitList &pandoraCaloHitList, pandora::FloatVector &hitE, pandora::FloatVector &hitX, pandora::FloatVector &hitY, + pandora::FloatVector &hitZ) const; + + /** + * @brief Set cluster energies and errors + * + * @param pPandoraPfo the address of the pandora pfo + * @param pPandoraCluster the address of the pandora cluster + * @param pLcioCluster the address of the lcio cluster to be set energies and erros + * @param clusterCorrectEnergy a number to receive the cluster correct energy + */ + void SetClusterEnergyAndError(const pandora::ParticleFlowObject *const pPandoraPfo, const pandora::Cluster *const pPandoraCluster, + edm4hep::Cluster *const pLcioCluster, float &clusterCorrectEnergy) const; + + /** + * @brief Set cluster position, errors and other shape info, by calculating culster shape first + * + * @param nHitsInCluster number of hits in cluster + * @param hitE the vector of the energy of hits + * @param hitX the vector of the x position of hits + * @param hitY the vector of the y position of hits + * @param hitZ the vector of the z position of hits + * @param pLcioCluster the lcio cluster to be set positions and errors + * @param clusterPosition a CartesianVector to receive the cluster position + */ + void SetClusterPositionAndError(const unsigned int nHitsInCluster, pandora::FloatVector &hitE, pandora::FloatVector &hitX, + pandora::FloatVector &hitY, pandora::FloatVector &hitZ, edm4hep::Cluster *const pLcioCluster, pandora::CartesianVector &clusterPositionVec) const; + + /** + * @brief Calculate reference point for pfo with tracks + * + * @param pPandoraPfo the address of the pandora pfo + * @param referencePoint a CartesianVector to receive the reference point + */ + pandora::StatusCode CalculateTrackBasedReferencePoint(const pandora::ParticleFlowObject *const pPandoraPfo, pandora::CartesianVector &referencePoint) const; + + /** + * @brief Set reference point of the reconstructed particle + * + * @param referencePoint a CartesianVector of the reference point + * @param pReconstructedParticle the address of the reconstructed particle to be reference point + */ + void SetRecoParticleReferencePoint(const pandora::CartesianVector &referencePoint, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Add tracks to reconstructed particle + * + * @param pPandoraPfo the address of the pandora pfo + * @param pReconstructedParticle the address of the reconstructed particle to be added tracks + */ + void AddTracksToRecoParticle(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Set properties of reconstructed particle from pandora pfo + * + * @param pPandoraPfo the address of the pandora pfo + * @param pReconstructedParticle the address of the reconstructed particle to be set properties + */ + void SetRecoParticlePropertiesFromPFO(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const; + + /** + * @brief Whether parent and daughter tracks are associated with the same pfo + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated with reconstructed particle + * + * @return boolean + */ + bool IsValidParentTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether sibling tracks are associated with the same pfo + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated with reconstructed particle + * + * @return boolean + */ + bool HasValidSiblingTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether the track is the closest (of those associated with the same pfo) to the interaction point + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated to reconstructed particle + * + * @return boolean + */ + bool IsClosestTrackToIP(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + /** + * @brief Whether at least one track sibling track is associated to the reconstructed particle + * + * @param pPandoraTrack the address of the pandora track + * @param allTrackList list of all tracks associated to reconstructed particle + * + * @return boolean + */ + bool AreAnyOtherSiblingsInList(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const; + + const Settings m_settings; ///< The pfo creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object from which to extract the pfos +}; + +#endif // #ifndef PFO_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/TrackCreator.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/TrackCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..1e1588c2629db7a4f7728b9edb62b86f5cf3fd0e --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/TrackCreator.h @@ -0,0 +1,373 @@ +/** + * @file MarlinPandora/include/TrackCreator.h + * + * @brief Header file for the track creator class. + * + * $Log: $ + */ + +#ifndef TRACK_CREATOR_H +#define TRACK_CREATOR_H 1 + + + + +#include "GaudiKernel/ISvcLocator.h" + +#include "edm4hep/Track.h" +#include "edm4hep/TrackConst.h" +#include "edm4hep/TrackState.h" +#include "edm4hep/ReconstructedParticleConst.h" + +#include "Api/PandoraApi.h" +#include "Objects/Helix.h" + +namespace gear { class GearMgr; } + +class CollectionMaps; + +typedef std::vector<const edm4hep::Track *> TrackVector; +//typedef std::set<const edm4hep::Track *> TrackList; +typedef std::set<unsigned int> TrackList; +//typedef std::map<edm4hep::Track *, int> TrackToPidMap; +typedef std::map<edm4hep::ConstTrack, int> TrackToPidMap; +/* +inline LCCollectionVec *newTrkCol(const std::string &name, LCEvent *evt , bool isSubset) +{ + LCCollectionVec* col = new LCCollectionVec( LCIO::TRACK ) ; + + LCFlagImpl hitFlag(0) ; + hitFlag.setBit( LCIO::TRBIT_HITS ) ; + col->setFlag( hitFlag.getFlag() ) ; + evt->addCollection( col , name ) ; + col->setSubset( isSubset ) ; + + return col ; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief TrackCreator class + */ +class TrackCreator +{ +public: + typedef std::vector<double> DoubleVector; + typedef std::vector<std::string> StringVector; + + /** + * @brief Settings class + */ + class Settings + { + public: + /** + * @brief Default constructor + */ + Settings(); + + StringVector m_trackCollections; ///< The reconstructed track collections + StringVector m_kinkVertexCollections; ///< The kink vertex collections + StringVector m_prongVertexCollections; ///< The prong vertex collections + StringVector m_splitVertexCollections; ///< The split vertex collections + StringVector m_v0VertexCollections; ///< The v0 vertex collections + + StringVector m_prongSplitVertexCollections; ///< Concatenated list of prong and split vertex collections + int m_shouldFormTrackRelationships; ///< Whether to form pandora track relationships using v0 and kink info + + int m_minTrackHits; ///< Track quality cut: the minimum number of track hits + int m_minFtdTrackHits; ///< Track quality cut: the minimum number of FTD track hits for FTD only tracks + int m_maxTrackHits; ///< Track quality cut: the maximum number of track hits + + float m_d0TrackCut; ///< Track d0 cut used to determine whether track can be used to form pfo + float m_z0TrackCut; ///< Track z0 cut used to determine whether track can be used to form pfo + + int m_usingNonVertexTracks; ///< Whether can form pfos from tracks that don't start at vertex + int m_usingUnmatchedNonVertexTracks; ///< Whether can form pfos from unmatched tracks that don't start at vertex + int m_usingUnmatchedVertexTracks; ///< Whether can form pfos from unmatched tracks that start at vertex + float m_unmatchedVertexTrackMaxEnergy; ///< Maximum energy for unmatched vertex track + + float m_d0UnmatchedVertexTrackCut; ///< d0 cut used to determine whether unmatched vertex track can form pfo + float m_z0UnmatchedVertexTrackCut; ///< z0 cut used to determine whether unmatched vertex track can form pfo + float m_zCutForNonVertexTracks; ///< Non vtx track z cut to determine whether track can be used to form pfo + + int m_reachesECalNTpcHits; ///< Minimum number of tpc hits to consider track as reaching ecal + int m_reachesECalNFtdHits; ///< Minimum number of ftd hits to consider track as reaching ecal + float m_reachesECalTpcOuterDistance; ///< Max distance from track to tpc r max to id whether track reaches ecal + int m_reachesECalMinFtdLayer; ///< Min layer in Ftd for tracks to be considered to have reached decal + float m_reachesECalTpcZMaxDistance; ///< Max distance from track to tpc z max to id whether track reaches ecal + float m_reachesECalFtdZMaxDistance; ///< Max distance from track hit to ftd z position to identify ftd hits + float m_curvatureToMomentumFactor; ///< Constant relating track curvature in b field to momentum + + float m_minTrackECalDistanceFromIp; ///< Sanity check on separation between ip and track projected ecal position + float m_maxTrackSigmaPOverP; ///< Track fraction momentum error cut + float m_minMomentumForTrackHitChecks; ///< Min track momentum required to perform final quality checks on number of hits + + float m_tpcMembraneMaxZ; ///< Tpc membrane max z coordinate + float m_maxTpcInnerRDistance; ///< Track cut on distance from tpc inner r to id whether track can form pfo + float m_minTpcHitFractionOfExpected; ///< Minimum fraction of TPC hits compared to expected + int m_minFtdHitsForTpcHitFraction; ///< Minimum number of FTD hits to ignore TPC hit fraction + }; + + /** + * @brief Constructor + * + * @param settings the creator settings + * @param pPandora address of the relevant pandora instance + */ + //TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora); + TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc); + + /** + * @brief Destructor + */ + ~TrackCreator(); + + /** + * @brief Create associations between tracks, V0s, kinks, etc + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateTrackAssociations(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode CreateTrackAssociations(const CollectionMaps& collectionMaps); + + /** + * @brief Create tracks, insert user code here + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode CreateTracks(EVENT::LCEvent *pLCEvent); + pandora::StatusCode CreateTracks(const CollectionMaps& collectionMaps); + + /** + * @brief Get the track vector + * + * @return The track vector + */ + const TrackVector &GetTrackVector() const; + + /** + * @brief Reset the track creator + */ + void Reset(); + +private: + /** + * @brief Extract kink information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractKinks(const EVENT::LCEvent *const pLCEvent); + pandora::StatusCode ExtractKinks(const CollectionMaps& collectionMaps); + + /** + * @brief Extract prong and split information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractProngsAndSplits(const EVENT::LCEvent *const pLCEvent); + + /** + * @brief Extract v0 information from specified lcio collections + * + * @param pLCEvent the lcio event + */ + //pandora::StatusCode ExtractV0s(const EVENT::LCEvent *const pLCEvent); + + /** + * @brief Whether the track vertex conflicts with previously provided relationship information + * + * @param trackVec the vector of tracks associated with the vertex + */ + //bool IsConflictingRelationship(const EVENT::TrackVec &trackVec) const; + //bool IsConflictingRelationship(edm4hep::ConstTrack &trackVec) const; + bool IsConflictingRelationship(const edm4hep::ConstReconstructedParticle &Particle) const; + + /** + * @brief Whether a track is a v0 track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsV0(const EVENT::Track *const pTrack) const; + bool IsV0(unsigned int pTrack_id) const; + + /** + * @brief Whether a track is a parent track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsParent(const EVENT::Track *const pTrack) const; + bool IsParent(unsigned int pTrack_id) const; + + /** + * @brief Whether a track is a daughter track + * + * @param pTrack the lcio track + * + * @return boolean + */ + //bool IsDaughter(const EVENT::Track *const pTrack) const; + bool IsDaughter(unsigned int pTrack_id) const; + + /** + * @brief Copy track states stored in lcio tracks to pandora track parameters + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void GetTrackStates(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void GetTrackStates(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Copy track state from lcio track state instance to pandora input track state + * + * @param pTrackState the lcio track state instance + * @param inputTrackState the pandora input track state + */ + //void CopyTrackState(const TrackState *const pTrackState, pandora::InputTrackState &inputTrackState) const; + void CopyTrackState(const edm4hep::TrackState & pTrackState, pandora::InputTrackState &inputTrackState) const; + + /** + * @brief Obtain track time when it reaches ECAL + * + * @param pTrack the lcio track + */ + //float CalculateTrackTimeAtCalorimeter(const EVENT::Track *const pTrack) const; + float CalculateTrackTimeAtCalorimeter(const edm4hep::Track *const pTrack) const; + + /** + * @brief Decide whether track reaches the ecal surface + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void TrackReachesECAL(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void TrackReachesECAL(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + //void TrackReachesECAL(const edm4hep::Track& pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Determine whether a track can be used to form a pfo under the following conditions: + * 1) if the track proves to be associated with a cluster, OR + * 2) if the track proves to have no cluster associations + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + */ + //void DefineTrackPfoUsage(const EVENT::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + void DefineTrackPfoUsage(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Whether track passes the quality cuts required in order to be used to form a pfo + * + * @param pTrack the lcio track + * @param trackParameters the track parameters + * + * @return boolean + */ + //bool PassesQualityCuts(const EVENT::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const; + bool PassesQualityCuts(const edm4hep::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const; + + /** + * @brief Get number of hits in TPC of a track + * + * @param pTrack the lcio track + * + * @return number of hits in TPC of a track + */ + //int GetNTpcHits(const EVENT::Track *const pTrack) const; + int GetNTpcHits(const edm4hep::Track *const pTrack) const; + + /** + * @brief Get number of hits in FTD of a track + * + * @param pTrack the lcio track + * + * @return number of hits in FTDof a track + */ + //int GetNFtdHits(const EVENT::Track *const pTrack) const; + int GetNFtdHits(const edm4hep::Track *const pTrack) const; + + const Settings m_settings; ///< The track creator settings + const pandora::Pandora *m_pPandora; ///< Address of the pandora object to create tracks and track relationships + + float m_bField; ///< The bfield + + float m_tpcInnerR; ///< The tpc inner radius + float m_tpcOuterR; ///< The tpc outer radius + unsigned int m_tpcMaxRow; ///< The tpc maximum row number + float m_tpcZmax; ///< The tpc maximum z coordinate + float m_cosTpc; ///< Cos(theta) value at end of tpc + + DoubleVector m_ftdInnerRadii; ///< List of ftd inner radii + DoubleVector m_ftdOuterRadii; ///< List of ftd outer radii + DoubleVector m_ftdZPositions; ///< List of ftd z positions + unsigned int m_nFtdLayers; ///< Number of ftd layers + float m_tanLambdaFtd; ///< Tan lambda for first ftd layer + + int m_eCalBarrelInnerSymmetry; ///< ECal barrel inner symmetry order + float m_eCalBarrelInnerPhi0; ///< ECal barrel inner phi 0 + float m_eCalBarrelInnerR; ///< ECal barrel inner radius + float m_eCalEndCapInnerZ; ///< ECal endcap inner z + + float m_minEtdZPosition; ///< Min etd z position + float m_minSetRadius; ///< Min set radius + + TrackVector m_trackVector; ///< The track vector + TrackList m_v0TrackList; ///< The list of v0 tracks + TrackList m_parentTrackList; ///< The list of parent tracks + TrackList m_daughterTrackList; ///< The list of daughter tracks + TrackToPidMap m_trackToPidMap; ///< The map from track addresses to particle ids, where set by kinks/V0s + gear::GearMgr* _GEAR; +}; + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline const TrackVector &TrackCreator::GetTrackVector() const +{ + return m_trackVector; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +inline void TrackCreator::Reset() +{ + m_trackVector.clear(); + m_v0TrackList.clear(); + m_parentTrackList.clear(); + m_daughterTrackList.clear(); + m_trackToPidMap.clear(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsV0(const Track *const pTrack) const +inline bool TrackCreator::IsV0(unsigned int pTrack_id) const // should check here, if id is correct one to do this +{ + //return (m_v0TrackList.end() != m_v0TrackList.find(pTrack)); + return (m_v0TrackList.end() != m_v0TrackList.find(pTrack_id)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsParent(const Track *const pTrack) const +inline bool TrackCreator::IsParent(unsigned int pTrack_id) const +{ + //return (m_parentTrackList.end() != m_parentTrackList.find(pTrack)); + return (m_parentTrackList.end() != m_parentTrackList.find(pTrack_id)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//inline bool TrackCreator::IsDaughter(const Track *const pTrack) const +inline bool TrackCreator::IsDaughter(unsigned int pTrack_id) const +{ + //return (m_daughterTrackList.end() != m_daughterTrackList.find(pTrack)); + return (m_daughterTrackList.end() != m_daughterTrackList.find(pTrack_id)); +} + +#endif // #ifndef TRACK_CREATOR_H diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/Utility.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/Utility.h new file mode 100644 index 0000000000000000000000000000000000000000..0bd75b5d94f4725581e44176a02fbb94a99088fa --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/Utility.h @@ -0,0 +1,6 @@ +#ifndef MYUTILITY +#define MYUTILITY 1 + +#include <sstream> +std::string Convert (float number); +#endif diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/include/cellIDDecoder.h b/Reconstruction/PFA/Pandora/MatrixPandora/include/cellIDDecoder.h new file mode 100644 index 0000000000000000000000000000000000000000..f15159967865ae3ab64def320daf820def08bcf8 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/include/cellIDDecoder.h @@ -0,0 +1,127 @@ +#ifndef cellIDDecoder_h +#define cellIDDecoder_h 1 + +//#include <vector> +//#include "EVENT/LCObject.h" +#include "EVENT/LCCollection.h" +//#include "EVENT/SimTrackerHit.h" +#include "UTIL/BitField64.h" +#include "lcio.h" +#include <string> + +// fixes problem in gcc 4.0.3 +#include "EVENT/LCParameters.h" + +//#include <sstream> +//#include <typeinfo> + +//##################### changed for EMD4HEP ######## +//need check !! + +namespace ID_UTIL{ + + + /** Convenient class for decoding cellIDs from collection parameter LCIO::CellIDEncoding. + * See UTIL::BitField64 for a description of the encoding string. + * + * @see BitField64 + * @version $Id: CellIDDecoder.h,v 1.9.16.1 2011-03-04 14:09:07 engels Exp $ + */ + template <class T> + class CellIDDecoder { + + public: + + CellIDDecoder() = default ; + CellIDDecoder(const CellIDDecoder& ) = delete ; + CellIDDecoder& operator=(const CellIDDecoder& ) = delete ; + + + /** Constructor takes encoding string as argument. + */ + CellIDDecoder( const std::string& encoder_str ) : _oldHit(0) { + + if( encoder_str.length() == 0 ){ + throw( lcio::Exception( "CellIDDecoder : string of length zero provided as encoder string" ) ) ; + } + _b = new UTIL::BitField64( encoder_str ) ; + + } + + /** Constructor reads encoding string from collection parameter LCIO::CellIDEncoding. + */ + CellIDDecoder( const EVENT::LCCollection* col ) : _oldHit(0) { + + std::string initString("") ; + + if( col !=0 ) + initString = col->getParameters().getStringVal( lcio::LCIO::CellIDEncoding ) ; + + if( initString.size() == 0 ) { + + initString = _defaultEncoding ; + + std::cout << " ----------------------------------------- " << std::endl + << " WARNING: CellIDDecoder - no CellIDEncoding parameter in collection ! " + << std::endl + << " -> using default : \"" << initString << "\"" + << std::endl + << " ------------------------------------------ " + << std::endl ; + } + + _b = new UTIL::BitField64( initString ) ; + } + + ~CellIDDecoder(){ + + delete _b ; + } + + + /** Provides access to the bit fields, e.g. <br> + * int layer = myCellIDEncoding( hit )[ "layer" ] ; + * + */ + inline const UTIL::BitField64 & operator()( const T* hit ){ + + if( hit != _oldHit && hit ) { + auto id = hit->getCellID(); + unsigned int id0 = id&0xFFFFFFFF; + unsigned int id1 = id>>32; + //lcio::long64 val = lcio::long64( hit->getCellID0() & 0xffffffff ) | ( lcio::long64( hit->getCellID1() ) << 32 ) ; + lcio::long64 val = lcio::long64( id0 & 0xffffffff ) | ( lcio::long64( id1 ) << 32 ) ; + + _b->setValue( val ) ; + + _oldHit = hit ; + } + + return *_b ; + } + + + /** This can be used to set the default encoding that is used if no + * CellIDEncoding parameter is set in the collection, e.g. in older lcio files. + */ + static void setDefaultEncoding(const std::string& defaultEncoding ) { + + _defaultEncoding = std::string( defaultEncoding ) ; + } + + protected: + UTIL::BitField64* _b{} ; + const T* _oldHit{NULL} ; + + static std::string _defaultEncoding; + } ; + + template <class T> + std::string CellIDDecoder<T>::_defaultEncoding + = std::string("byte0:8,byte1:8,byte2:8,byte3:8,byte4:8,byte5:8,byte6:8,byte7:8") ; + + +} // namespace +#endif + + diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/CaloHitCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/CaloHitCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3196cde227b8c14c647aa2e042c89b36ba91ad9e --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/CaloHitCreator.cpp @@ -0,0 +1,959 @@ +/** + * @file MarlinPandora/src/CaloHitCreator.cc + * + * @brief Implementation of the calo hit creator class. + * + * $Log: $ + */ + + +#include "gear/GearParameters.h" +#include "gear/CalorimeterParameters.h" +#include "gear/GearDistanceProperties.h" +#include "gear/GearPointProperties.h" +#include "gear/GEAR.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/LayerLayout.h" + +#include <DD4hep/Detector.h> +#include <DDRec/DetectorData.h> +#include <DDRec/CellIDPositionConverter.h> +#include <DD4hep/Objects.h> + +#include "UTIL/CellIDDecoder.h" +#include "cellIDDecoder.h" +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" + +#include "PandoraMatrixAlg.h" +#include "CaloHitCreator.h" + +#include <algorithm> +#include <cmath> +#include <limits> + + +CaloHitCreator::CaloHitCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc, bool encoder_style) : + m_settings(settings), + m_pPandora(pPandora) +{ + m_encoder_str = ""; + m_encoder_str_MUON = ""; + m_encoder_str_LCal = ""; + m_encoder_str_LHCal = ""; + if(encoder_style==0) + { + m_encoder_str = "M:3,S-1:3,I:9,J:9,K-1:6";// LCIO style + m_encoder_str_MUON="S-1:4,M:3,K-1:6,I:16,GRZone:3,J:32:16"; + m_encoder_str_LCal="I:10,J:10,K:10,S-1:2"; + m_encoder_str_LHCal=m_encoder_str; + } + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + IGeoSvc* Svc = 0; + StatusCode sc1 = svcloc->service("GeoSvc", Svc, false); + if ( !sc1 ) + { + throw "Failed to find GeoSvc ..."; + } + m_dd4hep = Svc->lcdd(); + const dd4hep::DetElement &detElement = m_dd4hep->detector("CaloDetector"); + dd4hep::rec::LayeredCalorimeterData* Data = detElement.extension<dd4hep::rec::LayeredCalorimeterData>() ; + if(!Data) throw "Failed to get LayeredCalorimeterData ..."; + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(*m_dd4hep); + /* + m_compact = "/junofs/users/wxfang/MyGit/lcg97/UsingK4FWCore/0514/CEPCSW/Detector/DetEcalMatrix/compact/det.xml"; + dd4hep::Detector& description = dd4hep::Detector::getInstance(); + description.fromCompact( m_compact ); + m_cellIDConverter = new dd4hep::rec::CellIDPositionConverter(description); + */ + + m_eCalBarrelOuterZ = Data->extent[3]; + m_eCalBarrelInnerPhi0 = Data->inner_phi0; + m_eCalBarrelInnerSymmetry = Data->inner_symmetry; + m_hCalBarrelOuterZ = (_GEAR->getHcalBarrelParameters().getExtent()[3]); + m_muonBarrelOuterZ = (_GEAR->getYokeBarrelParameters().getExtent()[3]); + m_coilOuterR = (_GEAR->getGearParameters("CoilParameters").getDoubleVal("Coil_cryostat_outer_radius")); + m_hCalBarrelInnerPhi0 = (_GEAR->getHcalBarrelParameters().getPhi0()); + m_hCalBarrelInnerSymmetry = (_GEAR->getHcalBarrelParameters().getSymmetryOrder()); + m_muonBarrelInnerPhi0 = (_GEAR->getYokeBarrelParameters().getPhi0()); + m_muonBarrelInnerSymmetry = (_GEAR->getYokeBarrelParameters().getSymmetryOrder()); + m_hCalEndCapOuterR = (_GEAR->getHcalEndcapParameters().getExtent()[1]); + m_hCalEndCapOuterZ = (_GEAR->getHcalEndcapParameters().getExtent()[3]); + m_hCalBarrelOuterR = (_GEAR->getHcalBarrelParameters().getExtent()[1]); + m_hCalBarrelOuterPhi0 =((std::find(_GEAR->getHcalBarrelParameters().getIntKeys().begin(), + _GEAR->getHcalBarrelParameters().getIntKeys().end(), + "Hcal_outer_polygon_phi0") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ? + _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_phi0") + : 0)); + m_hCalBarrelOuterSymmetry = ((std::find(_GEAR->getHcalBarrelParameters().getIntKeys().begin(), + _GEAR->getHcalBarrelParameters().getIntKeys().end(), + "Hcal_outer_polygon_order") != _GEAR->getHcalBarrelParameters().getIntKeys().end() ? + _GEAR->getHcalBarrelParameters().getIntVal("Hcal_outer_polygon_order") + : 0)); + + + const gear::LayerLayout &hCalEndCapLayerLayout(_GEAR->getHcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &hCalBarrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); + m_hCalEndCapLayerThickness = hCalEndCapLayerLayout.getThickness(hCalEndCapLayerLayout.getNLayers() - 1); + m_hCalBarrelLayerThickness = hCalBarrelLayerLayout.getThickness(hCalBarrelLayerLayout.getNLayers() - 1); + if ((m_hCalEndCapLayerThickness < std::numeric_limits<float>::epsilon()) || (m_hCalBarrelLayerThickness < std::numeric_limits<float>::epsilon())) + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +CaloHitCreator::~CaloHitCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateCaloHits(const CollectionMaps& collectionMaps) +{ + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateECalCaloHits (collectionMaps)); + // not used for ECAL Matrix + /* + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateMuonCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateLCalCaloHits (collectionMaps)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateLHCalCaloHits(collectionMaps)); + */ + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateECalCaloHits(const CollectionMaps& collectionMaps) +{ + std::cout<<"start CreateECalCaloHits:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_eCalCaloHitCollections.begin(), iterEnd = m_settings.m_eCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getEcalEndcapParameters().getLayerLayout()); + const dd4hep::DetElement &detElement = m_dd4hep->detector("CaloDetector"); + dd4hep::rec::LayeredCalorimeterData* Data = detElement.extension<dd4hep::rec::LayeredCalorimeterData>() ; + const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer>& barrelLayerLayout = Data->layers; + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + const std::string layerCodingString(m_encoder_str); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("CreateECalCaloHits pCaloHit Collection type mismatch"); + + float eCalToMip(m_settings.m_eCalToMip), eCalMipThreshold(m_settings.m_eCalMipThreshold), eCalToEMGeV(m_settings.m_eCalToEMGeV), + eCalToHadGeVBarrel(m_settings.m_eCalToHadGeVBarrel), eCalToHadGeVEndCap(m_settings.m_eCalToHadGeVEndCap); + + // Hybrid ECAL including pure ScECAL. + if (m_settings.m_useEcalScLayers) + { + std::string collectionName(*iter); + std::transform(collectionName.begin(), collectionName.end(), collectionName.begin(), ::tolower); + + if (collectionName.find("ecal", 0) == std::string::npos) + std::cout << "WARNING: mismatching hybrid Ecal collection name. " << collectionName << std::endl; + + if (collectionName.find("si", 0) != std::string::npos) + { + eCalToMip = m_settings.m_eCalSiToMip; + eCalMipThreshold = m_settings.m_eCalSiMipThreshold; + eCalToEMGeV = m_settings.m_eCalSiToEMGeV; + eCalToHadGeVBarrel = m_settings.m_eCalSiToHadGeVBarrel; + eCalToHadGeVEndCap = m_settings.m_eCalSiToHadGeVEndCap; + } + else if (collectionName.find("sc", 0) != std::string::npos) + { + eCalToMip = m_settings.m_eCalScToMip; + eCalMipThreshold = m_settings.m_eCalScMipThreshold; + eCalToEMGeV = m_settings.m_eCalScToEMGeV; + eCalToHadGeVBarrel = m_settings.m_eCalScToHadGeVBarrel; + eCalToHadGeVEndCap = m_settings.m_eCalScToHadGeVEndCap; + } + } + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::ECAL; + caloHitParameters.m_isDigital = false;//FIXME, maybe this means the MIP thershold cut haven't be applied yet ? + /* + dd4hep::Position position = m_cellIDConverter->position(pCaloHit->getCellID()); + long id_sys,id_x,id_y,id_z ; + GetCoding(pCaloHit, id_sys, id_x, id_y, id_z); + std::cout << "ECAL id =" << pCaloHit->getCellID()<<",sys="<<id_sys<<",x="<<id_x<<",y="<<id_y<<",z="<<id_z << std::endl; + std::cout << "ECAL id =" << pCaloHit->getCellID()<<",x="<<position.x()<<",y="<<position.y()<<",z="<<position.z() << std::endl; + */ + caloHitParameters.m_isInOuterSamplingLayer = false; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + + if (std::fabs(pCaloHit->getPosition()[2]) < m_eCalBarrelOuterZ) + { + caloHitParameters.m_layer = GetBarrelLayer(pCaloHit, barrelLayerLayout); + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_eCalBarrelInnerSymmetry, m_eCalBarrelInnerPhi0, 6, caloHitParameters, absorberCorrection);//6 + caloHitParameters.m_hadronicEnergy = eCalToHadGeVBarrel * pCaloHit->getEnergy(); + + } + else + { // will not be used for ECAL Matrix + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1;//FIXME, should use + 1? because the decoded layer is start from 0. + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + caloHitParameters.m_hadronicEnergy = eCalToHadGeVEndCap * pCaloHit->getEnergy(); + } + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * eCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < eCalMipThreshold) + continue; + + caloHitParameters.m_electromagneticEnergy = eCalToEMGeV * pCaloHit->getEnergy(); + + // ATTN If using strip splitting, must correct cell sizes for use in PFA to minimum of strip width and strip length + if (m_settings.m_stripSplittingOn) + { + const float splitCellSize(std::min(caloHitParameters.m_cellSize0.Get(), caloHitParameters.m_cellSize1.Get())); + caloHitParameters.m_cellSize0 = splitCellSize; + caloHitParameters.m_cellSize1 = splitCellSize; + } + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract ecal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract ecal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout<< "Failed to extract ecal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateHCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_hCalCaloHitCollections.begin(), iterEnd = m_settings.m_hCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getHcalEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getHcalBarrelParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str); + const std::string layerCodingString(m_encoder_str); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("CreateHCalCaloHits Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::HCAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers); + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + + if (std::fabs(pCaloHit->getPosition()[2]) < m_hCalBarrelOuterZ) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_hCalBarrelInnerSymmetry, m_hCalBarrelInnerPhi0, + m_hCalBarrelInnerSymmetry - int(cellIdDecoder(pCaloHit)[ staveCoding] / 2), caloHitParameters, absorberCorrection); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + } + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_hCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_hCalMipThreshold) + continue; + + caloHitParameters.m_hadronicEnergy = std::min(m_settings.m_hCalToHadGeV * pCaloHit->getEnergy(), m_settings.m_maxHCalHitHadronicEnergy); + caloHitParameters.m_electromagneticEnergy = m_settings.m_hCalToEMGeV * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Error, Failed to extract hcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract hcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract hcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateMuonCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_muonCaloHitCollections.begin(), iterEnd = m_settings.m_muonCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getYokeEndcapParameters().getLayerLayout()); + const gear::LayerLayout &barrelLayerLayout(_GEAR->getYokeBarrelParameters().getLayerLayout()); + const gear::LayerLayout &plugLayerLayout(_GEAR->getYokePlugParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_MUON); + const std::string layerCodingString(m_encoder_str_MUON); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + const std::string staveCoding(this->GetStaveCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("Muon Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::MUON; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()] + 1;//FIXME, should use +1? it starts from 0. + caloHitParameters.m_isInOuterSamplingLayer = true; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + const float radius(std::sqrt(pCaloHit->getPosition()[0] * pCaloHit->getPosition()[0] + + pCaloHit->getPosition()[1] * pCaloHit->getPosition()[1])); + + const bool isWithinCoil(radius < m_coilOuterR); + const bool isInBarrelRegion(std::fabs(pCaloHit->getPosition()[2]) < m_muonBarrelOuterZ); + + float absorberCorrection(1.); + + if (isInBarrelRegion && isWithinCoil) + { + this->GetEndCapCaloHitProperties(pCaloHit, plugLayerLayout, caloHitParameters, absorberCorrection); + } + else if (isInBarrelRegion) + { + this->GetBarrelCaloHitProperties(pCaloHit, barrelLayerLayout, m_muonBarrelInnerSymmetry, m_muonBarrelInnerPhi0, + cellIdDecoder(pCaloHit)[ staveCoding ], caloHitParameters, absorberCorrection); + } + else + { + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + } + + if (m_settings.m_muonDigitalHits > 0) + { + caloHitParameters.m_isDigital = true; + caloHitParameters.m_inputEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_hadronicEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_electromagneticEnergy = m_settings.m_muonHitEnergy; + caloHitParameters.m_mipEquivalentEnergy = 1.f; + } + else + { + caloHitParameters.m_isDigital = false; + caloHitParameters.m_inputEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_hadronicEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_electromagneticEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_muonToMip; + } + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract muon hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract muon hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract muon hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateLCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_lCalCaloHitCollections.begin(), iterEnd = m_settings.m_lCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getLcalParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LCal); + const std::string layerCodingString(m_encoder_str_LCal); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("LCal Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::ECAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = false; + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_eCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_eCalMipThreshold) + continue; + + caloHitParameters.m_electromagneticEnergy = m_settings.m_eCalToEMGeV * pCaloHit->getEnergy(); + caloHitParameters.m_hadronicEnergy = m_settings.m_eCalToHadGeVEndCap * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract lcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract lcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract lcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode CaloHitCreator::CreateLHCalCaloHits(const CollectionMaps& collectionMaps) +{ + for (StringVector::const_iterator iter = m_settings.m_lHCalCaloHitCollections.begin(), iterEnd = m_settings.m_lHCalCaloHitCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloHit.find(*iter) == collectionMaps.collectionMap_CaloHit.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::CalorimeterHit>& pCaloHitCollection = (collectionMaps.collectionMap_CaloHit.find(*iter))->second; + const int nElements(pCaloHitCollection.size()); + + std::cout<<(*iter)<<"has nElements="<<nElements<<std::endl; + if (0 == nElements) + continue; + + const gear::LayerLayout &endcapLayerLayout(_GEAR->getLHcalParameters().getLayerLayout()); + + ID_UTIL::CellIDDecoder<const edm4hep::CalorimeterHit> cellIdDecoder(m_encoder_str_LHCal); + const std::string layerCodingString(m_encoder_str_LHCal); + const std::string layerCoding(this->GetLayerCoding(layerCodingString)); + + for (int i = 0; i < nElements; ++i) + { + try + { + const edm4hep::CalorimeterHit& pCaloHit0 = pCaloHitCollection.at(i); + const edm4hep::CalorimeterHit* pCaloHit = &(pCaloHit0); + + if (NULL == pCaloHit) + throw ("LHCal Collection type mismatch"); + + PandoraApi::CaloHit::Parameters caloHitParameters; + caloHitParameters.m_hitType = pandora::HCAL; + caloHitParameters.m_isDigital = false; + caloHitParameters.m_layer = cellIdDecoder(pCaloHit)[layerCoding.c_str()]; + caloHitParameters.m_isInOuterSamplingLayer = (this->GetNLayersFromEdge(pCaloHit) <= m_settings.m_nOuterSamplingLayers); + this->GetCommonCaloHitProperties(pCaloHit, caloHitParameters); + + float absorberCorrection(1.); + this->GetEndCapCaloHitProperties(pCaloHit, endcapLayerLayout, caloHitParameters, absorberCorrection); + + caloHitParameters.m_mipEquivalentEnergy = pCaloHit->getEnergy() * m_settings.m_hCalToMip * absorberCorrection; + + if (caloHitParameters.m_mipEquivalentEnergy.Get() < m_settings.m_hCalMipThreshold) + continue; + + caloHitParameters.m_hadronicEnergy = std::min(m_settings.m_hCalToHadGeV * pCaloHit->getEnergy(), m_settings.m_maxHCalHitHadronicEnergy); + caloHitParameters.m_electromagneticEnergy = m_settings.m_hCalToEMGeV * pCaloHit->getEnergy(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::CaloHit::Create(*m_pPandora, caloHitParameters)); + m_calorimeterHitVector.push_back(const_cast<edm4hep::CalorimeterHit*>(pCaloHit)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract lhcal calo hit: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract lhcal calo hit: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract lhcal calo hit collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetCommonCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, PandoraApi::CaloHit::Parameters &caloHitParameters) const +{ + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + const pandora::CartesianVector positionVector(pCaloHitPosition[0], pCaloHitPosition[1], pCaloHitPosition[2]); + + caloHitParameters.m_cellGeometry = pandora::RECTANGULAR; + caloHitParameters.m_positionVector = positionVector; + caloHitParameters.m_expectedDirection = positionVector.GetUnitVector(); + caloHitParameters.m_pParentAddress = pCaloHit; + caloHitParameters.m_inputEnergy = pCaloHit->getEnergy(); + caloHitParameters.m_time = pCaloHit->getTime(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetEndCapCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + PandoraApi::CaloHit::Parameters &caloHitParameters, float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::ENDCAP; + + const int physicalLayer(std::min(static_cast<int>(caloHitParameters.m_layer.Get()), layerLayout.getNLayers() - 1)); + caloHitParameters.m_cellSize0 = layerLayout.getCellSize0(physicalLayer); + caloHitParameters.m_cellSize1 = layerLayout.getCellSize1(physicalLayer); + caloHitParameters.m_cellThickness = layerLayout.getThickness(physicalLayer); + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.getAbsorberThickness(physicalLayer)); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING CaloHitCreator::GetEndCapCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.getNLayers(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.getAbsorberThickness(i)); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + + caloHitParameters.m_cellNormalVector = (pCaloHit->getPosition()[2] > 0) ? pandora::CartesianVector(0, 0, 1) : + pandora::CartesianVector(0, 0, -1); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void CaloHitCreator::GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const gear::LayerLayout &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::BARREL; + + const int physicalLayer(std::min(static_cast<int>(caloHitParameters.m_layer.Get()), layerLayout.getNLayers() - 1)); + caloHitParameters.m_cellSize0 = layerLayout.getCellSize0(physicalLayer); + caloHitParameters.m_cellSize1 = layerLayout.getCellSize1(physicalLayer); + caloHitParameters.m_cellThickness = layerLayout.getThickness(physicalLayer); + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.getAbsorberThickness(physicalLayer)); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + //std::cout<<"m_layer="<<caloHitParameters.m_layer.Get()<<",layerLayout.getNLayers() - 1="<<layerLayout.getNLayers() - 1<<",layerAbsorberThickness="<<layerAbsorberThickness<<std::endl; + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"interactionLength="<<interactionLength<<",layerAbsorberThickness="<<layerAbsorberThickness<<",radiationLength="<<radiationLength<<",physicalLayer="<<physicalLayer<<",l1="<<caloHitParameters.m_layer.Get()<<",l2="<<layerLayout.getNLayers()-1<<std::endl; + std::cout<<"WARNIN CaloHitCreator::GetBarrelCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.getNLayers(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.getAbsorberThickness(i)); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + + if (barrelSymmetryOrder > 2) + { + const float phi = barrelPhi0 + (2. * M_PI * static_cast<float>(staveNumber) / static_cast<float>(barrelSymmetryOrder)); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(-std::sin(phi), std::cos(phi), 0); + } + else + { + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + + if (pCaloHitPosition[1] != 0) + { + const float phi = barrelPhi0 + std::atan(pCaloHitPosition[0] / pCaloHitPosition[1]); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(std::sin(phi), std::cos(phi), 0); + } + else + { + caloHitParameters.m_cellNormalVector = (pCaloHitPosition[0] > 0) ? pandora::CartesianVector(1, 0, 0) : + pandora::CartesianVector(-1, 0, 0); + } + } +} + +void CaloHitCreator::GetBarrelCaloHitProperties(const edm4hep::CalorimeterHit *const pCaloHit, const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer> &layerLayout, + unsigned int barrelSymmetryOrder, float barrelPhi0, unsigned int staveNumber, PandoraApi::CaloHit::Parameters &caloHitParameters, + float &absorberCorrection) const +{ + caloHitParameters.m_hitRegion = pandora::BARREL; + + const int physicalLayer = std::max(0, int(caloHitParameters.m_layer.Get()-1) ); + caloHitParameters.m_cellSize0 = layerLayout.at(physicalLayer).cellSize0; + caloHitParameters.m_cellSize1 = layerLayout.at(physicalLayer).cellSize1; + caloHitParameters.m_cellThickness = layerLayout.at(physicalLayer).sensitive_thickness; + + const float radiationLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength((pandora::ECAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthECal : + (pandora::HCAL == caloHitParameters.m_hitType.Get()) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + const float layerAbsorberThickness(layerLayout.at(physicalLayer).absorberThickness); + caloHitParameters.m_nCellRadiationLengths = radiationLength * layerAbsorberThickness; + caloHitParameters.m_nCellInteractionLengths = interactionLength * layerAbsorberThickness; + + + if (caloHitParameters.m_nCellRadiationLengths.Get() < std::numeric_limits<float>::epsilon() || caloHitParameters.m_nCellInteractionLengths.Get() < std::numeric_limits<float>::epsilon()) + { + std::cout<<"interactionLength="<<interactionLength<<",layerAbsorberThickness="<<layerAbsorberThickness<<",radiationLength="<<radiationLength<<",physicalLayer="<<physicalLayer<<",l1="<<caloHitParameters.m_layer.Get()<<",l2="<<layerLayout.size()-1<<std::endl; + std::cout<<"WARNIN CaloHitCreator::GetBarrelCaloHitProperties Calo hit has 0 radiation length or interaction length: \ + not creating a Pandora calo hit." << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + absorberCorrection = 1.; + for (unsigned int i = 0, iMax = layerLayout.size(); i < iMax; ++i) + { + const float absorberThickness(layerLayout.at(i).absorberThickness); + + if (absorberThickness < std::numeric_limits<float>::epsilon()) + continue; + + if (layerAbsorberThickness > std::numeric_limits<float>::epsilon()) + absorberCorrection = absorberThickness / layerAbsorberThickness; + + break; + } + if (barrelSymmetryOrder > 2) + { + float phi = barrelPhi0 + (2. * M_PI * float(staveNumber) / float(barrelSymmetryOrder)); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(-std::sin(phi), std::cos(phi), 0); + //std::cout<<"barrelPhi0="<<barrelPhi0<<",phi="<<phi<<",GetX()="<<caloHitParameters.m_cellNormalVector.Get().GetX()<<",GetY()="<<caloHitParameters.m_cellNormalVector.Get().GetY()<<",GetZ()="<<caloHitParameters.m_cellNormalVector.Get().GetZ()<<std::endl; + } + else + { + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + + if (pCaloHitPosition[1] != 0) + { + const float phi = barrelPhi0 + std::atan(pCaloHitPosition[0] / pCaloHitPosition[1]); + caloHitParameters.m_cellNormalVector = pandora::CartesianVector(std::sin(phi), std::cos(phi), 0); + } + else + { + caloHitParameters.m_cellNormalVector = (pCaloHitPosition[0] > 0) ? pandora::CartesianVector(1, 0, 0) : + pandora::CartesianVector(-1, 0, 0); + } + } +} +//------------------------------------------------------------------------------------------------------------------------------------------ +int CaloHitCreator::GetBarrelLayer(const edm4hep::CalorimeterHit *const pCaloHit, const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer> &layerLayout) const +{ + int layer = -1 ; + for (unsigned int i = 0, iMax = layerLayout.size(); i < iMax; ++i) + { + const float distance(layerLayout.at(i).distance); + const float sensitive_thickness(layerLayout.at(i).sensitive_thickness); + if( (distance - 0.5*sensitive_thickness) <= pCaloHit->getPosition().x && pCaloHit->getPosition().x <= (distance + 0.5*sensitive_thickness)) {layer = i+1 ; break;} + } + if(layer==-1) + { + int lmax = layerLayout.size()-1; + std::cout<<"Error BarrelLayer, set to default 1, Hit.x="<<pCaloHit->getPosition().x<<", min_x="<<layerLayout.at(0).distance-0.5*layerLayout.at(0).sensitive_thickness<<", max_x="<<layerLayout.at(lmax).distance+0.5*layerLayout.at(lmax).sensitive_thickness<<std::endl; + layer = 1; + } + return layer; +} + +int CaloHitCreator::GetNLayersFromEdge(const edm4hep::CalorimeterHit *const pCaloHit) const +{ + // Calo hit coordinate calculations + const float barrelMaximumRadius(this->GetMaximumRadius(pCaloHit, m_hCalBarrelOuterSymmetry, m_hCalBarrelOuterPhi0)); + const float endCapMaximumRadius(this->GetMaximumRadius(pCaloHit, m_settings.m_hCalEndCapInnerSymmetryOrder, m_settings.m_hCalEndCapInnerPhiCoordinate)); + const float caloHitAbsZ(std::fabs(pCaloHit->getPosition()[2])); + + // Distance from radial outer + float radialDistanceToEdge(std::numeric_limits<float>::max()); + + if (caloHitAbsZ < m_eCalBarrelOuterZ) + { + radialDistanceToEdge = (m_hCalBarrelOuterR - barrelMaximumRadius) / m_hCalBarrelLayerThickness; + } + else + { + radialDistanceToEdge = (m_hCalEndCapOuterR - endCapMaximumRadius) / m_hCalEndCapLayerThickness; + } + + // Distance from rear of endcap outer + float rearDistanceToEdge(std::numeric_limits<float>::max()); + + if (caloHitAbsZ >= m_eCalBarrelOuterZ) + { + rearDistanceToEdge = (m_hCalEndCapOuterZ - caloHitAbsZ) / m_hCalEndCapLayerThickness; + } + else + { + const float rearDistance((m_eCalBarrelOuterZ - caloHitAbsZ) / m_hCalBarrelLayerThickness); + + if (rearDistance < m_settings.m_layersFromEdgeMaxRearDistance) + { + const float overlapDistance((m_hCalEndCapOuterR - endCapMaximumRadius) / m_hCalEndCapLayerThickness); + rearDistanceToEdge = std::max(rearDistance, overlapDistance); + } + } + + return static_cast<int>(std::min(radialDistanceToEdge, rearDistanceToEdge)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +float CaloHitCreator::GetMaximumRadius(const edm4hep::CalorimeterHit *const pCaloHit, const unsigned int symmetryOrder, const float phi0) const +{ + + const float pCaloHitPosition[3]={pCaloHit->getPosition()[0], pCaloHit->getPosition()[1], pCaloHit->getPosition()[2]}; + if (symmetryOrder <= 2) + return std::sqrt((pCaloHitPosition[0] * pCaloHitPosition[0]) + (pCaloHitPosition[1] * pCaloHitPosition[1])); + + float maximumRadius(0.f); + const float twoPi(2.f * M_PI); + + for (unsigned int i = 0; i < symmetryOrder; ++i) + { + const float phi = phi0 + i * twoPi / static_cast<float>(symmetryOrder); + float radius = pCaloHitPosition[0] * std::cos(phi) + pCaloHitPosition[1] * std::sin(phi); + + if (radius > maximumRadius) + maximumRadius = radius; + } + + return maximumRadius; +} + +void CaloHitCreator::GetCoding(const edm4hep::CalorimeterHit* pCaloHit, long& sys, long& x, long& y, long& z) const +{ + //sys = (pCaloHit->getCellID() << (64-8)) >> (64-8) ; + //x = (pCaloHit->getCellID() << (64-(8+16))) >> (64-(8+16)) ; + //y = (pCaloHit->getCellID() << (64-(8+16+16))) >> (64-(8+16+16)) ; + //z = (pCaloHit->getCellID() << (64-(8+16+16+16))) >> (64-(8+16+16+16)) ; + unsigned long long id = pCaloHit->getCellID(); + sys = id & 0xFF ; + x = (id >> 8) & 0xFFFF ; + y = (id >> (8+16)) & 0xFFFF ; + z = (id >> (8+16+16)) & 0xFFFF ; +} +//------------------------------------------------------------------------------------------------------------------------------------------ + +std::string CaloHitCreator::GetLayerCoding(const std::string &encodingString) const +{ + if (encodingString.find("layer") != std::string::npos) + return std::string("layer"); + + if (encodingString.find("K-1") != std::string::npos) + return std::string("K-1"); + + if (encodingString.find("K") != std::string::npos) + return std::string("K"); + + return std::string("unknown_layer_encoding"); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +std::string CaloHitCreator::GetStaveCoding(const std::string &encodingString) const +{ + if (encodingString.find("stave") != std::string::npos) + return std::string("stave"); + + if (encodingString.find("S-1") != std::string::npos) + return std::string("S-1"); + + return std::string("unknown_stave_encoding") ; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +CaloHitCreator::Settings::Settings() : + m_absorberRadLengthECal(1.f), + m_absorberIntLengthECal(1.f), + m_absorberRadLengthHCal(1.f), + m_absorberIntLengthHCal(1.f), + m_absorberRadLengthOther(1.f), + m_absorberIntLengthOther(1.f), + m_eCalToMip(1.f), + m_hCalToMip(1.f), + m_muonToMip(1.f), + m_eCalMipThreshold(0.f), + m_hCalMipThreshold(0.f), + m_muonMipThreshold(0.f), + m_eCalToEMGeV(1.f), + m_eCalToHadGeVBarrel(1.f), + m_eCalToHadGeVEndCap(1.f), + m_hCalToEMGeV(1.f), + m_hCalToHadGeV(1.f), + m_muonDigitalHits(1), + m_muonHitEnergy(0.5f), + m_maxHCalHitHadronicEnergy(10000.f), + m_nOuterSamplingLayers(3), + m_layersFromEdgeMaxRearDistance(250.f), + m_hCalEndCapInnerSymmetryOrder(4), + m_hCalEndCapInnerPhiCoordinate(0.f), + m_stripSplittingOn(0), + m_useEcalScLayers(0), + m_eCalSiToMip(1.f), + m_eCalScToMip(1.f), + m_eCalSiMipThreshold(0.f), + m_eCalScMipThreshold(0.f), + m_eCalSiToEMGeV(1.f), + m_eCalScToEMGeV(1.f), + m_eCalSiToHadGeVBarrel(1.f), + m_eCalScToHadGeVBarrel(1.f), + m_eCalSiToHadGeVEndCap(1.f), + m_eCalScToHadGeVEndCap(1.f) +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/GeometryCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/GeometryCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ab6cc805b00cc2f2a74c5baecdeba10c9cb1907 --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/GeometryCreator.cpp @@ -0,0 +1,488 @@ +/** + * @file MarlinPandora/src/GeometryCreator.cc + * + * @brief Implementation of the geometry creator class. + * + * $Log: $ + */ +#include "GaudiKernel/IService.h" + +#include "GearSvc/IGearSvc.h" +#include "gear/BField.h" +#include "gear/GEAR.h" +#include "gear/GearParameters.h" +#include "gear/CalorimeterParameters.h" +#include "gear/TPCParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/LayerLayout.h" + +#include "GeometryCreator.h" + +#include <DD4hep/Detector.h> +#include <DDRec/DetectorData.h> + +GeometryCreator::GeometryCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora) +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +GeometryCreator::~GeometryCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +//pandora::StatusCode GeometryCreator::CreateGeometry() const +//pandora::StatusCode GeometryCreator::CreateGeometry(ISvcLocator* svcloc) const +pandora::StatusCode GeometryCreator::CreateGeometry(ISvcLocator* svcloc) +{ + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + IGeoSvc* Svc = 0; + StatusCode sc1 = svcloc->service("GeoSvc", Svc, false); + if ( !sc1 ) + { + throw "Failed to find GeoSvc ..."; + } + m_dd4hep = Svc->lcdd(); + + + //auto _gear = service<IGearSvc>("GearSvc"); + //if ( !_gear ) + //{ + // throw "Failed to find GearSvc ..."; + //} + //_GEAR = _gear->getGearMgr(); + + + try + { + SubDetectorTypeMap subDetectorTypeMap; + this->SetMandatorySubDetectorParameters(subDetectorTypeMap); + + SubDetectorNameMap subDetectorNameMap; + this->SetAdditionalSubDetectorParameters(subDetectorNameMap); + + if (std::string::npos != _GEAR->getDetectorName().find("ILD")) + this->SetILDSpecificGeometry(subDetectorTypeMap, subDetectorNameMap); + + for (SubDetectorTypeMap::const_iterator iter = subDetectorTypeMap.begin(), iterEnd = subDetectorTypeMap.end(); iter != iterEnd; ++iter) + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::SubDetector::Create(*m_pPandora, iter->second)); + + for (SubDetectorNameMap::const_iterator iter = subDetectorNameMap.begin(), iterEnd = subDetectorNameMap.end(); iter != iterEnd; ++iter) + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::SubDetector::Create(*m_pPandora, iter->second)); + } + catch (gear::Exception &exception) + { + std::cout << "Failure in marlin pandora geometry creator, gear exception: " << exception.what() << std::endl; + throw exception; + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetMandatorySubDetectorParameters(SubDetectorTypeMap &subDetectorTypeMap) const +{ + std::cout << "Begin SetMandatorySubDetectorParameters:" << std::endl; + PandoraApi::Geometry::SubDetector::Parameters eCalBarrelParameters, eCalEndCapParameters, hCalBarrelParameters, hCalEndCapParameters, + muonBarrelParameters, muonEndCapParameters; + + this->SetDefaultSubDetectorParameters(m_dd4hep, "CaloDetector", pandora::ECAL_BARREL, eCalBarrelParameters); + //this->SetDefaultSubDetectorParameters(_GEAR->getEcalBarrelParameters(), "ECalBarrel", pandora::ECAL_BARREL, eCalBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getEcalEndcapParameters(), "ECalEndCap", pandora::ECAL_ENDCAP, eCalEndCapParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getHcalBarrelParameters(), "HCalBarrel", pandora::HCAL_BARREL, hCalBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getHcalEndcapParameters(), "HCalEndCap", pandora::HCAL_ENDCAP, hCalEndCapParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getYokeBarrelParameters(), "MuonBarrel", pandora::MUON_BARREL, muonBarrelParameters); + this->SetDefaultSubDetectorParameters(_GEAR->getYokeEndcapParameters(), "MuonEndCap", pandora::MUON_ENDCAP, muonEndCapParameters); + + subDetectorTypeMap[pandora::ECAL_BARREL] = eCalBarrelParameters; + subDetectorTypeMap[pandora::ECAL_ENDCAP] = eCalEndCapParameters; + subDetectorTypeMap[pandora::HCAL_BARREL] = hCalBarrelParameters; + subDetectorTypeMap[pandora::HCAL_ENDCAP] = hCalEndCapParameters; + subDetectorTypeMap[pandora::MUON_BARREL] = muonBarrelParameters; + subDetectorTypeMap[pandora::MUON_ENDCAP] = muonEndCapParameters; + + PandoraApi::Geometry::SubDetector::Parameters trackerParameters; + const gear::TPCParameters &tpcParameters(_GEAR->getTPCParameters()); + trackerParameters.m_subDetectorName = "Tracker"; + trackerParameters.m_subDetectorType = pandora::INNER_TRACKER; + trackerParameters.m_innerRCoordinate = tpcParameters.getPadLayout().getPlaneExtent()[0]; + trackerParameters.m_innerZCoordinate = 0.f; + trackerParameters.m_innerPhiCoordinate = 0.f; + trackerParameters.m_innerSymmetryOrder = 0; + trackerParameters.m_outerRCoordinate = tpcParameters.getPadLayout().getPlaneExtent()[1]; + trackerParameters.m_outerZCoordinate = tpcParameters.getMaxDriftLength(); + trackerParameters.m_outerPhiCoordinate = 0.f; + trackerParameters.m_outerSymmetryOrder = 0; + trackerParameters.m_isMirroredInZ = true; + trackerParameters.m_nLayers = 0; + subDetectorTypeMap[pandora::INNER_TRACKER] = trackerParameters; + + PandoraApi::Geometry::SubDetector::Parameters coilParameters; + const gear::GearParameters &gearParameters(_GEAR->getGearParameters("CoilParameters")); + coilParameters.m_subDetectorName = "Coil"; + coilParameters.m_subDetectorType = pandora::COIL; + coilParameters.m_innerRCoordinate = gearParameters.getDoubleVal("Coil_cryostat_inner_radius"); + coilParameters.m_innerZCoordinate = 0.f; + coilParameters.m_innerPhiCoordinate = 0.f; + coilParameters.m_innerSymmetryOrder = 0; + coilParameters.m_outerRCoordinate = gearParameters.getDoubleVal("Coil_cryostat_outer_radius"); + coilParameters.m_outerZCoordinate = gearParameters.getDoubleVal("Coil_cryostat_half_z"); + coilParameters.m_outerPhiCoordinate = 0.f; + coilParameters.m_outerSymmetryOrder = 0; + coilParameters.m_isMirroredInZ = true; + coilParameters.m_nLayers = 0; + subDetectorTypeMap[pandora::COIL] = coilParameters; + std::cout << "End SetMandatorySubDetectorParameters" << std::endl; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetAdditionalSubDetectorParameters(SubDetectorNameMap &subDetectorNameMap) const +{ + std::cout << "Begin SetAdditionalSubDetectorParameters:" << std::endl; + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getEcalPlugParameters(), "ECalPlug", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << " warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getHcalRingParameters(), "HCalRing", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout<< "warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getLcalParameters(), "LCal", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << "warning pandora geometry creator: " << exception.what() << std::endl; + } + + try + { + PandoraApi::Geometry::SubDetector::Parameters parameters; + this->SetDefaultSubDetectorParameters(_GEAR->getLHcalParameters(), "LHCal", pandora::SUB_DETECTOR_OTHER, parameters); + subDetectorNameMap[parameters.m_subDetectorName.Get()] = parameters; + } + catch (gear::Exception &exception) + { + std::cout << "warning pandora geometry creator: " << exception.what() << std::endl; + } + std::cout << "End SetAdditionalSubDetectorParameters" << std::endl; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void GeometryCreator::SetDefaultSubDetectorParameters(const gear::CalorimeterParameters &inputParameters, const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const +{ + const gear::LayerLayout &layerLayout = inputParameters.getLayerLayout(); + + parameters.m_subDetectorName = subDetectorName; + parameters.m_subDetectorType = subDetectorType; + parameters.m_innerRCoordinate = inputParameters.getExtent()[0]; + parameters.m_innerZCoordinate = inputParameters.getExtent()[2]; + parameters.m_innerPhiCoordinate = inputParameters.getPhi0(); + parameters.m_innerSymmetryOrder = inputParameters.getSymmetryOrder(); + parameters.m_outerRCoordinate = inputParameters.getExtent()[1]; + parameters.m_outerZCoordinate = inputParameters.getExtent()[3]; + parameters.m_outerPhiCoordinate = inputParameters.getPhi0(); + parameters.m_outerSymmetryOrder = inputParameters.getSymmetryOrder(); + parameters.m_isMirroredInZ = true; + parameters.m_nLayers = layerLayout.getNLayers(); + std::cout << "inputParameters.getExtent()[0]="<<inputParameters.getExtent()[0]<<",inputParameters.getExtent()[1]="<<inputParameters.getExtent()[1]<<",inputParameters.getExtent()[2]="<<inputParameters.getExtent()[2]<<",inputParameters.getExtent()[3]="<<inputParameters.getExtent()[3]<< std::endl; + + // ATTN Not always going to be correct for any optional subdetectors, but impact of this is negligible for ILD + const float radiationLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + for (int i = 0; i < layerLayout.getNLayers(); ++i) + { + PandoraApi::Geometry::LayerParameters layerParameters; + layerParameters.m_closestDistanceToIp = layerLayout.getDistance(i) + (0.5 * (layerLayout.getThickness(i) + layerLayout.getAbsorberThickness(i))); + layerParameters.m_nRadiationLengths = radiationLength * layerLayout.getAbsorberThickness(i); + layerParameters.m_nInteractionLengths = interactionLength * layerLayout.getAbsorberThickness(i); + parameters.m_layerParametersVector.push_back(layerParameters); + } +} + +void GeometryCreator::SetDefaultSubDetectorParameters(const dd4hep::Detector* theDetector , const std::string &subDetectorName, + const pandora::SubDetectorType subDetectorType, PandoraApi::Geometry::SubDetector::Parameters ¶meters) const +{ + //const std::vector< dd4hep::DetElement > &detElements = theDetector.detectors("EcalMatrix", true); + const dd4hep::DetElement &detElement = theDetector->detector(subDetectorName); + dd4hep::rec::LayeredCalorimeterData* Data = detElement.extension<dd4hep::rec::LayeredCalorimeterData>() ; + + + parameters.m_subDetectorName = subDetectorName; + parameters.m_subDetectorType = subDetectorType; + parameters.m_innerRCoordinate = Data->extent[0]; + parameters.m_innerZCoordinate = Data->extent[2]; + parameters.m_innerPhiCoordinate = Data->inner_phi0; + parameters.m_innerSymmetryOrder = Data->inner_symmetry; + parameters.m_outerRCoordinate = Data->extent[1]; + parameters.m_outerZCoordinate = Data->extent[3]; + parameters.m_outerPhiCoordinate = Data->outer_phi0; + parameters.m_outerSymmetryOrder = Data->outer_symmetry; + parameters.m_nLayers = Data->layers.size(); + parameters.m_isMirroredInZ = true; + const std::vector<dd4hep::rec::LayeredCalorimeterData::Layer>& layers= Data->layers; + std::cout << "Extent()[0]="<<Data->extent[0]<<",Extent()[1]="<<Data->extent[1]<<",Extent()[2]="<<Data->extent[2]<<",Extent()[3]="<<Data->extent[3]<< std::endl; + + // ATTN Not always going to be correct for any optional subdetectors, but impact of this is negligible for ILD + const float radiationLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberRadLengthHCal : m_settings.m_absorberRadLengthOther); + const float interactionLength(((pandora::ECAL_BARREL == subDetectorType) || (pandora::ECAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthECal : + ((pandora::HCAL_BARREL == subDetectorType) || (pandora::HCAL_ENDCAP == subDetectorType)) ? m_settings.m_absorberIntLengthHCal : m_settings.m_absorberIntLengthOther); + + //for (int i = 0; i < layerLayout.getNLayers(); ++i) + for (auto const& layer : layers) + { + PandoraApi::Geometry::LayerParameters layerParameters; + //layerParameters.m_closestDistanceToIp = layer.distance + 0.5 * layer.sensitive_thickness;//Thickness of the sensitive element (e.g. scintillator) + layerParameters.m_closestDistanceToIp = layer.distance ; + layerParameters.m_nRadiationLengths = radiationLength * layer.absorberThickness; + layerParameters.m_nInteractionLengths = interactionLength * layer.absorberThickness; + std::cout<<"m_closestDistanceToIp="<<layerParameters.m_closestDistanceToIp.Get()<<",m_nRadiationLengths="<<layerParameters.m_nRadiationLengths.Get()<<",m_nInteractionLengths="<<layerParameters.m_nInteractionLengths.Get()<<std::endl; + parameters.m_layerParametersVector.push_back(layerParameters); + } +} +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::SetILDSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap, SubDetectorNameMap &subDetectorNameMap) const +{ + // Set positions of gaps in ILD detector and add information missing from GEAR parameters file + try + { + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerPhiCoordinate = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_phi0"); + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerSymmetryOrder = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order"); + } + catch (gear::Exception &) + { + // aLaVideauGeometry + return this->SetILD_SDHCALSpecificGeometry(subDetectorTypeMap); + } + + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_eCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_eCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_eCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_eCalEndCapOuterPhiCoordinate; + + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_hCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_hCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_hCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_hCalEndCapOuterPhiCoordinate; + + subDetectorNameMap["HCalRing"].m_innerSymmetryOrder = m_settings.m_hCalRingInnerSymmetryOrder; + subDetectorNameMap["HCalRing"].m_innerPhiCoordinate = m_settings.m_hCalRingInnerPhiCoordinate; + subDetectorNameMap["HCalRing"].m_outerSymmetryOrder = m_settings.m_hCalRingOuterSymmetryOrder; + subDetectorNameMap["HCalRing"].m_outerPhiCoordinate = m_settings.m_hCalRingOuterPhiCoordinate; + + // Gaps in detector active material + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalBarrelBoxGaps()); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalEndCapBoxGaps()); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateHCalBarrelConcentricGaps()); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::SetILD_SDHCALSpecificGeometry(SubDetectorTypeMap &subDetectorTypeMap) const +{ + // Non-default values (and those missing from GEAR parameters file)... + // The following 2 parameters have no sense for Videau Geometry, set them to 0 + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerPhiCoordinate = 0; + subDetectorTypeMap[pandora::HCAL_BARREL].m_outerSymmetryOrder = 0; + + // Endcap is identical to standard ILD geometry, only HCAL barrel is different + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_eCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_eCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_eCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::ECAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_eCalEndCapOuterPhiCoordinate; + + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerSymmetryOrder = m_settings.m_hCalEndCapInnerSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_innerPhiCoordinate = m_settings.m_hCalEndCapInnerPhiCoordinate; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerSymmetryOrder = m_settings.m_hCalEndCapOuterSymmetryOrder; + subDetectorTypeMap[pandora::HCAL_ENDCAP].m_outerPhiCoordinate = m_settings.m_hCalEndCapOuterPhiCoordinate; + + // TODO implement gaps between modules + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalBarrelBoxGaps() const +{ + const std::string detectorName(_GEAR->getDetectorName()); + + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + const unsigned int innerSymmetryOrder(hCalBarrelParameters.getSymmetryOrder()); + const unsigned int outerSymmetryOrder(hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order")); + + if ((0 == innerSymmetryOrder) || (2 != outerSymmetryOrder / innerSymmetryOrder)) + { + std::cout << " Detector " << detectorName << " doesn't conform to expected ILD-specific geometry" << std::endl; + return pandora::STATUS_CODE_INVALID_PARAMETER; + } + + const float innerRadius(hCalBarrelParameters.getExtent()[0]); + const float outerRadius(hCalBarrelParameters.getExtent()[1]); + const float outerZ(hCalBarrelParameters.getExtent()[3]); + const float phi0(hCalBarrelParameters.getPhi0()); + + const float staveGap(hCalBarrelParameters.getDoubleVal("Hcal_stave_gaps")); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(innerSymmetryOrder, phi0, innerRadius, outerRadius, + -outerZ, outerZ, staveGap)); + + const float outerPseudoPhi0(M_PI / static_cast<float>(innerSymmetryOrder)); + const float cosOuterPseudoPhi0(std::cos(outerPseudoPhi0)); + + if ((0 == outerPseudoPhi0) || (0.f == cosOuterPseudoPhi0)) + { + std::cout << " Detector " << detectorName << " doesn't conform to expected ILD-specific geometry" << std::endl; + return pandora::STATUS_CODE_INVALID_PARAMETER; + } + + const float middleStaveGap(hCalBarrelParameters.getDoubleVal("Hcal_middle_stave_gaps")); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(innerSymmetryOrder, outerPseudoPhi0, + innerRadius / cosOuterPseudoPhi0, outerRadius, -outerZ, outerZ, middleStaveGap)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalEndCapBoxGaps() const +{ + const gear::CalorimeterParameters &hCalEndCapParameters = _GEAR->getHcalEndcapParameters(); + + const float staveGap(hCalEndCapParameters.getDoubleVal("Hcal_stave_gaps")); + const float innerRadius(hCalEndCapParameters.getExtent()[0]); + const float outerRadius(hCalEndCapParameters.getExtent()[1]); + const float innerZ(hCalEndCapParameters.getExtent()[2]); + const float outerZ(hCalEndCapParameters.getExtent()[3]); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(m_settings.m_hCalEndCapInnerSymmetryOrder, + m_settings.m_hCalEndCapInnerPhiCoordinate, innerRadius, outerRadius, innerZ, outerZ, staveGap, + pandora::CartesianVector(-innerRadius, 0, 0))); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CreateRegularBoxGaps(m_settings.m_hCalEndCapInnerSymmetryOrder, + m_settings.m_hCalEndCapInnerPhiCoordinate, innerRadius, outerRadius, -outerZ, -innerZ, staveGap, + pandora::CartesianVector(innerRadius, 0, 0))); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateHCalBarrelConcentricGaps() const +{ + const gear::CalorimeterParameters &hCalBarrelParameters = _GEAR->getHcalBarrelParameters(); + const float gapWidth(hCalBarrelParameters.getDoubleVal("Hcal_stave_gaps")); + + PandoraApi::Geometry::ConcentricGap::Parameters gapParameters; + + gapParameters.m_minZCoordinate = -0.5f * gapWidth; + gapParameters.m_maxZCoordinate = 0.5f * gapWidth; + gapParameters.m_innerRCoordinate = hCalBarrelParameters.getExtent()[0]; + gapParameters.m_innerPhiCoordinate = hCalBarrelParameters.getPhi0(); + gapParameters.m_innerSymmetryOrder = hCalBarrelParameters.getSymmetryOrder(); + gapParameters.m_outerRCoordinate = hCalBarrelParameters.getExtent()[1]; + gapParameters.m_outerPhiCoordinate = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_phi0"); + gapParameters.m_outerSymmetryOrder = hCalBarrelParameters.getIntVal("Hcal_outer_polygon_order"); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::ConcentricGap::Create(*m_pPandora, gapParameters)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode GeometryCreator::CreateRegularBoxGaps(unsigned int symmetryOrder, float phi0, float innerRadius, float outerRadius, + float minZ, float maxZ, float gapWidth, pandora::CartesianVector vertexOffset) const +{ + const pandora::CartesianVector basicGapVertex(pandora::CartesianVector(-0.5f * gapWidth, innerRadius, minZ) + vertexOffset); + const pandora::CartesianVector basicSide1(gapWidth, 0, 0); + const pandora::CartesianVector basicSide2(0, outerRadius - innerRadius, 0); + const pandora::CartesianVector basicSide3(0, 0, maxZ - minZ); + + for (unsigned int i = 0; i < symmetryOrder; ++i) + { + const float phi = phi0 + (2. * M_PI * static_cast<float>(i) / static_cast<float>(symmetryOrder)); + const float sinPhi(std::sin(phi)); + const float cosPhi(std::cos(phi)); + + PandoraApi::Geometry::BoxGap::Parameters gapParameters; + + gapParameters.m_vertex = pandora::CartesianVector(cosPhi * basicGapVertex.GetX() + sinPhi * basicGapVertex.GetY(), + -sinPhi * basicGapVertex.GetX() + cosPhi * basicGapVertex.GetY(), basicGapVertex.GetZ()); + gapParameters.m_side1 = pandora::CartesianVector(cosPhi * basicSide1.GetX() + sinPhi * basicSide1.GetY(), + -sinPhi * basicSide1.GetX() + cosPhi * basicSide1.GetY(), basicSide1.GetZ()); + gapParameters.m_side2 = pandora::CartesianVector(cosPhi * basicSide2.GetX() + sinPhi * basicSide2.GetY(), + -sinPhi * basicSide2.GetX() + cosPhi * basicSide2.GetY(), basicSide2.GetZ()); + gapParameters.m_side3 = pandora::CartesianVector(cosPhi * basicSide3.GetX() + sinPhi * basicSide3.GetY(), + -sinPhi * basicSide3.GetX() + cosPhi * basicSide3.GetY(), basicSide3.GetZ()); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Geometry::BoxGap::Create(*m_pPandora, gapParameters)); + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +GeometryCreator::Settings::Settings() : + m_absorberRadLengthECal(1.f), + m_absorberIntLengthECal(1.f), + m_absorberRadLengthHCal(1.f), + m_absorberIntLengthHCal(1.f), + m_absorberRadLengthOther(1.f), + m_absorberIntLengthOther(1.f), + m_eCalEndCapInnerSymmetryOrder(4), + m_eCalEndCapInnerPhiCoordinate(0.f), + m_eCalEndCapOuterSymmetryOrder(8), + m_eCalEndCapOuterPhiCoordinate(0.f), + m_hCalEndCapInnerSymmetryOrder(4), + m_hCalEndCapInnerPhiCoordinate(0.f), + m_hCalEndCapOuterSymmetryOrder(16), + m_hCalEndCapOuterPhiCoordinate(0.f), + m_hCalRingInnerSymmetryOrder(8), + m_hCalRingInnerPhiCoordinate(0.f), + m_hCalRingOuterSymmetryOrder(16), + m_hCalRingOuterPhiCoordinate(0.f) +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/MCParticleCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/MCParticleCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..21a2a741bcc28617dba766d43600ee1f818ded8e --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/MCParticleCreator.cpp @@ -0,0 +1,372 @@ +/** + * @file MarlinPandora/src/MCParticleCreator.cc + * + * @brief Implementation of the mc particle creator class. + * + * $Log: $ + */ + + +#include "edm4hep/MCParticleConst.h" +#include "edm4hep/MCParticle.h" +#include "edm4hep/MCRecoCaloAssociation.h" +#include "edm4hep/SimCalorimeterHitConst.h" +#include "edm4hep/CaloHitContributionConst.h" +#include "edm4hep/Track.h" +#include "edm4hep/MCRecoTrackerAssociation.h" +#include "edm4hep/SimTrackerHitConst.h" + + + + +#include "PandoraMatrixAlg.h" +#include "MCParticleCreator.h" + +#include <cmath> +#include <limits> +#include <assert.h> + +MCParticleCreator::MCParticleCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora), + m_bField(settings.m_bField) +{ +m_id_pMC_map = new std::map<unsigned int, const edm4hep::MCParticle*>; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +MCParticleCreator::~MCParticleCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode MCParticleCreator::CreateMCParticles(const CollectionMaps& collectionMaps ) const +{ + for (StringVector::const_iterator iter = m_settings.m_mcParticleCollections.begin(), iterEnd = m_settings.m_mcParticleCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_MC.find(*iter) == collectionMaps.collectionMap_MC.end()) continue; + try + { + const std::vector<edm4hep::MCParticle>& pMCParticleCollection = (collectionMaps.collectionMap_MC.find(*iter))->second; + std::cout<<"Do CreateMCParticles, collection:"<<(*iter)<<", size="<<pMCParticleCollection.size()<<std::endl; + for (int im = 0; im < pMCParticleCollection.size(); im++) + { + try + { + const edm4hep::MCParticle& pMcParticle = pMCParticleCollection.at(im); + PandoraApi::MCParticle::Parameters mcParticleParameters; + mcParticleParameters.m_energy = sqrt(pMcParticle.getMomentum()[0] * pMcParticle.getMomentum()[0] + pMcParticle.getMomentum()[1] * pMcParticle.getMomentum()[1] + pMcParticle.getMomentum()[2] * pMcParticle.getMomentum()[2] + pMcParticle.getMass() * pMcParticle.getMass()); + mcParticleParameters.m_particleId = pMcParticle.getPDG(); + mcParticleParameters.m_mcParticleType = pandora::MC_3D; + mcParticleParameters.m_pParentAddress = &pMcParticle; + unsigned int p_id = pMcParticle.id(); + const edm4hep::MCParticle* p_mc = &pMcParticle; + (*m_id_pMC_map) [p_id] = p_mc; + mcParticleParameters.m_momentum = pandora::CartesianVector(pMcParticle.getMomentum()[0], pMcParticle.getMomentum()[1], + pMcParticle.getMomentum()[2]); + mcParticleParameters.m_vertex = pandora::CartesianVector(pMcParticle.getVertex()[0], pMcParticle.getVertex()[1], + pMcParticle.getVertex()[2]); + mcParticleParameters.m_endpoint = pandora::CartesianVector(pMcParticle.getEndpoint()[0], pMcParticle.getEndpoint()[1], + pMcParticle.getEndpoint()[2]); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::MCParticle::Create(*m_pPandora, mcParticleParameters)); + + // Create parent-daughter relationships + for(std::vector<edm4hep::ConstMCParticle>::const_iterator itDaughter = pMcParticle.daughters_begin(), + itDaughterEnd = pMcParticle.daughters_end(); itDaughter != itDaughterEnd; ++itDaughter) + { + for (int ida = 0; ida < pMCParticleCollection.size(); ida++) + { + if(pMCParticleCollection.at(ida).id()==(*itDaughter).id()) + { + + const edm4hep::MCParticle& dMcParticle = pMCParticleCollection.at(ida); + if(&pMcParticle == &dMcParticle){std::cout<< "error, mother and daughter are the same mc particle, don't save SetMCParentDaughterRelationship"<<std::endl;} + else PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetMCParentDaughterRelationship(*m_pPandora, &pMcParticle, &dMcParticle)); + break; + } + } + } + + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to extract MCParticle: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "Failed to extract MCParticle: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract MCParticles collection: " << *iter << ", " << std::endl; + } + } + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode MCParticleCreator::CreateTrackToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const TrackVector &trackVector) const +{ + for (StringVector::const_iterator iter = m_settings.m_lcTrackRelationCollections.begin(), iterEnd = m_settings.m_lcTrackRelationCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pMCRelationCollection = pLCEvent->getCollection(*iter); + UTIL::LCRelationNavigator navigate(pMCRelationCollection); + + for (TrackVector::const_iterator trackIter = trackVector.begin(), trackIterEnd = trackVector.end(); + trackIter != trackIterEnd; ++trackIter) + { + try + { + EVENT::Track *pTrack = *trackIter; + const EVENT::LCObjectVec &objectVec = navigate.getRelatedToObjects(*trackIter); + + // Get reconstructed momentum at dca + const pandora::Helix helixFit(pTrack->getPhi(), pTrack->getD0(), pTrack->getZ0(), pTrack->getOmega(), pTrack->getTanLambda(), m_bField); + const float recoMomentum(helixFit.GetMomentum().GetMagnitude()); + + // Use momentum magnitude to identify best mc particle + MCParticle *pBestMCParticle = NULL; + float bestDeltaMomentum(std::numeric_limits<float>::max()); + + for (EVENT::LCObjectVec::const_iterator itRel = objectVec.begin(), itRelEnd = objectVec.end(); itRel != itRelEnd; ++itRel) + { + EVENT::MCParticle *pMCParticle = NULL; + pMCParticle = dynamic_cast<MCParticle *>(*itRel); + + if (NULL == pMCParticle) + continue; + + const float trueMomentum(pandora::CartesianVector(pMCParticle->getMomentum()[0], pMCParticle->getMomentum()[1], + pMCParticle->getMomentum()[2]).GetMagnitude()); + + const float deltaMomentum(std::fabs(recoMomentum - trueMomentum)); + + if (deltaMomentum < bestDeltaMomentum) + { + pBestMCParticle = pMCParticle; + bestDeltaMomentum = deltaMomentum; + } + } + + if (NULL == pBestMCParticle) + continue; + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackToMCParticleRelationship(*m_pPandora, pTrack, + pBestMCParticle)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + streamlog_out(ERROR) << "Failed to extract track to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract track to mc particle relationship: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract track to mc particle relationships collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode MCParticleCreator::CreateCaloHitToMCParticleRelationships(const EVENT::LCEvent *const pLCEvent, const CalorimeterHitVector &calorimeterHitVector) const +{ + typedef std::map<MCParticle *, float> MCParticleToEnergyWeightMap; + MCParticleToEnergyWeightMap mcParticleToEnergyWeightMap; + + for (StringVector::const_iterator iter = m_settings.m_lcCaloHitRelationCollections.begin(), iterEnd = m_settings.m_lcCaloHitRelationCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pMCRelationCollection = pLCEvent->getCollection(*iter); + UTIL::LCRelationNavigator navigate(pMCRelationCollection); + + for (CalorimeterHitVector::const_iterator caloHitIter = calorimeterHitVector.begin(), + caloHitIterEnd = calorimeterHitVector.end(); caloHitIter != caloHitIterEnd; ++caloHitIter) + { + try + { + mcParticleToEnergyWeightMap.clear(); + const EVENT::LCObjectVec &objectVec = navigate.getRelatedToObjects(*caloHitIter); + + for (EVENT::LCObjectVec::const_iterator itRel = objectVec.begin(), itRelEnd = objectVec.end(); itRel != itRelEnd; ++itRel) + { + EVENT::SimCalorimeterHit *pSimHit = dynamic_cast<SimCalorimeterHit *>(*itRel); + + if (NULL == pSimHit) + continue; + + for (int iCont = 0, iEnd = pSimHit->getNMCContributions(); iCont < iEnd; ++iCont) + { + mcParticleToEnergyWeightMap[pSimHit->getParticleCont(iCont)] += pSimHit->getEnergyCont(iCont); + } + } + + for (MCParticleToEnergyWeightMap::const_iterator mcParticleIter = mcParticleToEnergyWeightMap.begin(), + mcParticleIterEnd = mcParticleToEnergyWeightMap.end(); mcParticleIter != mcParticleIterEnd; ++mcParticleIter) + { + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*m_pPandora, + *caloHitIter, mcParticleIter->first, mcParticleIter->second)); + } + } + catch (pandora::StatusCodeException &statusCodeException) + { + streamlog_out(ERROR) << "Failed to extract calo hit to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract calo hit to mc particle relationship: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract calo hit to mc particle relationships collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ + +//-------------- using sim calo hit and digi calo hit, no weight here--------------------------------------------------------------------------------------------------------------- +pandora::StatusCode MCParticleCreator::CreateCaloHitToMCParticleRelationships(const CollectionMaps& collectionMaps, const CalorimeterHitVector &calorimeterHitVector) const +{ + std::cout<<"Do CreateCaloHitToMCParticleRelationships"<<std::endl; + typedef std::map<const edm4hep::MCParticle *, float> MCParticleToEnergyWeightMap; + MCParticleToEnergyWeightMap mcParticleToEnergyWeightMap; + + for (StringVector::const_iterator iter = m_settings.m_CaloHitRelationCollections.begin(), iterEnd = m_settings.m_CaloHitRelationCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_CaloRel.find(*iter) == collectionMaps.collectionMap_CaloRel.end()) continue; + try + { + const std::vector<edm4hep::MCRecoCaloAssociation>& pMCRecoCaloAssociationCollection = (collectionMaps.collectionMap_CaloRel.find(*iter))->second; + + for (unsigned i_calo=0; i_calo < calorimeterHitVector.size(); i_calo++) + { + try + { + mcParticleToEnergyWeightMap.clear(); + for(unsigned ic=0; ic < pMCRecoCaloAssociationCollection.size(); ic++) + { + if( pMCRecoCaloAssociationCollection.at(ic).getRec().id() != (*(calorimeterHitVector.at(i_calo))).id() ) continue; + + const edm4hep::ConstSimCalorimeterHit pSimHit = pMCRecoCaloAssociationCollection.at(ic).getSim(); + for (int iCont = 0, iEnd = pSimHit.contributions_size(); iCont < iEnd; ++iCont) + { + edm4hep::ConstCaloHitContribution conb = pSimHit.getContributions(iCont); + const edm4hep::ConstMCParticle ipa = conb.getParticle(); + float ien = conb.getEnergy(); + if( m_id_pMC_map->find(ipa.id()) == m_id_pMC_map->end() ) continue; + const edm4hep::MCParticle * p_tmp = (*m_id_pMC_map)[ipa.id()]; + mcParticleToEnergyWeightMap[p_tmp] += ien; + } + + } + + for (MCParticleToEnergyWeightMap::const_iterator mcParticleIter = mcParticleToEnergyWeightMap.begin(), + mcParticleIterEnd = mcParticleToEnergyWeightMap.end(); mcParticleIter != mcParticleIterEnd; ++mcParticleIter) + { + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetCaloHitToMCParticleRelationship(*m_pPandora, + calorimeterHitVector.at(i_calo), mcParticleIter->first, mcParticleIter->second)); + } + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract calo hit to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract calo hit to mc particle relationship " << std::endl; + } + } + } + catch (...) + { + std::cout<<"DEBUG5 Failed to extract calo hit to mc particle relationships collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + + +//-------------- using sim tracker hit and tracker hit, no weight here--------------------------------------------------------------------------------------------------------------- +pandora::StatusCode MCParticleCreator::CreateTrackToMCParticleRelationships(const CollectionMaps& collectionMaps, const TrackVector &trackVector) const +{ + std::cout<<"Do CreateTrackToMCParticleRelationships"<<std::endl; + for (unsigned ik = 0; ik < trackVector.size(); ik++) + { + const edm4hep::Track *pTrack = trackVector.at(ik); + // Get reconstructed momentum at dca + const pandora::Helix helixFit(pTrack->getTrackStates(0).phi, pTrack->getTrackStates(0).D0, pTrack->getTrackStates(0).Z0, pTrack->getTrackStates(0).omega, pTrack->getTrackStates(0).tanLambda, m_bField); + const float recoMomentum(helixFit.GetMomentum().GetMagnitude()); + // Use momentum magnitude to identify best mc particle + edm4hep::MCParticle *pBestMCParticle = NULL; + float bestDeltaMomentum(std::numeric_limits<float>::max()); + try + { + for (StringVector::const_iterator iter = m_settings.m_TrackRelationCollections.begin(), iterEnd = m_settings.m_TrackRelationCollections.end(); iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_TrkRel.find(*iter) == collectionMaps.collectionMap_TrkRel.end()) continue; + const std::vector<edm4hep::MCRecoTrackerAssociation>& pMCRecoTrackerAssociationCollection = (collectionMaps.collectionMap_TrkRel.find(*iter))->second; + for(unsigned ith=0 ; ith<pTrack->trackerHits_size(); ith++) + { + for(unsigned ic=0; ic < pMCRecoTrackerAssociationCollection.size(); ic++) + { + if( pMCRecoTrackerAssociationCollection.at(ic).getRec().id() != pTrack->getTrackerHits(ith).id() ) continue; + const edm4hep::ConstSimTrackerHit pSimHit = pMCRecoTrackerAssociationCollection.at(ic).getSim(); + const edm4hep::ConstMCParticle ipa = pSimHit.getMCParticle(); + if( m_id_pMC_map->find(ipa.id()) == m_id_pMC_map->end() ) continue; + const float trueMomentum(pandora::CartesianVector(ipa.getMomentum()[0], ipa.getMomentum()[1], ipa.getMomentum()[2]).GetMagnitude()); + const float deltaMomentum(std::fabs(recoMomentum - trueMomentum)); + if (deltaMomentum < bestDeltaMomentum) + { + pBestMCParticle =const_cast<edm4hep::MCParticle*>((*m_id_pMC_map)[ipa.id()]); + bestDeltaMomentum = deltaMomentum; + } + } + } + } + + if (NULL == pBestMCParticle) continue; + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackToMCParticleRelationship(*m_pPandora, pTrack, pBestMCParticle)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract track to mc particle relationship: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout<<"WARNING Failed to extract track to mc particle relationship: " << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +MCParticleCreator::Settings::Settings() +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/PandoraMatrixAlg.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/PandoraMatrixAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..566f61e5b116ba626db23dba934b495e3f2e8b8d --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/PandoraMatrixAlg.cpp @@ -0,0 +1,958 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#include "GearSvc/IGearSvc.h" +#include "PandoraMatrixAlg.h" +#include "EventSeeder/IEventSeeder.h" +#include "edm4hep/Vector3f.h" +#include "edm4hep/Vector3d.h" +#include "edm4hep/SimCalorimeterHit.h" +#include "edm4hep/CaloHitContribution.h" +#include "edm4hep/ClusterConst.h" +#include "UTIL/ILDConf.h" +#include <cmath> +#include <algorithm> +#include "gear/BField.h" +#include <gear/GEAR.h> + +#include "LCContent.h" + +#include "TInterpreter.h" + +pandora::Pandora* PandoraMatrixAlg::m_pPandora=0; + +DECLARE_COMPONENT( PandoraMatrixAlg ) + +template<typename T ,typename T1> +StatusCode getCol(T & t, T1 & t1) +{ + try { + t1 = t.get(); + } + catch ( GaudiException &e ) { + std::cout << "Collection " << t.fullKey() << " is unavailable in event " << std::endl; + } + return StatusCode::SUCCESS; +} + + + +PandoraMatrixAlg::PandoraMatrixAlg(const std::string& name, ISvcLocator* svcLoc) + : GaudiAlgorithm(name, svcLoc), + _nEvt(0) +{ + m_CollectionMaps = new CollectionMaps(); + + declareProperty("ReadMCParticle" , m_mcParCol_r, "Handle of the MCParticle input collection" ); + declareProperty("ReadECALBarrel" , m_ECALBarrel_r, "Handle of the ECALBarrel input collection" ); + declareProperty("ReadECALEndcap" , m_ECALEndcap_r, "Handle of the ECALEndcap input collection" ); + declareProperty("ReadECALOther" , m_ECALOther_r, "Handle of the ECALOther input collection" ); + declareProperty("ReadHCALBarrel" , m_HCALBarrel_r, "Handle of the HCALBarrel input collection" ); + declareProperty("ReadHCALEndcap" , m_HCALEndcap_r, "Handle of the HCALEndcap input collection" ); + declareProperty("ReadHCALOther" , m_HCALOther_r, "Handle of the HCALOther input collection" ); + declareProperty("ReadMUON" , m_MUON_r, "Handle of the MUON input collection" ); + declareProperty("ReadLCAL" , m_LCAL_r, "Handle of the LCAL input collection" ); + declareProperty("ReadLHCAL" , m_LHCAL_r, "Handle of the LHCAL input collection" ); + declareProperty("ReadBCAL" , m_BCAL_r, "Handle of the BCAL input collection" ); + declareProperty("ReadKinkVertices" , m_KinkVertices_r, "Handle of the KinkVertices input collection" ); + declareProperty("ReadProngVertices" , m_ProngVertices_r, "Handle of the ProngVertices input collection" ); + declareProperty("ReadSplitVertices" , m_SplitVertices_r, "Handle of the SplitVertices input collection" ); + declareProperty("ReadV0Vertices" , m_V0Vertices_r, "Handle of the V0Vertices input collection" ); + declareProperty("ReadTracks" , m_MarlinTrkTracks_r, "Handle of the Tracks input collection" ); + declareProperty("MCRecoCaloAssociation" , m_MCRecoCaloAssociation_r, "Handle of the MCRecoCaloAssociation input collection" ); + declareProperty("MCRecoTrackerAssociation" , m_MCRecoTrackerAssociation_r, "Handle of the MCRecoTrackerAssociation input collection" ); + declareProperty("WriteClusterCollection" , m_ClusterCollection_w, "Handle of the ClusterCollection output collection" ); + declareProperty("WriteReconstructedParticleCollection", m_ReconstructedParticleCollection_w, "Handle of the ReconstructedParticleCollection output collection" ); + declareProperty("WriteVertexCollection" , m_VertexCollection_w, "Handle of the VertexCollection output collection" ); + +} + + +void PandoraMatrixAlg::FinaliseSteeringParameters(ISvcLocator* svcloc) +{ + // ATTN: This function seems to be necessary for operations that cannot easily be performed at construction of the processor, + // when the steering file is parsed e.g. the call to GEAR to get the inner bfield + + m_caloHitCreatorSettings.m_absorberRadLengthECal = m_geometryCreatorSettings.m_absorberRadLengthECal; + m_caloHitCreatorSettings.m_absorberIntLengthECal = m_geometryCreatorSettings.m_absorberIntLengthECal; + m_caloHitCreatorSettings.m_absorberRadLengthHCal = m_geometryCreatorSettings.m_absorberRadLengthHCal; + m_caloHitCreatorSettings.m_absorberIntLengthHCal = m_geometryCreatorSettings.m_absorberIntLengthHCal; + m_caloHitCreatorSettings.m_absorberRadLengthOther = m_geometryCreatorSettings.m_absorberRadLengthOther; + m_caloHitCreatorSettings.m_absorberIntLengthOther = m_geometryCreatorSettings.m_absorberIntLengthOther; + + m_caloHitCreatorSettings.m_hCalEndCapInnerSymmetryOrder = m_geometryCreatorSettings.m_hCalEndCapInnerSymmetryOrder; + m_caloHitCreatorSettings.m_hCalEndCapInnerPhiCoordinate = m_geometryCreatorSettings.m_hCalEndCapInnerPhiCoordinate; + + m_trackCreatorSettings.m_prongSplitVertexCollections = m_trackCreatorSettings.m_prongVertexCollections; + m_trackCreatorSettings.m_prongSplitVertexCollections.insert(m_trackCreatorSettings.m_prongSplitVertexCollections.end(), + m_trackCreatorSettings.m_splitVertexCollections.begin(), m_trackCreatorSettings.m_splitVertexCollections.end()); + + //m_settings.m_innerBField = marlin::Global::GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z(); + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + gear::GearMgr* _GEAR = iSvc->getGearMgr(); + m_settings.m_innerBField = _GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z(); + std::cout<<"m_innerBField="<<m_settings.m_innerBField<<std::endl; + m_mcParticleCreatorSettings.m_bField = m_settings.m_innerBField; +} + + + + +StatusCode PandoraMatrixAlg::initialize() +{ + + gInterpreter->GenerateDictionary("vector<vector<float> >", "vector"); + gInterpreter->GenerateDictionary("vector<vector<int> >", "vector"); + + std::cout<<"hi init PandoraMatrixAlg"<<std::endl; + + std::string s_output =m_AnaOutput; + m_fout = new TFile(s_output.c_str(),"RECREATE"); + m_tree = new TTree("evt","tree"); + m_tree->Branch("m_pReco_PID" , &m_pReco_PID); + m_tree->Branch("m_pReco_mc_id" , &m_pReco_mc_id); + m_tree->Branch("m_pReco_mc_weight", &m_pReco_mc_weight); + m_tree->Branch("m_pReco_mass" , &m_pReco_mass); + m_tree->Branch("m_pReco_energy", &m_pReco_energy); + m_tree->Branch("m_pReco_px" , &m_pReco_px); + m_tree->Branch("m_pReco_py" , &m_pReco_py); + m_tree->Branch("m_pReco_pz" , &m_pReco_pz); + m_tree->Branch("m_pReco_charge", &m_pReco_charge); + + m_tree->Branch("m_mc_id" , &m_mc_id); + m_tree->Branch("m_mc_p_size", &m_mc_p_size); + m_tree->Branch("m_mc_pid" , &m_mc_pid ); + m_tree->Branch("m_mc_mass" , &m_mc_mass ); + m_tree->Branch("m_mc_px" , &m_mc_px ); + m_tree->Branch("m_mc_py" , &m_mc_py ); + m_tree->Branch("m_mc_pz" , &m_mc_pz ); + m_tree->Branch("m_mc_charge", &m_mc_charge); + m_tree->Branch("m_hasConversion", &m_hasConversion); + + + m_tree->Branch("m_hits_x", &m_hits_x); + m_tree->Branch("m_hits_y", &m_hits_y); + m_tree->Branch("m_hits_z", &m_hits_z); + m_tree->Branch("m_hits_E", &m_hits_E); + + + // XML file + m_settings.m_pandoraSettingsXmlFile = m_PandoraSettingsXmlFile ; + // Hadronic energy non-linearity correction + m_settings.m_inputEnergyCorrectionPoints = m_InputEnergyCorrectionPoints; + m_settings.m_outputEnergyCorrectionPoints = m_OutputEnergyCorrectionPoints; + // B-field parameters + m_settings.m_muonBarrelBField = m_MuonBarrelBField; + m_settings.m_muonEndCapBField = m_MuonEndCapBField; + + m_trackCreatorSettings.m_trackCollections = m_TrackCollections ; + m_trackCreatorSettings.m_kinkVertexCollections = m_KinkVertexCollections; + m_trackCreatorSettings.m_prongVertexCollections = m_ProngVertexCollections; + m_trackCreatorSettings.m_splitVertexCollections = m_SplitVertexCollections; + m_trackCreatorSettings.m_v0VertexCollections = m_V0VertexCollections; + + m_caloHitCreatorSettings.m_eCalCaloHitCollections = m_ECalCaloHitCollections; + m_caloHitCreatorSettings.m_hCalCaloHitCollections = m_HCalCaloHitCollections; + m_caloHitCreatorSettings.m_lCalCaloHitCollections = m_LCalCaloHitCollections; + m_caloHitCreatorSettings.m_lHCalCaloHitCollections = m_LHCalCaloHitCollections; + m_caloHitCreatorSettings.m_muonCaloHitCollections = m_MuonCaloHitCollections; + m_mcParticleCreatorSettings.m_mcParticleCollections = m_MCParticleCollections; + m_mcParticleCreatorSettings.m_CaloHitRelationCollections = m_RelCaloHitCollections; + m_mcParticleCreatorSettings.m_TrackRelationCollections = m_RelTrackCollections; + + + // Absorber properties + m_geometryCreatorSettings.m_absorberRadLengthECal = m_AbsorberRadLengthECal; + m_geometryCreatorSettings.m_absorberIntLengthECal = m_AbsorberIntLengthECal; + m_geometryCreatorSettings.m_absorberRadLengthHCal = m_AbsorberRadLengthHCal; + m_geometryCreatorSettings.m_absorberIntLengthHCal = m_AbsorberIntLengthHCal; + m_geometryCreatorSettings.m_absorberRadLengthOther = m_AbsorberRadLengthOther; + m_geometryCreatorSettings.m_absorberIntLengthOther = m_AbsorberIntLengthOther; + + // Name of PFO collection written by GaudiPandora + + m_pfoCreatorSettings.m_clusterCollectionName = m_ClusterCollectionName;// not used + m_pfoCreatorSettings.m_pfoCollectionName = m_PFOCollectionName;// + m_pfoCreatorSettings.m_startVertexCollectionName = m_StartVertexCollectionName; // + m_pfoCreatorSettings.m_startVertexAlgName = m_StartVertexAlgorithmName;// + + m_pfoCreatorSettings.m_emStochasticTerm = m_EMStochasticTerm; + m_pfoCreatorSettings.m_hadStochasticTerm = m_HadStochasticTerm; + m_pfoCreatorSettings.m_emConstantTerm = m_EMConstantTerm; + m_pfoCreatorSettings.m_hadConstantTerm = m_HadConstantTerm; + + // Calibration constants + m_caloHitCreatorSettings.m_eCalToMip = m_ECalToMipCalibration; + m_caloHitCreatorSettings.m_hCalToMip = m_HCalToMipCalibration; + m_caloHitCreatorSettings.m_eCalMipThreshold = m_ECalMipThreshold; + m_caloHitCreatorSettings.m_muonToMip = m_MuonToMipCalibration; + m_caloHitCreatorSettings.m_hCalMipThreshold = m_HCalMipThreshold; + m_caloHitCreatorSettings.m_eCalToEMGeV = m_ECalToEMGeVCalibration; + m_caloHitCreatorSettings.m_hCalToEMGeV = m_HCalToEMGeVCalibration; + m_caloHitCreatorSettings.m_eCalToHadGeVEndCap = m_ECalToHadGeVCalibrationEndCap; + m_caloHitCreatorSettings.m_eCalToHadGeVBarrel = m_ECalToHadGeVCalibrationBarrel; + m_caloHitCreatorSettings.m_hCalToHadGeV = m_HCalToHadGeVCalibration; + m_caloHitCreatorSettings.m_muonDigitalHits = m_DigitalMuonHits; + m_caloHitCreatorSettings.m_muonHitEnergy = m_MuonHitEnergy; + m_caloHitCreatorSettings.m_maxHCalHitHadronicEnergy = m_MaxHCalHitHadronicEnergy; + m_caloHitCreatorSettings.m_nOuterSamplingLayers = m_NOuterSamplingLayers; + m_caloHitCreatorSettings.m_layersFromEdgeMaxRearDistance = m_LayersFromEdgeMaxRearDistance; + + // Track relationship parameters + m_trackCreatorSettings.m_shouldFormTrackRelationships = m_ShouldFormTrackRelationships; + // Initial track hit specifications + m_trackCreatorSettings.m_minTrackHits = m_MinTrackHits; + m_trackCreatorSettings.m_minFtdTrackHits = m_MinFtdTrackHits; + m_trackCreatorSettings.m_maxTrackHits = m_MaxTrackHits; + ////m_trackCreatorSettings.m_useOldTrackStateCalculation = m_UseOldTrackStateCalculation; + // Track PFO usage parameters + m_trackCreatorSettings.m_d0TrackCut = m_D0TrackCut; + m_trackCreatorSettings.m_z0TrackCut = m_Z0TrackCut; + m_trackCreatorSettings.m_usingNonVertexTracks = m_UseNonVertexTracks; + m_trackCreatorSettings.m_usingUnmatchedNonVertexTracks = m_UseUnmatchedNonVertexTracks; + m_trackCreatorSettings.m_usingUnmatchedVertexTracks = m_UseUnmatchedVertexTracks; + m_trackCreatorSettings.m_unmatchedVertexTrackMaxEnergy = m_UnmatchedVertexTrackMaxEnergy; + m_trackCreatorSettings.m_d0UnmatchedVertexTrackCut = m_D0UnmatchedVertexTrackCut; + m_trackCreatorSettings.m_z0UnmatchedVertexTrackCut = m_Z0UnmatchedVertexTrackCut; + m_trackCreatorSettings.m_zCutForNonVertexTracks = m_ZCutForNonVertexTracks; + // Track "reaches ecal" parameters + m_trackCreatorSettings.m_reachesECalNTpcHits = m_ReachesECalNTpcHits; + m_trackCreatorSettings.m_reachesECalNFtdHits = m_ReachesECalNFtdHits; + m_trackCreatorSettings.m_reachesECalTpcOuterDistance = m_ReachesECalTpcOuterDistance; + m_trackCreatorSettings.m_reachesECalMinFtdLayer = m_ReachesECalMinFtdLayer; + m_trackCreatorSettings.m_reachesECalTpcZMaxDistance = m_ReachesECalTpcZMaxDistance; + m_trackCreatorSettings.m_reachesECalFtdZMaxDistance = m_ReachesECalFtdZMaxDistance; + m_trackCreatorSettings.m_curvatureToMomentumFactor = m_CurvatureToMomentumFactor; + m_trackCreatorSettings.m_minTrackECalDistanceFromIp = m_MinTrackECalDistanceFromIp; + // Final track quality parameters + m_trackCreatorSettings.m_maxTrackSigmaPOverP = m_MaxTrackSigmaPOverP; + m_trackCreatorSettings.m_minMomentumForTrackHitChecks = m_MinMomentumForTrackHitChecks; + m_trackCreatorSettings.m_tpcMembraneMaxZ = m_TpcMembraneMaxZ; + m_trackCreatorSettings.m_minTpcHitFractionOfExpected = m_MinTpcHitFractionOfExpected; + m_trackCreatorSettings.m_minFtdHitsForTpcHitFraction = m_MinFtdHitsForTpcHitFraction; + m_trackCreatorSettings.m_maxTpcInnerRDistance = m_MaxTpcInnerRDistance; + + + // Additional geometry parameters + m_geometryCreatorSettings.m_eCalEndCapInnerSymmetryOrder = m_ECalEndCapInnerSymmetryOrder; + m_geometryCreatorSettings.m_eCalEndCapInnerPhiCoordinate = m_ECalEndCapInnerPhiCoordinate; + m_geometryCreatorSettings.m_eCalEndCapOuterSymmetryOrder = m_ECalEndCapOuterSymmetryOrder; + m_geometryCreatorSettings.m_eCalEndCapOuterPhiCoordinate = m_ECalEndCapOuterPhiCoordinate; + m_geometryCreatorSettings.m_hCalEndCapInnerSymmetryOrder = m_HCalEndCapInnerSymmetryOrder; + m_geometryCreatorSettings.m_hCalEndCapInnerPhiCoordinate = m_HCalEndCapInnerPhiCoordinate; + m_geometryCreatorSettings.m_hCalEndCapOuterSymmetryOrder = m_HCalEndCapOuterSymmetryOrder; + m_geometryCreatorSettings.m_hCalEndCapOuterPhiCoordinate = m_HCalEndCapOuterPhiCoordinate; + m_geometryCreatorSettings.m_hCalRingInnerSymmetryOrder = m_HCalRingInnerSymmetryOrder; + m_geometryCreatorSettings.m_hCalRingInnerPhiCoordinate = m_HCalRingInnerPhiCoordinate; + m_geometryCreatorSettings.m_hCalRingOuterSymmetryOrder = m_HCalRingOuterSymmetryOrder; + m_geometryCreatorSettings.m_hCalRingOuterPhiCoordinate = m_HCalRingOuterPhiCoordinate; + + // For Strip Splitting method and also for hybrid ECAL + m_caloHitCreatorSettings.m_stripSplittingOn = m_StripSplittingOn; + m_caloHitCreatorSettings.m_useEcalScLayers = m_UseEcalScLayers; + // Parameters for hybrid ECAL + // Energy to MIP for Si-layers and Sc-layers, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToMip = m_ECalSiToMipCalibration; + //Sc + m_caloHitCreatorSettings.m_eCalScToMip = m_ECalScToMipCalibration; + // MipThreshold for Si-layers and Sc-layers, respectively. + // Si + m_caloHitCreatorSettings.m_eCalSiMipThreshold = m_ECalSiMipThreshold; + //Sc + m_caloHitCreatorSettings.m_eCalScMipThreshold = m_ECalScMipThreshold; + // EcalToEM for Si-layers and Sc-layers, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToEMGeV = m_ECalSiToEMGeVCalibration; + //Sc + m_caloHitCreatorSettings.m_eCalScToEMGeV = m_ECalScToEMGeVCalibration; + // EcalToHad for Si-layers and Sc-layers of the endcaps, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToHadGeVEndCap = m_ECalSiToHadGeVCalibrationEndCap; + //Sc + m_caloHitCreatorSettings.m_eCalScToHadGeVEndCap = m_ECalScToHadGeVCalibrationEndCap; + // EcalToHad for Si-layers and Sc-layers of the barrel, respectively. + //Si + m_caloHitCreatorSettings.m_eCalSiToHadGeVBarrel = m_ECalSiToHadGeVCalibrationBarrel; + //Sc + m_caloHitCreatorSettings.m_eCalScToHadGeVBarrel = m_ECalScToHadGeVCalibrationBarrel; + + try + { + ISvcLocator* svcloc = serviceLocator(); + this->FinaliseSteeringParameters(svcloc); + m_pPandora = new pandora::Pandora(); + m_pMCParticleCreator = new MCParticleCreator(m_mcParticleCreatorSettings, m_pPandora); + m_pGeometryCreator = new GeometryCreator(m_geometryCreatorSettings, m_pPandora); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pGeometryCreator->CreateGeometry(svcloc)); + m_pCaloHitCreator = new CaloHitCreator(m_caloHitCreatorSettings, m_pPandora, svcloc, 0); + m_pTrackCreator = new TrackCreator(m_trackCreatorSettings, m_pPandora, svcloc); + m_pPfoCreator = new PfoCreator(m_pfoCreatorSettings, m_pPandora); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->RegisterUserComponents()); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::ReadSettings(*m_pPandora, m_settings.m_pandoraSettingsXmlFile)); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Failed to initialize gaudi pandora: " << statusCodeException.ToString() << std::endl; + throw statusCodeException; + } + catch (...) + { + std::cout << "Failed to initialize gaudi pandora: unrecognized exception" << std::endl; + throw; + } + + + return GaudiAlgorithm::initialize(); +} + +StatusCode PandoraMatrixAlg::execute() +{ + + try + { + std::cout<<"execute PandoraMatrixAlg"<<std::endl; + + updateMap(); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateMCParticles(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pCaloHitCreator->CreateCaloHits(*m_CollectionMaps)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateCaloHitToMCParticleRelationships(*m_CollectionMaps, m_pCaloHitCreator->GetCalorimeterHitVector() )); + //PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pTrackCreator->CreateTrackAssociations(*m_CollectionMaps)); + //PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pTrackCreator->CreateTracks(*m_CollectionMaps)); + //PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pMCParticleCreator->CreateTrackToMCParticleRelationships(*m_CollectionMaps, m_pTrackCreator->GetTrackVector() )); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::ProcessEvent(*m_pPandora)); + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, m_pPfoCreator->CreateParticleFlowObjects(*m_CollectionMaps, m_ClusterCollection_w, m_ReconstructedParticleCollection_w, m_VertexCollection_w)); + + StatusCode sc0 = CreateMCRecoParticleAssociation(); + StatusCode sc = Ana(); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Reset(*m_pPandora)); + this->Reset(); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout << "Gaudi pandora failed to process event: " << statusCodeException.ToString() << std::endl; + throw statusCodeException; + } + catch (...) + { + std::cout << "Gaudi pandora failed to process event: unrecognized exception" << std::endl; + throw; + } + + info() << "PandoraMatrixAlg Processed " << _nEvt << " events " << endmsg; + _nEvt ++ ; + + return StatusCode::SUCCESS; +} + +StatusCode PandoraMatrixAlg::finalize() +{ + info() << "Finalized. Processed " << _nEvt << " events " <<",saved tree with entries="<<m_tree->GetEntries()<< endmsg; + m_fout->cd(); + m_tree->Write(); + m_fout->Close(); + delete m_pPandora; + delete m_pGeometryCreator; + delete m_pCaloHitCreator; + delete m_pTrackCreator; + delete m_pMCParticleCreator; + delete m_pPfoCreator; + return GaudiAlgorithm::finalize(); +} + + + + +pandora::StatusCode PandoraMatrixAlg::RegisterUserComponents() const +{ + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterAlgorithms(*m_pPandora)); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterBasicPlugins(*m_pPandora)); + + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterBFieldPlugin(*m_pPandora, + m_settings.m_innerBField, m_settings.m_muonBarrelBField, m_settings.m_muonEndCapBField)); + + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, LCContent::RegisterNonLinearityEnergyCorrection(*m_pPandora, + "NonLinearity", pandora::HADRONIC, m_settings.m_inputEnergyCorrectionPoints, m_settings.m_outputEnergyCorrectionPoints)); + + + + return pandora::STATUS_CODE_SUCCESS; +} + + +void PandoraMatrixAlg::Reset() +{ + m_pCaloHitCreator->Reset(); + m_pTrackCreator->Reset(); + m_pMCParticleCreator->Reset(); + + std::vector<int>() .swap(m_pReco_PID ); + std::vector< std::vector<int> >() .swap(m_pReco_mc_id); + std::vector< std::vector<float> >().swap(m_pReco_mc_weight); + std::vector<float>().swap(m_pReco_mass); + std::vector<float>().swap(m_pReco_energy); + std::vector<float>().swap(m_pReco_px); + std::vector<float>().swap(m_pReco_py); + std::vector<float>().swap(m_pReco_pz); + std::vector<float>().swap(m_pReco_charge); + + std::vector<int>() .swap(m_mc_id); + std::vector<int>() .swap(m_mc_p_size); + std::vector<int>() .swap(m_mc_pid ); + std::vector<float>().swap(m_mc_mass ); + std::vector<float>().swap(m_mc_px ); + std::vector<float>().swap(m_mc_py ); + std::vector<float>().swap(m_mc_pz ); + std::vector<float>().swap(m_mc_charge); + + std::vector<float>() .swap(m_hits_x); + std::vector<float>() .swap(m_hits_y); + std::vector<float>() .swap(m_hits_z); + std::vector<float>() .swap(m_hits_E); + + m_hasConversion = 0; + + m_CollectionMaps->clear(); +} + +const pandora::Pandora *PandoraMatrixAlg::GetPandora() const +{ + if (NULL == m_pPandora) + throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + return m_pPandora; +} +PandoraMatrixAlg::Settings::Settings() : + m_innerBField(3.5f), + m_muonBarrelBField(-1.5f), + m_muonEndCapBField(0.01f) +{ +} +CollectionMaps::CollectionMaps() +{ +} +void CollectionMaps::clear() +{ +CollectionMap_MC.clear(); +CollectionMap_CaloHit.clear(); +CollectionMap_Vertex.clear(); +CollectionMap_Track.clear(); +collectionMap_MC.clear(); +collectionMap_CaloHit.clear(); +collectionMap_Vertex.clear(); +collectionMap_Track.clear(); +collectionMap_CaloRel.clear(); +collectionMap_TrkRel.clear(); +} + +StatusCode PandoraMatrixAlg::updateMap() +{ + const edm4hep::MCParticleCollection* MCParticle = nullptr; + const edm4hep::CalorimeterHitCollection* ECALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* ECALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* ECALOther = nullptr; + const edm4hep::CalorimeterHitCollection* HCALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* HCALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* HCALOther = nullptr; + const edm4hep::CalorimeterHitCollection* MUON = nullptr; + const edm4hep::CalorimeterHitCollection* LCAL = nullptr; + const edm4hep::CalorimeterHitCollection* LHCAL = nullptr; + const edm4hep::CalorimeterHitCollection* BCAL = nullptr; + const edm4hep::VertexCollection* KinkVertices = nullptr; + const edm4hep::VertexCollection* ProngVertices = nullptr; + const edm4hep::VertexCollection* SplitVertices = nullptr; + const edm4hep::VertexCollection* V0Vertices = nullptr; + const edm4hep::TrackCollection* MarlinTrkTracks = nullptr; + const edm4hep::MCRecoCaloAssociationCollection* mcRecoCaloAssociation = nullptr; + const edm4hep::MCRecoTrackerAssociationCollection* mcRecoTrackerAssociation = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + sc = getCol(m_ECALBarrel_r, ECALBarrel ); + sc = getCol(m_ECALEndcap_r, ECALEndcap ); + sc = getCol(m_ECALOther_r , ECALOther ); + sc = getCol(m_HCALBarrel_r, HCALBarrel ); + sc = getCol(m_HCALEndcap_r, HCALEndcap ); + sc = getCol(m_HCALOther_r , HCALOther ); + sc = getCol(m_MUON_r , MUON ); + sc = getCol(m_LCAL_r , LCAL ); + sc = getCol(m_LHCAL_r , LHCAL ); + sc = getCol(m_BCAL_r , BCAL ); + sc = getCol(m_KinkVertices_r , KinkVertices ); + sc = getCol(m_ProngVertices_r , ProngVertices); + sc = getCol(m_SplitVertices_r , SplitVertices); + sc = getCol(m_V0Vertices_r , V0Vertices ); + sc = getCol(m_MarlinTrkTracks_r , MarlinTrkTracks ); + sc = getCol(m_MCRecoCaloAssociation_r , mcRecoCaloAssociation ); + sc = getCol(m_MCRecoTrackerAssociation_r , mcRecoTrackerAssociation); + + if (NULL != MCParticle ) + { + std::vector<edm4hep::MCParticle> v_mc; + m_CollectionMaps->CollectionMap_MC ["MCParticle"] = MCParticle ; + m_CollectionMaps->collectionMap_MC ["MCParticle"] = v_mc; + for(unsigned int i=0 ; i< MCParticle->size(); i++) m_CollectionMaps->collectionMap_MC ["MCParticle"].push_back(MCParticle->at(i)); + } + if (NULL != ECALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALBarrel"] = ECALBarrel ; + m_CollectionMaps->collectionMap_CaloHit["ECALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< ECALBarrel->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALBarrel"].push_back(ECALBarrel->at(i)); + } + if (NULL != ECALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALEndcap"] = ECALEndcap ; + m_CollectionMaps->collectionMap_CaloHit["ECALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< ECALEndcap->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALEndcap"].push_back(ECALEndcap->at(i)); + } + if (NULL != ECALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["ECALOther"] = ECALOther ; + m_CollectionMaps->collectionMap_CaloHit["ECALOther"] = v_cal ; + for(unsigned int i=0 ; i< ECALOther->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["ECALOther"].push_back(ECALOther->at(i)); + } + if (NULL != HCALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALBarrel"] = HCALBarrel ; + m_CollectionMaps->collectionMap_CaloHit["HCALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< HCALBarrel->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALBarrel"].push_back(HCALBarrel->at(i)); + } + if (NULL != HCALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALEndcap"] = HCALEndcap ; + m_CollectionMaps->collectionMap_CaloHit["HCALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< HCALEndcap->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALEndcap"].push_back(HCALEndcap->at(i)); + } + if (NULL != HCALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["HCALOther"] = HCALOther ; + m_CollectionMaps->collectionMap_CaloHit["HCALOther"] = v_cal ; + for(unsigned int i=0 ; i< HCALOther->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["HCALOther"].push_back(HCALOther->at(i)); + } + if (NULL != MUON ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["MUON"] = MUON ; + m_CollectionMaps->collectionMap_CaloHit["MUON"] = v_cal ; + for(unsigned int i=0 ; i< MUON->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["MUON"].push_back(MUON->at(i)); + } + if (NULL != LCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["LCAL"] = LCAL ; + m_CollectionMaps->collectionMap_CaloHit["LCAL"] = v_cal ; + for(unsigned int i=0 ; i< LCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["LCAL"].push_back(LCAL->at(i)); + } + if (NULL != LHCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["LHCAL"] = LHCAL ; + m_CollectionMaps->collectionMap_CaloHit["LHCAL"] = v_cal ; + for(unsigned int i=0 ; i< LHCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["LHCAL"].push_back(LHCAL->at(i)); + } + if (NULL != BCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + m_CollectionMaps->CollectionMap_CaloHit["BCAL"] = BCAL ; + m_CollectionMaps->collectionMap_CaloHit["BCAL"] = v_cal ; + for(unsigned int i=0 ; i< BCAL->size(); i++) m_CollectionMaps->collectionMap_CaloHit ["BCAL"].push_back(BCAL->at(i)); + } + if (NULL != KinkVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["KinkVertices"] = KinkVertices ; + m_CollectionMaps->collectionMap_Vertex["KinkVertices"] = v_cal ; + for(unsigned int i=0 ; i< KinkVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["KinkVertices"].push_back(KinkVertices->at(i)); + } + if (NULL != ProngVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["ProngVertices"] = ProngVertices ; + m_CollectionMaps->collectionMap_Vertex["ProngVertices"] = v_cal ; + for(unsigned int i=0 ; i< ProngVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["ProngVertices"].push_back(ProngVertices->at(i)); + } + if (NULL != SplitVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["SplitVertices"] = SplitVertices ; + m_CollectionMaps->collectionMap_Vertex["SplitVertices"] = v_cal ; + for(unsigned int i=0 ; i< SplitVertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["SplitVertices"].push_back(SplitVertices->at(i)); + } + if (NULL != V0Vertices ) + { + std::vector<edm4hep::Vertex> v_cal; + m_CollectionMaps->CollectionMap_Vertex["V0Vertices"] = V0Vertices ; + m_CollectionMaps->collectionMap_Vertex["V0Vertices"] = v_cal ; + for(unsigned int i=0 ; i< V0Vertices->size(); i++) m_CollectionMaps->collectionMap_Vertex ["V0Vertices"].push_back(V0Vertices->at(i)); + } + if (NULL != MarlinTrkTracks ) + { + std::vector<edm4hep::Track> v_cal; + m_CollectionMaps->CollectionMap_Track["MarlinTrkTracks"] = MarlinTrkTracks ; + m_CollectionMaps->collectionMap_Track["MarlinTrkTracks"] = v_cal ; + for(unsigned int i=0 ; i< MarlinTrkTracks->size(); i++) m_CollectionMaps->collectionMap_Track ["MarlinTrkTracks"].push_back(MarlinTrkTracks->at(i)); + } + if (NULL != mcRecoCaloAssociation ) + { + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + m_CollectionMaps->collectionMap_CaloRel["RecoCaloAssociation_ECALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoCaloAssociation->size(); i++) m_CollectionMaps->collectionMap_CaloRel ["RecoCaloAssociation_ECALBarrel"].push_back(mcRecoCaloAssociation->at(i)); + } + + else + { + if (NULL != MCParticle ) + { + for(unsigned int i=0 ; i< MCParticle->size(); i++) + { + if(MCParticle->at(i).parents_size()==0) + { + std::cout<<"create recoCaloAssociation by hand now"<<std::endl; + for(std::map<std::string, std::vector<edm4hep::CalorimeterHit> >::iterator iter = m_CollectionMaps->collectionMap_CaloHit.begin(); iter != m_CollectionMaps->collectionMap_CaloHit.end(); iter++) + { + std::string prefix = "RecoCaloAssociation_"; + std::string key = prefix + iter->first; + std::cout<<"create for "<<key<<std::endl; + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + m_CollectionMaps->collectionMap_CaloRel[key] = v_cal ; + for(std::vector<edm4hep::CalorimeterHit>::iterator it=iter->second.begin(); it != iter->second.end(); it ++) + { + edm4hep::SimCalorimeterHit sim_hit( it->getCellID(), it->getEnergy(), it->getPosition() ); + edm4hep::CaloHitContribution conb ( MCParticle->at(i).getPDG(), it->getEnergy(), 0, it->getPosition() ); + conb.setParticle( MCParticle->at(i) ); + sim_hit.addToContributions(conb); + edm4hep::MCRecoCaloAssociation calo_association; + calo_association.setRec(*it); + calo_association.setSim(sim_hit); + m_CollectionMaps->collectionMap_CaloRel[key].push_back(calo_association); + } + } + break; + } + } + } + } + + if (NULL != mcRecoTrackerAssociation ) + { + std::vector<edm4hep::MCRecoTrackerAssociation> v_cal; + m_CollectionMaps->collectionMap_TrkRel["RecoTrackerAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoTrackerAssociation->size(); i++) m_CollectionMaps->collectionMap_TrkRel ["RecoTrackerAssociation"].push_back(mcRecoTrackerAssociation->at(i)); + } + return StatusCode::SUCCESS; +} + + +StatusCode PandoraMatrixAlg::updateMap(CollectionMaps & tmp_map) +{ + const edm4hep::MCParticleCollection* MCParticle = nullptr; + const edm4hep::CalorimeterHitCollection* ECALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* ECALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* ECALOther = nullptr; + const edm4hep::CalorimeterHitCollection* HCALBarrel = nullptr; + const edm4hep::CalorimeterHitCollection* HCALEndcap = nullptr; + const edm4hep::CalorimeterHitCollection* HCALOther = nullptr; + const edm4hep::CalorimeterHitCollection* MUON = nullptr; + const edm4hep::CalorimeterHitCollection* LCAL = nullptr; + const edm4hep::CalorimeterHitCollection* LHCAL = nullptr; + const edm4hep::CalorimeterHitCollection* BCAL = nullptr; + const edm4hep::VertexCollection* KinkVertices = nullptr; + const edm4hep::VertexCollection* ProngVertices = nullptr; + const edm4hep::VertexCollection* SplitVertices = nullptr; + const edm4hep::VertexCollection* V0Vertices = nullptr; + const edm4hep::TrackCollection* MarlinTrkTracks = nullptr; + const edm4hep::MCRecoCaloAssociationCollection* mcRecoCaloAssociation = nullptr; + const edm4hep::MCRecoTrackerAssociationCollection* mcRecoTrackerAssociation = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + sc = getCol(m_ECALBarrel_r, ECALBarrel ); + sc = getCol(m_ECALEndcap_r, ECALEndcap ); + sc = getCol(m_ECALOther_r , ECALOther ); + sc = getCol(m_HCALBarrel_r, HCALBarrel ); + sc = getCol(m_HCALEndcap_r, HCALEndcap ); + sc = getCol(m_HCALOther_r , HCALOther ); + sc = getCol(m_MUON_r , MUON ); + sc = getCol(m_LCAL_r , LCAL ); + sc = getCol(m_LHCAL_r , LHCAL ); + sc = getCol(m_BCAL_r , BCAL ); + sc = getCol(m_KinkVertices_r , KinkVertices ); + sc = getCol(m_ProngVertices_r , ProngVertices); + sc = getCol(m_SplitVertices_r , SplitVertices); + sc = getCol(m_V0Vertices_r , V0Vertices ); + sc = getCol(m_MarlinTrkTracks_r , MarlinTrkTracks ); + sc = getCol(m_MCRecoCaloAssociation_r , mcRecoCaloAssociation ); + sc = getCol(m_MCRecoTrackerAssociation_r , mcRecoTrackerAssociation ); + + if (NULL != MCParticle ) + { + std::vector<edm4hep::MCParticle> v_mc; + tmp_map.CollectionMap_MC ["MCParticle"] = MCParticle ; + tmp_map.collectionMap_MC ["MCParticle"] = v_mc; + for(unsigned int i=0 ; i< MCParticle->size(); i++) tmp_map.collectionMap_MC ["MCParticle"].push_back(MCParticle->at(i)); + } + if (NULL != ECALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALBarrel"] = ECALBarrel ; + tmp_map.collectionMap_CaloHit["ECALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< ECALBarrel->size(); i++) tmp_map.collectionMap_CaloHit ["ECALBarrel"].push_back(ECALBarrel->at(i)); + } + if (NULL != ECALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALEndcap"] = ECALEndcap ; + tmp_map.collectionMap_CaloHit["ECALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< ECALEndcap->size(); i++) tmp_map.collectionMap_CaloHit ["ECALEndcap"].push_back(ECALEndcap->at(i)); + } + if (NULL != ECALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["ECALOther"] = ECALOther ; + tmp_map.collectionMap_CaloHit["ECALOther"] = v_cal ; + for(unsigned int i=0 ; i< ECALOther->size(); i++) tmp_map.collectionMap_CaloHit ["ECALOther"].push_back(ECALOther->at(i)); + } + if (NULL != HCALBarrel ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALBarrel"] = HCALBarrel ; + tmp_map.collectionMap_CaloHit["HCALBarrel"] = v_cal ; + for(unsigned int i=0 ; i< HCALBarrel->size(); i++) tmp_map.collectionMap_CaloHit ["HCALBarrel"].push_back(HCALBarrel->at(i)); + } + if (NULL != HCALEndcap ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALEndcap"] = HCALEndcap ; + tmp_map.collectionMap_CaloHit["HCALEndcap"] = v_cal ; + for(unsigned int i=0 ; i< HCALEndcap->size(); i++) tmp_map.collectionMap_CaloHit ["HCALEndcap"].push_back(HCALEndcap->at(i)); + } + if (NULL != HCALOther ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["HCALOther"] = HCALOther ; + tmp_map.collectionMap_CaloHit["HCALOther"] = v_cal ; + for(unsigned int i=0 ; i< HCALOther->size(); i++) tmp_map.collectionMap_CaloHit ["HCALOther"].push_back(HCALOther->at(i)); + } + if (NULL != MUON ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["MUON"] = MUON ; + tmp_map.collectionMap_CaloHit["MUON"] = v_cal ; + for(unsigned int i=0 ; i< MUON->size(); i++) tmp_map.collectionMap_CaloHit ["MUON"].push_back(MUON->at(i)); + } + if (NULL != LCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["LCAL"] = LCAL ; + tmp_map.collectionMap_CaloHit["LCAL"] = v_cal ; + for(unsigned int i=0 ; i< LCAL->size(); i++) tmp_map.collectionMap_CaloHit ["LCAL"].push_back(LCAL->at(i)); + } + if (NULL != LHCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["LHCAL"] = LHCAL ; + tmp_map.collectionMap_CaloHit["LHCAL"] = v_cal ; + for(unsigned int i=0 ; i< LHCAL->size(); i++) tmp_map.collectionMap_CaloHit ["LHCAL"].push_back(LHCAL->at(i)); + } + if (NULL != BCAL ) + { + std::vector<edm4hep::CalorimeterHit> v_cal; + tmp_map.CollectionMap_CaloHit["BCAL"] = BCAL ; + tmp_map.collectionMap_CaloHit["BCAL"] = v_cal ; + for(unsigned int i=0 ; i< BCAL->size(); i++) tmp_map.collectionMap_CaloHit ["BCAL"].push_back(BCAL->at(i)); + } + if (NULL != KinkVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["KinkVertices"] = KinkVertices ; + tmp_map.collectionMap_Vertex["KinkVertices"] = v_cal ; + for(unsigned int i=0 ; i< KinkVertices->size(); i++) tmp_map.collectionMap_Vertex ["KinkVertices"].push_back(KinkVertices->at(i)); + } + if (NULL != ProngVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["ProngVertices"] = ProngVertices ; + tmp_map.collectionMap_Vertex["ProngVertices"] = v_cal ; + for(unsigned int i=0 ; i< ProngVertices->size(); i++) tmp_map.collectionMap_Vertex ["ProngVertices"].push_back(ProngVertices->at(i)); + } + if (NULL != SplitVertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["SplitVertices"] = SplitVertices ; + tmp_map.collectionMap_Vertex["SplitVertices"] = v_cal ; + for(unsigned int i=0 ; i< SplitVertices->size(); i++) tmp_map.collectionMap_Vertex ["SplitVertices"].push_back(SplitVertices->at(i)); + } + if (NULL != V0Vertices ) + { + std::vector<edm4hep::Vertex> v_cal; + tmp_map.CollectionMap_Vertex["V0Vertices"] = V0Vertices ; + tmp_map.collectionMap_Vertex["V0Vertices"] = v_cal ; + for(unsigned int i=0 ; i< V0Vertices->size(); i++) tmp_map.collectionMap_Vertex ["V0Vertices"].push_back(V0Vertices->at(i)); + } + if (NULL != MarlinTrkTracks ) + { + std::vector<edm4hep::Track> v_cal; + tmp_map.CollectionMap_Track["MarlinTrkTracks"] = MarlinTrkTracks ; + tmp_map.collectionMap_Track["MarlinTrkTracks"] = v_cal ; + for(unsigned int i=0 ; i< MarlinTrkTracks->size(); i++) tmp_map.collectionMap_Track ["MarlinTrkTracks"].push_back(MarlinTrkTracks->at(i)); + } + if (NULL != mcRecoCaloAssociation ) + { + std::vector<edm4hep::MCRecoCaloAssociation> v_cal; + tmp_map.collectionMap_CaloRel["RecoCaloAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoCaloAssociation->size(); i++) tmp_map.collectionMap_CaloRel ["RecoCaloAssociation"].push_back(mcRecoCaloAssociation->at(i)); + } + if (NULL != mcRecoTrackerAssociation ) + { + std::vector<edm4hep::MCRecoTrackerAssociation> v_cal; + tmp_map.collectionMap_TrkRel["RecoTrackerAssociation"] = v_cal ; + for(unsigned int i=0 ; i< mcRecoTrackerAssociation->size(); i++) tmp_map.collectionMap_TrkRel ["RecoTrackerAssociation"].push_back(mcRecoTrackerAssociation->at(i)); + } + return StatusCode::SUCCESS; +} + + +StatusCode PandoraMatrixAlg::Ana() +{ + int n_current = m_tree->GetEntries()+1; + const edm4hep::ReconstructedParticleCollection* reco_col = m_ReconstructedParticleCollection_w.get(); + const edm4hep::MCRecoParticleAssociationCollection* reco_associa_col = m_MCRecoParticleAssociation_w.get(); + std::cout<<"reco_col size="<<reco_col->size()<<std::endl; + for(int i=0; i<reco_col->size();i++) + { + std::cout<<"reco="<<i<<std::endl; + const edm4hep::ReconstructedParticle pReco = reco_col->at(i); + const float px = pReco.getMomentum()[0]; + const float py = pReco.getMomentum()[1]; + const float pz = pReco.getMomentum()[2]; + const float energy = pReco.getEnergy(); + const float mass = pReco.getMass(); + const float charge = pReco.getCharge(); + const int type = pReco.getType(); + std::cout<<"MYDBUG evt="<<n_current<<",rec i="<<i<<",particleId="<<type<<",mass="<<mass<<",charge="<<charge<<",energy="<<energy<<",px="<<px<<",py="<<py<<",pz="<<pz<<std::endl; + m_pReco_PID.push_back(type); + m_pReco_mass.push_back(mass); + m_pReco_charge.push_back(charge); + m_pReco_energy.push_back(energy); + m_pReco_px.push_back(px); + m_pReco_py.push_back(py); + m_pReco_pz.push_back(pz); + std::vector<int> tmp_mc_id; + std::vector<float> tmp_mc_weight; + for(int j=0; j < reco_associa_col->size(); j++) + { + if(reco_associa_col->at(j).getRec().id() != pReco.id() ) continue; + std::cout<<"MC pid ="<<reco_associa_col->at(j).getSim().getPDG()<<",weight="<<reco_associa_col->at(j).getWeight()<<", px="<<reco_associa_col->at(j).getSim().getMomentum()[0]<<", py="<<reco_associa_col->at(j).getSim().getMomentum()[1]<<",pz="<<reco_associa_col->at(j).getSim().getMomentum()[2]<<std::endl; + tmp_mc_id .push_back(reco_associa_col->at(j).getSim().id()); + tmp_mc_weight.push_back(reco_associa_col->at(j).getWeight()); + } + m_pReco_mc_id .push_back(tmp_mc_id); + m_pReco_mc_weight.push_back(tmp_mc_weight); + } + const edm4hep::MCParticleCollection* MCParticle = nullptr; + StatusCode sc = StatusCode::SUCCESS; + sc = getCol(m_mcParCol_r , MCParticle ); + if (NULL != MCParticle ) + { + for(unsigned int i=0 ; i< MCParticle->size(); i++) + { + m_mc_id .push_back(MCParticle->at(i).id()); + m_mc_p_size.push_back(MCParticle->at(i).parents_size()); + m_mc_pid .push_back(MCParticle->at(i).getPDG()); + m_mc_mass .push_back(MCParticle->at(i).getMass()); + m_mc_px .push_back(MCParticle->at(i).getMomentum()[0]); + m_mc_py .push_back(MCParticle->at(i).getMomentum()[1]); + m_mc_pz .push_back(MCParticle->at(i).getMomentum()[2]); + m_mc_charge.push_back(MCParticle->at(i).getCharge()); + //for(unsigned int j =0 ; j< MCParticle->at(i).daughters_size(); j++) da_pids.push_back( MCParticle->at(i).getDaughters(j).getPDG()); + if(MCParticle->at(i).parents_size()==0) std::cout<<"MYDBUG evt="<<n_current<<", mc i="<<i<<",px="<<MCParticle->at(i).getMomentum()[0]<<",py="<<MCParticle->at(i).getMomentum()[1]<<",pz="<<MCParticle->at(i).getMomentum()[2]<<std::endl; + if (MCParticle->at(i).getPDG() != 22) continue; + int hasEm = 0; + int hasEp = 0; + for(unsigned int j =0 ; j< MCParticle->at(i).daughters_size(); j++) + { + if (MCParticle->at(i).getDaughters(j).getPDG() == 11 ) hasEm=1; + else if (MCParticle->at(i).getDaughters(j).getPDG() == -11 ) hasEp=1; + } + if(hasEm && hasEp) m_hasConversion=1; + } + } + //sanity check calo info + const edm4hep::CalorimeterHitCollection* CaloCol = nullptr; + sc = getCol(m_ECALBarrel_r, CaloCol); + if (NULL != CaloCol ) + { + for(unsigned int i=0 ; i< CaloCol->size(); i++) + { + m_hits_x.push_back(CaloCol->at(i).getPosition()[0]); + m_hits_y.push_back(CaloCol->at(i).getPosition()[1]); + m_hits_z.push_back(CaloCol->at(i).getPosition()[2]); + m_hits_E.push_back(CaloCol->at(i).getEnergy() ); + } + } + + m_tree->Fill(); + return StatusCode::SUCCESS; +} + +// create simple MCRecoParticleAssociation using calorimeter hit only +StatusCode PandoraMatrixAlg::CreateMCRecoParticleAssociation() +{ + edm4hep::MCRecoParticleAssociationCollection* pMCRecoParticleAssociationCollection = m_MCRecoParticleAssociation_w.createAndPut(); + const edm4hep::ReconstructedParticleCollection* reco_col = m_ReconstructedParticleCollection_w.get(); + std::cout<<"CreateMCRecoParticleAssociation, reco_col size="<<reco_col->size()<<std::endl; + for(int i=0; i<reco_col->size();i++) + { + std::map<int, edm4hep::ConstMCParticle> mc_map; + std::map<int, float > id_edep_map; + float tot_en = 0 ; + const edm4hep::ReconstructedParticle pReco = reco_col->at(i); + for(int j=0; j < pReco.clusters_size(); j++) + { + edm4hep::ConstCluster cluster = pReco.getClusters(j); + for(int k=0; k < cluster.hits_size(); k++) + { + edm4hep::ConstCalorimeterHit hit = cluster.getHits(k); + for(std::map<std::string, std::vector<edm4hep::MCRecoCaloAssociation> >::iterator iter = m_CollectionMaps->collectionMap_CaloRel.begin(); iter != m_CollectionMaps->collectionMap_CaloRel.end(); iter++) + { + for(std::vector<edm4hep::MCRecoCaloAssociation>::iterator it = iter->second.begin(); it != iter->second.end(); it ++) + { + if(it->getRec().id() != hit.id()) continue; + for(std::vector<edm4hep::ConstCaloHitContribution>::const_iterator itc = it->getSim().contributions_begin(); itc != it->getSim().contributions_end(); itc++) + { + if(mc_map.find(itc->getParticle().id()) == mc_map.end()) mc_map[itc->getParticle().id()] = itc->getParticle() ; + if(id_edep_map.find(itc->getParticle().id()) != id_edep_map.end()) id_edep_map[itc->getParticle().id()] = id_edep_map[itc->getParticle().id()] + itc->getEnergy() ; + else id_edep_map[itc->getParticle().id()] = itc->getEnergy() ; + tot_en += itc->getEnergy() ; + } + } + } + } + } + for(std::map<int, edm4hep::ConstMCParticle>::iterator it = mc_map.begin(); it != mc_map.end(); it ++) + { + edm4hep::MCRecoParticleAssociation association = pMCRecoParticleAssociationCollection->create(); + association.setRec(pReco); + association.setSim(it->second); + if(tot_en==0) + { + association.setWeight(0); + std::cout<<"Found 0 cluster energy"<<std::endl; + } + else if(id_edep_map.find(it->first) != id_edep_map.end()) association.setWeight(id_edep_map[it->first]/tot_en); + else std::cout<<"Error in creating MCRecoParticleAssociation"<<std::endl; + } + } + return StatusCode::SUCCESS; +} + diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/PfoCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/PfoCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b197f2dbb907b3c98597c5e7acf9b700208b155e --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/PfoCreator.cpp @@ -0,0 +1,429 @@ +/** + * @file MarlinPandora/src/PfoCreator.cc + * + * @brief Implementation of the pfo creator class. + * + * $Log: $ + */ + +//#include "CalorimeterHitType.h" + +#include "Api/PandoraApi.h" + +#include "Objects/Cluster.h" +#include "Objects/ParticleFlowObject.h" +#include "Objects/Track.h" + +#include "Pandora/PdgTable.h" +#include "PfoCreator.h" +#include "PandoraMatrixAlg.h" + +#include <algorithm> +#include <cmath> + +PfoCreator::PfoCreator(const Settings &settings, const pandora::Pandora *const pPandora) : + m_settings(settings), + m_pPandora(pPandora) +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PfoCreator::~PfoCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode PfoCreator::CreateParticleFlowObjects(CollectionMaps& collectionMaps, DataHandle<edm4hep::ClusterCollection>& _pClusterCollection, DataHandle<edm4hep::ReconstructedParticleCollection>& _pReconstructedParticleCollection, DataHandle<edm4hep::VertexCollection>& _pStartVertexCollection) +{ + m_collectionMaps = &collectionMaps; + edm4hep::ClusterCollection* pClusterCollection = _pClusterCollection.createAndPut(); + edm4hep::ReconstructedParticleCollection* pReconstructedParticleCollection = _pReconstructedParticleCollection.createAndPut(); + edm4hep::VertexCollection* pStartVertexCollection = _pStartVertexCollection.createAndPut(); + + const pandora::PfoList *pPandoraPfoList = NULL; + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*m_pPandora, pPandoraPfoList)); + + + //IMPL::LCFlagImpl lcFlagImpl(pClusterCollection->getFlag()); + //lcFlagImpl.setBit(LCIO::CLBIT_HITS); + //pClusterCollection->setFlag(lcFlagImpl.getFlag()); + + pandora::StringVector subDetectorNames; + this->InitialiseSubDetectorNames(subDetectorNames); + //pClusterCollection->parameters().setValues("ClusterSubdetectorNames", subDetectorNames); + + // Create lcio "reconstructed particles" from the pandora "particle flow objects" + std::cout<<"pPandoraPfoList size="<<pPandoraPfoList->size()<<std::endl; + for (pandora::PfoList::const_iterator pIter = pPandoraPfoList->begin(), pIterEnd = pPandoraPfoList->end(); pIter != pIterEnd; ++pIter) + { + const pandora::ParticleFlowObject *const pPandoraPfo(*pIter); + //IMPL::ReconstructedParticleImpl *const pReconstructedParticle(new ReconstructedParticleImpl()); + edm4hep::ReconstructedParticle pReconstructedParticle0 = pReconstructedParticleCollection->create(); + edm4hep::ReconstructedParticle* pReconstructedParticle = &pReconstructedParticle0; + + const bool hasTrack(!pPandoraPfo->GetTrackList().empty()); + const pandora::ClusterList &clusterList(pPandoraPfo->GetClusterList()); + + //std::cout<<"ClusterList size="<<clusterList.size()<<std::endl; + float clustersTotalEnergy(0.f); + pandora::CartesianVector referencePoint(0.f, 0.f, 0.f), clustersWeightedPosition(0.f, 0.f, 0.f); + for (pandora::ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter) + { + const pandora::Cluster *const pPandoraCluster(*cIter); + pandora::CaloHitList pandoraCaloHitList; + pPandoraCluster->GetOrderedCaloHitList().FillCaloHitList(pandoraCaloHitList); + pandoraCaloHitList.insert(pandoraCaloHitList.end(), pPandoraCluster->GetIsolatedCaloHitList().begin(), pPandoraCluster->GetIsolatedCaloHitList().end()); + + pandora::FloatVector hitE, hitX, hitY, hitZ; + //IMPL::ClusterImpl *const p_Cluster(new ClusterImpl()); + edm4hep::Cluster p_Cluster0 = pClusterCollection->create(); + edm4hep::Cluster* p_Cluster = &p_Cluster0; + this->SetClusterSubDetectorEnergies(subDetectorNames, p_Cluster, pandoraCaloHitList, hitE, hitX, hitY, hitZ); + + float clusterCorrectEnergy(0.f); + this->SetClusterEnergyAndError(pPandoraPfo, pPandoraCluster, p_Cluster, clusterCorrectEnergy); + + pandora::CartesianVector clusterPosition(0.f, 0.f, 0.f); + const unsigned int nHitsInCluster(pandoraCaloHitList.size()); + this->SetClusterPositionAndError(nHitsInCluster, hitE, hitX, hitY, hitZ, p_Cluster, clusterPosition); + + if (!hasTrack) + { + clustersWeightedPosition += clusterPosition * clusterCorrectEnergy; + clustersTotalEnergy += clusterCorrectEnergy; + } + + //pClusterCollection->addElement(p_Cluster); + edm4hep::ConstCluster p_ClusterCon = *p_Cluster; + pReconstructedParticle->addToClusters(p_ClusterCon); + } + + if (!hasTrack) + { + if (clustersTotalEnergy < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING PfoCreator::CreateParticleFlowObjects: invalid cluster energy " << clustersTotalEnergy << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = clustersWeightedPosition * (1.f / clustersTotalEnergy); + } + } + else + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->CalculateTrackBasedReferencePoint(pPandoraPfo, referencePoint)); + } + + this->SetRecoParticleReferencePoint(referencePoint, pReconstructedParticle); + this->AddTracksToRecoParticle(pPandoraPfo, pReconstructedParticle); + this->SetRecoParticlePropertiesFromPFO(pPandoraPfo, pReconstructedParticle); + + edm4hep::Vertex pStartVertex0 = pStartVertexCollection->create(); + edm4hep::Vertex* pStartVertex = &pStartVertex0; + //pStartVertex->setAlgorithmType(m_settings.m_startVertexAlgName.c_str()); + pStartVertex->setAlgorithmType(0); + const float ref_value[3] = {referencePoint.GetX(),referencePoint.GetY(),referencePoint.GetZ()}; + pStartVertex->setPosition(edm4hep::Vector3f(ref_value)); + pStartVertex->setAssociatedParticle(*pReconstructedParticle); + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::InitialiseSubDetectorNames(pandora::StringVector &subDetectorNames) const +{ + subDetectorNames.push_back("ecal"); + subDetectorNames.push_back("hcal"); + subDetectorNames.push_back("yoke"); + subDetectorNames.push_back("lcal"); + subDetectorNames.push_back("lhcal"); + subDetectorNames.push_back("bcal"); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterSubDetectorEnergies(const pandora::StringVector &subDetectorNames, edm4hep::Cluster *const p_Cluster, + const pandora::CaloHitList &pandoraCaloHitList, pandora::FloatVector &hitE, pandora::FloatVector &hitX, pandora::FloatVector &hitY, + pandora::FloatVector &hitZ) const +{ + for (pandora::CaloHitList::const_iterator hIter = pandoraCaloHitList.begin(), hIterEnd = pandoraCaloHitList.end(); hIter != hIterEnd; ++hIter) + { + const pandora::CaloHit *const pPandoraCaloHit(*hIter); + edm4hep::CalorimeterHit *const pCalorimeterHit0 = (edm4hep::CalorimeterHit*)(pPandoraCaloHit->GetParentAddress()); + const edm4hep::CalorimeterHit pCalorimeterHit = *pCalorimeterHit0; + + p_Cluster->addToHits(pCalorimeterHit); + + const float caloHitEnergy(pCalorimeterHit.getEnergy()); + hitE.push_back(caloHitEnergy); + hitX.push_back(pCalorimeterHit.getPosition()[0]); + hitY.push_back(pCalorimeterHit.getPosition()[1]); + hitZ.push_back(pCalorimeterHit.getPosition()[2]); + /* + std::vector<float> &subDetectorEnergies = p_Cluster->subdetectorEnergies(); + subDetectorEnergies.resize(subDetectorNames.size()); + + switch (CHT(pCalorimeterHit->getType()).caloID()) + { + case CHT::ecal: subDetectorEnergies[ECAL_INDEX ] += caloHitEnergy; break; + case CHT::hcal: subDetectorEnergies[HCAL_INDEX ] += caloHitEnergy; break; + case CHT::yoke: subDetectorEnergies[YOKE_INDEX ] += caloHitEnergy; break; + case CHT::lcal: subDetectorEnergies[LCAL_INDEX ] += caloHitEnergy; break; + case CHT::lhcal: subDetectorEnergies[LHCAL_INDEX] += caloHitEnergy; break; + case CHT::bcal: subDetectorEnergies[BCAL_INDEX ] += caloHitEnergy; break; + default: streamlog_out(WARNING) << "PfoCreator::SetClusterSubDetectorEnergies: no subdetector found for hit with type: " << pCalorimeterHit->getType() << std::endl; + } + */ + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterEnergyAndError(const pandora::ParticleFlowObject *const pPandoraPfo, const pandora::Cluster *const pPandoraCluster, + edm4hep::Cluster *const p_Cluster, float &clusterCorrectEnergy) const +{ + const bool isEmShower((pandora::PHOTON == pPandoraPfo->GetParticleId()) || (pandora::E_MINUS == std::abs(pPandoraPfo->GetParticleId()))); + clusterCorrectEnergy = (isEmShower ? pPandoraCluster->GetCorrectedElectromagneticEnergy(*m_pPandora) : pPandoraCluster->GetCorrectedHadronicEnergy(*m_pPandora)); + + if (clusterCorrectEnergy < std::numeric_limits<float>::epsilon()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + + const float stochasticTerm(isEmShower ? m_settings.m_emStochasticTerm : m_settings.m_hadStochasticTerm); + const float constantTerm(isEmShower ? m_settings.m_emConstantTerm : m_settings.m_hadConstantTerm); + const float energyError(std::sqrt(stochasticTerm * stochasticTerm / clusterCorrectEnergy + constantTerm * constantTerm) * clusterCorrectEnergy); + + p_Cluster->setEnergy(clusterCorrectEnergy); + p_Cluster->setEnergyError(energyError); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetClusterPositionAndError(const unsigned int nHitsInCluster, pandora::FloatVector &hitE, pandora::FloatVector &hitX, + pandora::FloatVector &hitY, pandora::FloatVector &hitZ, edm4hep::Cluster *const p_Cluster, pandora::CartesianVector &clusterPositionVec) const +{ + ClusterShapes *const pClusterShapes(new ClusterShapes(nHitsInCluster, hitE.data(), hitX.data(), hitY.data(), hitZ.data())); + + try + { + p_Cluster->setPhi(std::atan2(pClusterShapes->getEigenVecInertia()[1], pClusterShapes->getEigenVecInertia()[0])); + p_Cluster->setITheta(std::acos(pClusterShapes->getEigenVecInertia()[2])); + p_Cluster->setPosition(pClusterShapes->getCentreOfGravity()); + //ATTN these two lines below would only compile with ilcsoft HEAD V2015-10-13 and above + //p_Cluster->setPositionError(pClusterShapes->getCenterOfGravityErrors()); + //p_Cluster->setDirectionError(pClusterShapes->getEigenVecInertiaErrors()); + clusterPositionVec.SetValues(pClusterShapes->getCentreOfGravity()[0], pClusterShapes->getCentreOfGravity()[1], pClusterShapes->getCentreOfGravity()[2]); + } + catch (...) + { + std::cout<<"WARNING PfoCreator::SetClusterPositionAndError: unidentified exception caught." << std::endl; + } + + delete pClusterShapes; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode PfoCreator::CalculateTrackBasedReferencePoint(const pandora::ParticleFlowObject *const pPandoraPfo, pandora::CartesianVector &referencePoint) const +{ + const pandora::TrackList &trackList(pPandoraPfo->GetTrackList()); + + float totalTrackMomentumAtDca(0.f), totalTrackMomentumAtStart(0.f); + pandora::CartesianVector referencePointAtDCAWeighted(0.f, 0.f, 0.f), referencePointAtStartWeighted(0.f, 0.f, 0.f); + + bool hasSiblings(false); + for (pandora::TrackList::const_iterator tIter = trackList.begin(), tIterEnd = trackList.end(); tIter != tIterEnd; ++tIter) + { + const pandora::Track *const pPandoraTrack(*tIter); + + if (!this->IsValidParentTrack(pPandoraTrack, trackList)) + continue; + + if (this->HasValidSiblingTrack(pPandoraTrack, trackList)) + { + // Presence of sibling tracks typically represents a conversion + const pandora::CartesianVector &trackStartPoint((pPandoraTrack->GetTrackStateAtStart()).GetPosition()); + const float trackStartMomentum(((pPandoraTrack->GetTrackStateAtStart()).GetMomentum()).GetMagnitude()); + referencePointAtStartWeighted += trackStartPoint * trackStartMomentum; + totalTrackMomentumAtStart += trackStartMomentum; + hasSiblings = true; + } + else + { + const edm4hep::Track *const pLcioTrack0 = (edm4hep::Track*)(pPandoraTrack->GetParentAddress()); + const edm4hep::Track pLcioTrack = *pLcioTrack0; + + const float z0(pPandoraTrack->GetZ0()); + pandora::CartesianVector intersectionPoint(0.f, 0.f, 0.f); + + //intersectionPoint.SetValues(pLcioTrack->getD0() * std::cos(pLcioTrack->getPhi()), pLcioTrack->getD0() * std::sin(pLcioTrack->getPhi()), z0); + if(pLcioTrack.trackStates_size()==0) throw "zero trackStates size find"; + intersectionPoint.SetValues(pLcioTrack.getTrackStates(0).D0 * std::cos(pLcioTrack.getTrackStates(0).phi), pLcioTrack.getTrackStates(0).D0 * std::sin(pLcioTrack.getTrackStates(0).phi), z0); + const float trackMomentumAtDca((pPandoraTrack->GetMomentumAtDca()).GetMagnitude()); + referencePointAtDCAWeighted += intersectionPoint * trackMomentumAtDca; + totalTrackMomentumAtDca += trackMomentumAtDca; + } + } + + if (hasSiblings) + { + if (totalTrackMomentumAtStart < std::numeric_limits<float>::epsilon()) + { + std::cout<<" WARNING PfoCreator::CalculateTrackBasedReferencePoint: invalid track momentum " << totalTrackMomentumAtStart << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = referencePointAtStartWeighted * (1.f / totalTrackMomentumAtStart); + } + } + else + { + if (totalTrackMomentumAtDca < std::numeric_limits<float>::epsilon()) + { + std::cout<<"WARNING PfoCreator::CalculateTrackBasedReferencePoint: invalid track momentum " << totalTrackMomentumAtDca << std::endl; + throw pandora::StatusCodeException(pandora::STATUS_CODE_FAILURE); + } + else + { + referencePoint = referencePointAtDCAWeighted * (1.f / totalTrackMomentumAtDca); + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::IsValidParentTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &parentTrackList(pPandoraTrack->GetParentList()); + + for (pandora::TrackList::const_iterator iter = parentTrackList.begin(), iterEnd = parentTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + continue; + + // ATTN This track must have a parent not in the all track list; still use it if it is the closest to the ip + std::cout<<"WARNING PfoCreator::IsValidParentTrack: mismatch in track relationship information, use information as available " << std::endl; + + if (this->IsClosestTrackToIP(pPandoraTrack, allTrackList)) + return true; + + return false; + } + + // Ideal case: All parents are associated to same pfo + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::HasValidSiblingTrack(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &siblingTrackList(pPandoraTrack->GetSiblingList()); + + for (pandora::TrackList::const_iterator iter = siblingTrackList.begin(), iterEnd = siblingTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + continue; + + // ATTN This track must have a sibling not in the all track list; still use it if it has a second sibling that is in the list + std::cout<<"WARNING PfoCreator::HasValidSiblingTrack: mismatch in track relationship information, use information as available " << std::endl; + + if (this->AreAnyOtherSiblingsInList(pPandoraTrack, allTrackList)) + return true; + + return false; + } + + // Ideal case: All siblings associated to same pfo + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::IsClosestTrackToIP(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::Track *pClosestTrack(NULL); + float closestTrackDisplacement(std::numeric_limits<float>::max()); + + for (pandora::TrackList::const_iterator iter = allTrackList.begin(), iterEnd = allTrackList.end(); iter != iterEnd; ++iter) + { + const pandora::Track *const pTrack(*iter); + const float trialTrackDisplacement(pTrack->GetTrackStateAtStart().GetPosition().GetMagnitude()); + + if (trialTrackDisplacement < closestTrackDisplacement) + { + closestTrackDisplacement = trialTrackDisplacement; + pClosestTrack = pTrack; + } + } + + return (pPandoraTrack == pClosestTrack); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool PfoCreator::AreAnyOtherSiblingsInList(const pandora::Track *const pPandoraTrack, const pandora::TrackList &allTrackList) const +{ + const pandora::TrackList &siblingTrackList(pPandoraTrack->GetSiblingList()); + + for (pandora::TrackList::const_iterator iter = siblingTrackList.begin(), iterEnd = siblingTrackList.end(); iter != iterEnd; ++iter) + { + if (allTrackList.end() != std::find(allTrackList.begin(), allTrackList.end(), *iter)) + return true; + } + + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetRecoParticleReferencePoint(const pandora::CartesianVector &referencePoint, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const float referencePointArray[3] = {referencePoint.GetX(), referencePoint.GetY(), referencePoint.GetZ()}; + pReconstructedParticle->setReferencePoint(referencePointArray); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::AddTracksToRecoParticle(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const pandora::TrackList &trackList(pPandoraPfo->GetTrackList()); + + for (pandora::TrackList::const_iterator tIter = trackList.begin(), tIterEnd = trackList.end(); tIter != tIterEnd; ++tIter) + { + const pandora::Track *const pTrack(*tIter); + const edm4hep::Track *const pLcioTrack0 = (edm4hep::Track*)(pTrack->GetParentAddress()); + const edm4hep::Track pLcioTrack = *pLcioTrack0; + pReconstructedParticle->addToTracks(pLcioTrack); + + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void PfoCreator::SetRecoParticlePropertiesFromPFO(const pandora::ParticleFlowObject *const pPandoraPfo, edm4hep::ReconstructedParticle *const pReconstructedParticle) const +{ + const float momentum[3] = {pPandoraPfo->GetMomentum().GetX(), pPandoraPfo->GetMomentum().GetY(), pPandoraPfo->GetMomentum().GetZ()}; + pReconstructedParticle->setMomentum(momentum); + pReconstructedParticle->setEnergy(pPandoraPfo->GetEnergy()); + pReconstructedParticle->setMass(pPandoraPfo->GetMass()); + pReconstructedParticle->setCharge(pPandoraPfo->GetCharge()); + pReconstructedParticle->setType(pPandoraPfo->GetParticleId()); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PfoCreator::Settings::Settings(): + m_emStochasticTerm(0.17f), + m_hadStochasticTerm(0.6f), + m_emConstantTerm(0.01f), + m_hadConstantTerm(0.03f) +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/TrackCreator.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/TrackCreator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a3c0f15a7107e3671d246b80d69918f82c952de --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/TrackCreator.cpp @@ -0,0 +1,987 @@ +/** + * @file MarlinPandora/src/TrackCreator.cc + * + * @brief Implementation of the track creator class. + * + * $Log: $ + */ + + +#include "UTIL/ILDConf.h" + +#include "edm4hep/Vertex.h" +#include "edm4hep/ReconstructedParticle.h" + +#include "gear/BField.h" +#include "gear/CalorimeterParameters.h" +#include "gear/PadRowLayout2D.h" +#include "gear/TPCParameters.h" +#include "gear/FTDParameters.h" +#include "gear/FTDLayerLayout.h" + +#include "GaudiKernel/IService.h" +#include "GearSvc/IGearSvc.h" +#include "PandoraMatrixAlg.h" + +#include "TrackCreator.h" +#include "Pandora/PdgTable.h" + +#include <algorithm> +#include <cmath> +#include <limits> + +TrackCreator::TrackCreator(const Settings &settings, const pandora::Pandora *const pPandora, ISvcLocator* svcloc) : + m_settings(settings), + m_pPandora(pPandora) +{ + + IGearSvc* iSvc = 0; + StatusCode sc = svcloc->service("GearSvc", iSvc, false); + if ( !sc ) + { + throw "Failed to find GearSvc ..."; + } + _GEAR = iSvc->getGearMgr(); + + + m_bField = (_GEAR->getBField().at(gear::Vector3D(0., 0., 0.)).z()); + m_tpcInnerR = (_GEAR->getTPCParameters().getPadLayout().getPlaneExtent()[0]); + m_tpcOuterR = (_GEAR->getTPCParameters().getPadLayout().getPlaneExtent()[1]); + m_tpcMaxRow = (_GEAR->getTPCParameters().getPadLayout().getNRows()); + m_tpcZmax = (_GEAR->getTPCParameters().getMaxDriftLength()); + m_eCalBarrelInnerSymmetry = (_GEAR->getEcalBarrelParameters().getSymmetryOrder()); + m_eCalBarrelInnerPhi0 = (_GEAR->getEcalBarrelParameters().getPhi0()); + m_eCalBarrelInnerR = (_GEAR->getEcalBarrelParameters().getExtent()[0]); + m_eCalEndCapInnerZ = (_GEAR->getEcalEndcapParameters().getExtent()[2]); + // fg: FTD description in GEAR has changed ... + try + { + m_ftdInnerRadii = _GEAR->getGearParameters("FTD").getDoubleVals("FTDInnerRadius"); + m_ftdOuterRadii = _GEAR->getGearParameters("FTD").getDoubleVals("FTDOuterRadius"); + m_ftdZPositions = _GEAR->getGearParameters("FTD").getDoubleVals("FTDZCoordinate"); + m_nFtdLayers = m_ftdZPositions.size(); + } + catch (gear::UnknownParameterException &) + { + const gear::FTDLayerLayout &ftdLayerLayout(_GEAR->getFTDParameters().getFTDLayerLayout()); + std::cout << " Filling FTD parameters from gear::FTDParameters - n layers: " << ftdLayerLayout.getNLayers() << std::endl; + + for(unsigned int i = 0, N = ftdLayerLayout.getNLayers(); i < N; ++i) + { + // Create a disk to represent even number petals front side + m_ftdInnerRadii.push_back(ftdLayerLayout.getSensitiveRinner(i)); + m_ftdOuterRadii.push_back(ftdLayerLayout.getMaxRadius(i)); + + // Take the mean z position of the staggered petals + const double zpos(ftdLayerLayout.getZposition(i)); + m_ftdZPositions.push_back(zpos); + std::cout << " layer " << i << " - mean z position = " << zpos << std::endl; + } + + m_nFtdLayers = m_ftdZPositions.size() ; + } + + // Check tpc parameters + if ((std::fabs(m_tpcZmax) < std::numeric_limits<float>::epsilon()) || (std::fabs(m_tpcInnerR) < std::numeric_limits<float>::epsilon()) + || (std::fabs(m_tpcOuterR - m_tpcInnerR) < std::numeric_limits<float>::epsilon())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + m_cosTpc = m_tpcZmax / std::sqrt(m_tpcZmax * m_tpcZmax + m_tpcInnerR * m_tpcInnerR); + + // Check ftd parameters + if ((0 == m_nFtdLayers) || (m_nFtdLayers != m_ftdInnerRadii.size()) || (m_nFtdLayers != m_ftdOuterRadii.size())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + + for (unsigned int iFtdLayer = 0; iFtdLayer < m_nFtdLayers; ++iFtdLayer) + { + if ((std::fabs(m_ftdOuterRadii[iFtdLayer]) < std::numeric_limits<float>::epsilon()) || + (std::fabs(m_ftdInnerRadii[iFtdLayer]) < std::numeric_limits<float>::epsilon())) + { + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + } + } + + m_tanLambdaFtd = m_ftdZPositions[0] / m_ftdOuterRadii[0]; + + // Calculate etd and set parameters + // fg: make SET and ETD optional - as they might not be in the model ... + try + { + const DoubleVector &etdZPositions(_GEAR->getGearParameters("ETD").getDoubleVals("ETDLayerZ")); + const DoubleVector &setInnerRadii(_GEAR->getGearParameters("SET").getDoubleVals("SETLayerRadius")); + + if (etdZPositions.empty() || setInnerRadii.empty()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_INVALID_PARAMETER); + + m_minEtdZPosition = *(std::min_element(etdZPositions.begin(), etdZPositions.end())); + m_minSetRadius = *(std::min_element(setInnerRadii.begin(), setInnerRadii.end())); + } + catch(gear::UnknownParameterException &) + { + std::cout << "Warnning, ETDLayerZ or SETLayerRadius parameters missing from GEAR parameters!" << std::endl + << " -> both will be set to " << std::numeric_limits<float>::quiet_NaN() << std::endl; + + //fg: Set them to NAN, so that they cannot be used to set trackParameters.m_reachesCalorimeter = true; + m_minEtdZPosition = std::numeric_limits<float>::quiet_NaN(); + m_minSetRadius = std::numeric_limits<float>::quiet_NaN(); + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +TrackCreator::~TrackCreator() +{ +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::CreateTrackAssociations(const CollectionMaps& collectionMaps) +{ +// Don't use it now, because the Vertex.getAssociatedParticle() doesn't work for LCIO to plcio transfer +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractKinks(collectionMaps)); +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractProngsAndSplits(const CollectionMaps& collectionMaps)); +// PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, this->ExtractV0s(const CollectionMaps& collectionMaps)); + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode TrackCreator::ExtractKinks(const CollectionMaps& collectionMaps) +{ + std::cout<<"start TrackCreator::ExtractKinks:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_kinkVertexCollections.begin(), iterEnd = m_settings.m_kinkVertexCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.CollectionMap_Vertex.find(*iter) == collectionMaps.CollectionMap_Vertex.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const edm4hep::VertexCollection *pKinkCollection = (collectionMaps.CollectionMap_Vertex.find(*iter))->second; + + for (int i = 0, iMax = pKinkCollection->size(); i < iMax; ++i) + { + try + { + const edm4hep::Vertex pVertex0 = pKinkCollection->at(i); + const edm4hep::Vertex* pVertex = &(pVertex0); + + if (NULL == pVertex) throw ("Collection type mismatch"); + + std::cout<<"pVertex0 getChi2="<<pVertex0.getChi2()<<std::endl; + std::cout<<"pVertex getChi2="<<pVertex->getChi2()<<std::endl; + std::cout<<"Hi 0 "<<std::endl; + const plcio::ConstReconstructedParticle pReconstructedParticle0 = pVertex0.getAssociatedParticle(); + std::cout<<"Hi 1"<<std::endl; + //EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const plcio::ConstReconstructedParticle pReconstructedParticle = pVertex->getAssociatedParticle(); + std::cout<<"Hi 2:"<<&pReconstructedParticle<<std::endl; + //const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + //plcio::ConstTrack trackVec = pReconstructedParticle.getTracks(); + + std::cout<<"pReconstructedParticle0 en="<<pReconstructedParticle0.getEnergy()<<std::endl; + std::cout<<"pReconstructedParticle en="<<pReconstructedParticle.getEnergy()<<std::endl; + //if (this->IsConflictingRelationship(trackVec))continue; + if (this->IsConflictingRelationship(pReconstructedParticle))continue; + + //const int vertexPdgCode(pReconstructedParticle->getType()); + const int vertexPdgCode(pReconstructedParticle.getType()); + + // Extract the kink vertex information + //for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + //for (unsigned int iTrack = 0, nTracks = trackVec.tracks_size(); iTrack < nTracks; ++iTrack) + for (unsigned int iTrack = 0, nTracks = pReconstructedParticle.tracks_size(); iTrack < nTracks; ++iTrack) + { + //EVENT::Track *pTrack = trackVec[iTrack]; + //plcio::ConstTrack pTrack = trackVec.getTracks(iTrack); + plcio::ConstTrack pTrack = pReconstructedParticle.getTracks(iTrack); + //(0 == iTrack) ? m_parentTrackList.insert(pTrack) : m_daughterTrackList.insert(pTrack); + (0 == iTrack) ? m_parentTrackList.insert(pTrack.id()) : m_daughterTrackList.insert(pTrack.id()); + //std::cout << "KinkTrack " << iTrack << ", nHits " << pTrack.getTrackerHits().size() << std::endl; + std::cout << "KinkTrack " << iTrack << ", nHits " << pTrack.trackerHits_size() << std::endl; + + int trackPdgCode = pandora::UNKNOWN_PARTICLE_TYPE; + + if (0 == iTrack) + { + trackPdgCode = vertexPdgCode; + } + else + { + switch (vertexPdgCode) + { + case pandora::PI_PLUS : + case pandora::K_PLUS : + trackPdgCode = pandora::MU_PLUS; + break; + case pandora::PI_MINUS : + case pandora::K_MINUS : + trackPdgCode = pandora::MU_MINUS; + break; + case pandora::HYPERON_MINUS_BAR : + case pandora::SIGMA_PLUS : + trackPdgCode = pandora::PI_PLUS; + break; + case pandora::SIGMA_MINUS : + case pandora::HYPERON_MINUS : + trackPdgCode = pandora::PI_PLUS; + break; + default : + //(pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + (pTrack.getTrackStates(0).omega > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + } + } + + m_trackToPidMap.insert(TrackToPidMap::value_type(pTrack, trackPdgCode)); + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track parent-daughter relationships + if (0 == iTrack) + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, pTrack, trackVec[jTrack])); + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(trackVec.getTracks(jTrack).id()) ) ); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(pReconstructedParticle.getTracks(jTrack).id()) ) ); + } + } + + // Make track sibling relationships + else + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, pTrack, trackVec[jTrack])); + //PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(trackVec.getTracks(jTrack).id()) )); + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, (int*)(pTrack.id()), (int*)(pReconstructedParticle.getTracks(jTrack).id()) )); + } + } + } + } + catch (...) + { + std::cout << "Failed to extract kink vertex: " << std::endl; + } + } + } + catch (...) + { + std::cout << "Failed to extract kink vertex collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ +/* +pandora::StatusCode TrackCreator::ExtractProngsAndSplits(const EVENT::LCEvent *const pLCEvent) +{ + for (StringVector::const_iterator iter = m_settings.m_prongSplitVertexCollections.begin(), iterEnd = m_settings.m_prongSplitVertexCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pProngOrSplitCollection = pLCEvent->getCollection(*iter); + + for (int i = 0, iMax = pProngOrSplitCollection->getNumberOfElements(); i < iMax; ++i) + { + try + { + EVENT::Vertex *pVertex = dynamic_cast<Vertex*>(pProngOrSplitCollection->getElementAt(i)); + + if (NULL == pVertex) + throw EVENT::Exception("Collection type mismatch"); + + EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + + if (this->IsConflictingRelationship(trackVec)) + continue; + + // Extract the prong/split vertex information + for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + { + EVENT::Track *pTrack = trackVec[iTrack]; + (0 == iTrack) ? m_parentTrackList.insert(pTrack) : m_daughterTrackList.insert(pTrack); + streamlog_out(DEBUG) << "Prong or Split Track " << iTrack << ", nHits " << pTrack->getTrackerHits().size() << std::endl; + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track parent-daughter relationships + if (0 == iTrack) + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackParentDaughterRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + + // Make track sibling relationships + else + { + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract prong/split vertex: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract prong/split vertex collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::ExtractV0s(const EVENT::LCEvent *const pLCEvent) +{ + for (StringVector::const_iterator iter = m_settings.m_v0VertexCollections.begin(), iterEnd = m_settings.m_v0VertexCollections.end(); + iter != iterEnd; ++iter) + { + try + { + const EVENT::LCCollection *pV0Collection = pLCEvent->getCollection(*iter); + + for (int i = 0, iMax = pV0Collection->getNumberOfElements(); i < iMax; ++i) + { + try + { + EVENT::Vertex *pVertex = dynamic_cast<Vertex*>(pV0Collection->getElementAt(i)); + + if (NULL == pVertex) + throw EVENT::Exception("Collection type mismatch"); + + EVENT::ReconstructedParticle *pReconstructedParticle = pVertex->getAssociatedParticle(); + const EVENT::TrackVec &trackVec(pReconstructedParticle->getTracks()); + + if (this->IsConflictingRelationship(trackVec)) + continue; + + // Extract the v0 vertex information + const int vertexPdgCode(pReconstructedParticle->getType()); + + for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + { + EVENT::Track *pTrack = trackVec[iTrack]; + m_v0TrackList.insert(pTrack); + streamlog_out(DEBUG) << "V0Track " << iTrack << ", nHits " << pTrack->getTrackerHits().size() << std::endl; + + int trackPdgCode = pandora::UNKNOWN_PARTICLE_TYPE; + + switch (vertexPdgCode) + { + case pandora::PHOTON : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::E_PLUS : trackPdgCode = pandora::E_MINUS; + break; + case pandora::LAMBDA : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PROTON : trackPdgCode = pandora::PI_MINUS; + break; + case pandora::LAMBDA_BAR : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PROTON_BAR; + break; + case pandora::K_SHORT : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + default : + (pTrack->getOmega() > 0) ? trackPdgCode = pandora::PI_PLUS : trackPdgCode = pandora::PI_MINUS; + break; + } + + m_trackToPidMap.insert(TrackToPidMap::value_type(pTrack, trackPdgCode)); + + if (0 == m_settings.m_shouldFormTrackRelationships) + continue; + + // Make track sibling relationships + for (unsigned int jTrack = iTrack + 1; jTrack < nTracks; ++jTrack) + { + PANDORA_RETURN_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::SetTrackSiblingRelationship(*m_pPandora, + pTrack, trackVec[jTrack])); + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(WARNING) << "Failed to extract v0 vertex: " << exception.what() << std::endl; + } + } + } + catch (EVENT::Exception &exception) + { + streamlog_out(DEBUG5) << "Failed to extract v0 vertex collection: " << *iter << ", " << exception.what() << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} +*/ +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool TrackCreator::IsConflictingRelationship(const edm4hep::ConstReconstructedParticle &Particle) const +{ + //for (unsigned int iTrack = 0, nTracks = trackVec.size(); iTrack < nTracks; ++iTrack) + //for (unsigned int iTrack = 0, nTracks = trackVec.tracks_size(); iTrack < nTracks; ++iTrack) + std::cout<<"Particle en="<<Particle.getEnergy()<<std::endl; + for (unsigned int iTrack = 0, nTracks = Particle.tracks_size(); iTrack < nTracks; ++iTrack) + { + //EVENT::Track *pTrack = trackVec[iTrack]; + edm4hep::ConstTrack pTrack = Particle.getTracks(iTrack) ; + unsigned int pTrack_id = pTrack.id() ; + + //if (this->IsDaughter(pTrack) || this->IsParent(pTrack) || this->IsV0(pTrack)) + if (this->IsDaughter(pTrack_id) || this->IsParent(pTrack_id) || this->IsV0(pTrack_id)) + return true; + } + + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +pandora::StatusCode TrackCreator::CreateTracks(const CollectionMaps& collectionMaps) +{ + std::cout<<"start TrackCreator::CreateTracks:"<<std::endl; + for (StringVector::const_iterator iter = m_settings.m_trackCollections.begin(), iterEnd = m_settings.m_trackCollections.end(); + iter != iterEnd; ++iter) + { + if(collectionMaps.collectionMap_Track.find(*iter) == collectionMaps.collectionMap_Track.end()) { std::cout<<"not find "<<(*iter)<<std::endl; continue;} + try + { + const std::vector<edm4hep::Track>& pTrackCollection = (collectionMaps.collectionMap_Track.find(*iter))->second; + std::cout<<(*iter)<<" size="<<pTrackCollection.size()<<std::endl; + + for (int i = 0, iMax = pTrackCollection.size(); i < iMax; ++i) + { + try + { + const edm4hep::Track& pTrack0 = pTrackCollection.at(i); + const edm4hep::Track* pTrack = (const edm4hep::Track*)(&pTrack0); + + if (NULL == pTrack) throw ("Collection type mismatch"); + + int minTrackHits = m_settings.m_minTrackHits; + //const float tanLambda(std::fabs(pTrack->getTanLambda())); + //std::cout<<"track states size="<<pTrack->trackStates_size()<<std::endl; + const float tanLambda(std::fabs(pTrack->getTrackStates(0).tanLambda)); + + if (tanLambda > m_tanLambdaFtd) + { + int expectedFtdHits(0); + + for (unsigned int iFtdLayer = 0; iFtdLayer < m_nFtdLayers; ++iFtdLayer) + { + if ((tanLambda > m_ftdZPositions[iFtdLayer] / m_ftdOuterRadii[iFtdLayer]) && + (tanLambda < m_ftdZPositions[iFtdLayer] / m_ftdInnerRadii[iFtdLayer])) + { + expectedFtdHits++; + } + } + + minTrackHits = std::max(m_settings.m_minFtdTrackHits, expectedFtdHits); + } + + const int nTrackHits(static_cast<int>(pTrack->trackerHits_size())); + + if ((nTrackHits < minTrackHits) || (nTrackHits > m_settings.m_maxTrackHits)) + continue; + + // Proceed to create the pandora track + PandoraApi::Track::Parameters trackParameters; + //trackParameters.m_d0 = pTrack->getD0(); + trackParameters.m_d0 = pTrack->getTrackStates(0).D0; + //trackParameters.m_z0 = pTrack->getZ0(); + trackParameters.m_z0 = pTrack->getTrackStates(0).Z0; + trackParameters.m_pParentAddress = pTrack; + // By default, assume tracks are charged pions + const float signedCurvature(pTrack->getTrackStates(0).omega); + trackParameters.m_particleId = (signedCurvature > 0) ? pandora::PI_PLUS : pandora::PI_MINUS; + trackParameters.m_mass = pandora::PdgTable::GetParticleMass(pandora::PI_PLUS); + + // Use particle id information from V0 and Kink finders + TrackToPidMap::const_iterator iter_t = m_trackToPidMap.find(*pTrack); + + if(iter_t != m_trackToPidMap.end()) + { + trackParameters.m_particleId = (*iter_t).second; + trackParameters.m_mass = pandora::PdgTable::GetParticleMass((*iter_t).second); + } + + if (std::numeric_limits<float>::epsilon() < std::fabs(signedCurvature)) + trackParameters.m_charge = static_cast<int>(signedCurvature / std::fabs(signedCurvature)); + + this->GetTrackStates(pTrack, trackParameters); + this->TrackReachesECAL(pTrack, trackParameters); + this->DefineTrackPfoUsage(pTrack, trackParameters); + + PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::Track::Create(*m_pPandora, trackParameters)); + m_trackVector.push_back(pTrack); + } + catch (pandora::StatusCodeException &statusCodeException) + { + std::cout<<"ERROR Failed to extract a track: " << statusCodeException.ToString() << std::endl; + } + catch (...) + { + std::cout << "WARNNING Failed to extract a track "<< std::endl; + } + } + } + catch (...) + { + std::cout<<"WARNING Failed to extract track collection: " << *iter << std::endl; + } + } + + return pandora::STATUS_CODE_SUCCESS; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::GetTrackStates(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + //const TrackState *pTrackState = pTrack->getTrackState(TrackState::AtIP); + edm4hep::TrackState pTrackState = pTrack->getTrackStates(1); // ref /cvmfs/cepcsw.ihep.ac.cn/prototype/LCIO/include/EVENT/TrackState.h + + //if (!pTrackState) throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + //const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState->getOmega())); + const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState.omega)); + //trackParameters.m_momentumAtDca = pandora::CartesianVector(std::cos(pTrackState->getPhi()), std::sin(pTrackState->getPhi()), pTrackState->getTanLambda()) * pt; + trackParameters.m_momentumAtDca = pandora::CartesianVector(std::cos(pTrackState.phi), std::sin(pTrackState.phi), pTrackState.tanLambda) * pt; + //this->CopyTrackState(pTrack->getTrackState(TrackState::AtFirstHit), trackParameters.m_trackStateAtStart); + this->CopyTrackState(pTrack->getTrackStates(2), trackParameters.m_trackStateAtStart); + + //fg: curling TPC tracks have pointers to track segments stored -> need to get track states from last segment! + //const EVENT::Track *pEndTrack = (pTrack->getTracks().empty() ? pTrack : pTrack->getTracks().back()); + auto pEndTrack = (pTrack->tracks_size() ==0 ) ? *pTrack : pTrack->getTracks(pTrack->tracks_size()-1); + + //std::cout<<"GetTrackStates 1.6"<<", end track trackStates_size()="<<pEndTrack.trackStates_size()<<std::endl; + + //this->CopyTrackState(pEndTrack->getTrackState(TrackState::AtLastHit), trackParameters.m_trackStateAtEnd); + //this->CopyTrackState(pEndTrack->getTrackState(TrackState::AtCalorimeter), trackParameters.m_trackStateAtCalorimeter); + + this->CopyTrackState(pEndTrack.getTrackStates(3), trackParameters.m_trackStateAtEnd); + //this->CopyTrackState(pEndTrack.getTrackStates(4), trackParameters.m_trackStateAtCalorimeter); + //FIXME ? LCIO input only has 4 states, so 4 can't be used. + this->CopyTrackState(pEndTrack.getTrackStates(3), trackParameters.m_trackStateAtCalorimeter); + + + trackParameters.m_isProjectedToEndCap = ((std::fabs(trackParameters.m_trackStateAtCalorimeter.Get().GetPosition().GetZ()) < m_eCalEndCapInnerZ) ? false : true); + + // Convert generic time (length from reference point to intersection, divided by momentum) into nanoseconds + const float minGenericTime(this->CalculateTrackTimeAtCalorimeter(pTrack)); + const float particleMass(trackParameters.m_mass.Get()); + const float particleEnergy(std::sqrt(particleMass * particleMass + trackParameters.m_momentumAtDca.Get().GetMagnitudeSquared())); + trackParameters.m_timeAtCalorimeter = minGenericTime * particleEnergy / 299.792f; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +float TrackCreator::CalculateTrackTimeAtCalorimeter(const edm4hep::Track *const pTrack) const +{ + //const pandora::Helix helix(pTrack->getPhi(), pTrack->getD0(), pTrack->getZ0(), pTrack->getOmega(), pTrack->getTanLambda(), m_bField); + const pandora::Helix helix(pTrack->getTrackStates(0).phi, pTrack->getTrackStates(0).D0, pTrack->getTrackStates(0).Z0, pTrack->getTrackStates(0).omega, pTrack->getTrackStates(0).tanLambda, m_bField); + const pandora::CartesianVector &referencePoint(helix.GetReferencePoint()); + + // First project to endcap + float minGenericTime(std::numeric_limits<float>::max()); + + pandora::CartesianVector bestECalProjection(0.f, 0.f, 0.f); + const int signPz((helix.GetMomentum().GetZ() > 0.f) ? 1 : -1); + (void) helix.GetPointInZ(static_cast<float>(signPz) * m_eCalEndCapInnerZ, referencePoint, bestECalProjection, minGenericTime); + + // Then project to barrel surface(s) + pandora::CartesianVector barrelProjection(0.f, 0.f, 0.f); + if (m_eCalBarrelInnerSymmetry > 0) + { + // Polygon + float twopi_n = 2. * M_PI / (static_cast<float>(m_eCalBarrelInnerSymmetry)); + + for (int i = 0; i < m_eCalBarrelInnerSymmetry; ++i) + { + float genericTime(std::numeric_limits<float>::max()); + const float phi(twopi_n * static_cast<float>(i) + m_eCalBarrelInnerPhi0); + + const pandora::StatusCode statusCode(helix.GetPointInXY(m_eCalBarrelInnerR * std::cos(phi), m_eCalBarrelInnerR * std::sin(phi), + std::cos(phi + 0.5 * M_PI), std::sin(phi + 0.5 * M_PI), referencePoint, barrelProjection, genericTime)); + + if ((pandora::STATUS_CODE_SUCCESS == statusCode) && (genericTime < minGenericTime)) + { + minGenericTime = genericTime; + bestECalProjection = barrelProjection; + } + } + } + else + { + // Cylinder + float genericTime(std::numeric_limits<float>::max()); + const pandora::StatusCode statusCode(helix.GetPointOnCircle(m_eCalBarrelInnerR, referencePoint, barrelProjection, genericTime)); + + if ((pandora::STATUS_CODE_SUCCESS == statusCode) && (genericTime < minGenericTime)) + { + minGenericTime = genericTime; + bestECalProjection = barrelProjection; + } + } + + if (bestECalProjection.GetMagnitudeSquared() < std::numeric_limits<float>::epsilon()) + throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + + return minGenericTime; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::CopyTrackState(const edm4hep::TrackState & pTrackState, pandora::InputTrackState &inputTrackState) const +{ + //if (!pTrackState) throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_INITIALIZED); + //const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState->getOmega())); + const double pt(m_bField * 2.99792e-4 / std::fabs(pTrackState.omega)); + + //const double px(pt * std::cos(pTrackState->getPhi())); + const double px(pt * std::cos(pTrackState.phi)); + //const double py(pt * std::sin(pTrackState->getPhi())); + const double py(pt * std::sin(pTrackState.phi)); + //const double pz(pt * pTrackState->getTanLambda()); + const double pz(pt * pTrackState.tanLambda); + + const double xs(pTrackState.referencePoint[0]); + const double ys(pTrackState.referencePoint[1]); + const double zs(pTrackState.referencePoint[2]); + + inputTrackState = pandora::TrackState(xs, ys, zs, px, py, pz); +} + + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::TrackReachesECAL(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + + // Calculate hit position information + float hitZMin(std::numeric_limits<float>::max()); + float hitZMax(-std::numeric_limits<float>::max()); + float hitOuterR(-std::numeric_limits<float>::max()); + + int maxOccupiedFtdLayer=0; + + + const unsigned int nTrackHits(pTrack->trackerHits_size()); + for (unsigned int i = 0; i < nTrackHits; ++i) + { + + const edm4hep::ConstTrackerHit Hit ( pTrack->getTrackerHits(i) ); + const edm4hep::Vector3d pos = Hit.getPosition(); + + float x = float(pos[0]); + float y = float(pos[1]); + float z = float(pos[2]); + float r = std::sqrt(x * x + y * y); + + if (z > hitZMax) hitZMax = z; + + if (z < hitZMin) hitZMin = z; + + if (r > hitOuterR) hitOuterR = r; + + if ((r > m_tpcInnerR) && (r < m_tpcOuterR) && (std::fabs(z) <= m_tpcZmax)) continue; + + for (unsigned int j = 0; j < m_nFtdLayers; ++j) + { + if ((r > m_ftdInnerRadii[j]) && (r < m_ftdOuterRadii[j]) && + (std::fabs(z) - m_settings.m_reachesECalFtdZMaxDistance < m_ftdZPositions[j]) && + (std::fabs(z) + m_settings.m_reachesECalFtdZMaxDistance > m_ftdZPositions[j])) + { + //if (static_cast<int>(j) > maxOccupiedFtdLayer) maxOccupiedFtdLayer = static_cast<int>(j); + if ( j > maxOccupiedFtdLayer) maxOccupiedFtdLayer = j; + break; + } + } + } + const int nTpcHits(this->GetNTpcHits(pTrack)); + const int nFtdHits(this->GetNFtdHits(pTrack)); + + // Look to see if there are hits in etd or set, implying track has reached edge of ecal + if ((hitOuterR > m_minSetRadius) || (hitZMax > m_minEtdZPosition)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + + // Require sufficient hits in tpc or ftd, then compare extremal hit positions with tracker dimensions + if ((nTpcHits >= m_settings.m_reachesECalNTpcHits) || (nFtdHits >= m_settings.m_reachesECalNFtdHits)) + { + if ((hitOuterR - m_tpcOuterR > m_settings.m_reachesECalTpcOuterDistance) || + (std::fabs(hitZMax) - m_tpcZmax > m_settings.m_reachesECalTpcZMaxDistance) || + (std::fabs(hitZMin) - m_tpcZmax > m_settings.m_reachesECalTpcZMaxDistance) || + (maxOccupiedFtdLayer >= m_settings.m_reachesECalMinFtdLayer)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + } + + // If track is lowpt, it may curl up and end inside tpc inner radius + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float cosAngleAtDca(std::fabs(momentumAtDca.GetZ()) / momentumAtDca.GetMagnitude()); + const float pX(momentumAtDca.GetX()), pY(momentumAtDca.GetY()); + const float pT(std::sqrt(pX * pX + pY * pY)); + + if ((cosAngleAtDca > m_cosTpc) || (pT < m_settings.m_curvatureToMomentumFactor * m_bField * m_tpcOuterR)) + { + trackParameters.m_reachesCalorimeter = true; + return; + } + + trackParameters.m_reachesCalorimeter = false; + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +void TrackCreator::DefineTrackPfoUsage(const edm4hep::Track *const pTrack, PandoraApi::Track::Parameters &trackParameters) const +{ + bool canFormPfo(false); + bool canFormClusterlessPfo(false); + + //if (trackParameters.m_reachesCalorimeter.Get() && !this->IsParent(pTrack)) + if (trackParameters.m_reachesCalorimeter.Get() && !this->IsParent(pTrack->id())) + { + //const float d0(std::fabs(pTrack->getD0())), z0(std::fabs(pTrack->getZ0())); + const float d0(std::fabs(pTrack->getTrackStates(0).D0)), z0(std::fabs(pTrack->getTrackStates(0).Z0)); + + //EVENT::TrackerHitVec trackerHitvec(pTrack->getTrackerHits()); + float rInner(std::numeric_limits<float>::max()), zMin(std::numeric_limits<float>::max()); + + //for (EVENT::TrackerHitVec::const_iterator iter = trackerHitvec.begin(), iterEnd = trackerHitvec.end(); iter != iterEnd; ++iter) + for (std::vector<edm4hep::ConstTrackerHit>::const_iterator iter = pTrack->trackerHits_begin(), iterEnd = pTrack->trackerHits_end(); iter != iterEnd; ++iter) + { + //const double *pPosition((*iter)->getPosition()); + const edm4hep::Vector3d pPosition = (*iter).getPosition(); + const float x(pPosition[0]), y(pPosition[1]), absoluteZ(std::fabs(pPosition[2])); + const float r(std::sqrt(x * x + y * y)); + + if (r < rInner) + rInner = r; + + if (absoluteZ < zMin) + zMin = absoluteZ; + } + + if (this->PassesQualityCuts(pTrack, trackParameters)) + { + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + const float pX(momentumAtDca.GetX()), pY(momentumAtDca.GetY()), pZ(momentumAtDca.GetZ()); + const float pT(std::sqrt(pX * pX + pY * pY)); + + const float zCutForNonVertexTracks(m_tpcInnerR * std::fabs(pZ / pT) + m_settings.m_zCutForNonVertexTracks); + const bool passRzQualityCuts((zMin < zCutForNonVertexTracks) && (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)); + + const bool isV0(this->IsV0(pTrack->id())); + const bool isDaughter(this->IsDaughter(pTrack->id())); + + // Decide whether track can be associated with a pandora cluster and used to form a charged PFO + if ((d0 < m_settings.m_d0TrackCut) && (z0 < m_settings.m_z0TrackCut) && (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)) + { + canFormPfo = true; + } + else if (passRzQualityCuts && (0 != m_settings.m_usingNonVertexTracks)) + { + canFormPfo = true; + } + else if (isV0 || isDaughter) + { + canFormPfo = true; + } + + // Decide whether track can be used to form a charged PFO, even if track fails to be associated with a pandora cluster + const float particleMass(trackParameters.m_mass.Get()); + const float trackEnergy(std::sqrt(momentumAtDca.GetMagnitudeSquared() + particleMass * particleMass)); + + if ((0 != m_settings.m_usingUnmatchedVertexTracks) && (trackEnergy < m_settings.m_unmatchedVertexTrackMaxEnergy)) + { + if ((d0 < m_settings.m_d0UnmatchedVertexTrackCut) && (z0 < m_settings.m_z0UnmatchedVertexTrackCut) && + (rInner < m_tpcInnerR + m_settings.m_maxTpcInnerRDistance)) + { + canFormClusterlessPfo = true; + } + else if (passRzQualityCuts && (0 != m_settings.m_usingNonVertexTracks) && (0 != m_settings.m_usingUnmatchedNonVertexTracks)) + { + canFormClusterlessPfo = true; + } + else if (isV0 || isDaughter) + { + canFormClusterlessPfo = true; + } + } + } + else if (this->IsDaughter(pTrack->id()) || this->IsV0(pTrack->id())) + { + std::cout<<"WARNING Recovering daughter or v0 track " << trackParameters.m_momentumAtDca.Get().GetMagnitude() << std::endl; + canFormPfo = true; + } + } + + trackParameters.m_canFormPfo = canFormPfo; + trackParameters.m_canFormClusterlessPfo = canFormClusterlessPfo; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +bool TrackCreator::PassesQualityCuts(const edm4hep::Track *const pTrack, const PandoraApi::Track::Parameters &trackParameters) const +{ + // First simple sanity checks + if (trackParameters.m_trackStateAtCalorimeter.Get().GetPosition().GetMagnitude() < m_settings.m_minTrackECalDistanceFromIp) + return false; + + //if (std::fabs(pTrack->getOmega()) < std::numeric_limits<float>::epsilon()) + if (std::fabs(pTrack->getTrackStates(0).omega) < std::numeric_limits<float>::epsilon()) + { + std::cout<<"ERROR Track has Omega = 0 " << std::endl; + return false; + } + + // Check momentum uncertainty is reasonable to use track + const pandora::CartesianVector &momentumAtDca(trackParameters.m_momentumAtDca.Get()); + //const float sigmaPOverP(std::sqrt(pTrack->getCovMatrix()[5]) / std::fabs(pTrack->getOmega())); + const float sigmaPOverP(std::sqrt(pTrack->getTrackStates(0).covMatrix[5]) / std::fabs(pTrack->getTrackStates(0).omega)); + + if (sigmaPOverP > m_settings.m_maxTrackSigmaPOverP) + { + std::cout<<"WARNING Dropping track : " << momentumAtDca.GetMagnitude() << "+-" << sigmaPOverP * (momentumAtDca.GetMagnitude()) + << " chi2 = " << pTrack->getChi2() << " " << pTrack->getNdf() + << " from " << pTrack->trackerHits_size() << std::endl; + return false; + } + + // Require reasonable number of TPC hits + if (momentumAtDca.GetMagnitude() > m_settings.m_minMomentumForTrackHitChecks) + { + const float pX(fabs(momentumAtDca.GetX())); + const float pY(fabs(momentumAtDca.GetY())); + const float pZ(fabs(momentumAtDca.GetZ())); + const float pT(std::sqrt(pX * pX + pY * pY)); + const float rInnermostHit(pTrack->getRadiusOfInnermostHit()); + + if ((std::numeric_limits<float>::epsilon() > std::fabs(pT)) || (std::numeric_limits<float>::epsilon() > std::fabs(pZ)) || (rInnermostHit == m_tpcOuterR)) + { + std::cout<<"ERROR Invalid track parameter, pT " << pT << ", pZ " << pZ << ", rInnermostHit " << rInnermostHit << std::endl; + return false; + } + + float nExpectedTpcHits(0.); + + if (pZ < m_tpcZmax / m_tpcOuterR * pT) + { + const float innerExpectedHitRadius(std::max(m_tpcInnerR, rInnermostHit)); + const float frac((m_tpcOuterR - innerExpectedHitRadius) / (m_tpcOuterR - m_tpcInnerR)); + nExpectedTpcHits = m_tpcMaxRow * frac; + } + + if ((pZ <= m_tpcZmax / m_tpcInnerR * pT) && (pZ >= m_tpcZmax / m_tpcOuterR * pT)) + { + const float innerExpectedHitRadius(std::max(m_tpcInnerR, rInnermostHit)); + const float frac((m_tpcZmax * pT / pZ - innerExpectedHitRadius) / (m_tpcOuterR - innerExpectedHitRadius)); + nExpectedTpcHits = frac * m_tpcMaxRow; + } + + // TODO Get TPC membrane information from GEAR when available + if (std::fabs(pZ) / momentumAtDca.GetMagnitude() < m_settings.m_tpcMembraneMaxZ / m_tpcInnerR) + nExpectedTpcHits = 0; + + const int nTpcHits(this->GetNTpcHits(pTrack)); + const int nFtdHits(this->GetNFtdHits(pTrack)); + + const int minTpcHits = static_cast<int>(nExpectedTpcHits * m_settings.m_minTpcHitFractionOfExpected); + + if ((nTpcHits < minTpcHits) && (nFtdHits < m_settings.m_minFtdHitsForTpcHitFraction)) + { + std::cout<<"WARNING Dropping track : " << momentumAtDca.GetMagnitude() << " Number of TPC hits = " << nTpcHits + << " < " << minTpcHits << " nftd = " << nFtdHits << std::endl; + return false; + } + } + + return true; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int TrackCreator::GetNTpcHits(const edm4hep::Track *const pTrack) const +{ + // ATTN + //fg: hit numbers are now given in different order wrt LOI: + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 1 ] = hitsInFit ; + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 2 ] = hitCount ; + // ---- use hitsInFit : + //return pTrack->getSubdetectorHitNumbers()[ 2 * lcio::ILDDetID::TPC - 1 ]; + return pTrack->getSubDetectorHitNumbers(2 * lcio::ILDDetID::TPC - 1);// still use LCIO code now +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +int TrackCreator::GetNFtdHits(const edm4hep::Track *const pTrack) const +{ + // ATTN + //fg: hit numbers are now given in different order wrt LOI: + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 1 ] = hitsInFit ; + // trk->subdetectorHitNumbers()[ 2 * ILDDetID::TPC - 2 ] = hitCount ; + // ---- use hitsInFit : + //return pTrack->getSubdetectorHitNumbers()[ 2 * lcio::ILDDetID::FTD - 1 ]; + return pTrack->getSubDetectorHitNumbers( 2 * lcio::ILDDetID::FTD - 1 ); +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------------------------------------------------------ + +TrackCreator::Settings::Settings() : + m_shouldFormTrackRelationships(1), + m_minTrackHits(5), + m_minFtdTrackHits(0), + m_maxTrackHits(5000.f), + m_d0TrackCut(50.f), + m_z0TrackCut(50.f), + m_usingNonVertexTracks(1), + m_usingUnmatchedNonVertexTracks(0), + m_usingUnmatchedVertexTracks(1), + m_unmatchedVertexTrackMaxEnergy(5.f), + m_d0UnmatchedVertexTrackCut(5.f), + m_z0UnmatchedVertexTrackCut(5.f), + m_zCutForNonVertexTracks(250.f), + m_reachesECalNTpcHits(11), + m_reachesECalNFtdHits(4), + m_reachesECalTpcOuterDistance(-100.f), + m_reachesECalMinFtdLayer(9), + m_reachesECalTpcZMaxDistance(-50.f), + m_reachesECalFtdZMaxDistance(1.f), + m_curvatureToMomentumFactor(0.3f / 2000.f), + m_minTrackECalDistanceFromIp(100.f), + m_maxTrackSigmaPOverP(0.15f), + m_minMomentumForTrackHitChecks(1.f), + m_tpcMembraneMaxZ(10.f), + m_maxTpcInnerRDistance(50.f), + m_minTpcHitFractionOfExpected(0.2f), + m_minFtdHitsForTpcHitFraction(2) +{ +} diff --git a/Reconstruction/PFA/Pandora/MatrixPandora/src/Utility.cpp b/Reconstruction/PFA/Pandora/MatrixPandora/src/Utility.cpp new file mode 100644 index 0000000000000000000000000000000000000000..819fa15d4771c80d65e6437d22ebd46120d311de --- /dev/null +++ b/Reconstruction/PFA/Pandora/MatrixPandora/src/Utility.cpp @@ -0,0 +1,7 @@ +#include "Utility.h" + +std::string Convert (float number){ + std::ostringstream buff; + buff<<number; + return buff.str(); +} diff --git a/Reconstruction/PFA/Pandora/PandoraSettingsDefault.xml b/Reconstruction/PFA/Pandora/PandoraSettingsDefault.xml new file mode 100644 index 0000000000000000000000000000000000000000..8bf0e965b235f94400e68629ec565f5f9fd14db2 --- /dev/null +++ b/Reconstruction/PFA/Pandora/PandoraSettingsDefault.xml @@ -0,0 +1,447 @@ +<!-- Pandora settings xml file --> + +<pandora> + <!-- GLOBAL SETTINGS --> + <IsMonitoringEnabled>true</IsMonitoringEnabled> + <ShouldDisplayAlgorithmInfo>false</ShouldDisplayAlgorithmInfo> + <ShouldCollapseMCParticlesToPfoTarget>true</ShouldCollapseMCParticlesToPfoTarget> + + <!-- PLUGIN SETTINGS --> + <!--HadronicEnergyCorrectionPlugins>SoftwareCompensation</HadronicEnergyCorrectionPlugins--> + <EmShowerPlugin>LCEmShowerId</EmShowerPlugin> + <PhotonPlugin>LCPhotonId</PhotonPlugin> + <ElectronPlugin>LCElectronId</ElectronPlugin> + <MuonPlugin>LCMuonId</MuonPlugin> + + <!-- ALGORITHM SETTINGS --> + + <!-- Set calo hit properties, then select tracks and hits to use for clustering --> + <algorithm type = "CaloHitPreparation"/> + <algorithm type = "EventPreparation"> + <OutputTrackListName>Tracks</OutputTrackListName> + <OutputCaloHitListName>CaloHits</OutputCaloHitListName> + <OutputMuonCaloHitListName>MuonYokeHits</OutputMuonCaloHitListName> + <ReplacementTrackListName>Tracks</ReplacementTrackListName> + <ReplacementCaloHitListName>CaloHits</ReplacementCaloHitListName> + </algorithm> + + <!-- Standalone muon clustering --> + <algorithm type = "MuonReconstruction"> + <algorithm type = "ConeClustering" description = "MuonClusterFormation"> + <TanConeAngleCoarse>0.3</TanConeAngleCoarse> + <ConeApproachMaxSeparation>2000</ConeApproachMaxSeparation> + <MaxClusterDirProjection>2000</MaxClusterDirProjection> + <ShouldUseIsolatedHits>true</ShouldUseIsolatedHits> + <LayersToStepBackCoarse>30</LayersToStepBackCoarse> + <AdditionalPadWidthsCoarse>1</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsCoarse>1.8</SameLayerPadWidthsCoarse> + <ShouldUseTrackSeed>false</ShouldUseTrackSeed> + <MaxTrackSeedSeparation>0</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <!-- Input lists --> + <InputTrackListName>Tracks</InputTrackListName> + <InputCaloHitListName>CaloHits</InputCaloHitListName> + <InputMuonCaloHitListName>MuonYokeHits</InputMuonCaloHitListName> + <!-- Output lists --> + <OutputTrackListName>MuonRemovedTracks</OutputTrackListName> + <OutputCaloHitListName>MuonRemovedCaloHits</OutputCaloHitListName> + <OutputMuonCaloHitListName>MuonRemovedYokeHits</OutputMuonCaloHitListName> + <OutputMuonClusterListName>MuonClusters</OutputMuonClusterListName> + <OutputMuonPfoListName>MuonPfos</OutputMuonPfoListName> + <!-- Current list management --> + <ReplacementTrackListName>MuonRemovedTracks</ReplacementTrackListName> + <ReplacementCaloHitListName>MuonRemovedCaloHits</ReplacementCaloHitListName> + <ReplaceCurrentClusterList>false</ReplaceCurrentClusterList> + <ReplaceCurrentPfoList>false</ReplaceCurrentPfoList> + </algorithm> + + <!-- Standalone photon clustering --> + <algorithm type = "PhotonReconstruction"> + <algorithm type = "ConeClustering" description = "PhotonClusterFormation"> + <ClusterSeedStrategy>0</ClusterSeedStrategy> + <ShouldUseTrackSeed>false</ShouldUseTrackSeed> + <ShouldUseOnlyECalHits>true</ShouldUseOnlyECalHits> + <ConeApproachMaxSeparation>250.</ConeApproachMaxSeparation> + </algorithm> + <ClusterListName>PhotonClusters</ClusterListName> + <ReplaceCurrentClusterList>false</ReplaceCurrentClusterList> + <ShouldMakePdfHistograms>false</ShouldMakePdfHistograms> + <HistogramFile>/junofs/users/wxfang/MyGit/MarlinPandora/scripts/PandoraLikelihoodData9EBin.xml</HistogramFile> + </algorithm> + + <!-- Clustering parent algorithm runs a daughter clustering algorithm --> + <algorithm type = "ClusteringParent"> + <algorithm type = "ConeClustering" description = "ClusterFormation"/> + <algorithm type = "TopologicalAssociationParent" description = "ClusterAssociation"> + <associationAlgorithms> + <algorithm type = "LoopingTracks"/> + <algorithm type = "BrokenTracks"/> + <algorithm type = "ShowerMipMerging"/> + <algorithm type = "ShowerMipMerging2"/> + <algorithm type = "BackscatteredTracks"/> + <algorithm type = "BackscatteredTracks2"/> + <algorithm type = "ShowerMipMerging3"/> + <algorithm type = "ShowerMipMerging4"/> + <algorithm type = "ProximityBasedMerging"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + <algorithm type = "ConeBasedMerging"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + <algorithm type = "MipPhotonSeparation"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + <algorithm type = "HighEnergyPhotonRecovery"> + <algorithm type = "TrackClusterAssociation"/> + <AdditionalClusterListNames>PhotonClusters</AdditionalClusterListNames> + </algorithm> + <algorithm type = "SoftClusterMerging"> + <algorithm type = "TrackClusterAssociation"/> + <AdditionalClusterListNames>PhotonClusters</AdditionalClusterListNames> + </algorithm> + <algorithm type = "IsolatedHitMerging"> + <AdditionalClusterListNames>PhotonClusters</AdditionalClusterListNames> + </algorithm> + </associationAlgorithms> + </algorithm> + <ClusterListName>PrimaryClusters</ClusterListName> + <ReplaceCurrentClusterList>true</ReplaceCurrentClusterList> + </algorithm> + + <!-- Reclustering algorithms run multiple clustering algorithms --> + <algorithm type = "SplitTrackAssociations" instance = "SplitTrackAssociations1"> + <clusteringAlgorithms> + <algorithm type = "ConeClustering" instance = "Reclustering1"> + <TanConeAngleFine>0.24</TanConeAngleFine> + <TanConeAngleCoarse>0.4</TanConeAngleCoarse> + <AdditionalPadWidthsFine>2</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>2</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>2.24</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>1.44</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering2"> + <TanConeAngleFine>0.18</TanConeAngleFine> + <TanConeAngleCoarse>0.3</TanConeAngleCoarse> + <AdditionalPadWidthsFine>1.5</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>1.5</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>1.68</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>1.08</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering3"> + <TanConeAngleFine>0.15</TanConeAngleFine> + <TanConeAngleCoarse>0.25</TanConeAngleCoarse> + <AdditionalPadWidthsFine>1.25</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>1.25</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>1.4</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>0.9</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering4"> + <TanConeAngleFine>0.12</TanConeAngleFine> + <TanConeAngleCoarse>0.2</TanConeAngleCoarse> + <AdditionalPadWidthsFine>1</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>1</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>1.12</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>0.72</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering5"> + <TanConeAngleFine>0.09</TanConeAngleFine> + <TanConeAngleCoarse>0.15</TanConeAngleCoarse> + <AdditionalPadWidthsFine>0.75</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>0.75</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>0.84</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>0.54</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering6"> + <TanConeAngleFine>0.075</TanConeAngleFine> + <TanConeAngleCoarse>0.125</TanConeAngleCoarse> + <AdditionalPadWidthsFine>0.625</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>0.625</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>0.7</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>0.45</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering7"> + <TanConeAngleFine>0.06</TanConeAngleFine> + <TanConeAngleCoarse>0.1</TanConeAngleCoarse> + <AdditionalPadWidthsFine>0.5</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>0.5</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>0.56</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>0.36</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering8"> + <TanConeAngleFine>0.045</TanConeAngleFine> + <TanConeAngleCoarse>0.075</TanConeAngleCoarse> + <AdditionalPadWidthsFine>0.375</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>0.375</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>0.42</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>0.27</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering9"> + <TanConeAngleFine>0.03</TanConeAngleFine> + <TanConeAngleCoarse>0.05</TanConeAngleCoarse> + <AdditionalPadWidthsFine>0.25</AdditionalPadWidthsFine> + <AdditionalPadWidthsCoarse>0.25</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsFine>0.28</SameLayerPadWidthsFine> + <SameLayerPadWidthsCoarse>0.18</SameLayerPadWidthsCoarse> + <MaxTrackSeedSeparation>100</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering10"> + <MaxTrackSeedSeparation>250</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>3</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>3</MaxLayersToTrackLikeHit> + <TrackPathWidth>2</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering11"> + <ShouldUseTrackSeed>false</ShouldUseTrackSeed> + <MaxTrackSeedSeparation>0</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <algorithm type = "ConeClustering" instance = "Reclustering12"> + <MaxTrackSeedSeparation>1000</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>6</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>3</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + </clusteringAlgorithms> + <algorithm type = "TopologicalAssociationParent" description = "ClusterAssociation" instance = "reclusterAssociation"> + <associationAlgorithms> + <algorithm type = "LoopingTracks"/> + <algorithm type = "BrokenTracks"/> + <algorithm type = "ShowerMipMerging"/> + <algorithm type = "ShowerMipMerging2"/> + <algorithm type = "BackscatteredTracks"/> + <algorithm type = "BackscatteredTracks2"/> + <algorithm type = "ShowerMipMerging3"/> + <algorithm type = "ShowerMipMerging4"/> + <algorithm type = "ProximityBasedMerging"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + <algorithm type = "ConeBasedMerging"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + <algorithm type = "MipPhotonSeparation"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + <algorithm type = "SoftClusterMerging"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + <algorithm type = "IsolatedHitMerging"/> + </associationAlgorithms> + </algorithm> + <algorithm type = "TrackClusterAssociation" description = "TrackClusterAssociation"></algorithm> + <UsingOrderedAlgorithms>true</UsingOrderedAlgorithms> + <ShouldUseForcedClustering>true</ShouldUseForcedClustering> + <algorithm type = "ForcedClustering" description = "ForcedClustering"/> + </algorithm> + + <algorithm type = "SplitMergedClusters" instance = "SplitMergedClusters1"> + <clusteringAlgorithms> + <algorithm type = "ConeClustering" instance = "Reclustering1"/> + <algorithm type = "ConeClustering" instance = "Reclustering2"/> + <algorithm type = "ConeClustering" instance = "Reclustering3"/> + <algorithm type = "ConeClustering" instance = "Reclustering4"/> + <algorithm type = "ConeClustering" instance = "Reclustering5"/> + <algorithm type = "ConeClustering" instance = "Reclustering6"/> + <algorithm type = "ConeClustering" instance = "Reclustering7"/> + <algorithm type = "ConeClustering" instance = "Reclustering8"/> + <algorithm type = "ConeClustering" instance = "Reclustering9"/> + <algorithm type = "ConeClustering" instance = "Reclustering10"/> + <algorithm type = "ConeClustering" instance = "Reclustering11"/> + <algorithm type = "ConeClustering" instance = "Reclustering12"/> + </clusteringAlgorithms> + <algorithm type = "TopologicalAssociationParent" description = "ClusterAssociation" instance = "reclusterAssociation"></algorithm> + <algorithm type = "TrackClusterAssociation" description = "TrackClusterAssociation"></algorithm> + <UsingOrderedAlgorithms>true</UsingOrderedAlgorithms> + <ShouldUseForcedClustering>true</ShouldUseForcedClustering> + <algorithm type = "ForcedClustering" description = "ForcedClustering"/> + </algorithm> + + <algorithm type = "TrackDrivenMerging"> + <algorithm type = "TrackClusterAssociation" description = "TrackClusterAssociation"></algorithm> + </algorithm> + + <algorithm type = "ResolveTrackAssociations"> + <clusteringAlgorithms> + <algorithm type = "ConeClustering" instance = "Reclustering1"/> + <algorithm type = "ConeClustering" instance = "Reclustering2"/> + <algorithm type = "ConeClustering" instance = "Reclustering3"/> + <algorithm type = "ConeClustering" instance = "Reclustering4"/> + <algorithm type = "ConeClustering" instance = "Reclustering5"/> + <algorithm type = "ConeClustering" instance = "Reclustering6"/> + <algorithm type = "ConeClustering" instance = "Reclustering7"/> + <algorithm type = "ConeClustering" instance = "Reclustering8"/> + <algorithm type = "ConeClustering" instance = "Reclustering9"/> + <algorithm type = "ConeClustering" instance = "Reclustering10"/> + <algorithm type = "ConeClustering" instance = "Reclustering11"/> + <algorithm type = "ConeClustering" instance = "Reclustering12"/> + </clusteringAlgorithms> + <algorithm type = "TopologicalAssociationParent" description = "ClusterAssociation" instance = "reclusterAssociation"></algorithm> + <algorithm type = "TrackClusterAssociation" description = "TrackClusterAssociation"></algorithm> + <UsingOrderedAlgorithms>true</UsingOrderedAlgorithms> + <ShouldUseForcedClustering>true</ShouldUseForcedClustering> + <algorithm type = "ForcedClustering" description = "ForcedClustering"/> + </algorithm> + + <algorithm type = "SplitTrackAssociations" instance = "SplitTrackAssociations1"/> + <algorithm type = "SplitMergedClusters" instance = "SplitMergedClusters1"/> + + <algorithm type = "TrackDrivenAssociation"> + <clusteringAlgorithms> + <algorithm type = "ConeClustering" instance = "Reclustering1"/> + <algorithm type = "ConeClustering" instance = "Reclustering2"/> + <algorithm type = "ConeClustering" instance = "Reclustering3"/> + <algorithm type = "ConeClustering" instance = "Reclustering4"/> + <algorithm type = "ConeClustering" instance = "Reclustering5"/> + <algorithm type = "ConeClustering" instance = "Reclustering6"/> + <algorithm type = "ConeClustering" instance = "Reclustering7"/> + <algorithm type = "ConeClustering" instance = "Reclustering8"/> + <algorithm type = "ConeClustering" instance = "Reclustering9"/> + <algorithm type = "ConeClustering" instance = "Reclustering10"/> + <algorithm type = "ConeClustering" instance = "Reclustering11"/> + <algorithm type = "ConeClustering" instance = "Reclustering12"/> + </clusteringAlgorithms> + <algorithm type = "TopologicalAssociationParent" description = "ClusterAssociation" instance = "reclusterAssociation"></algorithm> + <algorithm type = "TrackClusterAssociation" description = "TrackClusterAssociation"></algorithm> + <UsingOrderedAlgorithms>true</UsingOrderedAlgorithms> + </algorithm> + + <algorithm type = "SplitTrackAssociations" instance = "SplitTrackAssociations1"/> + <algorithm type = "SplitMergedClusters" instance = "SplitMergedClusters1"/> + + <algorithm type = "ExitingTrack"> + <clusteringAlgorithms> + <algorithm type = "ConeClustering" instance = "Reclustering1"/> + <algorithm type = "ConeClustering" instance = "Reclustering2"/> + <algorithm type = "ConeClustering" instance = "Reclustering3"/> + <algorithm type = "ConeClustering" instance = "Reclustering4"/> + <algorithm type = "ConeClustering" instance = "Reclustering5"/> + <algorithm type = "ConeClustering" instance = "Reclustering6"/> + <algorithm type = "ConeClustering" instance = "Reclustering7"/> + <algorithm type = "ConeClustering" instance = "Reclustering8"/> + <algorithm type = "ConeClustering" instance = "Reclustering9"/> + <algorithm type = "ConeClustering" instance = "Reclustering10"/> + <algorithm type = "ConeClustering" instance = "Reclustering11"/> + <algorithm type = "ConeClustering" instance = "Reclustering12"/> + </clusteringAlgorithms> + <algorithm type = "TopologicalAssociationParent" description = "ClusterAssociation" instance = "reclusterAssociation"></algorithm> + <algorithm type = "TrackClusterAssociation" description = "TrackClusterAssociation"></algorithm> + <UsingOrderedAlgorithms>true</UsingOrderedAlgorithms> + <ShouldUseForcedClustering>true</ShouldUseForcedClustering> + <algorithm type = "ForcedClustering" description = "ForcedClustering"/> + </algorithm> + + <!-- Muon clustering --> + <algorithm type = "ClusteringParent"> + <algorithm type = "ConeClustering" description = "ClusterFormation"> + <TanConeAngleCoarse>0.75</TanConeAngleCoarse> + <AdditionalPadWidthsCoarse>12.5</AdditionalPadWidthsCoarse> + <SameLayerPadWidthsCoarse>14</SameLayerPadWidthsCoarse> + <ShouldUseTrackSeed>false</ShouldUseTrackSeed> + <MaxClusterDirProjection>1000</MaxClusterDirProjection> + <MaxTrackSeedSeparation>0</MaxTrackSeedSeparation> + <MaxLayersToTrackSeed>0</MaxLayersToTrackSeed> + <MaxLayersToTrackLikeHit>0</MaxLayersToTrackLikeHit> + <TrackPathWidth>0</TrackPathWidth> + </algorithm> + <InputCaloHitListName>MuonRemovedYokeHits</InputCaloHitListName> + <RestoreOriginalCaloHitList>true</RestoreOriginalCaloHitList> + <ClusterListName>MuonRemovedYokeClusters</ClusterListName> + <ReplaceCurrentClusterList>false</ReplaceCurrentClusterList> + </algorithm> + + <algorithm type = "MuonClusterAssociation"> + <TargetClusterListName>PrimaryClusters</TargetClusterListName> + <MuonClusterListName>MuonRemovedYokeClusters</MuonClusterListName> + </algorithm> + + <!-- Photon recovery --> + <algorithm type = "PhotonRecovery"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + + <algorithm type = "MuonPhotonSeparation"> + <algorithm type = "TrackClusterAssociation"/> + </algorithm> + + <!-- Prepare particle flow objects --> + <algorithm type = "TrackPreparation"> + <CandidateListNames>Input</CandidateListNames> + <MergedCandidateListName>PfoCandidates</MergedCandidateListName> + <PfoTrackListName>PfoCreation</PfoTrackListName> + <trackClusterAssociationAlgorithms> + <algorithm type = "TrackClusterAssociation"/> + <algorithm type = "LoopingTrackAssociation"/> + <algorithm type = "TrackRecovery"/> + <algorithm type = "TrackRecoveryHelix"/> + <algorithm type = "TrackRecoveryInteractions"/> + </trackClusterAssociationAlgorithms> + </algorithm> + + <algorithm type = "MainFragmentRemoval"/> + <algorithm type = "NeutralFragmentRemoval"/> + <algorithm type = "PhotonFragmentRemoval"/> + + <algorithm type = "ClusterPreparation"> + <CandidateListNames>PrimaryClusters PhotonClusters</CandidateListNames> + <MergedCandidateListName>PfoCreation</MergedCandidateListName> + </algorithm> + + <algorithm type = "PhotonSplitting"/> + <algorithm type = "PhotonFragmentMerging"/> + + <!-- Create particle flow objects --> + <algorithm type = "ForceSplitTrackAssociations"/> + <algorithm type = "PfoCreation"> + <OutputPfoListName>PrimaryAndPhotonPfos</OutputPfoListName> + </algorithm> + + <algorithm type = "PfoPreparation"> + <CandidateListNames>PrimaryAndPhotonPfos MuonPfos</CandidateListNames> + <MergedCandidateListName>OutputPfos</MergedCandidateListName> + </algorithm> + + <!-- Particle flow object modification algorithms --> + <algorithm type = "FinalParticleId"/> + <algorithm type = "V0PfoCreation"/> + <!--algorithm type = "DumpPfosMonitoring"/--> + <!--algorithm type = "VisualMonitoring"/--> +</pandora> diff --git a/Simulation/DetSimAna/CMakeLists.txt b/Simulation/DetSimAna/CMakeLists.txt index 9ce9742255109c63a8b3f1898f0c4d945214dfe7..e0c9aca523f0e6f33ffc9b33c40a2d7aca33c971 100644 --- a/Simulation/DetSimAna/CMakeLists.txt +++ b/Simulation/DetSimAna/CMakeLists.txt @@ -12,17 +12,33 @@ find_package(DD4hep COMPONENTS DDG4 REQUIRED) # For EDM & I/O find_package(podio REQUIRED) -find_package(plcio REQUIRED) +find_package(EDM4HEP REQUIRED) # find_package(LCIO REQUIRED) set(DetSimAna_srcs - src/ExampleAnaElemTool.cpp +# src/ExampleAnaElemTool.cpp + src/Edm4hepWriterAnaElemTool.cpp ) message("podio_LIBRARIES: ${podio_LIBRARIES}") -message("plcio_LIBRARIES: ${plcio_LIBRARIES}") gaudi_add_module(DetSimAna ${DetSimAna_srcs} - INCLUDE_DIRS DetSimInterface FWCore DD4hep GaudiKernel Geant4 - ${plcio_INCLUDE_DIRS} ${podio_INCLUDE_DIRS} - LINK_LIBRARIES DetSimInterface FWCore DD4hep ${DD4hep_COMPONENT_LIBRARIES} GaudiKernel Geant4 - ${plcio_LIBRARIES} ${podio_LIBRARIES} + INCLUDE_DIRS + # DetSimInterface + # FWCore + # DD4hep + # GaudiKernel + # Geant4 + # ${plcio_INCLUDE_DIRS} + # ${podio_INCLUDE_DIRS} + LINK_LIBRARIES + # DetSimInterface + # FWCore + DD4hep + ${DD4hep_COMPONENT_LIBRARIES} + GaudiKernel + # Geant4 + + -Wl,--no-as-needed + EDM4HEP::edm4hep EDM4HEP::edm4hepDict + -Wl,--as-needed + # ${podio_LIBRARIES} ) diff --git a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1efe317dacdd17cacbf796f7bd61241b7c9079b7 --- /dev/null +++ b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp @@ -0,0 +1,293 @@ +#include "Edm4hepWriterAnaElemTool.h" + +#include "G4Event.hh" +#include "G4THitsCollection.hh" + +#include "DD4hep/Detector.h" +#include "DD4hep/Plugins.h" +#include "DDG4/Geant4Converter.h" +#include "DDG4/Geant4Mapping.h" +#include "DDG4/Geant4HitCollection.h" +#include "DDG4/Geant4Data.h" +#include "DDG4/Geant4Hits.h" + +DECLARE_COMPONENT(Edm4hepWriterAnaElemTool) + +void +Edm4hepWriterAnaElemTool::BeginOfRunAction(const G4Run*) { + G4cout << "Begin Run of detector simultion..." << G4endl; +} + +void +Edm4hepWriterAnaElemTool::EndOfRunAction(const G4Run*) { + G4cout << "End Run of detector simultion..." << G4endl; +} + +void +Edm4hepWriterAnaElemTool::BeginOfEventAction(const G4Event* anEvent) { + msg() << "Event " << anEvent->GetEventID() << endmsg; + + // reset + m_track2primary.clear(); + +} + +void +Edm4hepWriterAnaElemTool::EndOfEventAction(const G4Event* anEvent) { + auto mcCol = m_mcParCol.get(); + msg() << "mcCol size: " << mcCol->size() << endmsg; + // save all data + + // create collections. + auto trackercols = m_trackerCol.createAndPut(); + auto calorimetercols = m_calorimeterCol.createAndPut(); + auto calocontribcols = m_caloContribCol.createAndPut(); + + auto vxdcols = m_VXDCol.createAndPut(); + auto ftdcols = m_FTDCol.createAndPut(); + auto sitcols = m_SITCol.createAndPut(); + auto tpccols = m_TPCCol.createAndPut(); + auto setcols = m_SETCol.createAndPut(); + + auto ecalbarrelcol = m_EcalBarrelCol.createAndPut(); + auto ecalbarrelcontribcols = m_EcalBarrelContributionCol.createAndPut(); + auto ecalendcapscol = m_EcalEndcapsCol.createAndPut(); + auto ecalendcapscontribcols = m_EcalEndcapsContributionCol.createAndPut(); + auto ecalendcapringcol = m_EcalEndcapRingCol.createAndPut(); + auto ecalendcapringcontribcol = m_EcalEndcapRingContributionCol.createAndPut(); + + // readout defined in DD4hep + auto lcdd = &(dd4hep::Detector::getInstance()); + auto allReadouts = lcdd->readouts(); + + for (auto& readout : allReadouts) { + info() << "Readout " << readout.first << endmsg; + } + + // retrieve the hit collections + G4HCofThisEvent* collections = anEvent->GetHCofThisEvent(); + if (!collections) { + warning() << "No collections found. " << endmsg; + return; + } + int Ncol = collections->GetNumberOfCollections(); + for (int icol = 0; icol < Ncol; ++icol) { + G4VHitsCollection* collect = collections->GetHC(icol); + if (!collect) { + warning() << "Collection iCol " << icol << " is missing" << endmsg; + continue; + } + size_t nhits = collect->GetSize(); + info() << "Collection " << collect->GetName() + << " #" << icol + << " has " << nhits << " hits." + << endmsg; + if (nhits==0) { + // just skip this collection. + continue; + } + + edm4hep::SimTrackerHitCollection* tracker_col_ptr = nullptr; + edm4hep::SimCalorimeterHitCollection* calo_col_ptr = nullptr; + edm4hep::CaloHitContributionCollection* calo_contrib_col_ptr = nullptr; + + // the mapping between hit collection and the data handler + if (collect->GetName() == "VXDCollection") { + tracker_col_ptr = vxdcols; + } else if (collect->GetName() == "FTDCollection") { + tracker_col_ptr = ftdcols; + } else if (collect->GetName() == "SITCollection") { + tracker_col_ptr = sitcols; + } else if (collect->GetName() == "TPCCollection") { + tracker_col_ptr = tpccols; + } else if (collect->GetName() == "SETCollection") { + tracker_col_ptr = setcols; + } else if (collect->GetName() == "SETCollection") { + tracker_col_ptr = setcols; + } else if (collect->GetName() == "CaloHitsCollection") { + calo_col_ptr = calorimetercols; + calo_contrib_col_ptr = calocontribcols; + } else if (collect->GetName() == "EcalBarrelCollection") { + calo_col_ptr = ecalbarrelcol; + calo_contrib_col_ptr = ecalbarrelcontribcols; + } else if (collect->GetName() == "EcalEndcapsCollection") { + calo_col_ptr = ecalendcapscol; + calo_contrib_col_ptr = ecalendcapscontribcols; + } else if (collect->GetName() == "EcalEndcapRingCollection") { + calo_col_ptr = ecalendcapringcol; + calo_contrib_col_ptr = ecalendcapringcontribcol; + } else { + warning() << "Unknown collection name: " << collect->GetName() + << ". Please register in Edm4hepWriterAnaElemTool. " << endmsg; + continue; + } + + + + // There are different types (new and old) + + dd4hep::sim::Geant4HitCollection* coll = dynamic_cast<dd4hep::sim::Geant4HitCollection*>(collect); + if (coll) { + info() << " cast to dd4hep::sim::Geant4HitCollection. " << endmsg; + for(size_t i=0; i<nhits; ++i) { + + dd4hep::sim::Geant4HitData* h = coll->hit(i); + + dd4hep::sim::Geant4Tracker::Hit* trk_hit = dynamic_cast<dd4hep::sim::Geant4Tracker::Hit*>(h); + if ( 0 != trk_hit ) { + dd4hep::sim::Geant4HitData::Contribution& t = trk_hit->truth; + int trackID = t.trackID; + // t.trackID = m_truth->particleID(trackID); + } + // Geant4Calorimeter::Hit* cal_hit = dynamic_cast<Geant4Calorimeter::Hit*>(h); + // if ( 0 != cal_hit ) { + // Geant4HitData::Contributions& c = cal_hit->truth; + // for(Geant4HitData::Contributions::iterator j=c.begin(); j!=c.end(); ++j) { + // Geant4HitData::Contribution& t = *j; + // int trackID = t.trackID; + // // t.trackID = m_truth->particleID(trackID); + // } + // } + } + continue; + } + + typedef G4THitsCollection<dd4hep::sim::Geant4Hit> HitCollection; + HitCollection* coll2 = dynamic_cast<HitCollection*>(collect); + + if (coll2) { + info() << " cast to G4THitsCollection<dd4hep::sim::Geant4Hit>. " << endmsg; + + int n_trk_hit = 0; + int n_cal_hit = 0; + + for(size_t i=0; i<nhits; ++i) { + dd4hep::sim::Geant4Hit* h = dynamic_cast<dd4hep::sim::Geant4Hit*>(coll2->GetHit(i)); + if (!h) { + warning() << "Failed to cast to dd4hep::sim::Geant4Hit. " << endmsg; + continue; + } + + dd4hep::sim::Geant4TrackerHit* trk_hit = dynamic_cast<dd4hep::sim::Geant4TrackerHit*>(h); + if (trk_hit) { + ++n_trk_hit; + // auto edm_trk_hit = trackercols->create(); + auto edm_trk_hit = tracker_col_ptr->create(); + + edm_trk_hit.setCellID(trk_hit->cellID); + edm_trk_hit.setEDep(trk_hit->energyDeposit/CLHEP::GeV); + edm_trk_hit.setTime(trk_hit->truth.time/CLHEP::ns); + edm_trk_hit.setPathLength(trk_hit->length/CLHEP::mm); + // lc_hit->setMCParticle(lc_mcp); + double pos[3] = {trk_hit->position.x()/CLHEP::mm, + trk_hit->position.y()/CLHEP::mm, + trk_hit->position.z()/CLHEP::mm}; + edm_trk_hit.setPosition(edm4hep::Vector3d(pos)); + + float mom[3] = {trk_hit->momentum.x()/CLHEP::GeV, + trk_hit->momentum.y()/CLHEP::GeV, + trk_hit->momentum.z()/CLHEP::GeV}; + edm_trk_hit.setMomentum(edm4hep::Vector3f(mom)); + } + + dd4hep::sim::Geant4CalorimeterHit* cal_hit = dynamic_cast<dd4hep::sim::Geant4CalorimeterHit*>(h); + if (cal_hit) { + ++n_cal_hit; + auto edm_calo_hit = calo_col_ptr->create(); + edm_calo_hit.setCellID(cal_hit->cellID); + edm_calo_hit.setEnergy(cal_hit->energyDeposit/CLHEP::GeV); + float pos[3] = {cal_hit->position.x()/CLHEP::mm, + cal_hit->position.y()/CLHEP::mm, + cal_hit->position.z()/CLHEP::mm}; + edm_calo_hit.setPosition(edm4hep::Vector3f(pos)); + + // contribution + typedef dd4hep::sim::Geant4CalorimeterHit::Contributions Contributions; + typedef dd4hep::sim::Geant4CalorimeterHit::Contribution Contribution; + for (Contributions::const_iterator j = cal_hit->truth.begin(); + j != cal_hit->truth.end(); ++j) { + const Contribution& c = *j; + // The legacy Hit object does not contains positions of contributions. + // float contrib_pos[] = {float(c.x/mm), float(c.y/mm), float(c.z/mm)}; + auto edm_calo_contrib = calo_contrib_col_ptr->create(); + edm_calo_contrib.setPDG(c.pdgID); + edm_calo_contrib.setEnergy(c.deposit/CLHEP::GeV); + edm_calo_contrib.setTime(c.time/CLHEP::ns); + edm_calo_contrib.setStepPosition(edm4hep::Vector3f(pos)); + + // from the track id, get the primary track + int pritrkid = m_track2primary[c.trackID]; + if (pritrkid<=0) { + error() << "Failed to find the primary track for trackID #" << c.trackID << endmsg; + pritrkid = 1; + } + + edm_calo_contrib.setParticle(mcCol->at(pritrkid-1)); // todo + edm_calo_hit.addToContributions(edm_calo_contrib); + } + } + + } + + info() << n_trk_hit << " hits cast to dd4hep::sim::Geant4TrackerHit. " << endmsg; + info() << n_cal_hit << " hits cast to dd4hep::sim::Geant4CalorimeterHit. " << endmsg; + + + continue; + } + + warning() << "Failed to convert to collection " + << collect->GetName() + << endmsg; + + } +} + +void +Edm4hepWriterAnaElemTool::PreUserTrackingAction(const G4Track* track) { + int curtrkid = track->GetTrackID(); + int curparid = track->GetParentID(); + int pritrkid = curparid; + + // try to find the primary track id from the parent track id. + if (curparid) { + auto it = m_track2primary.find(curparid); + if (it == m_track2primary.end()) { + error() << "Failed to find primary track for track id " << curparid << endmsg; + } else { + pritrkid = it->second; + } + } else { + // curparid is 0, it is primary + pritrkid = curtrkid; + } + + + m_track2primary[curtrkid] = pritrkid; +} + +void +Edm4hepWriterAnaElemTool::PostUserTrackingAction(const G4Track*) { + +} + +void +Edm4hepWriterAnaElemTool::UserSteppingAction(const G4Step*) { + +} + +StatusCode +Edm4hepWriterAnaElemTool::initialize() { + StatusCode sc; + + return sc; +} + +StatusCode +Edm4hepWriterAnaElemTool::finalize() { + StatusCode sc; + + return sc; +} + + diff --git a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.h b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.h new file mode 100644 index 0000000000000000000000000000000000000000..2e69d24e8f6d5858f1efa86a543c2816aefbf83d --- /dev/null +++ b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.h @@ -0,0 +1,100 @@ +#ifndef Edm4hepWriterAnaElemTool_h +#define Edm4hepWriterAnaElemTool_h + +#include <map> + +#include "GaudiKernel/AlgTool.h" +#include "FWCore/DataHandle.h" +#include "DetSimInterface/IAnaElemTool.h" + +#include "edm4hep/MCParticleCollection.h" +#include "edm4hep/SimTrackerHitCollection.h" +#include "edm4hep/SimCalorimeterHitCollection.h" +#include "edm4hep/CaloHitContributionCollection.h" + +class Edm4hepWriterAnaElemTool: public extends<AlgTool, IAnaElemTool> { + +public: + + using extends::extends; + + /// IAnaElemTool interface + // Run + virtual void BeginOfRunAction(const G4Run*) override; + virtual void EndOfRunAction(const G4Run*) override; + + // Event + virtual void BeginOfEventAction(const G4Event*) override; + virtual void EndOfEventAction(const G4Event*) override; + + // Tracking + virtual void PreUserTrackingAction(const G4Track*) override; + virtual void PostUserTrackingAction(const G4Track*) override; + + // Stepping + virtual void UserSteppingAction(const G4Step*) override; + + + /// Overriding initialize and finalize + StatusCode initialize() override; + StatusCode finalize() override; + +private: + // In order to associate MCParticle with contribution, we need to access MC Particle. + DataHandle<edm4hep::MCParticleCollection> m_mcParCol{"MCParticle", + Gaudi::DataHandle::Writer, this}; + + // Generic collections for Tracker and Calorimeter + DataHandle<edm4hep::SimTrackerHitCollection> m_trackerCol{"SimTrackerCol", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::SimCalorimeterHitCollection> m_calorimeterCol{"SimCalorimeterCol", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::CaloHitContributionCollection> m_caloContribCol{"SimCaloContributionCol", + Gaudi::DataHandle::Writer, this}; + + // Dedicated collections for CEPC + DataHandle<edm4hep::SimTrackerHitCollection> m_VXDCol{"VXDCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::SimTrackerHitCollection> m_FTDCol{"FTDCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::SimTrackerHitCollection> m_SITCol{"SITCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::SimTrackerHitCollection> m_TPCCol{"TPCCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::SimTrackerHitCollection> m_SETCol{"SETCollection", + Gaudi::DataHandle::Writer, this}; + + // Ecal + DataHandle<edm4hep::SimCalorimeterHitCollection> m_EcalBarrelCol{"EcalBarrelCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::CaloHitContributionCollection> m_EcalBarrelContributionCol{ + "EcalBarrelContributionCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::SimCalorimeterHitCollection> m_EcalEndcapsCol{"EcalEndcapsCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::CaloHitContributionCollection> m_EcalEndcapsContributionCol{ + "EcalEndcapsContributionCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::SimCalorimeterHitCollection> m_EcalEndcapRingCol{"EcalEndcapRingCollection", + Gaudi::DataHandle::Writer, this}; + DataHandle<edm4hep::CaloHitContributionCollection> m_EcalEndcapRingContributionCol{ + "EcalEndcapRingContributionCollection", + Gaudi::DataHandle::Writer, this}; + +private: + // in order to associate the hit contribution with the primary track, + // we have a bookkeeping of every track. + // The primary track will assign the same key/value. + + // Following is an example: + // 1 -> 1, + // 2 -> 2, + // 3 -> 1, + // Now, if parent of trk #4 is trk #3, using the mapping {3->1} could + // locate the primary trk #1. + + std::map<int, int> m_track2primary; + +}; + +#endif diff --git a/Simulation/DetSimCore/CMakeLists.txt b/Simulation/DetSimCore/CMakeLists.txt index 95d56bc0fff525e284be32dc355be27c9207a0c9..bf58dded63633952e51bc3400513d450366c60e6 100644 --- a/Simulation/DetSimCore/CMakeLists.txt +++ b/Simulation/DetSimCore/CMakeLists.txt @@ -9,7 +9,8 @@ gaudi_depends_on_subdirs( find_package(Geant4 REQUIRED ui_all vis_all) include(${Geant4_USE_FILE}) find_package(podio REQUIRED) -find_package(plcio REQUIRED) +find_package(EDM4HEP REQUIRED) +find_package(DD4hep COMPONENTS DDG4 REQUIRED) set(DetSimCore_srcs src/DetSimAlg.cpp @@ -24,7 +25,20 @@ set(DetSimCore_srcs src/SteppingAction.cpp ) +message(" Geant4_LIBRARIES: ${Geant4_LIBRARIES}") + gaudi_add_module(DetSimCore ${DetSimCore_srcs} - INCLUDE_DIRS DetSimInterface GaudiKernel Geant4 plcio ${plcio_INCLUDE_DIRS} ${podio_INCLUDE_DIRS} - LINK_LIBRARIES DetSimInterface GaudiKernel Geant4 plcio podio + INCLUDE_DIRS + # DetSimInterface + # GaudiKernel + # Geant4 + # plcio ${plcio_INCLUDE_DIRS} ${podio_INCLUDE_DIRS} + LINK_LIBRARIES + DetSimInterface + GaudiKernel + # Geant4 + # ${Geant4_LIBRARIES} + DD4hep ${DD4hep_COMPONENT_LIBRARIES} + EDM4HEP::edm4hep EDM4HEP::edm4hepDict + # podio ) diff --git a/Simulation/DetSimCore/src/G4PrimaryCnvTool.cpp b/Simulation/DetSimCore/src/G4PrimaryCnvTool.cpp index 3a79e9d95bf268bd5777ed88d6321b369b103c66..d725aa27dead84d3b95df9fc66c0c990f9189fe4 100644 --- a/Simulation/DetSimCore/src/G4PrimaryCnvTool.cpp +++ b/Simulation/DetSimCore/src/G4PrimaryCnvTool.cpp @@ -24,7 +24,7 @@ bool G4PrimaryCnvTool::mutate(G4Event* anEvent) { } // vertex - const plcio::DoubleThree& vertex = p.getVertex(); + const edm4hep::Vector3d& vertex = p.getVertex(); double t = p.getTime()*CLHEP::ns; G4PrimaryVertex* g4vtx = new G4PrimaryVertex(vertex.x*CLHEP::mm, vertex.y*CLHEP::mm, @@ -36,7 +36,7 @@ bool G4PrimaryCnvTool::mutate(G4Event* anEvent) { G4ParticleDefinition* particle_def = particletbl->FindParticle(pdgcode); // momentum - const plcio::FloatThree& momentum = p.getMomentum(); + const edm4hep::Vector3f& momentum = p.getMomentum(); G4PrimaryParticle* g4prim = new G4PrimaryParticle(particle_def, momentum.x*CLHEP::GeV, momentum.y*CLHEP::GeV, diff --git a/Simulation/DetSimCore/src/G4PrimaryCnvTool.h b/Simulation/DetSimCore/src/G4PrimaryCnvTool.h index 3aaf2997ceccd780f3b477809db33ba093d791b0..ed0fd4b5ba5453ad229d9e0981eced6e6036c9d4 100644 --- a/Simulation/DetSimCore/src/G4PrimaryCnvTool.h +++ b/Simulation/DetSimCore/src/G4PrimaryCnvTool.h @@ -5,8 +5,8 @@ #include "DetSimInterface/IG4PrimaryCnvTool.h" #include "FWCore/DataHandle.h" -#include "plcio/EventHeaderCollection.h" -#include "plcio/MCParticleCollection.h" +#include "edm4hep/EventHeaderCollection.h" +#include "edm4hep/MCParticleCollection.h" class G4PrimaryCnvTool: public extends<AlgTool, IG4PrimaryCnvTool> { public: @@ -16,7 +16,7 @@ public: bool mutate(G4Event* anEvent) override; private: - DataHandle<plcio::MCParticleCollection> m_mcParCol{"MCParticle", Gaudi::DataHandle::Reader, this}; + DataHandle<edm4hep::MCParticleCollection> m_mcParCol{"MCParticle", Gaudi::DataHandle::Reader, this}; }; diff --git a/Simulation/DetSimGeom/CMakeLists.txt b/Simulation/DetSimGeom/CMakeLists.txt index fa2c440132cce35f7cbe21f14bbc850f42c2eac7..a3b5f3249132d19400359fd728b2dbe676df34a9 100644 --- a/Simulation/DetSimGeom/CMakeLists.txt +++ b/Simulation/DetSimGeom/CMakeLists.txt @@ -16,6 +16,14 @@ set(DetSimGeom_srcs ) gaudi_add_module(DetSimGeom ${DetSimGeom_srcs} - INCLUDE_DIRS DetSimInterface DetInterface DD4hep GaudiKernel Geant4 - LINK_LIBRARIES DetSimInterface DD4hep ${DD4hep_COMPONENT_LIBRARIES} GaudiKernel Geant4 + INCLUDE_DIRS + # DetSimInterface + # DetInterface + # DD4hep + # GaudiKernel + # Geant4 + LINK_LIBRARIES + DD4hep ${DD4hep_COMPONENT_LIBRARIES} + GaudiKernel + # Geant4 ) diff --git a/Simulation/DetSimGeom/src/AnExampleDetElemTool.cpp b/Simulation/DetSimGeom/src/AnExampleDetElemTool.cpp index 8ba60b44292a86bf678bbfe650b1e44078bcbfb9..ff31cdf11c5cf4167272597d227ea9c58a0f997e 100644 --- a/Simulation/DetSimGeom/src/AnExampleDetElemTool.cpp +++ b/Simulation/DetSimGeom/src/AnExampleDetElemTool.cpp @@ -92,7 +92,26 @@ AnExampleDetElemTool::ConstructSDandField() { << endmsg; // continue; // Sensitive detectors are deleted in ~G4SDManager - G4VSensitiveDetector* g4sd = dd4hep::PluginService::Create<G4VSensitiveDetector*>(typ, nam, lcdd); + G4VSensitiveDetector* g4sd = nullptr; + + // try to use SD tool to find the SD + if (!g4sd) { + if (typ=="calorimeter") { + m_calo_sdtool = ToolHandle<ISensDetTool>("CalorimeterSensDetTool"); + if (m_calo_sdtool) { + info() << "Find the CalorimeterSensDetTool." << endmsg; + g4sd = m_calo_sdtool->createSD(nam); + info() << "create g4SD: " << g4sd << endmsg; + } + } else if (typ=="tracker") { + + } + } + + if (!g4sd) { + g4sd = dd4hep::PluginService::Create<G4VSensitiveDetector*>(typ, nam, lcdd); + } + if (g4sd == nullptr) { std::string tmp = typ; tmp[0] = ::toupper(tmp[0]); diff --git a/Simulation/DetSimGeom/src/AnExampleDetElemTool.h b/Simulation/DetSimGeom/src/AnExampleDetElemTool.h index 7c922dad0e2d7c5a44c8c2ea869024b48e913135..b0b22861b892c0817876e9c325853e843acf7dc4 100644 --- a/Simulation/DetSimGeom/src/AnExampleDetElemTool.h +++ b/Simulation/DetSimGeom/src/AnExampleDetElemTool.h @@ -3,11 +3,14 @@ #include "GaudiKernel/AlgTool.h" #include "GaudiKernel/Property.h" -#include "DetSimInterface/IDetElemTool.h" +#include <GaudiKernel/ToolHandle.h> + #include "G4SystemOfUnits.hh" #include "G4PhysicalConstants.hh" #include "DetInterface/IGeoSvc.h" +#include "DetSimInterface/IDetElemTool.h" +#include "DetSimInterface/ISensDetTool.h" class AnExampleDetElemTool: public extends<AlgTool, IDetElemTool> { @@ -29,7 +32,7 @@ private: Gaudi::Property<std::string> m_dd4hep_xmls{this, "detxml"}; SmartIF<IGeoSvc> m_geosvc; - + ToolHandle<ISensDetTool> m_calo_sdtool; }; #endif diff --git a/Simulation/DetSimInterface/CMakeLists.txt b/Simulation/DetSimInterface/CMakeLists.txt index 1eec6f6e84ca919543dcf62995c4ada9937649e4..8950d300d14e0df6f5319d26bd209a2a79a28b31 100644 --- a/Simulation/DetSimInterface/CMakeLists.txt +++ b/Simulation/DetSimInterface/CMakeLists.txt @@ -1,6 +1,8 @@ gaudi_subdir(DetSimInterface v0r0) +gaudi_depends_on_subdirs(GaudiKernel) + # DetSimInterface (headers only) set(DetSimInterface_srcs src/IDetSimSvc.cpp diff --git a/Simulation/DetSimInterface/DetSimInterface/ISensDetTool.h b/Simulation/DetSimInterface/DetSimInterface/ISensDetTool.h new file mode 100644 index 0000000000000000000000000000000000000000..bdba7547e422e2f290e0d306db7fa0a8ad89dac6 --- /dev/null +++ b/Simulation/DetSimInterface/DetSimInterface/ISensDetTool.h @@ -0,0 +1,28 @@ +#ifndef ISensDetTool_h +#define ISensDetTool_h +/* + * ISensDetTool is a tool to configure and create a Geant4's sensitive detector. + * After create the SD, the Geant4 will take ownership of the SD. + * + * This tool is used to replace the DDG4's Geant4SensitiveDetector. + * It will be invoked in ConstructSDandField(). + * + * -- 12 June 2020, Tao Lin <lintao@ihep.ac.cn> + */ + +#include "GaudiKernel/IAlgTool.h" + +class G4VSensitiveDetector; + +class ISensDetTool: virtual public IAlgTool { +public: + + DeclareInterfaceID(ISensDetTool, 0, 1); + + virtual ~ISensDetTool() {}; + + virtual G4VSensitiveDetector* createSD(const std::string& name) = 0; + +}; + +#endif diff --git a/Simulation/DetSimSD/CMakeLists.txt b/Simulation/DetSimSD/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..10b1a15a3f0d9ed6cf91a635ea6d53eca49daba3 --- /dev/null +++ b/Simulation/DetSimSD/CMakeLists.txt @@ -0,0 +1,35 @@ + +gaudi_subdir(DetSimSD v0r0) + +gaudi_depends_on_subdirs( + FWCore + Detector/DetInterface + Simulation/DetSimInterface +) + +find_package(Geant4 REQUIRED ui_all vis_all) +include(${Geant4_USE_FILE}) +find_package(DD4hep COMPONENTS DDG4 REQUIRED) + +set(DetSimSD_srcs + src/CalorimeterSensDetTool.cpp + + src/DDG4SensitiveDetector.cpp + src/CaloSensitiveDetector.cpp +) + +gaudi_add_module(DetSimSD ${DetSimSD_srcs} + INCLUDE_DIRS + # DetSimInterface + # FWCore + # DD4hep + # GaudiKernel + # Geant4 + LINK_LIBRARIES + # DetSimInterface + # FWCore + DD4hep + ${DD4hep_COMPONENT_LIBRARIES} + GaudiKernel + # Geant4 +) diff --git a/Simulation/DetSimSD/DetSimSD/CaloSensitiveDetector.h b/Simulation/DetSimSD/DetSimSD/CaloSensitiveDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..28b3ab3b11f7e48b6f300402e1e9e9edefd986bb --- /dev/null +++ b/Simulation/DetSimSD/DetSimSD/CaloSensitiveDetector.h @@ -0,0 +1,36 @@ +#ifndef CaloSensitiveDetector_h +#define CaloSensitiveDetector_h + +/* + * This is an implementation of Calo SD. + * + * -- 13 June 2020, Tao Lin <lintao@ihep.ac.cn> + */ + +#include "DetSimSD/DDG4SensitiveDetector.h" + +class CaloSensitiveDetector: public DDG4SensitiveDetector { +public: + typedef dd4hep::sim::Geant4CalorimeterHit CalorimeterHit; + typedef G4THitsCollection<CalorimeterHit> CaloHitCollection; + +public: + CaloSensitiveDetector(const std::string& name, dd4hep::Detector& description); + +public: + // Geant4 interface + + virtual void Initialize(G4HCofThisEvent* HCE); + virtual G4bool ProcessHits(G4Step* step,G4TouchableHistory* history); + virtual void EndOfEvent(G4HCofThisEvent* HCE); + +protected: + CalorimeterHit* find(const HitCollection*, const dd4hep::sim::HitCompare<CalorimeterHit>&); + +protected: + + HitCollection* m_hc; +}; + + +#endif diff --git a/Simulation/DetSimSD/DetSimSD/DDG4SensitiveDetector.h b/Simulation/DetSimSD/DetSimSD/DDG4SensitiveDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..f7806f7de5f97c5cf36a60c6b22e6d1491ccb24e --- /dev/null +++ b/Simulation/DetSimSD/DetSimSD/DDG4SensitiveDetector.h @@ -0,0 +1,71 @@ +#ifndef DDG4SensitiveDetector_h +#define DDG4SensitiveDetector_h + +/* + * In order to access ID from DDG4, some utilities are necessary to retrieve information + * from DDG4. This base class defines such interfaces and utilities. + * + * Refer to the class DDG4/include/DDG4/Geant4SensitiveDetector.h for some APIs usage. + * + * We keep to reuse some types already defined in DDG4: + * - Geant4Hits + * + * -- 12 June 2020, Tao Lin <lintao@ihep.ac.cn> + */ + + +#include "DD4hep/Detector.h" +#include "DDG4/Geant4Hits.h" + +#include "G4Step.hh" +#include "G4HCofThisEvent.hh" +#include "G4TouchableHistory.hh" +#include "G4VSensitiveDetector.hh" +#include "G4THitsCollection.hh" + + +class DDG4SensitiveDetector: public G4VSensitiveDetector { +public: + typedef dd4hep::sim::Geant4Hit Geant4Hit; + typedef G4THitsCollection<dd4hep::sim::Geant4Hit> HitCollection; + typedef dd4hep::sim::Geant4Hit::Contribution HitContribution; + +public: + DDG4SensitiveDetector(const std::string& name, dd4hep::Detector& description); + +public: + // Geant4 interface + + virtual void Initialize(G4HCofThisEvent* HCE); + virtual G4bool ProcessHits(G4Step* step,G4TouchableHistory* history); + virtual void EndOfEvent(G4HCofThisEvent* HCE); + +public: + // DDG4 utilities + /// Returns the volumeID of the sensitive volume corresponding to the step - + /// combining the VolIDS of the complete geometry path (Geant4TouchableHistory) + // from the current sensitive volume to the world volume + virtual long long getVolumeID(G4Step* step); + + /// Returns the volumeID of the sensitive volume corresponding to the step - + /// combining the VolIDS of the complete geometry path (Geant4TouchableHistory) + // from the current sensitive volume to the world volume + virtual long long getCellID(G4Step* step); + + +protected: + /// Reference to the detector description object + dd4hep::Detector& m_detDesc; + + /// Reference to the detector element describing this sensitive element + dd4hep::DetElement m_detector; + + /// Reference to the sensitive detector element + dd4hep::SensitiveDetector m_sensitive; + + /// Reference to the readout structure + dd4hep::Readout m_readout; + +}; + +#endif diff --git a/Simulation/DetSimSD/src/CaloSensitiveDetector.cpp b/Simulation/DetSimSD/src/CaloSensitiveDetector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1547f9fe3506be659803ef0d8f5da2e3bcd79fdf --- /dev/null +++ b/Simulation/DetSimSD/src/CaloSensitiveDetector.cpp @@ -0,0 +1,68 @@ +#include "DetSimSD/CaloSensitiveDetector.h" + +#include "G4SDManager.hh" + +#include <algorithm> + +CaloSensitiveDetector::CaloSensitiveDetector(const std::string& name, dd4hep::Detector& description) + : DDG4SensitiveDetector(name, description), + m_hc(nullptr) { + const std::string& coll_name = m_sensitive.hitsCollection(); + collectionName.insert(coll_name); +} + +void +CaloSensitiveDetector::Initialize(G4HCofThisEvent* HCE) { + + // the collection name is provided by DD4hep + const std::string& coll_name = collectionName[0]; + // m_hc = new G4THitsCollection<CalorimeterHit>(GetName(), coll_name); + m_hc = new HitCollection(GetName(), coll_name); + + int HCID = -1; + if(HCID<0) HCID = G4SDManager::GetSDMpointer()->GetCollectionID(m_hc); + HCE->AddHitsCollection( HCID, m_hc ); + +} + +G4bool +CaloSensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*) { + + // std::cout << "CaloSensitiveDetector::ProcessHits" << std::endl; + + dd4hep::sim::Geant4StepHandler h(step); + dd4hep::Position pos = 0.5 * (h.prePos() + h.postPos()); + HitContribution contrib = dd4hep::sim::Geant4Hit::extractContribution(step); + CalorimeterHit* hit=find(m_hc,dd4hep::sim::HitPositionCompare<CalorimeterHit>(pos)); + + // G4cout << "----------- Geant4GenericSD<Calorimeter>::buildHits : position : " << pos << G4endl; + if ( !hit ) { + hit = new CalorimeterHit(pos); + hit->cellID = getCellID( step ); + m_hc->insert(hit); + } + hit->truth.push_back(contrib); + hit->energyDeposit += contrib.deposit; + + + + return true; +} + +void +CaloSensitiveDetector::EndOfEvent(G4HCofThisEvent* HCE) { + +} + +CaloSensitiveDetector::CalorimeterHit* +CaloSensitiveDetector::find(const CaloSensitiveDetector::HitCollection* c, + const dd4hep::sim::HitCompare<CaloSensitiveDetector::CalorimeterHit>& cmp) { + typedef std::vector<CalorimeterHit*> _V; + const _V* v = (const _V*) c->GetVector(); + for (_V::const_iterator i = v->begin(); i != v->end(); ++i) { + if (cmp(*i)) { + return *i; + } + } + return 0; +} diff --git a/Simulation/DetSimSD/src/CalorimeterSensDetTool.cpp b/Simulation/DetSimSD/src/CalorimeterSensDetTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d8c30b10e8663a8977f99aa08eefd0113f2c3918 --- /dev/null +++ b/Simulation/DetSimSD/src/CalorimeterSensDetTool.cpp @@ -0,0 +1,43 @@ +#include "CalorimeterSensDetTool.h" + +#include "G4VSensitiveDetector.hh" + +#include "DetSimSD/CaloSensitiveDetector.h" + +#include "DD4hep/Detector.h" + +DECLARE_COMPONENT(CalorimeterSensDetTool); + +StatusCode +CalorimeterSensDetTool::initialize() { + StatusCode sc; + + + m_geosvc = service<IGeoSvc>("GeoSvc"); + if (!m_geosvc) { + error() << "Failed to find GeoSvc." << endmsg; + return StatusCode::FAILURE; + } + + + return sc; +} + +StatusCode +CalorimeterSensDetTool::finalize() { + StatusCode sc; + + return sc; +} + +G4VSensitiveDetector* +CalorimeterSensDetTool::createSD(const std::string& name) { + + dd4hep::Detector* dd4hep_geo = m_geosvc->lcdd(); + + G4VSensitiveDetector* sd = new CaloSensitiveDetector(name, *dd4hep_geo); + + return sd; +} + + diff --git a/Simulation/DetSimSD/src/CalorimeterSensDetTool.h b/Simulation/DetSimSD/src/CalorimeterSensDetTool.h new file mode 100644 index 0000000000000000000000000000000000000000..775d24510bba9da061e0a76ae2816cc762f7ada6 --- /dev/null +++ b/Simulation/DetSimSD/src/CalorimeterSensDetTool.h @@ -0,0 +1,34 @@ +#ifndef CalorimeterSensDetTool_h +#define CalorimeterSensDetTool_h + +/* + * CalorimeterSensDetTool is used to create the Calorimeter SD. + * + * -- 12 June 2020, Tao Lin <lintao@ihep.ac.cn> + */ + +#include "GaudiKernel/AlgTool.h" +#include "DetSimInterface/ISensDetTool.h" +#include "DetInterface/IGeoSvc.h" + +class CalorimeterSensDetTool: public extends<AlgTool, ISensDetTool> { + +public: + + using extends::extends; + + /// Overriding initialize and finalize + StatusCode initialize() override; + StatusCode finalize() override; + + /// Override ISensDetTool + virtual G4VSensitiveDetector* createSD(const std::string& name) override; + +private: + + // in order to initialize SD, we need to get the lcdd() + SmartIF<IGeoSvc> m_geosvc; + +}; + +#endif diff --git a/Simulation/DetSimSD/src/DDG4SensitiveDetector.cpp b/Simulation/DetSimSD/src/DDG4SensitiveDetector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25ce06c0a2da935a1d8d7e4bad09e360962f1985 --- /dev/null +++ b/Simulation/DetSimSD/src/DDG4SensitiveDetector.cpp @@ -0,0 +1,76 @@ +#include "DetSimSD/DDG4SensitiveDetector.h" + +#include "DDG4/Geant4SensitiveDetector.h" +#include "DDG4/Geant4Converter.h" +#include "DDG4/Geant4Hits.h" +#include "DD4hep/Segmentations.h" + +#include "DD4hep/Printout.h" +#include "DD4hep/Detector.h" + +// Geant4 include files +#include "G4Step.hh" +#include "G4PVPlacement.hh" + +// ROOT include files +#include "TGeoNode.h" + +#include "DD4hep/DD4hepUnits.h" +#include "CLHEP/Units/SystemOfUnits.h" + +// convert from CLHEP to DD4hep +static const double MM_2_CM = (dd4hep::millimeter/CLHEP::millimeter); + + +DDG4SensitiveDetector::DDG4SensitiveDetector(const std::string& name, dd4hep::Detector& description) + : G4VSensitiveDetector(name), m_detDesc(description), + m_detector(), m_sensitive(), m_readout() { + m_detector = description.detector(name); + m_sensitive = description.sensitiveDetector(name); + m_readout = m_sensitive.readout(); + +} + +void +DDG4SensitiveDetector::Initialize(G4HCofThisEvent* HCE) { + +} + +G4bool +DDG4SensitiveDetector::ProcessHits(G4Step* step, G4TouchableHistory*) { + + return true; +} + +void +DDG4SensitiveDetector::EndOfEvent(G4HCofThisEvent* HCE) { + +} + +long long +DDG4SensitiveDetector::getVolumeID(G4Step* aStep) { + + dd4hep::sim::Geant4StepHandler step(aStep); + dd4hep::sim::Geant4VolumeManager volMgr = dd4hep::sim::Geant4Mapping::instance().volumeManager(); + dd4hep::VolumeID id = volMgr.volumeID(step.preTouchable()); + + return id; +} + +long long +DDG4SensitiveDetector::getCellID(G4Step* step) { + dd4hep::sim::Geant4StepHandler h(step); + dd4hep::sim::Geant4VolumeManager volMgr = dd4hep::sim::Geant4Mapping::instance().volumeManager(); + dd4hep::VolumeID volID = volMgr.volumeID(h.preTouchable()); + + dd4hep::Segmentation seg = m_readout.segmentation(); + if ( seg.isValid() ) { + G4ThreeVector global = 0.5 * ( h.prePosG4()+h.postPosG4()); + G4ThreeVector local = h.preTouchable()->GetHistory()->GetTopTransform().TransformPoint(global); + dd4hep::Position loc(local.x()*MM_2_CM, local.y()*MM_2_CM, local.z()*MM_2_CM); + dd4hep::Position glob(global.x()*MM_2_CM, global.y()*MM_2_CM, global.z()*MM_2_CM); + dd4hep::VolumeID cID = seg.cellID(loc,glob,volID); + return cID; + } + return volID; +}