diff --git a/CMakeLists.txt b/CMakeLists.txt index d61767cd27059897de71b342b0a5ae64cb6b7c71..52ac9db021b8950221e1c903844cc0a56e322fa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,11 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.12) project(EICD VERSION 1.1.0 LANGUAGES CXX) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + #--- Declare options ----------------------------------------------------------- option(BUILD_DATA_MODEL "Run podio class generator yaml file" ON) @@ -47,7 +50,7 @@ PODIO_GENERATE_DICTIONARY(eicd ${headers} set_target_properties(eicd-dictgen PROPERTIES EXCLUDE_FROM_ALL TRUE) target_sources(eicd PRIVATE eicd.cxx) -add_subdirectory(source) +add_subdirectory(utils) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/eicd diff --git a/eic_data.yaml b/eic_data.yaml index 53cdde0c6125e4e773acb768fe9d38bfc7bdfc08..7932b84e9c481ee339af4b108f32b1fc646626e0 100644 --- a/eic_data.yaml +++ b/eic_data.yaml @@ -41,7 +41,7 @@ components: bool operator==(const eic::Index& rhs) const {return equals(rhs);}\n bool operator!=(const eic::Index& rhs) const {return !equals(rhs);}\n bool operator<(const eic::Index& rhs) const {return long_form() < rhs.long_form();}\n - int64_t long_form() const {int64_t l = static_cast<int64_t>(source) << 32 | value; return l;}\n + uint64_t long_form() const {int64_t l = static_cast<int64_t>(source) << 32 | value; return l;}\n explicit operator bool() const {return valid();} " @@ -57,24 +57,6 @@ components: operator float() const {return value;} " - - ## first-second pair of float s - eic::FloatPair: - Members: - - float first - - float second - ExtraCode: - includes: "#include <tuple>" - declaration: " - FloatPair() : first{0}, second{0} {}\n - FloatPair(double a, double b) : first{static_cast<float>(a)}, second{static_cast<float>(b)} {}\n - FloatPair(const std::pair<float, float>& p) : first{p.first}, second{p.second} {}\n - FloatPair& operator=(const std::pair<float, float>& p) {first = p.first; second = p.second; return *this;}\n - float& operator[](unsigned i) {return *(&first + i);}\n - const float& operator[](unsigned i) const {return *(&first + i);}\n - operator std::pair<float, float>() const {return {first, second};}\n - " - eic::VectorXY: Members: - float x // [mm] or [GeV] @@ -96,23 +78,44 @@ components: VectorXY scale(double f) const {return {f*x, f*y};}\n " - eic::Direction: + # Copy from EDM4hep with conversion operators added + # TODO: uncomment Vector2f conversions when we migrate to new EDM4hep version + eicd::Vector2f : Members: - - float theta // [rad, 0->pi] - - float phi // [rad, -pi->pi] + - float a + - float b + ExtraCode: + declaration: " + Vector2f() : a(0),b(0) {}\n + Vector2f(float aa,float bb) : a(aa),b(bb) {}\n + Vector2f(const float* v) : a(v[0]), b(v[1]) {}\n + bool operator==(const Vector2f& v) const { return (a==v.a&&b==v.b) ; }\n + float operator[](unsigned i) const { return *( &a + i ) ; }\n + //Vector2f(const edm4hep::Vector2f& v) : a{v.a}, b{v.b} {}\n + //operator edm4hep::Vector2f() const {return {a, b};}\n + " + includes: " + // #include <edm4hep/Vector2f.h>\n + " + + # Copy from EDM4hep with conversion operators added + eicd::Vector3f : + Members: + - float x + - float y + - float z ExtraCode: - includes: "#include <cmath>\n#include <tuple>" declaration: " - Direction() : theta{0}, phi{0} {}\n - Direction(double th, double ph) : theta{static_cast<float>(th)}, phi{static_cast<float>(ph)} {}\n - Direction(double x, double y, double z)\n - : theta{static_cast<float>(acos(z/std::hypot(x,y,z)))}\n - , phi{static_cast<float>(atan2(y,x))} {}\n - template <class VectorType> Direction(const VectorType& v) : Direction(v.theta(), v.phi()) {}\n - operator std::pair<float, float>() const {return {theta, phi};}\n - float eta() const {return -log(tan(0.5*theta));}\n - Direction add(const Direction& rhs) const {return {theta+rhs.theta, phi+rhs.phi};}\n - Direction subtract(const Direction& rhs) const {return {theta-rhs.theta, phi-rhs.phi};}\n + Vector3f() : x(0),y(0),z(0) {}\n + Vector3f(float xx, float yy, float zz) : x(xx),y(yy),z(zz) {}\n + Vector3f(const float* v) : x(v[0]),y(v[1]),z(v[2]) {}\n + bool operator==(const Vector3f& v) const { return (x==v.x&&y==v.y&&z==v.z) ; }\n + float operator[](unsigned i) const { return *( &x + i ) ; }\n + Vector3f(const edm4hep::Vector3f& v) : x{v.x}, y{v.y}, z{v.z} {} + operator edm4hep::Vector3f() const {return {x, y, z};}\n + " + includes: " + #include <edm4hep/Vector3f.h>\n " eic::VectorXYZ: @@ -125,7 +128,8 @@ components: declaration: " VectorXYZ() : x{0}, y{0}, z{0} {}\n VectorXYZ(double xx, double yy, double zz) : x{static_cast<float>(xx)}, y{static_cast<float>(yy)}, z{static_cast<float>(zz)} {}\n - template<class VectorPolarType> VectorXYZ(const VectorPolarType& v) : VectorXYZ(v.x(), v.y(), v.z()) {}\n + template <class V> + VectorXYZ(const V& v) : x{v.x}, y{v.y}, z{v.z} {}\n float& operator[](unsigned i) {return *(&x + i);}\n const float& operator[](unsigned i) const {return *(&x + i);}\n float mag() const {return std::hypot(x, y, z);}\n @@ -138,25 +142,7 @@ components: VectorXYZ add(const VectorXYZ& rhs) const {return {x+rhs.x, y+rhs.y, z+rhs.z};}\n VectorXYZ subtract(const VectorXYZ& rhs) const {return {x-rhs.x, y-rhs.y, z-rhs.z};}\n VectorXYZ scale(double f) const {return {f*x, f*y, f*z};}\n - " - eic::VectorPolar: - Members: - - float r // [mm] or [GeV] - - float theta // [rad, 0->pi] - - float phi // [rad, -pi->pi] - ExtraCode: - includes: "#include <cmath>\n#include<tuple>" - declaration: " - VectorPolar() : r{0}, theta{0}, phi{0} {}\n - VectorPolar(double rr, double th, double ph) : r{static_cast<float>(rr)}, theta{static_cast<float>(th)}, phi{static_cast<float>(ph)} {}\n - template<class VectorXYZType> VectorPolar(const VectorXYZType& v) : VectorPolar(v.r(), v.theta(), v.phi()) {}\n - float mag() const {return r;}\n - float x() const {return r * cos(phi) * sin(theta);}\n - float y() const {return r * sin(phi) * sin(theta);}\n - float z() const {return r * cos(theta);}\n - float eta() const {return -log(tan(0.5*theta));}\n - operator std::tuple<float, float, float>() {return {r, theta, phi};}\n - " + " eic::VectorXYZT: Members: @@ -265,12 +251,6 @@ components: return *(&xy + i + j - 1);\n }\n " - ## ProtoCluster hit relation - eic::ProtoClusterHit: - Members: - - eic::Index ID // ID of the hit - - uint32_t index // Raw index of the hit in the relevant array - - eic::Weight weight // weight of the hit ## A point along a track eic::TrackPoint: @@ -314,8 +294,8 @@ datatypes: Author: "W. Armstrong, S. Joosten" Members: - eic::Index ID // Unique particle index - - eic::VectorXYZ p // Momentum [GeV] - - eic::VectorXYZ v // Vertex [mm] + - eicd::Vector3f p // Momentum [GeV] + - eicd::Vector3f v // Vertex [mm] - float time // Time in [ns] - int32_t pid // Particle PDG code - int16_t status // Status code @@ -334,7 +314,8 @@ datatypes: - int16_t status // Status code - int16_t charge // Particle charge (or sign) - eic::Weight weight // Particle weight, e.g. from PID algorithm [0-1] - - eic::Direction direction // Direction (theta/phi of this particle [rad]) + - float theta // Polar angle of this particle [rad] + - float phi // Azimuthal angle of this particle [rad] - float momentum // particle 3-momentum magnitude [GeV] - float energy // Particle energy, consistent with PID assigment [GeV] - float mass // The mass of the particle in [GeV] @@ -353,80 +334,61 @@ datatypes: Description: "Raw (digitized) calorimeter hit" Author: "W. Armstrong, S. Joosten" Members: - - eic::Index ID // Unique hit ID. For MC, the value equals the Geant4 hit index. - - int64_t cellID // The detector specific (geometrical) cell id. - - int64_t amplitude // The amplitude of the hit in ADC counts. - - int64_t time // Timing in TDC + - uint64_t cellID // The detector specific (geometrical) cell id. + - uint64_t amplitude // The amplitude of the hit in ADC counts. + - uint64_t timeStamp // Timing in TDC eic::CalorimeterHit: Description: "Calorimeter hit" Author: "W. Armstrong, S. Joosten" Members: - - eic::Index ID // Unique hit ID, same as one of the involved raw hits. - - int64_t cellID // The detector specific (geometrical) cell id. - - int32_t layer // Layer for this hit - - int32_t sector // Sector for this hit + - uint64_t cellID // The detector specific (geometrical) cell id. - float energy // The energy for this hit in [GeV]. - float energyError // Error on energy [GeV]. - float time // The time of the hit in [ns]. + - float timeError // Error on the time - eic::VectorXYZ position // The global position of the hit in world coordinates [mm]. - - eic::VectorXYZ local // The local position of the hit in detector coordinates [mm]. - eic::VectorXYZ dimension // The dimension information of the cell [mm]. - ## TODO: deterimine if position/dimension is really what we want - ## compared to position/positionError for consistency with TrackerHit - + - int32_t sector // Sector that this hit occured in + - int32_t layer // Layer that the hit occured in + - eic::VectorXYZ local // The local coordinates of the hit in the detector segment [mm]. ## ========================================================================== ## Clustering ## ========================================================================== eic::ProtoCluster: - Description: "Relational info linking hits to their associated cluster" + Description: "Collection of hits identified by the clustering algorithm to belong together" Author: "S. Joosten" - Members: - - eic::Index ID // ID of the cluster + OneToManyRelations: + - eic::CalorimeterHit hits // Hits associated with this cluster VectorMembers: - - eic::ProtoClusterHit hits // List of hits associated with the cluster + - float weights // Weight for each of the hits, mirrors hits array eic::Cluster: - Description: "EIC cluster" + Description: "EIC hit cluster, reworked to more closely resemble EDM4hep" Author: "W. Armstrong, S. Joosten, C.Peng" Members: - - eic::Index ID // Unique ID for this cluster, value identical to ProtoCluster ID + # main variables + - int32_t type // Flagword that defines the type of the cluster - float energy // Reconstructed energy of the cluster [GeV]. - float energyError // Error on the cluster energy [GeV] - float time // [ns] + - float timeError // Error on the cluster time - uint32_t nhits // Number of hits in the cluster. - eic::VectorXYZ position // Global position of the cluster [mm]. - eic::CovXYZ positionError // Covariance matrix of the position (6 Parameters). - - float radius // Shower radius [mm] - - float skewness // Shower skewness [unitless] - - eic::VectorPolar polar // Cluster position polar information - - float eta // Cluster pseudorapidity - - eic::Direction direction // Intrinsic direction of the cluster propagation [rad, 0->pi, -pi->pi] - - eic::Index mcID // For MC only - associated MC particle - - eic::ClusterLayer: - Description: "2D Cluster in a single layer for a multi-layer detector" - Author: "S. Joosten, C. Peng" - Members: - - eic::Index ID // Unique layer ID - - eic::Index clusterID // Associated full 3D cluster, -1 if none - - int32_t layer // Layer number for this cluster layer - - uint32_t nhits // Number of hits - - float energy // Energy in this cluster layer [GeV] - - float energyError // Error on energy [GeV] - - float radius // Shower radius [mm] - - float skewness // Skewness of hits distribution - - eic::VectorXYZ position // Global center position. [mm] - - eic::MergedClusterRelations: - Description: "Relational info between a merged cluster and its parents" - Author: "S. Joosten" - Members: - - eic::Index clusterID // Associated cluster ID - - uint32_t size // Number of valid parents - - std::array<eic::Index, 4> parent // (Up to 4) parents for this cluster + - float intrinsicTheta // Intrinsic cluster propagation direction polar angle [rad] + - float intrinsicPhi // Intrinsic cluster propagation direction azimuthal angle [rad] + - eic::CovXY intrinsicDirectionError // Error on the intrinsic cluster propagation direction + VectorMembers: + - float shapeParameters // Should be set in metadata, for now radius/skewness + - float hitContributions // Energy contributions of the hits. Runs parallel to ::hits() + - float subdetectorEnergies // Energies observed in each subdetector used for this cluster. + OneToManyRelations: + - eic::Cluster clusters // Clusters that have been combined to form this cluster + - eic::CalorimeterHit hits // Hits that have been combined to form this cluster + #- eic::ParticleID particleIDs // Particle IDs sorted by likelihood, TODO ## ========================================================================== ## RICH/Cherenkov data structures @@ -437,7 +399,7 @@ datatypes: Author: "S. Joosten, C. Peng" Members: - eic::Index ID // Unique hit ID. For MC, the value equals the Geant4 hit index. - - int64_t cellID // The detector specific (geometrical) cell id. + - uint64_t cellID // The detector specific (geometrical) cell id. - uint32_t amplitude // PMT signal amplitude [ADC] - uint32_t time // PMT signal time [TDC] @@ -446,7 +408,7 @@ datatypes: Author: "S. Joosten, C. Peng" Members: - eic::Index ID // Unique hit ID, same as one of the involved raw hits. - - int64_t cellID // The detector specific (geometrical) cell id. + - uint64_t cellID // The detector specific (geometrical) cell id. - float npe // Estimated number of photo-electrons [#] - float time // Time [ns] - float timeError // Error on the time [ns] @@ -476,7 +438,7 @@ datatypes: Author: "W. Armstrong, S. Joosten" Members: - eic::Index ID // Unique hit ID. For MC, the value equals the Geant4 hit index. - - int64_t cellID // The detector specific (geometrical) cell id. + - uint64_t cellID // The detector specific (geometrical) cell id. - int32_t time // TDC value. - int32_t charge // ADC value @@ -485,7 +447,7 @@ datatypes: Author: "W. Armstrong, S. Joosten" Members: - eic::Index ID // Unique hit ID, same as one of the involved raw hits. - - int64_t cellID // The detector specific (geometrical) cell id. + - uint64_t cellID // The detector specific (geometrical) cell id. - eic::VectorXYZ position // Hit (cell) position and time [mm, ns] - eic::CovDiagXYZ positionError // Covariance Matrix - float time // Hit time diff --git a/source/include/eicd/helpers.h b/source/include/eicd/helpers.h deleted file mode 100644 index 0fb2e9d6d31ed0760c029f6ccc5d4d9469b6ea1d..0000000000000000000000000000000000000000 --- a/source/include/eicd/helpers.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef EICD_HELPERS_HH -#define EICD_HELPERS_HH - - -#include <algorithm> -#include <cmath> -#include <exception> -#include <limits> -#include <string> -#include <vector> - -#include <Math/Vector4D.h> - -#include "eicd/TrackParametersCollection.h" -#include "eicd/ReconstructedParticleCollection.h" -#include "eicd/ReconstructedParticleData.h" - -namespace eicd::helpers { - - /** Four momentum from track and mass. - * Get a vector of 4-momenta from raw tracking info, using an externally - * provided particle mass assumption. - */ - inline auto momenta_from_tracking(const std::vector<eic::TrackParametersData>& tracks, - const double mass) - { - std::vector<ROOT::Math::PxPyPzMVector> momenta{tracks.size()}; - // transform our raw tracker info into proper 4-momenta - std::transform(tracks.begin(), tracks.end(), momenta.begin(), [mass](const auto& track) { - // make sure we don't divide by zero - if (fabs(track.qOverP) < 1e-9) { - return ROOT::Math::PxPyPzMVector{}; - } - const double p = fabs(1. / track.qOverP); - const double px = p * cos(track.phi) * sin(track.theta); - const double py = p * sin(track.phi) * sin(track.theta); - const double pz = p * cos(track.theta); - return ROOT::Math::PxPyPzMVector{px, py, pz, mass}; - }); - return momenta; - } -} // namespace eicd::helpers -#endif diff --git a/source/src/helpers.cxx b/source/src/helpers.cxx deleted file mode 100644 index d52ef6cd0ba1ad3d121246913a2e65dfbad11e3b..0000000000000000000000000000000000000000 --- a/source/src/helpers.cxx +++ /dev/null @@ -1,3 +0,0 @@ -#include "eicd/helpers.h" - - diff --git a/source/CMakeLists.txt b/utils/CMakeLists.txt similarity index 80% rename from source/CMakeLists.txt rename to utils/CMakeLists.txt index f820ec3874635437379a348f469ff18afaf36464..dba4b55269ca897529d0144b4fd30d8eb64ffee7 100644 --- a/source/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -10,35 +10,36 @@ find_package(ROOT REQUIRED COMPONENTS GenVector MathCore) # ) #add_custom_target(G__NPDetGeoCad_ROOTDICT DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/G__NPDetGeoCad.cxx) -add_library(eicd_core SHARED - src/helpers.cxx +add_library(eicd_utils SHARED + src/utils.cxx ) -target_compile_features(eicd_core +target_compile_features(eicd_utils PUBLIC cxx_auto_type PUBLIC cxx_trailing_return_types PUBLIC cxx_std_17 PRIVATE cxx_variadic_templates ) -target_compile_options(eicd_core PRIVATE +target_compile_options(eicd_utils PRIVATE -Wno-extra -Wno-ignored-qualifiers -Wno-overloaded-virtual -Wno-shadow) -target_link_libraries(eicd_core +target_link_libraries(eicd_utils PUBLIC eicd PUBLIC ROOT::GenVector ROOT::MathCore) -target_include_directories(eicd_core +target_include_directories(eicd_utils PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PUBLIC $<INSTALL_INTERFACE:include> ) install(FILES - include/eicd/helpers.h + include/eicd/analysis_utils.h + include/eicd/vector_utils.h DESTINATION include/eicd ) #install(FILES @@ -47,7 +48,7 @@ install(FILES # DESTINATION lib) -install(TARGETS eicd_core +install(TARGETS eicd_utils EXPORT ${PROJECT_NAME}Targets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib diff --git a/utils/include/eicd/analysis_utils.h b/utils/include/eicd/analysis_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..8a55a27cbe2d58c951be5194ebdbaaf83ebfc7f2 --- /dev/null +++ b/utils/include/eicd/analysis_utils.h @@ -0,0 +1,43 @@ +#ifndef EICD_UTILS_ANALYSIS_HH +#define EICD_UTILS_ANALYSIS_HH + +#include <algorithm> +#include <cmath> +#include <exception> +#include <limits> +#include <string> +#include <vector> + +#include <Math/Vector4D.h> + +#include <eicd/ReconstructedParticleCollection.h> +#include <eicd/ReconstructedParticleData.h> +#include <eicd/TrackParametersCollection.h> + +namespace eicd { + +/** Four momentum from track and mass. + * Get a vector of 4-momenta from raw tracking info, using an externally + * provided particle mass assumption. + */ +inline auto +momenta_from_tracking(const std::vector<eic::TrackParametersData>& tracks, + const double mass) { + std::vector<ROOT::Math::PxPyPzMVector> momenta{tracks.size()}; + // transform our raw tracker info into proper 4-momenta + std::transform(tracks.begin(), tracks.end(), momenta.begin(), + [mass](const auto& track) { + // make sure we don't divide by zero + if (fabs(track.qOverP) < 1e-9) { + return ROOT::Math::PxPyPzMVector{}; + } + const double p = fabs(1. / track.qOverP); + const double px = p * cos(track.phi) * sin(track.theta); + const double py = p * sin(track.phi) * sin(track.theta); + const double pz = p * cos(track.theta); + return ROOT::Math::PxPyPzMVector{px, py, pz, mass}; + }); + return momenta; +} +} // namespace eicd +#endif diff --git a/utils/include/eicd/vector_utils.h b/utils/include/eicd/vector_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..1c816282ece9f3b1c51447c2f3aeb87103747fb5 --- /dev/null +++ b/utils/include/eicd/vector_utils.h @@ -0,0 +1,133 @@ +#ifndef EICD_UTILS_VECTOR_HH +#define EICD_UTILS_VECTOR_HH + +#include <algorithm> +#include <cmath> +#include <exception> +#include <limits> +#include <string> +#include <vector> + +#include <Math/Vector4D.h> + +#include <edm4hep/Vector3f.h> + +#include <eicd/ReconstructedParticleCollection.h> +#include <eicd/ReconstructedParticleData.h> +#include <eicd/TrackParametersCollection.h> + +namespace eicd { + +template <class V> concept VectorHasX = requires(V v) { v.x; }; +template <class V> concept VectorHasY = requires(V v) { v.y; }; +template <class V> concept VectorHasZ = requires(V v) { v.z; }; +template <class V> concept ClassVector = requires(V v) { v.x(); }; +template <class V> +concept Vector2D = + VectorHasX<V>&& VectorHasY<V> && !VectorHasZ<V> && !ClassVector<V>; +template <class V> +concept Vector3D = + VectorHasX<V>&& VectorHasY<V>&& VectorHasZ<V> && !ClassVector<V>; +template <class V> concept VectorND = Vector2D<V> || Vector3D<V>; + +inline double etaToAngle(const double eta) { + return std::atan(std::exp(-eta)) * 2.; +} +inline double angleToEta(const double theta) { + return -std::log(std::tan(0.5 * theta)); +} + +// inline edm4hep::Vector2f VectorFromPolar(const double r, const double theta) +// { +// return {r * sin(theta), r * cos(theta)}; +//} +template <Vector3D V = edm4hep::Vector3f> +V sphericalToVector(const double r, const double theta, const double phi) { + using FloatType = decltype(V().x); + const double sth = sin(theta); + const double cth = cos(theta); + const double sph = sin(phi); + const double cph = cos(phi); + const FloatType x = r * sth * cph; + const FloatType y = r * sth * sph; + const FloatType z = r * cth; + return {x, y, z}; +} + +template <Vector3D V> double anglePolar(const V& v) { + return std::atan2(std::hypot(v.x, v.y), v.z); +} +template <VectorND V> double angleAzimuthal(const V& v) { + return std::atan2(v.y, v.x); +} +template <Vector3D V> double eta(const V& v) { + return angleToEta(anglePolar(v)); +} +template <Vector2D V> double magnitude(const V& v) { + return std::hypot(v.x, v.y); +} +template <Vector3D V> double magnitude(const V& v) { + return std::hypot(v.x, v.y, v.z); +} +template <Vector3D V> double magnitudeTransverse(const V& v) { + return std::hypot(v.x, v.y); +} +template <Vector3D V> double magnitudeLongitudinal(const V& v) { return v.z; } +template <VectorND V> V normalizeVector(const V& v, double norm = 1.) { + const double old = magnitude(v); + if (old == 0) { + return v; + } + return (norm > 0) ? v * norm / old : v * 0; +} +template <Vector3D V> V vectorTransverse(const V& v) { return {v.x, v.y, 0}; } +template <Vector3D V> V vectorLongitudinal(const V& v) { return {0, 0, v.z}; } +// Two vector functions +template <VectorND V> double angleBetween(const V& v1, const V& v2) { + const double dot = v1 * v2; + if (dot == 0) { + return 0.; + } + return acos(dot / (magnitude(v1) * magnitude(v2))); +} +// Project v onto v1 +template <Vector3D V> double projection(const V& v, const V& v1) { + const double norm = magnitude(v1); + if (norm == 0) { + return magnitude(v); + } + return v * v1 / norm; +} + +} // namespace eicd +template <eicd::Vector2D V> V operator+(const V& v1, const V& v2) { + return {v1.x + v2.x, v1.y + v2.y}; +} +template <eicd::Vector3D V> V operator+(const V& v1, const V& v2) { + return {v1.x + v2.x, v1.y + v2.y, v1.z + v2.z}; +} +template <eicd::Vector2D V> double operator*(const V& v1, const V& v2) { + return v1.x * v2.x + v1.y * v2.y; +} +template <eicd::Vector3D V> double operator*(const V& v1, const V& v2) { + return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; +} +template <eicd::Vector2D V> V operator*(const double d, const V& v) { + return {d * v.x, d * v.y}; +} +template <eicd::Vector3D V> V operator*(const double d, const V& v) { + return {d * v.x, d * v.y, d * v.z}; +} +template <eicd::Vector2D V> V operator*(const V& v, const double d) { + return {d * v.x, d * v.y}; +} +template <eicd::Vector3D V> V operator*(const V& v, const double d) { + return {d * v.x, d * v.y, d * v.z}; +} +template <eicd::VectorND V> V operator-(const V& v1, const V& v2) { + return v1 + (-1. * v2); +} +template <eicd::VectorND V> V operator/(const V& v, const double d) { + return (1. / d) * v; +} +#endif diff --git a/utils/src/utils.cxx b/utils/src/utils.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2e1256b5e6315132d0206281b00bda86924bcdea --- /dev/null +++ b/utils/src/utils.cxx @@ -0,0 +1,2 @@ +#include "eicd/analysis_utils.h" +#include "eicd/vector_utils.h"