├── src ├── modules │ ├── loki │ │ ├── geometry │ │ │ └── PanelGeometry.h │ │ ├── test │ │ │ └── PanelGeometryTest.cpp │ │ ├── configs │ │ │ ├── old │ │ │ │ ├── STFCTestIII.json │ │ │ │ ├── STFCTestII.json │ │ │ │ └── Loki.json │ │ │ └── LokiFull.json │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ └── generators │ │ │ ├── ReadoutGenerator.h │ │ │ ├── udpgen.cpp │ │ │ └── CMakeLists.txt │ ├── cspec │ │ ├── configs │ │ │ └── cspec.json │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ └── test │ │ │ └── CMakeLists.txt │ ├── miracles │ │ ├── configs │ │ │ └── miracles.json │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ ├── generators │ │ │ ├── CMakeLists.txt │ │ │ └── DatReader.h │ │ └── test │ │ │ └── CMakeLists.txt │ ├── bifrost │ │ ├── configs │ │ │ └── bifrost.json │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ ├── generators │ │ │ ├── udpgen.cpp │ │ │ └── CMakeLists.txt │ │ └── geometry │ │ │ └── BifrostConfig.h │ ├── dream │ │ ├── configs │ │ │ ├── DreamEndcap.json │ │ │ ├── fwec.json │ │ │ ├── hr.json │ │ │ └── sans.json │ │ ├── main.cpp │ │ ├── main_magic.cpp │ │ ├── main_heimdal.cpp │ │ ├── Counters.h │ │ ├── generators │ │ │ ├── udpgen.cpp │ │ │ ├── g4data │ │ │ │ ├── udpgen.cpp │ │ │ │ └── CMakeLists.txt │ │ │ └── CMakeLists.txt │ │ ├── geometry │ │ │ ├── DreamMantle.cpp │ │ │ ├── HeimdalMantle.cpp │ │ │ └── GeometryModule.h │ │ └── readout │ │ │ └── DataParser.h │ ├── tbl3he │ │ ├── configs │ │ │ ├── tbl3he.json │ │ │ ├── tbl3heconstcalib.json │ │ │ └── tbl3henullcalib.json │ │ ├── main.cpp │ │ ├── CMakeLists.txt │ │ └── test │ │ │ └── CMakeLists.txt │ ├── cbm │ │ ├── configs │ │ │ ├── cbm2Dtest.json │ │ │ ├── ibmtest.json │ │ │ ├── amor_onsite_ibm.json │ │ │ ├── utgaard_ibm_test.json │ │ │ ├── utgaard_ttl_test.json │ │ │ └── cbmtest.json │ │ ├── test │ │ │ ├── cbm_config_test.json │ │ │ └── cbm_base_test.json │ │ ├── main.cpp │ │ ├── generators │ │ │ ├── CMakeLists.txt │ │ │ └── udpgen.cpp │ │ └── Counters.h │ ├── timepix3 │ │ ├── configs │ │ │ └── timepix3.json │ │ ├── generators │ │ │ └── CMakeLists.txt │ │ ├── main.cpp │ │ ├── test │ │ │ ├── TimepixTestHelper.h │ │ │ └── util │ │ │ │ └── gen_readouts.py │ │ ├── Timepix3Base.h │ │ └── geometry │ │ │ └── Config.h │ ├── perfgen │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ └── PerfGenBase.h │ ├── nmx │ │ ├── main.cpp │ │ ├── NMXBase.h │ │ ├── generators │ │ │ ├── ReadoutGenerator.h │ │ │ ├── SmileReadoutGenerator.h │ │ │ ├── MultiHitReadoutGenerator.h │ │ │ ├── TrackReadoutGenerator.h │ │ │ ├── udpgen.cpp │ │ │ ├── udpgen_smile.cpp │ │ │ ├── udpgen_track.cpp │ │ │ └── udpgen_multihit.cpp │ │ ├── test │ │ │ └── CMakeLists.txt │ │ ├── CMakeLists.txt │ │ └── Counters.h │ ├── trex │ │ ├── main.cpp │ │ ├── configs │ │ │ └── let.json │ │ ├── TREXBase.h │ │ ├── generators │ │ │ ├── ReadoutGenerator.h │ │ │ ├── LETReadoutGenerator.h │ │ │ ├── udpgen.cpp │ │ │ └── udpgen_let.cpp │ │ ├── Counters.h │ │ ├── CMakeLists.txt │ │ ├── test │ │ │ └── CMakeLists.txt │ │ ├── geometry │ │ │ └── Geometry.h │ │ └── readout │ │ │ └── DataParser.h │ ├── freia │ │ ├── main_estia.cpp │ │ ├── main_freia.cpp │ │ ├── main_tblmb.cpp │ │ ├── FreiaBase.h │ │ ├── geometry │ │ │ └── TBLMBGeometry.h │ │ ├── generators │ │ │ ├── ReadoutGenerator.h │ │ │ ├── mb_udpgen.cpp │ │ │ └── udpgen.cpp │ │ └── Counters.h │ ├── caen │ │ ├── CaenBase.h │ │ ├── generators │ │ │ ├── udpgen.cpp │ │ │ └── CMakeLists.txt │ │ ├── CaenCounters.h │ │ └── geometry │ │ │ └── Interval.cpp │ └── CMakeLists.txt ├── efu │ ├── CMakeLists.txt │ ├── Executing artefacts.md │ ├── efu.md │ ├── test │ │ ├── CMakeLists.txt │ │ └── HwCheckTest.cpp │ ├── Graylog.h │ ├── ExitHandler.h │ ├── Launcher.cpp │ └── MainProg.h ├── common │ ├── readout │ │ ├── vmm3 │ │ │ ├── test │ │ │ │ ├── invalid_json_file.json │ │ │ │ ├── HybridTest.cpp │ │ │ │ └── vmm_config.json │ │ │ └── CMakeLists.txt │ │ ├── ess │ │ │ └── CMakeLists.txt │ │ └── CMakeLists.txt │ ├── system │ │ ├── arm.h │ │ ├── intel.h │ │ ├── SocketInterface.h │ │ └── gccintel.h │ ├── time │ │ ├── TimeString.h │ │ ├── TimeString.cpp │ │ ├── CMakeLists.txt │ │ ├── Timer.cpp │ │ └── Timer.h │ ├── reduction │ │ ├── test │ │ │ ├── HitVectorBenchmark.cpp │ │ │ ├── HitTest.cpp │ │ │ └── CMakeLists.txt │ │ ├── analysis │ │ │ ├── AbstractAnalyzer.cpp │ │ │ ├── test │ │ │ │ ├── AbstractAnalyzerTest.cpp │ │ │ │ └── CMakeLists.txt │ │ │ ├── CMakeLists.txt │ │ │ ├── EventAnalyzer.h │ │ │ └── AbstractAnalyzer.h │ │ ├── multigrid │ │ │ └── CMakeLists.txt │ │ ├── NeutronEvent.cpp │ │ ├── Hit.cpp │ │ ├── Hit2D.cpp │ │ ├── matching │ │ │ ├── test │ │ │ │ └── CMakeLists.txt │ │ │ ├── CMakeLists.txt │ │ │ ├── OverlapMatcher.h │ │ │ └── EndMatcher.h │ │ ├── clustering │ │ │ ├── test │ │ │ │ ├── Abstract2DClustererTest.cpp │ │ │ │ └── CMakeLists.txt │ │ │ └── CMakeLists.txt │ │ ├── NeutronEvent.h │ │ ├── reduction.md │ │ ├── CMakeLists.txt │ │ └── ReducedEvent.cpp │ ├── kafka │ │ ├── kafka.json │ │ ├── serializer │ │ │ └── CMakeLists.txt │ │ └── test │ │ │ ├── KafkaConfigTest.cpp │ │ │ └── AR51SerializerTest.cpp │ ├── monitor │ │ ├── DynamicHist.h │ │ ├── test │ │ │ └── CMakeLists.txt │ │ ├── CMakeLists.txt │ │ ├── Monitor.h │ │ ├── HistogramSerializer.h │ │ └── DynamicHist.cpp │ ├── debug │ │ ├── Hexdump.h │ │ ├── Expect.h │ │ ├── Log.cpp │ │ ├── Hexdump.cpp │ │ ├── Time.h │ │ └── TraceGroups.h │ ├── test │ │ └── ESSGeometryBenchmarkTest.cpp │ ├── testutils │ │ ├── SaveBuffer.h │ │ ├── DataFuzzer.cpp │ │ └── SaveBuffer.cpp │ ├── math │ │ ├── Units.h │ │ └── BitMath.h │ └── config │ │ └── Config.cpp ├── generators │ ├── CMakeLists.txt │ ├── udpgenpcap │ │ └── CMakeLists.txt │ └── functiongenerators │ │ ├── CMakeLists.txt │ │ └── FunctionGenerator.h └── README.md ├── documentation ├── figures │ └── efu_architecture.png ├── minimaldetector │ └── CMakeLists.txt ├── README.md └── DIRECTORIES.md ├── cmake ├── EnsureBuildType.cmake ├── templates │ ├── version_num.h.in │ └── Version.h.in ├── BuildString.cmake ├── AddTargetFlags.cmake ├── Memcheck.cmake └── modules │ ├── FindValgrindSdk.cmake │ └── FindIspc.cmake ├── generate-changelog.sh ├── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── utils ├── qtrunefu │ ├── efucfg │ └── README.md └── efushell │ ├── getstat.py │ ├── isefurunning.py │ ├── EFUMetrics.py │ ├── SocketDriver.py │ ├── efustatus.py │ └── efustatstocsv.py ├── CHANGELOG ├── changelog_2025-12-17.md └── changelog_2025-10-23.md ├── conanfile.txt ├── Dockerfile ├── docker_launch.sh ├── .ci └── docker │ └── Dockerfile_entrypoint.sh ├── LICENSE └── test └── performancetest.json /src/modules/loki/geometry/PanelGeometry.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/modules/loki/test/PanelGeometryTest.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/efu/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(test) 3 | -------------------------------------------------------------------------------- /src/modules/cspec/configs/cspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector": "cspec", 3 | "MaxRing": 4, 4 | "Resolution": 300, 5 | "MaxGroup": 180 6 | } 7 | -------------------------------------------------------------------------------- /documentation/figures/efu_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ess-dmsc/event-formation-unit/HEAD/documentation/figures/efu_architecture.png -------------------------------------------------------------------------------- /src/common/readout/vmm3/test/invalid_json_file.json: -------------------------------------------------------------------------------- 1 | "Even though I pretend to be, I am not a valid JSON file" 2 | { 3 | "key1" : 10, 4 | "key2" : 11, 5 | } 6 | -------------------------------------------------------------------------------- /src/modules/miracles/configs/miracles.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector": "miracles", 3 | "MaxRing": 4, 4 | "Resolution": 128, 5 | "MaxTOFNS" : 1000000000 6 | } 7 | -------------------------------------------------------------------------------- /src/modules/bifrost/configs/bifrost.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector": "bifrost", 3 | "MaxRing": 4, 4 | "Resolution": 300, 5 | "MaxGroup": 15, 6 | "MaxAmpl": 32767 7 | } 8 | -------------------------------------------------------------------------------- /src/common/system/arm.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | static __inline__ unsigned long long rdtsc() { 4 | unsigned long long val; 5 | asm volatile("mrs %0, cntvct_el0" : "=r" (val)); 6 | return val; 7 | } -------------------------------------------------------------------------------- /src/modules/dream/configs/DreamEndcap.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector": "DREAM", 4 | 5 | "MaxPulseTimeDiffNS" : 5000000000, 6 | 7 | "Config" : [ 8 | { "Ring" : 0, "FEN": 0, "Type": "BwEndCap"} 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /src/generators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 - 2024 European Spallation Source, ERIC. See LICENSE file 2 | #============================================================================= 3 | 4 | add_subdirectory(functiongenerators) 5 | add_subdirectory(udpgenpcap) 6 | -------------------------------------------------------------------------------- /src/common/system/intel.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | /// read time stamp counter - runs at processer Hz 4 | static __inline__ unsigned long long rdtsc() { 5 | unsigned hi, lo; 6 | __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); 7 | return ((unsigned long long)lo) | (((unsigned long long)hi) << 32); 8 | } -------------------------------------------------------------------------------- /cmake/EnsureBuildType.cmake: -------------------------------------------------------------------------------- 1 | option(CMAKE_BUILD_TYPE "Build type; \"Release\" or \"Debug\"." Debug) 2 | 3 | if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 4 | message(STATUS "Setting build type to 'Debug' as none was specified.") 5 | set(CMAKE_BUILD_TYPE Debug) 6 | else () 7 | message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") 8 | endif() 9 | -------------------------------------------------------------------------------- /src/modules/tbl3he/configs/tbl3he.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector": "tbl3he", 3 | "Resolution": 100, 4 | "MaxGroup": 7, 5 | "MaxPulseTimeNS" : 71428600, 6 | 7 | "NumOfFENs" : 2, 8 | 9 | "MinValidAmplitude" : 2, 10 | 11 | "Topology" : [ 12 | {"Ring" : 10, "FEN" : 0, "Bank" : 0}, 13 | {"Ring" : 9, "FEN" : 0, "Bank" : 1} 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /documentation/minimaldetector/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Detector Pipeline Plugins 3 | #============================================================================= 4 | 5 | set(minimaldetector_SRC 6 | minimaldetector.cpp 7 | ) 8 | # set(minimaldetector_INC 9 | # ) 10 | create_module(minimaldetector) 11 | -------------------------------------------------------------------------------- /src/common/readout/ess/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # ESS Readout System Tests 3 | #============================================================================= 4 | 5 | set(ReadoutParserTest_INC Parser.h ParserTestData.h) 6 | set(ReadoutParserTest_SRC ParserTest.cpp Parser.cpp) 7 | create_test_executable(ReadoutParserTest) 8 | -------------------------------------------------------------------------------- /src/modules/cbm/configs/cbm2Dtest.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "CBM", 4 | 5 | "TypeSubType" : 16, 6 | 7 | "MaxPulseTimeDiffNS" : 1000000000, 8 | 9 | "MaxTOFNS" : 10000000000, 10 | 11 | "MonitorRing" : 11, 12 | 13 | "MaxFENId" : 2, 14 | 15 | "Topology" : [ 16 | { "FEN": 0, "Channel": 3, "Type": "EVENT_2D", "Source" : "cbm", "Width": 512, "Height": 512} 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/cbm/configs/ibmtest.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "CBM", 4 | 5 | "TypeSubType" : 16, 6 | 7 | "MaxPulseTimeDiffNS" : 1000000000, 8 | 9 | "MaxTOFNS" : 10000000000, 10 | 11 | "MonitorRing" : 11, 12 | 13 | "MaxFENId" : 2, 14 | 15 | "Topology" : [ 16 | { "FEN": 0, "Channel": 0, "Type": "IBM", "Source" : "cbm1", "MaxTofBin": 71428572, "BinCount": 512} 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /generate-changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Changelog Generator Launcher 3 | # This script provides a convenient way to run the changelog generator using uv 4 | 5 | # Get the directory where this script is located (project root) 6 | PROJECT_ROOT="$(cd "$(dirname "$0")" && pwd)" 7 | 8 | # Change to project root and run with uv 9 | cd "$PROJECT_ROOT" 10 | uv run utils/changelog/generate_changelog.py "$@" 11 | -------------------------------------------------------------------------------- /src/modules/cbm/configs/amor_onsite_ibm.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "CBM", 4 | 5 | "TypeSubType" : 16, 6 | 7 | "MaxPulseTimeDiffNS" : 1000000000, 8 | 9 | "MaxTOFNS" : 10000000000, 10 | 11 | "MonitorRing" : 3, 12 | 13 | "MaxFENId" : 2, 14 | 15 | "Topology" : [ 16 | { "FEN": 0, "Channel": 0, "Type": "IBM", "Source" : "cbm1", "MaxTofBin": 150000000, "BinCount": 1500} 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/cbm/configs/utgaard_ibm_test.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "CBM", 4 | 5 | "TypeSubType" : 16, 6 | 7 | "MaxPulseTimeDiffNS" : 1000000000, 8 | 9 | "MaxTOFNS" : 10000000000, 10 | 11 | "MonitorRing" : 0, 12 | 13 | "MaxFENId" : 2, 14 | 15 | "Topology" : [ 16 | { "FEN": 0, "Channel": 0, "Type": "IBM", "Source" : "cbm1", "MaxTofBin": 71428572, "BinCount": 512} 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/loki/configs/old/STFCTestIII.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Comment" : "March 2022 test - Ring 0 has 16 FENs, part of bank 0", 4 | 5 | "Detector": "loki", 6 | 7 | "StrawResolution" : 512, 8 | 9 | "MaxPulseTimeNS" : 357142857, 10 | 11 | "MaxTOF" : 800000000, 12 | 13 | "PanelConfig" : [ 14 | { "Bank" : 0, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 32, "StrawOffset" : 0 } 15 | ] 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/efu/Executing artefacts.md: -------------------------------------------------------------------------------- 1 | # Running artefacts 2 | 3 | If you have downloaded the binary artifacts of this repository compiled using our Jenkins build nodes, you will need to manually set the path to the *lib* directory. This is done by setting the `LD_LIBRARY_PATH` environment variable. E.g. to run the EFU using the sonde module, execute the following line: 4 | 5 | ``` 6 | LD_LIBRARY_PATH=../lib ./efu -d ../lib/sonde 7 | ``` 8 | -------------------------------------------------------------------------------- /src/common/time/TimeString.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Get current time as a string 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | #include 11 | 12 | std::string timeString(); 13 | -------------------------------------------------------------------------------- /src/modules/timepix3/configs/timepix3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector": "timepix3", 3 | "XResolution": 256, 4 | "YResolution": 256, 5 | "ScaleUpFactor": 4, 6 | "ParallelThreads": 1, 7 | "comment": "ParallelThreads - Is the number of threads used for parallel processing during clustering. Value has to be power of 2", 8 | "MaxTimeGapNS": 800, 9 | "MaxCoordinateGap": 4, 10 | "MinEventSizeHits": 9, 11 | "FrequencyHz": 10 12 | } -------------------------------------------------------------------------------- /src/common/reduction/test/HitVectorBenchmark.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void BM_pushback_hits(benchmark::State &state) { 5 | HitVector hits; 6 | for (auto _ : state) { 7 | Hit hit; 8 | hit.coordinate = 50; 9 | hit.weight = 50; 10 | hit.time = 50; 11 | hits.push_back(hit); 12 | } 13 | } 14 | BENCHMARK(BM_pushback_hits); 15 | BENCHMARK_MAIN(); 16 | -------------------------------------------------------------------------------- /src/modules/perfgen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(.) 2 | 3 | #============================================================================= 4 | # Detector Pipeline Plugins 5 | #============================================================================= 6 | set(perfgen_INC 7 | PerfGenBase.h 8 | ) 9 | set(perfgen_SRC 10 | PerfGenBase.cpp 11 | main.cpp 12 | ) 13 | 14 | set(perfgen_LIB efu_essreadout) 15 | create_executable(perfgen) 16 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Issue reference / description 2 | 3 | The branch you merge from should already reference an event-formation-unit github ticket number. You can add a descriptive title, but if an issue is referenced, you don't have to. 4 | 5 | ## Checklist for submitter 6 | 7 | - [ ] Check for conflict with integration test 8 | - [ ] Unit tests pass 9 | 10 | --- 11 | 12 | ### Nominate for Group Code Review 13 | 14 | - [ ] Nominate for code review 15 | -------------------------------------------------------------------------------- /src/modules/cspec/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2023 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # cspec detector module and base test 5 | #============================================================================= 6 | 7 | add_subdirectory(test) 8 | 9 | 10 | set(cspec_SRC main.cpp) 11 | set(cspec_LIB efu_reduction caen_common efu_essreadout) 12 | create_executable(cspec) 13 | -------------------------------------------------------------------------------- /src/common/kafka/kafka.json: -------------------------------------------------------------------------------- 1 | { 2 | "KafkaParms" : [ 3 | {"message.max.bytes" : "10000000"}, 4 | {"fetch.message.max.bytes" : "10000000"}, 5 | {"message.copy.max.bytes" : "10000000"}, 6 | {"queue.buffering.max.kbytes" : "1000000"}, 7 | {"queue.buffering.max.messages" : "50000"}, 8 | {"queue.buffering.max.ms" : "100"}, 9 | {"statistics.interval.ms" : "1000"}, 10 | {"message.timeout.ms" : "600000"}, 11 | {"api.version.request" : "true"} 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/modules/cbm/configs/utgaard_ttl_test.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "CBM", 4 | 5 | "TypeSubType" : 16, 6 | 7 | "MaxPulseTimeDiffNS" : 1000000000, 8 | 9 | "MaxTOFNS" : 10000000000, 10 | 11 | "MonitorRing" : 0, 12 | 13 | "MaxFENId" : 2, 14 | 15 | "Topology" : [ 16 | { "FEN": 0, "Channel": 0, "Type": "EVENT_0D", "Source" : "cbm1", "PixelOffset": 0 }, 17 | { "FEN": 1, "Channel": 1, "Type": "EVENT_2D", "Source" : "cbm2", "Width": 512, "Height": 512 } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/common/reduction/analysis/AbstractAnalyzer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file AbstractAnalyzer.h 5 | /// \brief AbstractAnalyzer class implementation 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | 11 | /// \todo put stuff here, maybe? :) -------------------------------------------------------------------------------- /src/modules/loki/configs/old/STFCTestII.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector": "loki", 4 | 5 | "StrawResolution" : 512, 6 | 7 | "MaxPulseTimeNS" : 357142857, 8 | 9 | "PanelConfig" : [ 10 | { "Bank" : 0, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 16, "StrawOffset" : 0 }, 11 | { "Bank" : 1, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 16, "StrawOffset" : 448 }, 12 | { "Bank" : 2, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 16, "StrawOffset" : 896 } 13 | ] 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/loki/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # loki detector module and base test 5 | #============================================================================= 6 | 7 | add_subdirectory(generators) 8 | add_subdirectory(test) 9 | 10 | set(loki_SRC main.cpp) 11 | set(loki_LIB efu_reduction caen_common efu_essreadout) 12 | create_executable(loki) 13 | -------------------------------------------------------------------------------- /src/common/kafka/serializer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # Kafka related classes and tests 5 | #============================================================================= 6 | 7 | include_directories(.) 8 | 9 | set(DA00HistogramSerializerTest_SRC 10 | test/DA00HistogramSerializerTest.cpp 11 | ) 12 | 13 | create_test_executable(DA00HistogramSerializerTest) 14 | -------------------------------------------------------------------------------- /src/modules/bifrost/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # bifrost detector module and base test 5 | #============================================================================= 6 | 7 | add_subdirectory(generators) 8 | add_subdirectory(test) 9 | 10 | 11 | set(bifrost_SRC main.cpp) 12 | set(bifrost_LIB efu_reduction caen_common efu_essreadout) 13 | create_executable(bifrost) 14 | -------------------------------------------------------------------------------- /cmake/templates/version_num.h.in: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file */ 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Contain version numbers - do not manually edit this file 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #define EFU_VER_MAJ @MAJOR_VERSION@ 11 | 12 | #define EFU_VER_MIN @MINOR_VERSION@ 13 | 14 | #define EFU_VER_BUILD @PATCH_VERSION@ 15 | -------------------------------------------------------------------------------- /src/modules/miracles/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # miracles detector module and base test 5 | #============================================================================= 6 | 7 | add_subdirectory(generators) 8 | add_subdirectory(test) 9 | 10 | 11 | set(miracles_SRC main.cpp) 12 | set(miracles_LIB efu_reduction caen_common efu_essreadout) 13 | create_executable(miracles) 14 | -------------------------------------------------------------------------------- /src/common/monitor/DynamicHist.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016, 2017 European Spallation Source ERIC 2 | 3 | #pragma once 4 | #include 5 | #include 6 | 7 | class DynamicHist { 8 | public: 9 | std::vector hist; 10 | 11 | inline void bin(size_t i) { 12 | if (hist.size() <= i) 13 | hist.resize(i + 1, 0); 14 | hist[i]++; 15 | } 16 | 17 | inline bool empty() const { return hist.empty(); } 18 | 19 | std::string debug() const; 20 | std::string visualize(bool non_empty_only = false) const; 21 | }; 22 | -------------------------------------------------------------------------------- /src/modules/timepix3/generators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2024 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # tpx_generator for timepix3 efu 5 | #============================================================================= 6 | 7 | set(tpx_generator_PY 8 | tpx_generator.py 9 | ) 10 | 11 | install_python_executable(tpx_generator) 12 | set_target_properties(tpx_generator PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators") -------------------------------------------------------------------------------- /src/common/reduction/multigrid/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Classes for multigrid ModuleGeometry 3 | #============================================================================= 4 | 5 | include_directories(.) 6 | include_directories(${ESS_SOURCE_DIR}) 7 | 8 | set(MGModuleGeomTest_INC 9 | ModuleGeometry.h 10 | ) 11 | 12 | set(MGModuleGeomTest_SRC 13 | ModuleGeometry.cpp 14 | test/MGModuleGeomTest.cpp 15 | ) 16 | 17 | create_test_executable(MGModuleGeomTest) 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.o 4 | *.a 5 | *.so 6 | *.pyc 7 | *.pyo 8 | *.pyd 9 | __pycache__/ 10 | *.gcda 11 | *.gcno 12 | a.out 13 | *core 14 | 15 | # Misc programs project files 16 | */timepix_gen/* 17 | *Test$ 18 | */tpx_readouts 19 | 20 | #directories 21 | build/* 22 | cmake-build-*/ 23 | doxygen/ 24 | # MacOs folder metadata 25 | .DS_Store 26 | 27 | #IDE 28 | CMakeLists.txt.user 29 | .idea/ 30 | .atom* 31 | *.code-workspace 32 | .cache 33 | .vscode 34 | .devcontainer 35 | .clang-format 36 | resources 37 | uv.lock -------------------------------------------------------------------------------- /src/common/reduction/test/HitTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #include 4 | #include 5 | 6 | class HitTest : public TestBase { 7 | protected: 8 | Hit hit; 9 | void SetUp() override { 10 | } 11 | 12 | void TearDown() override {} 13 | }; 14 | 15 | TEST_F(HitTest, Debug) { EXPECT_FALSE(hit.to_string().empty()); } 16 | 17 | int main(int argc, char **argv) { 18 | testing::InitGoogleTest(&argc, argv); 19 | return RUN_ALL_TESTS(); 20 | } 21 | -------------------------------------------------------------------------------- /utils/qtrunefu/efucfg: -------------------------------------------------------------------------------- 1 | [servers] 2 | grafana_local = 127.0.0.1 3 | kafka_local = 127.0.0.1:9092 4 | grafana_office = 172.30.242.21 5 | kafka_office = 172.17.5.38:9092 6 | grafana_utgaard = 172.30.242.21 7 | kafka_utgaard = 172.30.242.20:9092 8 | 9 | [efuopts] 10 | hwcheck = False 11 | region = 0 12 | 13 | [datagen] 14 | throttle = 10000 15 | bytes = 1472 16 | 17 | [qtefu_latest] 18 | efudir = /essproj/event-formation-unit/build 19 | datadir = /ownCloud/DM/data/EFU_reference 20 | det = 21 | config = 22 | calib = 23 | grafana = 24 | kafka = 25 | hwcheck = 26 | region = 27 | -------------------------------------------------------------------------------- /src/common/reduction/NeutronEvent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file NeutronEvent.h 5 | /// \brief NeutronEvent class implementation 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | 12 | std::string NeutronEvent::to_string() const { 13 | return fmt::format("t:{:>20} pix:{:>10}", time, pixel_id); 14 | } 15 | -------------------------------------------------------------------------------- /src/modules/nmx/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for nmx 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("nmx", argc, argv); 13 | 14 | auto Detector = new Nmx::NmxBase(Main.DetectorSettings); 15 | 16 | return Main.run(Detector); 17 | } 18 | -------------------------------------------------------------------------------- /src/common/reduction/Hit.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016, 2017 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file Hit.cpp 5 | /// \brief Hit implementation 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | 12 | std::string Hit::to_string() const { 13 | return fmt::format("time={:>20} plane={:>3} coord={:>5} weight={:>5}", 14 | time, plane, coordinate, weight); 15 | } 16 | -------------------------------------------------------------------------------- /src/common/reduction/analysis/test/AbstractAnalyzerTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016, 2017 European Spallation Source ERIC 2 | 3 | #include 4 | 5 | #include 6 | 7 | class AbstractAnalyzerTest : public TestBase { 8 | protected: 9 | Hit hit; 10 | Cluster cluster; 11 | Event event; 12 | void SetUp() override {} 13 | void TearDown() override {} 14 | }; 15 | 16 | /// \todo tests needed 17 | 18 | int main(int argc, char **argv) { 19 | testing::InitGoogleTest(&argc, argv); 20 | return RUN_ALL_TESTS(); 21 | } 22 | -------------------------------------------------------------------------------- /src/modules/trex/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for trex 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("trex", argc, argv); 13 | 14 | auto Detector = new Trex::TrexBase(Main.DetectorSettings); 15 | 16 | return Main.run(Detector); 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/cbm/test/cbm_config_test.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "CBM", 4 | 5 | "TypeSubType" : 16, 6 | 7 | "NumberOfMonitors" : 11, 8 | 9 | "MaxPulseTimeDiffNS" : 1000000000, 10 | 11 | "MaxTOFNS" : 1000000000, 12 | 13 | "MaxFENId" : 2, 14 | 15 | "Topology" : [ 16 | { "FEN": 0, "Channel": 0, "Type": "EVENT_0D", "Source" : "cbm1", "PixelOffset": 0 }, 17 | { "FEN": 0, "Channel": 1, "Type": "IBM", "Source" : "cbm2", "MaxTofBin": 71428572, "BinCount": 512 }, 18 | { "FEN": 0, "Channel": 2, "Type": "EVENT_2D", "Source" : "cbm3", "Width": 512, "Height": 512 } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/modules/freia/main_estia.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for estia 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("estia", argc, argv); 13 | 14 | auto Detector = new Freia::FreiaBase(Main.DetectorSettings); 15 | 16 | return Main.run(Detector); 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/freia/main_freia.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for freia 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("freia", argc, argv); 13 | 14 | auto Detector = new Freia::FreiaBase(Main.DetectorSettings); 15 | 16 | return Main.run(Detector); 17 | } 18 | -------------------------------------------------------------------------------- /src/common/reduction/Hit2D.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file Hit2D.cpp 5 | /// \brief Hit2D implementation 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | 12 | std::string Hit2D::to_string() const { 13 | return fmt::format("time={:>20} x_coord={:>5} y_coord={:>5} weight={:>5}", 14 | time, x_coordinate, y_coordinate, weight); 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/perfgen/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for perfgen 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("perfgen", argc, argv); 13 | 14 | auto Detector = new PerfGen::PerfGenBase(Main.DetectorSettings); 15 | 16 | return Main.run(Detector); 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/timepix3/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for Timepix3 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("timepix3", argc, argv); 13 | 14 | auto Detector = new Timepix3::Timepix3Base(Main.DetectorSettings); 15 | 16 | return Main.run(Detector); 17 | } 18 | -------------------------------------------------------------------------------- /src/common/reduction/matching/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(AbstractMatcherTest_SRC 2 | AbstractMatcherTest.cpp 3 | ) 4 | create_test_executable(AbstractMatcherTest) 5 | 6 | set(OverlapMatcherTest_SRC 7 | OverlapMatcherTest.cpp 8 | ) 9 | create_test_executable(OverlapMatcherTest) 10 | 11 | set(GapMatcherTest_SRC 12 | GapMatcherTest.cpp 13 | ) 14 | create_test_executable(GapMatcherTest) 15 | 16 | set(EndMatcherTest_SRC 17 | EndMatcherTest.cpp 18 | ) 19 | create_test_executable(EndMatcherTest) 20 | 21 | 22 | set(CenterMatcherTest_SRC 23 | CenterMatcherTest.cpp 24 | ) 25 | create_test_executable(CenterMatcherTest) -------------------------------------------------------------------------------- /src/common/monitor/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(DynamicHistTest_INC 4 | ../DynamicHist.h 5 | ) 6 | set(DynamicHistTest_SRC 7 | ../DynamicHist.cpp 8 | DynamicHistTest.cpp 9 | ) 10 | create_test_executable(DynamicHistTest) 11 | 12 | set(HistogramTest_SRC 13 | HistogramTest.cpp 14 | ) 15 | create_test_executable(HistogramTest) 16 | 17 | set(HistogramSerializerTest_SRC 18 | HistogramSerializerTest.cpp 19 | ) 20 | create_test_executable(HistogramSerializerTest) 21 | 22 | set(HitSerializerTest_SRC 23 | HitSerializerTest.cpp 24 | ) 25 | create_test_executable(HitSerializerTest) 26 | 27 | # todo Monitor tests 28 | -------------------------------------------------------------------------------- /src/modules/cspec/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for CSPEC 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("cspec", argc, argv); 13 | 14 | auto Detector = 15 | new Caen::CaenBase(Main.DetectorSettings, DetectorType::CSPEC); 16 | 17 | return Main.run(Detector); 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/tbl3he/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for caen 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("tbl3he", argc, argv); 13 | 14 | auto Detector = 15 | new Caen::CaenBase(Main.DetectorSettings, DetectorType::TBL3HE); 16 | 17 | return Main.run(Detector); 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/cbm/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for Common Beam Monitor (CBM) detector module. 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main(DetectorType::CBM, argc, argv); 13 | 14 | auto Detector = new cbm::CbmBase(Main.DetectorSettings); 15 | 16 | return Main.run(Detector); 17 | } 18 | -------------------------------------------------------------------------------- /src/modules/miracles/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for miracles 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("miracles", argc, argv); 13 | 14 | auto Detector = 15 | new Caen::CaenBase(Main.DetectorSettings, DetectorType::MIRACLES); 16 | 17 | return Main.run(Detector); 18 | } 19 | -------------------------------------------------------------------------------- /src/modules/tbl3he/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2024 European Spallation Source, ERIC. See LICENSE file 2 | 3 | add_subdirectory(test) 4 | 5 | #============================================================================= 6 | # detector for tbl based on 3He tubes 7 | #============================================================================= 8 | 9 | set(tbl3he_INC 10 | geometry/Tbl3HeConfig.h 11 | geometry/Tbl3HeGeometry.h 12 | ) 13 | set(tbl3he_SRC 14 | geometry/Tbl3HeConfig.cpp 15 | geometry/Tbl3HeGeometry.cpp 16 | main.cpp 17 | ) 18 | set(tbl3he_LIB efu_reduction caen_common efu_essreadout) 19 | create_executable(tbl3he) 20 | -------------------------------------------------------------------------------- /src/modules/freia/main_tblmb.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Main entry for TBL-MB (multi-blade test-beam-line) 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | 12 | int main(int argc, char *argv[]) { 13 | MainProg Main("tblmb", argc, argv); 14 | 15 | auto Detector = new Freia::FreiaBase(Main.DetectorSettings); 16 | 17 | return Main.run(Detector); 18 | } 19 | -------------------------------------------------------------------------------- /src/efu/efu.md: -------------------------------------------------------------------------------- 1 | ### Starting the EFU 2 | 3 | To start the EFU with the __sonde__ pipeline from the __build__ directory: 4 | 5 | `> ./bin/efu -d lib/sonde --nohwcheck` 6 | 7 | 8 | There are quite a few additional command line options, but these ones are 9 | the most used 10 | 11 | Cmd option | Description 12 | ------------- | ------------- 13 | -p | UDP port for detector data 14 | -g | IP address for Graphite (metrics) server 15 | -b | Kafka broker "ipaddress:port" 16 | -f | Configurations file (detector specific) 17 | 18 | To get further help 19 | 20 | `> ./efu -h` 21 | -------------------------------------------------------------------------------- /src/generators/udpgenpcap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | #============================================================================= 3 | # PCAP generator 4 | #============================================================================= 5 | 6 | set(udpgen_pcap_SRC 7 | udpgen_pcap.cpp 8 | ReaderPcap.cpp 9 | ) 10 | set(udpgen_pcap_INC 11 | ReaderPcap.h 12 | ) 13 | set(udpgen_pcap_LIB 14 | ${PCAP_LIBRARY} 15 | ) 16 | create_executable(udpgen_pcap) 17 | set_target_properties(udpgen_pcap 18 | PROPERTIES 19 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators" 20 | ) 21 | -------------------------------------------------------------------------------- /src/common/debug/Hexdump.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Provide a printf based hexdump functionality 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | 14 | /// \brief make a hexdump-like printout of a buffer, mainly debugging 15 | /// \param DataPtr void pointer to the buffer containing data 16 | /// \param DataLen length of the data 17 | void hexDump(const void *DataPtr, size_t DataLen); 18 | -------------------------------------------------------------------------------- /src/common/test/ESSGeometryBenchmarkTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 European Spallation Source ERIC 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static void GetPixelID(benchmark::State &state) { 9 | uint32_t items = 0; 10 | 11 | ESSGeometry essgeom(100, 100, 100, 100); 12 | 13 | for (auto _ : state) { 14 | for (size_t i = 10; i < 20; i++) { 15 | benchmark::DoNotOptimize(essgeom.pixelMP3D(i, i, i, i)); 16 | items += 1; 17 | } 18 | } 19 | state.SetItemsProcessed(items); 20 | } 21 | BENCHMARK(GetPixelID); 22 | 23 | BENCHMARK_MAIN(); 24 | -------------------------------------------------------------------------------- /src/modules/bifrost/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for caen 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | DetectorType Type = DetectorType::BIFROST; 13 | 14 | MainProg Main(Type.toLowerCase(), argc, argv); 15 | auto Detector = new Caen::CaenBase(Main.DetectorSettings, Type); 16 | 17 | return Main.run(Detector); 18 | } 19 | -------------------------------------------------------------------------------- /documentation/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | A description of the contents of each directory in the root of the repository can be found in [DIRECTORIES.md](DIRECTORIES.md). 3 | 4 | 5 | ## Architecture and application 6 | Overview of the EFU architecture (detector agnostic) 7 | [EFU.md](EFU.md) 8 | 9 | Running the EFU 10 | [Running](../src/efu/efu.md) 11 | 12 | 13 | ## Event formation processing primitives 14 | [Definitions and assumptions](../src/common/reduction/primitives.md) 15 | 16 | [Reduction](../src/common/reduction/reduction.md) 17 | 18 | [Clustering](../src/common/reduction/clustering/clusterer.md) 19 | 20 | [Matching](../src/common/reduction/matching/matcher.md) 21 | -------------------------------------------------------------------------------- /src/modules/dream/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for dream 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char *argv[]) { 13 | MainProg Main("dream", argc, argv); 14 | 15 | auto Detector = 16 | new Dream::DreamBase(Main.DetectorSettings); 17 | 18 | return Main.run(Detector); 19 | } 20 | -------------------------------------------------------------------------------- /src/common/debug/Expect.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief macros LIKELY and UNLIKELY are hints for codegeneration, when some 6 | /// code path is unlikely or exceptional. 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | #if 1 12 | 13 | #define LIKELY(x) __builtin_expect(!!(x), 1) 14 | #define UNLIKELY(x) __builtin_expect(!!(x), 0) 15 | 16 | #else 17 | 18 | // option to disable 19 | #define LIKELY(x) (x) 20 | #define UNLIKELY(x) (x) 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /CHANGELOG/changelog_2025-12-17.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | **Generated on:** 2025-12-17 12:00:09 4 | **Commit range:** `2.0.0` to `2.0.1` 5 | **Total commits:** 2 6 | 7 | ## 🎫 JIRA Issues 8 | 9 | - [ECDC-5009](https://jira.ess.eu/browse/ECDC-5009) 10 | - [ECDC-5202](https://jira.ess.eu/browse/ECDC-5202) 11 | 12 | ## 🐛 Bug Fixes 13 | 14 | - **fix, update: missing librdkafka poll() in base classes - ECDC-5009** ([ECDC-5009](https://jira.ess.eu/browse/ECDC-5009)) - `fad098dc` by Tibor Bukovics 15 | 16 | ## 📝 General Changes 17 | 18 | - **Added Normalize flag to EFU json config file. Flag is default enabled.** [ECDC-5202](https://jira.ess.eu/browse/ECDC-5202) - `84ba7599` by Michael Christiansen 19 | -------------------------------------------------------------------------------- /src/common/testutils/SaveBuffer.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief test-helper class for saving a buffer to file 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | /// \brief save buffer to file 16 | void saveBuffer(const std::string &filename, void *buffer, uint64_t datasize); 17 | 18 | /// \brief helper function to remove temporary files after test 19 | void deleteFile(const std::string &filename); 20 | -------------------------------------------------------------------------------- /src/common/time/TimeString.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Get current time as a string 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | 12 | std::string timeString() { 13 | char cStartTime[50]; 14 | time_t rawtime; 15 | struct tm *timeinfo; 16 | time(&rawtime); 17 | timeinfo = localtime(&rawtime); 18 | strftime(cStartTime, 50, "%Y%m%d-%H%M%S", timeinfo); 19 | std::string startTime = cStartTime; 20 | return startTime; 21 | } 22 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Directories 3 | 4 | Source files for efu, detector modules and data generators. 5 | 6 | Directory | Function 7 | ------------- | ------------- 8 | common | common detector code 9 | efu | EFU main application code 10 | generators | detector data generators (for test) 11 | modules | detector implementations 12 | 13 | ## external modules 14 | It is possible to build modules with sources outside the efu repository. To 15 | do this we make use of EFU_EXTERNAL_DIR which is a cmake variable containing 16 | a list of directories with cmake modules to be included. 17 | 18 | > cmake -D EFU_EXTERNAL_DIR= "/tmp/thisrepo;/tmp/thatrepo" .. 19 | -------------------------------------------------------------------------------- /src/common/reduction/analysis/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(AbstractAnalyzerTest_SRC 2 | AbstractAnalyzerTest.cpp 3 | ) 4 | create_test_executable(AbstractAnalyzerTest) 5 | 6 | set(UtpcAnalyzerTest_SRC 7 | UtpcAnalyzerTest.cpp 8 | ) 9 | create_test_executable(UtpcAnalyzerTest) 10 | 11 | set(EventAnalyzerTest_SRC 12 | EventAnalyzerTest.cpp 13 | ) 14 | create_test_executable(EventAnalyzerTest) 15 | 16 | 17 | #todo make abstract geometry class, non MG-specific? 18 | set(MgAnalyzerTest_INC 19 | ${ESS_COMMON_DIR}/reduction/multigrid/ModuleGeometry.h 20 | ) 21 | set(MgAnalyzerTest_SRC 22 | MgAnalyzerTest.cpp 23 | ${ESS_COMMON_DIR}/reduction/multigrid/ModuleGeometry.cpp 24 | ) 25 | create_test_executable(MgAnalyzerTest) 26 | -------------------------------------------------------------------------------- /src/modules/loki/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for loki 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) { 12 | MainProg Main("loki", argc, argv); 13 | 14 | auto Detector = 15 | new Caen::CaenBase(Main.DetectorSettings, DetectorType::LOKI); 16 | // auto Detector = 17 | // new Caen::CaenBase(Main.DetectorSettings, DetectorFoo); 18 | // exit(-1); 19 | 20 | return Main.run(Detector); 21 | } 22 | -------------------------------------------------------------------------------- /src/common/math/Units.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Common data-size unit helpers 6 | //===----------------------------------------------------------------------===// 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace essmath::units { 13 | 14 | inline constexpr std::size_t Byte = 1ULL; 15 | inline constexpr std::size_t KiB = 1024ULL * Byte; 16 | inline constexpr std::size_t MiB = 1024ULL * KiB; 17 | inline constexpr std::size_t GiB = 1024ULL * MiB; 18 | inline constexpr std::size_t TiB = 1024ULL * GiB; 19 | 20 | } // namespace essmath::units 21 | 22 | -------------------------------------------------------------------------------- /src/common/config/Config.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Implementation og Config base class 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | 11 | #include 12 | 13 | // #undef TRC_LEVEL 14 | // #define TRC_LEVEL TRC_L_DEB 15 | 16 | namespace Configurations { 17 | 18 | Config::Config() 19 | : mMask(NONE) 20 | { 21 | 22 | } 23 | 24 | Config::Config(const std::string &ConfigFile) 25 | : mRoot(nullptr) 26 | , mConfigFile(ConfigFile) { 27 | } 28 | 29 | } // namespace Configurations 30 | -------------------------------------------------------------------------------- /src/common/reduction/clustering/test/Abstract2DClustererTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 European Spallation Source ERIC 2 | 3 | #include 4 | 5 | #include 6 | 7 | class Abstract2DClustererTest : public TestBase { 8 | protected: 9 | 10 | }; 11 | 12 | 13 | TEST_F(Abstract2DClustererTest, Constructor) { 14 | Cluster2DContainer clusters; 15 | std::string DebugStr = to_string(clusters, "", true); 16 | size_t OldLen = DebugStr.size(); 17 | DebugStr = to_string(clusters, "prepend_", true); 18 | ASSERT_TRUE(DebugStr.size() >= OldLen); 19 | } 20 | 21 | 22 | int main(int argc, char **argv) { 23 | testing::InitGoogleTest(&argc, argv); 24 | return RUN_ALL_TESTS(); 25 | } 26 | -------------------------------------------------------------------------------- /conanfile.txt: -------------------------------------------------------------------------------- 1 | [requires] 2 | benchmark/1.7.0 3 | cli11/1.9.1 4 | fmt/10.1.1 5 | graylog-logger/2.1.6@ess-dmsc/stable 6 | gtest/1.15.0 7 | nlohmann_json/3.10.5 8 | libpcap/1.10.1 9 | librdkafka/2.8.0 10 | logical-geometry/1.1.0@ess-dmsc/stable 11 | readerwriterqueue/07e22ec@ess-dmsc/stable 12 | concurrentqueue/1.0.3 13 | streaming-data-types/3624504@ess-dmsc/stable 14 | fakeit/2.4.1 15 | zlib/1.3.1 #override 16 | magic_enum/0.9.6 17 | 18 | [generators] 19 | CMakeToolchain 20 | CMakeDeps 21 | 22 | [options] 23 | librdkafka:shared=True 24 | librdkafka:ssl=True 25 | librdkafka:sasl=True 26 | 27 | [imports] 28 | lib, * -> ./lib 29 | lib64, * -> ./lib 30 | filesystem/lib, * -> ./lib 31 | system/lib, * -> ./lib 32 | ., LICENSE* -> ./licenses @ folder=True, ignore_case=True 33 | -------------------------------------------------------------------------------- /src/modules/dream/main_magic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for magic 6 | /// 7 | /// DREAM and MAGIC implementations are identical and the configuration 8 | /// file determines which geometry to use. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include 12 | #include 13 | 14 | int main(int argc, char *argv[]) { 15 | MainProg Main("magic", argc, argv); 16 | 17 | auto Detector = new Dream::DreamBase(Main.DetectorSettings); 18 | 19 | return Main.run(Detector); 20 | } 21 | -------------------------------------------------------------------------------- /src/common/debug/Log.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Log functions for the ESS logger 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include "Log.h" 9 | 10 | // GCOVR_EXCL_START 11 | 12 | #ifdef UNIT_TEST 13 | 14 | // Definition and initialization 15 | MockLogger *MockLogger::instance = nullptr; 16 | 17 | void mockLogFunction(const std::string &category, const std::string &message) { 18 | MockLogger *ptrToInstance = MockLogger::instance; 19 | if (ptrToInstance) { 20 | ptrToInstance->log(category, message); 21 | } 22 | } 23 | #endif 24 | 25 | // GCOVR_EXCL_STOP -------------------------------------------------------------------------------- /src/modules/dream/main_heimdal.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Main entry for heimdal 6 | /// 7 | /// DREAM, MAGIC and HEIMDAL implementations are identical and the configuration 8 | /// file determines which geometry to use. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include 12 | #include 13 | 14 | int main(int argc, char *argv[]) { 15 | MainProg Main("heimdal", argc, argv); 16 | 17 | auto Detector = 18 | new Dream::DreamBase(Main.DetectorSettings); 19 | 20 | return Main.run(Detector); 21 | } 22 | -------------------------------------------------------------------------------- /src/modules/bifrost/generators/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate Bifrost udp stream from a dat file 7 | //===----------------------------------------------------------------------===// 8 | 9 | // GCOVR_EXCL_START 10 | 11 | #include 12 | 13 | int main(int argc, char *argv[]) { 14 | 15 | ReadoutGenerator BifrostGen; 16 | uint8_t BifrostDataSize = sizeof(Caen::DataParser::CaenReadout); 17 | BifrostGen.setReadoutDataSize(BifrostDataSize); 18 | 19 | BifrostGen.argParse(argc, argv); 20 | 21 | BifrostGen.main(); 22 | BifrostGen.transmitLoop(); 23 | 24 | return 0; 25 | } 26 | 27 | // GCOVR_EXCL_STOP -------------------------------------------------------------------------------- /src/modules/freia/FreiaBase.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2024 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Freia detector base plugin interface definition 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | namespace Freia { 16 | 17 | class FreiaBase : public Detector { 18 | public: 19 | FreiaBase(BaseSettings const &settings); 20 | ~FreiaBase() = default; 21 | 22 | void processing_thread(); 23 | 24 | struct Counters Counters {}; 25 | 26 | std::string FlatBufferSource{"multiblade"}; 27 | }; 28 | 29 | } // namespace Freia 30 | -------------------------------------------------------------------------------- /cmake/BuildString.cmake: -------------------------------------------------------------------------------- 1 | function(makebuildstr) 2 | execute_process(COMMAND "whoami" OUTPUT_VARIABLE user_name OUTPUT_STRIP_TRAILING_WHITESPACE) 3 | execute_process(COMMAND "date" "+%F %H:%M:%S" OUTPUT_VARIABLE date OUTPUT_STRIP_TRAILING_WHITESPACE) 4 | execute_process(COMMAND "uname" "-n" OUTPUT_VARIABLE m_name OUTPUT_STRIP_TRAILING_WHITESPACE) 5 | execute_process(COMMAND "uname" "-r" OUTPUT_VARIABLE m_version OUTPUT_STRIP_TRAILING_WHITESPACE) 6 | execute_process(COMMAND "git" "rev-parse" "--short" "HEAD" OUTPUT_VARIABLE hash OUTPUT_STRIP_TRAILING_WHITESPACE) 7 | set(BUILDSTR "${date} [${m_name}:${user_name}] [${m_version}] ${hash}" PARENT_SCOPE) 8 | endfunction() 9 | 10 | set(BUILDSTR "") 11 | makebuildstr() 12 | 13 | message(STATUS "Build str: ${BUILDSTR}") 14 | 15 | add_definitions("-DBUILDSTR=${BUILDSTR}") 16 | -------------------------------------------------------------------------------- /src/modules/nmx/NMXBase.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 - 2023 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief NMX detector base plugin interface definition 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Nmx { 18 | 19 | class NmxBase : public Detector { 20 | public: 21 | NmxBase(BaseSettings const &settings); 22 | ~NmxBase() = default; 23 | 24 | void processing_thread(); 25 | 26 | struct Counters Counters {}; 27 | }; 28 | 29 | } // namespace Nmx 30 | -------------------------------------------------------------------------------- /src/generators/functiongenerators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2024 European Spallation Source, ERIC. See LICENSE file 2 | #============================================================================= 3 | 4 | 5 | #============================================================================= 6 | # Function Generators tests 7 | #============================================================================= 8 | 9 | set(DistributionGeneratorTest_INC 10 | DistributionGenerator.h 11 | ) 12 | set(DistributionGeneratorTest_SRC 13 | test/DistributionGeneratorTest.cpp 14 | DistributionGenerator.cpp 15 | ) 16 | create_test_executable(DistributionGeneratorTest) 17 | 18 | set(LinearGeneratorTest_INC 19 | LinearGenerator.h 20 | ) 21 | set(LinearGeneratorTest_SRC 22 | test/LinearGeneratorTest.cpp 23 | ) 24 | create_test_executable(LinearGeneratorTest) 25 | -------------------------------------------------------------------------------- /documentation/DIRECTORIES.md: -------------------------------------------------------------------------------- 1 | ## Directories 2 | The repository contains the following directories 3 | 4 | Directory | Function 5 | ------------- | ------------- 6 | cmake | cmake modules including third parties 7 | documentation | detailed documentation 8 | jenkins | Continuous Integration scripts 9 | src * | the detector event processing pipeline (and unit tests) 10 | utils | misc helper scripts and programs, notable efushell.py and efustats.py 11 | 12 | 13 | # utils 14 | Contain python scripts to query the command line interface of the event formation unit. 15 | Of particular use are 16 | * utils/efushell/efustats.py - reports detector-specific application counters 17 | * utils/efushell/efustatus/py - reports application information (sw version, available commands, ...) 18 | -------------------------------------------------------------------------------- /src/modules/freia/geometry/TBLMBGeometry.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief TBLMB geometry class 7 | /// 8 | /// Mapping from digital identifiers to x- and y- coordinates 9 | //===----------------------------------------------------------------------===// 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | // #undef TRC_LEVEL 18 | // #define TRC_LEVEL TRC_L_DEB 19 | 20 | namespace Freia { 21 | 22 | class TBLMBGeometry final : public AmorGeometry { 23 | public: 24 | TBLMBGeometry(Statistics &Stats, Config &Cfg) : AmorGeometry(Stats, Cfg) {} 25 | 26 | }; 27 | 28 | } // namespace Freia 29 | -------------------------------------------------------------------------------- /utils/efushell/getstat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from EFUMetrics import Metrics 4 | import argparse, sys 5 | 6 | parser = argparse.ArgumentParser() 7 | parser.add_argument('stat', metavar='stat', type=str, help="stat name (sub)string"); 8 | parser.add_argument("-i", metavar='ipaddr', help = "server ip address (default 127.0.0.1)", type = str, default = "127.0.0.1") 9 | parser.add_argument("-p", metavar='port', help = "server tcp port (default 8888)", type = int, default = 8888) 10 | args = parser.parse_args() 11 | 12 | my_metric = args.stat 13 | 14 | metrics = Metrics(args.i, args.p) 15 | 16 | res = metrics._get_efu_command("STAT_GET_COUNT") 17 | numstats = int(res.split()[1]) 18 | for statnum in range(1, numstats + 1): 19 | stat = metrics._get_efu_command("STAT_GET " + str(statnum)) 20 | if my_metric in stat: 21 | print(stat.split(" ")[2]) 22 | -------------------------------------------------------------------------------- /utils/efushell/isefurunning.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from EFUMetrics import Metrics 4 | import argparse, sys 5 | 6 | parser = argparse.ArgumentParser() 7 | parser.add_argument("-i", metavar='ipaddr', help = "server ip address (default 127.0.0.1)", 8 | type = str, default = "127.0.0.1") 9 | parser.add_argument("-p", metavar='port', help = "server tcp port (default 8888)", 10 | type = int, default = 8888) 11 | args = parser.parse_args() 12 | 13 | try: 14 | metrics = Metrics(args.i, args.p) 15 | 16 | res = metrics._get_efu_command("STAT_GET 1") 17 | print(res) 18 | 19 | packets = int(res.split()[2]) 20 | res = metrics._get_efu_command("RUNTIMESTATS") 21 | runtime = int(res.split()[1]) 22 | print("efu is running ({})".format(runtime)) 23 | except: 24 | print("efu is not running") 25 | sys.exit(1) 26 | 27 | sys.exit(0) 28 | -------------------------------------------------------------------------------- /src/efu/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # EFU Tests 3 | #============================================================================= 4 | 5 | # 6 | set(HwCheckTest_INC 7 | ../HwCheck.h 8 | ) 9 | set(HwCheckTest_SRC 10 | ../HwCheck.cpp 11 | HwCheckTest.cpp 12 | ) 13 | create_test_executable(HwCheckTest) 14 | 15 | # 16 | set(ServerTest_INC 17 | ../Server.h 18 | ../Parser.h 19 | ) 20 | set(ServerTest_SRC 21 | ServerTest.cpp 22 | ) 23 | create_test_executable(ServerTest) 24 | 25 | # 26 | set(ParserTest_SRC 27 | ParserTest.cpp 28 | ) 29 | set(ParserTest_INC 30 | ../Parser.h 31 | ) 32 | create_test_executable(ParserTest) 33 | 34 | # 35 | set(LauncherTest_SRC 36 | LauncherTest.cpp 37 | ) 38 | set(LauncherTest_INC 39 | ../Launcher.h 40 | ) 41 | 42 | 43 | create_test_executable(LauncherTest) 44 | -------------------------------------------------------------------------------- /utils/qtrunefu/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Qt based efu launcher 3 | This tool helps build a command line for launching efu. 4 | 5 | ## qtefu.py 6 | The user specifies three directories: basedir, efudir and datadir. The latter two must 7 | be relative to basedir. 8 | 9 | The program then finds the relevant binary files (efu executable and detector libraries), 10 | and configuration and calibration files. 11 | 12 | The user then selects the relevant files from the drop down menus and presses OK 13 | to launch the EFU. 14 | 15 | ## qtdatagen.py 16 | Still under development - do not use 17 | 18 | ## Custom configuration 19 | To customise the basedir and the location of efu binaries and configuration files, you 20 | can edit the efucfg file, rename it to .efucfg and place it in your homedir. 21 | 22 | ## Prerequisites 23 | We need Qt5 support which can be gotten by 24 | pip3 install PyQt5 25 | -------------------------------------------------------------------------------- /src/modules/freia/generators/ReadoutGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial VMM3a readouts with variable number 7 | /// of readouts 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | namespace Freia { 16 | 17 | class ReadoutGenerator : public ReadoutGeneratorBase { 18 | public: 19 | ReadoutGenerator() : ReadoutGeneratorBase(DetectorType::FREIA) {} 20 | 21 | protected: 22 | void generateData() override; 23 | 24 | const uint32_t TimeToFirstReadout{1000}; 25 | }; 26 | 27 | } // namespace Freia 28 | 29 | // GCOVR_EXCL_STOP 30 | -------------------------------------------------------------------------------- /src/modules/loki/generators/ReadoutGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial CAEN readouts with variable number 7 | /// of readouts 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Caen { 18 | class ReadoutGenerator : public ReadoutGeneratorBase { 19 | public: 20 | ReadoutGenerator() : ReadoutGeneratorBase(DetectorType::LOKI) {} 21 | 22 | protected: 23 | void generateData() override; 24 | }; 25 | 26 | } // namespace Caen 27 | // GCOVR_EXCL_STOP 28 | -------------------------------------------------------------------------------- /src/modules/trex/configs/let.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector" : "TREX", 3 | 4 | "InstrumentGeometry" : "LET", 5 | 6 | "Vessel_Config" : { 7 | "0": {"NumGrids": 51, "Rotation": true, "XOffset": 0, "Short": true, "MinADC": 20} 8 | }, 9 | 10 | "Config" : [ 11 | { "Ring" : 0, "VesselId": "0", "FEN": 0, "Hybrid" : 0, "HybridId" : "00000000000000000000000000000000"}, 12 | { "Ring" : 0, "VesselId": "0", "FEN": 0, "Hybrid" : 1, "HybridId" : "00000000000000000000000000000000"}, 13 | { "Ring" : 1, "VesselId": "0", "FEN": 0, "Hybrid" : 0, "HybridId" : "00000000000000000000000000000000"}, 14 | { "Ring" : 1, "VesselId": "0", "FEN": 0, "Hybrid" : 1, "HybridId" : "00000000000000000000000000000000"} 15 | ], 16 | 17 | 18 | "MaxPulseTimeNS" : 71438570, 19 | "DefaultMinADC": 50, 20 | "MaxGridsPerEvent": 5, 21 | "SizeX": 12, 22 | "SizeY": 51, 23 | "SizeZ": 16 24 | } 25 | -------------------------------------------------------------------------------- /src/modules/trex/TREXBase.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief TREX detector base plugin interface definition 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Trex { 18 | 19 | class TrexBase : public Detector { 20 | public: 21 | TrexBase(BaseSettings const &settings); 22 | ~TrexBase() = default; 23 | 24 | void processing_thread(); 25 | 26 | struct Counters Counters {}; 27 | 28 | protected: 29 | std::unique_ptr Serializer{nullptr}; 30 | }; 31 | 32 | } // namespace Trex 33 | -------------------------------------------------------------------------------- /src/efu/Graylog.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Collection of Graylog methods for EFU 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | class Graylog { 16 | public: 17 | ~Graylog() { EmptyGraylogMessageQueue(); }; 18 | 19 | static std::string ConsoleFormatter(const Log::LogMessage &Msg); 20 | 21 | static std::string FileFormatter(const Log::LogMessage &Msg); 22 | 23 | void EmptyGraylogMessageQueue(); 24 | 25 | void AddLoghandlerForNetwork(const std::string &DetectorName, const std::string &FileName, 26 | int LogLevel, const std::string &Address, int Port); 27 | }; 28 | -------------------------------------------------------------------------------- /src/modules/perfgen/PerfGenBase.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief pixel generator 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | namespace PerfGen { 16 | 17 | class PerfGenBase : public Detector { 18 | public: 19 | PerfGenBase(BaseSettings const &settings); 20 | ~PerfGenBase() {} 21 | 22 | void processingThread(); 23 | 24 | static const int kafka_buffer_size = 124000; /// entries 25 | 26 | protected: 27 | struct { 28 | // Processing Counters 29 | int64_t events_udder; 30 | } __attribute__((aligned(64))) Counters; 31 | }; 32 | 33 | } // namespace PerfGen 34 | -------------------------------------------------------------------------------- /src/modules/trex/generators/ReadoutGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial VMM3a readouts with variable number 7 | /// of readouts 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Trex { 18 | 19 | class ReadoutGenerator : public ReadoutGeneratorBase { 20 | public: 21 | ReadoutGenerator() : ReadoutGeneratorBase(DetectorType::TREX) {} 22 | 23 | protected: 24 | void generateData() override; 25 | }; 26 | 27 | } // namespace Trex 28 | 29 | // GCOVR_EXCL_STOP 30 | -------------------------------------------------------------------------------- /src/common/time/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | #============================================================================= 3 | # Add ess timing modules 4 | #============================================================================= 5 | 6 | include_directories(.) 7 | 8 | set(esstime_obj_SRC 9 | ESSTime.cpp 10 | TimeString.cpp 11 | Timer.cpp 12 | ) 13 | 14 | set(esstime_obj_INC 15 | ESSTime.h 16 | TimeString.h 17 | Timer.h 18 | ) 19 | 20 | add_library(EssTimingLib OBJECT 21 | ${esstime_obj_SRC} 22 | ${esstime_obj_INC} 23 | ) 24 | 25 | target_link_libraries(EssTimingLib 26 | PRIVATE 27 | ${EFU_COMMON_LIBS} 28 | ) 29 | 30 | add_library(EssTimingLib-unit_test OBJECT 31 | ${esstime_obj_SRC} 32 | ${esstime_obj_INC} 33 | ) 34 | 35 | # Set pre-compiler flag UNIT_TEST for the library 36 | target_compile_definitions(EssTimingLib-unit_test PUBLIC -DUNIT_TEST) 37 | 38 | enable_coverage_flags(EssTimingLib) 39 | -------------------------------------------------------------------------------- /src/modules/nmx/generators/ReadoutGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial VMM3a readouts with variable number 7 | /// of readouts 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Nmx { 18 | 19 | class ReadoutGenerator : public ReadoutGeneratorBase { 20 | public: 21 | ReadoutGenerator() : ReadoutGeneratorBase(DetectorType::NMX) {} 22 | 23 | protected: 24 | void generateData() override; 25 | int64_t Number{0}; 26 | }; 27 | 28 | } // namespace Nmx 29 | // GCOVR_EXCL_STOP 30 | -------------------------------------------------------------------------------- /cmake/templates/Version.h.in: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file */ 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief API for getting and comparing version numbers 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #define STRINGIFY(x) #x 13 | #define EFU_STR(x) STRINGIFY(x) 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | inline static const std::string efu_version() { 21 | // The following line is executed only once on startup or on first call to 22 | // function 23 | const static std::string version = "@VERSION_STRING@"; 24 | return version; 25 | } 26 | 27 | static inline const std::string efu_buildstr() { 28 | return std::string(EFU_STR(BUILDSTR)); 29 | } 30 | -------------------------------------------------------------------------------- /src/common/system/SocketInterface.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Socket interface for pure abstraction 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | /// \brief Socket interface used for transmitting data 12 | /// Socket interface for data communication abstraction. Pure abstract class will be used for 13 | /// injection into generator method that creates multiple packets and unit test. 14 | class SocketInterface { 15 | public: 16 | virtual ~SocketInterface() = default; 17 | /// \brief Send data in buffer with specified length 18 | /// \param dataBuffer pointer to data buffer. 19 | /// \param dataLength length of buffer. 20 | virtual int send(void const *dataBuffer, int dataLength) = 0; 21 | }; -------------------------------------------------------------------------------- /src/efu/ExitHandler.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Class to register exit handlers for program termination 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | #include 12 | 13 | class ExitHandler { 14 | public: 15 | enum class Exit { 16 | NoExit, 17 | Exit, 18 | }; 19 | /// \brief constructor does nothing 20 | static void InitExitHandler(); 21 | 22 | static Exit HandleLastSignal(); 23 | 24 | private: 25 | /// noncritical signals (Ctrl-C), stop threads nicely 26 | static void nonCritical(int a); 27 | 28 | /// Critical signals, immediate exit 29 | static void critical(int a); 30 | 31 | /// print a stack trace 32 | static void printTrace(void); 33 | }; 34 | -------------------------------------------------------------------------------- /src/modules/dream/configs/fwec.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector": "DREAM", 3 | 4 | "MaxPulseTimeDiffNS" : 5000000000, 5 | 6 | "Config" : [ 7 | { "Ring" : 2, "FEN": 0, "Type": "FwEndCap", "Index" : 0, "Index2" : 6}, 8 | { "Ring" : 2, "FEN": 1, "Type": "FwEndCap", "Index" : 0, "Index2" : 4}, 9 | { "Ring" : 2, "FEN": 2, "Type": "FwEndCap", "Index" : 1, "Index2" : 6}, 10 | { "Ring" : 2, "FEN": 3, "Type": "FwEndCap", "Index" : 1, "Index2" : 4}, 11 | { "Ring" : 2, "FEN": 4, "Type": "FwEndCap", "Index" : 2, "Index2" : 6}, 12 | { "Ring" : 2, "FEN": 5, "Type": "FwEndCap", "Index" : 2, "Index2" : 4}, 13 | { "Ring" : 2, "FEN": 6, "Type": "FwEndCap", "Index" : 3, "Index2" : 6}, 14 | { "Ring" : 2, "FEN": 7, "Type": "FwEndCap", "Index" : 3, "Index2" : 4}, 15 | { "Ring" : 2, "FEN": 8, "Type": "FwEndCap", "Index" : 4, "Index2" : 6}, 16 | { "Ring" : 2, "FEN": 9, "Type": "FwEndCap", "Index" : 4, "Index2" : 4} 17 | ] 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM screamingudder/ubuntu20.04-build-node:2.1.0 2 | 3 | ENV DEBIAN_FRONTEND=noninteractive 4 | 5 | ARG http_proxy 6 | 7 | ARG https_proxy 8 | 9 | ARG local_conan_server 10 | 11 | # Add local Conan server if one is defined in the environment 12 | RUN if [ ! -z "$local_conan_server" ]; then conan remote add --insert 0 ess-dmsc-local "$local_conan_server"; fi 13 | 14 | # Do the Conan install step first so that we don't have to rebuild all dependencies if something changes in the efu source 15 | RUN mkdir efu 16 | RUN mkdir efu_src 17 | COPY conanfile.txt efu_src/ 18 | RUN cd efu && conan install --build=outdated ../efu_src/conanfile.txt 19 | COPY cmake efu_src/cmake 20 | COPY utils/udp efu_src/utils/udp 21 | COPY src efu_src/src 22 | COPY CMakeLists.txt LICENSE README.md efu_src/ 23 | 24 | RUN cd efu && \ 25 | cmake -DCONAN="MANUAL" ../efu_src && \ 26 | make -j4 27 | 28 | COPY docker_launch.sh . 29 | CMD ["./docker_launch.sh"] 30 | -------------------------------------------------------------------------------- /src/modules/caen/CaenBase.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Caen detector base plugin interface definition 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace Caen { 16 | 17 | class CaenBase : public Detector { 18 | 19 | private: 20 | DetectorType Type; 21 | 22 | public: 23 | CaenBase(BaseSettings const &Settings, DetectorType type); 24 | ~CaenBase() = default; 25 | 26 | void processingThread(); 27 | 28 | struct CaenCounters Counters; 29 | 30 | protected: 31 | std::vector> Serializers; 32 | }; 33 | 34 | } // namespace Caen 35 | -------------------------------------------------------------------------------- /src/modules/freia/generators/mb_udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial VMM3 readouts for multi-blade based setups 7 | //===----------------------------------------------------------------------===// 8 | 9 | // GCOVR_EXCL_START 10 | 11 | #include 12 | #include 13 | 14 | using namespace vmm3; 15 | using VMM3Data = VMM3Parser::VMM3Data; 16 | 17 | int main(int argc, char *argv[]) { 18 | 19 | Freia::MultiBladeGenerator Generator; 20 | uint8_t MultiBladeDataSize = sizeof(VMM3Data); 21 | Generator.setReadoutDataSize(MultiBladeDataSize); 22 | 23 | Generator.argParse(argc, argv); 24 | Generator.main(); 25 | 26 | Generator.transmitLoop(); 27 | 28 | return 0; 29 | } 30 | // GCOVR_EXCL_STOP 31 | -------------------------------------------------------------------------------- /src/modules/trex/generators/LETReadoutGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial VMM3a readouts with variable number 7 | /// of readouts 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Trex { 18 | 19 | class LETReadoutGenerator : public ReadoutGeneratorBase { 20 | public: 21 | LETReadoutGenerator(): ReadoutGeneratorBase(DetectorType::TREX) {} 22 | 23 | protected: 24 | void generateData() override; 25 | 26 | uint64_t GlobalReadout{0}; 27 | }; 28 | 29 | } // namespace Trex 30 | // GCOVR_EXCL_STOP 31 | -------------------------------------------------------------------------------- /src/common/system/gccintel.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief functions specific to gcc compilers and cpu architecture 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #ifdef __ARM_ARCH 13 | #include 14 | #else 15 | #include 16 | #endif 17 | 18 | // gcc specific macros 19 | 20 | /// branch prediction macros 21 | #if 0 22 | #define likely(x) __builtin_expect(!!(x), 1) 23 | #define unlikely(x) __builtin_expect(!!(x), 0) 24 | #else 25 | #define likely(x) (x) 26 | #define unlikely(x) (x) 27 | #endif 28 | 29 | 30 | #ifdef RELEASE 31 | #define UNUSED 32 | #else 33 | #define UNUSED __attribute__((unused)) 34 | #endif 35 | 36 | #define ALIGN(x) __attribute__((aligned(x))) 37 | -------------------------------------------------------------------------------- /src/modules/loki/generators/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial LOKI readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | // GCOVR_EXCL_START 11 | 12 | int main(int argc, char *argv[]) { 13 | 14 | Caen::ReadoutGenerator LokiGen; 15 | uint8_t LokiDataSize = sizeof(Caen::DataParser::CaenReadout); 16 | LokiGen.setReadoutDataSize(LokiDataSize); 17 | 18 | LokiGen.argParse(argc, argv); 19 | 20 | std::unique_ptr readoutTimeGenerator = 21 | std::make_unique(LokiGen.Settings.Frequency); 22 | LokiGen.initialize(std::move(readoutTimeGenerator)); 23 | 24 | LokiGen.transmitLoop(); 25 | 26 | return 0; 27 | } 28 | // GCOVR_EXCL_STOP 29 | -------------------------------------------------------------------------------- /src/modules/nmx/generators/SmileReadoutGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial VMM3a readouts with variable number 7 | /// of readouts 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Nmx { 18 | 19 | class SmileReadoutGenerator : public ReadoutGeneratorBase { 20 | public: 21 | SmileReadoutGenerator() 22 | : ReadoutGeneratorBase(DetectorType::NMX) {} 23 | 24 | protected: 25 | void generateData() override; 26 | 27 | int64_t Number{0}; 28 | }; 29 | 30 | } // namespace Nmx 31 | 32 | // GCOVR_EXCL_STOP 33 | -------------------------------------------------------------------------------- /src/generators/functiongenerators/FunctionGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Interface for function generators 7 | //===----------------------------------------------------------------------===// 8 | // GCOVR_EXCL_START 9 | 10 | #pragma once 11 | #include 12 | 13 | class FunctionGenerator { 14 | public: 15 | /// \brief Number of Bins defines the resolution of the distribution function. 16 | static constexpr uint32_t DEFAULT_BIN_COUNT{512}; 17 | virtual ~FunctionGenerator() {} 18 | 19 | /// \brief Get the value at a given position in the generator function. 20 | virtual double getValueByPos(double) = 0; 21 | 22 | /// \brief return a parameter value used to generate a distribution function. 23 | virtual double getValue() = 0; 24 | 25 | }; 26 | 27 | // GCOVR_EXCL_STOP -------------------------------------------------------------------------------- /src/common/monitor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Classes for hit and histogram serialization for monitor streams 3 | #============================================================================= 4 | 5 | set(monitor_obj_SRC 6 | Histogram.cpp 7 | HistogramSerializer.cpp 8 | DynamicHist.cpp 9 | HitSerializer.cpp 10 | ) 11 | 12 | set(monitor_obj_INC 13 | Histogram.h 14 | HistogramSerializer.h 15 | DynamicHist.h 16 | HitSerializer.h 17 | ) 18 | 19 | add_library(MonitorLib OBJECT 20 | ${monitor_obj_SRC} 21 | ${monitor_obj_INC} 22 | ) 23 | 24 | target_link_libraries(MonitorLib 25 | PRIVATE 26 | ${EFU_COMMON_LIBS} 27 | ) 28 | 29 | enable_coverage_flags(MonitorLib) 30 | 31 | #============================================================================= 32 | # Tests 33 | #============================================================================= 34 | 35 | add_subdirectory(test) 36 | -------------------------------------------------------------------------------- /src/modules/nmx/generators/MultiHitReadoutGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial VMM3a readouts with variable number 7 | /// of readouts 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Nmx { 18 | 19 | class MultiHitReadoutGenerator : public ReadoutGeneratorBase { 20 | public: 21 | MultiHitReadoutGenerator() 22 | : ReadoutGeneratorBase(DetectorType::NMX) {} 23 | 24 | protected: 25 | void generateData() override; 26 | 27 | int64_t Number{0}; 28 | }; 29 | 30 | } // namespace Nmx 31 | 32 | // GCOVR_EXCL_STOP 33 | -------------------------------------------------------------------------------- /src/modules/timepix3/test/TimepixTestHelper.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Helper classes for Timepix3 tests 6 | //===----------- 7 | 8 | #include 9 | #include 10 | 11 | #pragma once 12 | 13 | template 14 | class MockupDataEventReceiver : public Observer::DataEventObserver { 15 | private: 16 | std::unique_ptr testData; 17 | int applyDataCalls{0}; 18 | 19 | public: 20 | void setData(const DataEvent &appliedData) { 21 | testData = std::make_unique(appliedData); 22 | } 23 | 24 | void applyData(const DataEvent &appliedData) override { 25 | applyDataCalls++; 26 | EXPECT_EQ(appliedData, *testData); 27 | }; 28 | 29 | int getApplyDataCalls() const { return applyDataCalls; } 30 | }; -------------------------------------------------------------------------------- /src/common/reduction/NeutronEvent.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file NeutronEvent.h 5 | /// \brief NeutronEvent class definitions 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | /// \class NeutronEvent NeutronEvent.h 12 | /// \brief The final reduced tuple for event formation -- (time, pixel_id) 13 | /// This struct is intended for queueing up and sorting before 14 | /// subtracting the most recent pulse time serializing them for 15 | /// transmission. This is the most atomic piece of information that 16 | /// can come out of an event-processing pipeline. 17 | 18 | #include 19 | #include 20 | 21 | struct NeutronEvent { 22 | uint64_t time{0}; 23 | uint32_t pixel_id{0}; 24 | 25 | std::string to_string() const; 26 | }; 27 | -------------------------------------------------------------------------------- /docker_launch.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Run specified executable, or the efu by default 4 | # If a config file or optional arguments are provided then pass 5 | # them to the executable, otherwise print the help message 6 | 7 | # if EXECUTABLE is given as "efu" or omitted, then run the efu 8 | if [ "${EXECUTABLE}" = "efu" ] || [ -z "${EXECUTABLE}" ]; then 9 | if [ -z "${CONFIG_FILE}" ] && [ -z "${OPT_ARGS}" ]; then 10 | ./efu/bin/efu --help 11 | elif [ -z "${OPT_ARGS}" ]; then 12 | ./efu/bin/efu --read_config=${CONFIG_FILE} 13 | else 14 | ./efu/bin/efu ${OPT_ARGS} 15 | fi 16 | # if specified executable doesn't exist then print an error 17 | elif [ ! -f ./efu/bin/${EXECUTABLE} ]; then 18 | echo "Could not find executable with name ${EXECUTABLE}" 19 | exit 1 20 | # if specified executable exists then run it 21 | else 22 | if [ -z "${OPT_ARGS}" ]; then 23 | ./efu/bin/${EXECUTABLE} --help 24 | else 25 | ./efu/bin/${EXECUTABLE} ${OPT_ARGS} 26 | fi 27 | fi 28 | -------------------------------------------------------------------------------- /src/modules/miracles/generators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | #============================================================================= 3 | # UDP generator for MIRACLES 4 | #============================================================================= 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | #============================================================================= 9 | # Generate MIRACLES readouts from (.dat) file 10 | #============================================================================= 11 | 12 | set(miracles_udp_from_dat_SRC 13 | DatReader.cpp 14 | essudpgen.cpp 15 | ) 16 | set(miracles_udp_from_dat_INC 17 | DatReader.h 18 | ${ESS_MODULE_DIR}/caen/readout/Readout.h 19 | PacketGenerator.h 20 | ) 21 | create_executable(miracles_udp_from_dat) 22 | set_target_properties(miracles_udp_from_dat 23 | PROPERTIES 24 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators" 25 | ) 26 | -------------------------------------------------------------------------------- /src/modules/trex/generators/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial TREX readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | // GCOVR_EXCL_START 11 | 12 | using namespace vmm3; 13 | 14 | int main(int argc, char *argv[]) { 15 | 16 | Trex::ReadoutGenerator TrexGen; 17 | uint8_t TrexDataSize = sizeof(VMM3Parser::VMM3Data); 18 | TrexGen.setReadoutDataSize(TrexDataSize); 19 | 20 | TrexGen.argParse(argc, argv); 21 | 22 | std::unique_ptr readoutTimeGenerator = 23 | std::make_unique(TrexGen.Settings.Frequency); 24 | TrexGen.initialize(std::move(readoutTimeGenerator)); 25 | 26 | TrexGen.transmitLoop(); 27 | 28 | return 0; 29 | } 30 | // GCOVR_EXCL_STOP 31 | -------------------------------------------------------------------------------- /src/common/math/BitMath.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Small functions for bit- and byte- manipulations, graycode, reverse 6 | /// bits 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace essmath { 14 | 15 | class BitMath { 16 | public: 17 | /// \todo this is a hack to allow compilation of code from 18 | /// ROOT using cling (variant of clang) without c++14 support. 19 | inline static 20 | #ifndef VMM_SDAT 21 | constexpr 22 | #endif 23 | uint64_t 24 | NextPowerOfTwo(uint64_t n) { 25 | n--; 26 | n |= n >> 1; 27 | n |= n >> 2; 28 | n |= n >> 4; 29 | n |= n >> 8; 30 | n |= n >> 16; 31 | n |= n >> 32; 32 | n++; 33 | return n; 34 | } 35 | }; 36 | 37 | } // namespace essmath 38 | -------------------------------------------------------------------------------- /src/modules/nmx/generators/TrackReadoutGenerator.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generator of artificial VMM3a readouts with variable number 7 | /// of readouts 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Nmx { 18 | 19 | class TrackReadoutGenerator : public ReadoutGeneratorBase { 20 | public: 21 | TrackReadoutGenerator() 22 | : ReadoutGeneratorBase(DetectorType::NMX) {} 23 | 24 | protected: 25 | void generateData() override; 26 | 27 | uint8_t ReadoutsPerEvent{8}; 28 | int64_t Number{0}; 29 | }; 30 | 31 | } // namespace Nmx 32 | 33 | // GCOVR_EXCL_STOP 34 | -------------------------------------------------------------------------------- /src/modules/trex/generators/udpgen_let.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial LET readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | // GCOVR_EXCL_START 11 | 12 | using namespace vmm3; 13 | 14 | int main(int argc, char *argv[]) { 15 | 16 | Trex::LETReadoutGenerator TrexGen; 17 | uint8_t TrexDataSize = sizeof(VMM3Parser::VMM3Data); 18 | TrexGen.setReadoutDataSize(TrexDataSize); 19 | 20 | TrexGen.argParse(argc, argv); 21 | 22 | std::unique_ptr readoutTimeGenerator = 23 | std::make_unique(TrexGen.Settings.Frequency); 24 | TrexGen.initialize(std::move(readoutTimeGenerator)); 25 | TrexGen.transmitLoop(); 26 | 27 | return 0; 28 | } 29 | // GCOVR_EXCL_STOP 30 | -------------------------------------------------------------------------------- /src/common/reduction/matching/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Classes for cluster matching across planes 3 | #============================================================================= 4 | 5 | set(matching_obj_SRC 6 | AbstractMatcher.cpp 7 | OverlapMatcher.cpp 8 | GapMatcher.cpp 9 | EndMatcher.cpp 10 | CenterMatcher.cpp 11 | ) 12 | 13 | set(matching_obj_INC 14 | AbstractMatcher.h 15 | OverlapMatcher.h 16 | GapMatcher.h 17 | EndMatcher.h 18 | CenterMatcher.h 19 | ) 20 | 21 | add_library(MatchingLib OBJECT 22 | ${matching_obj_SRC} 23 | ${matching_obj_INC} 24 | ) 25 | 26 | target_link_libraries(MatchingLib 27 | PRIVATE 28 | ${EFU_COMMON_LIBS} 29 | ) 30 | 31 | enable_coverage_flags(MatchingLib) 32 | 33 | #============================================================================= 34 | # Tests 35 | #============================================================================= 36 | 37 | add_subdirectory(test) 38 | -------------------------------------------------------------------------------- /src/modules/nmx/generators/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial NMX readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | // GCOVR_EXCL_START 11 | 12 | using namespace vmm3; 13 | using VMM3Data = VMM3Parser::VMM3Data; 14 | 15 | int main(int argc, char *argv[]) { 16 | 17 | Nmx::ReadoutGenerator NmxGen; 18 | uint8_t DataSize = sizeof(VMM3Data); 19 | NmxGen.setReadoutDataSize(DataSize); 20 | 21 | NmxGen.argParse(argc, argv); 22 | 23 | std::unique_ptr readoutTimeGenerator = 24 | std::make_unique(NmxGen.Settings.Frequency); 25 | NmxGen.initialize(std::move(readoutTimeGenerator)); 26 | 27 | NmxGen.transmitLoop(); 28 | 29 | return 0; 30 | } 31 | // GCOVR_EXCL_STOP 32 | -------------------------------------------------------------------------------- /src/modules/timepix3/Timepix3Base.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Timepix3 detector base plugin interface definition 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class Timepix3BaseTest; // For access to private members for testing 18 | 19 | namespace Timepix3 { 20 | 21 | class Timepix3Base : public Detector { 22 | 23 | public: 24 | struct Counters Counters; 25 | 26 | Timepix3Base(BaseSettings const &Settings); 27 | ~Timepix3Base() = default; 28 | 29 | void processingThread(); 30 | 31 | private: 32 | Config timepix3Configuration; 33 | }; 34 | } // namespace Timepix3 35 | -------------------------------------------------------------------------------- /src/common/reduction/clustering/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # \todo AbstractClusterer tests 2 | 3 | set(GapClustererTest_SRC 4 | GapClustererTest.cpp 5 | ) 6 | create_test_executable(GapClustererTest) 7 | 8 | 9 | 10 | set(Hierarchical2DClustererTest_SRC 11 | Hierarchical2DClustererTest.cpp 12 | ) 13 | create_test_executable(Hierarchical2DClustererTest) 14 | 15 | 16 | #todo make abstract geometry class, non MG-specific? 17 | set(GapClusterer2DTest_INC 18 | ${ESS_COMMON_DIR}/reduction/multigrid/ModuleGeometry.h 19 | ) 20 | set(GapClusterer2DTest_SRC 21 | GapClusterer2DTest.cpp 22 | ${ESS_COMMON_DIR}/reduction/multigrid/ModuleGeometry.cpp 23 | ) 24 | create_test_executable(GapClusterer2DTest) 25 | 26 | 27 | set(Abstract2DClustererTest_INC 28 | ${ESS_COMMON_DIR}/reduction/clustering/Abstract2DClusterer.h 29 | ) 30 | set(Abstract2DClustererTest_SRC 31 | Abstract2DClustererTest.cpp 32 | ${ESS_COMMON_DIR}/reduction/clustering/Abstract2DClusterer.cpp 33 | ) 34 | create_test_executable(Abstract2DClustererTest) 35 | -------------------------------------------------------------------------------- /src/common/reduction/analysis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Classes for clustered event analysis 3 | #============================================================================= 4 | 5 | include_directories(.) 6 | include_directories(${ESS_MODULE_DIR}) 7 | 8 | set(analysis_obj_SRC 9 | AbstractAnalyzer.cpp 10 | MgAnalyzer.cpp 11 | UtpcAnalyzer.cpp 12 | EventAnalyzer.cpp 13 | ) 14 | 15 | set(analysis_obj_INC 16 | AbstractAnalyzer.h 17 | MgAnalyzer.h 18 | UtpcAnalyzer.h 19 | EventAnalyzer.h 20 | ) 21 | 22 | add_library(AnalysisLib OBJECT 23 | ${analysis_obj_SRC} 24 | ${analysis_obj_INC} 25 | ) 26 | 27 | target_link_libraries(AnalysisLib 28 | PRIVATE 29 | ${EFU_COMMON_LIBS} 30 | ) 31 | 32 | enable_coverage_flags(AnalysisLib) 33 | 34 | #============================================================================= 35 | # Tests 36 | #============================================================================= 37 | 38 | add_subdirectory(test) 39 | -------------------------------------------------------------------------------- /src/modules/dream/Counters.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief DREAM application counters (for Grafana and low level debug) 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | struct Counters { 17 | // ESSReadout parser 18 | int64_t ErrorESSHeaders{0}; 19 | 20 | // DREAM DataParser 21 | int64_t DataHeaders{0}; 22 | int64_t Readouts{0}; 23 | int64_t BufferErrors{0}; 24 | int64_t DataLenErrors{0}; 25 | int64_t FiberErrors{0}; 26 | int64_t FENErrors{0}; 27 | 28 | // DREAM Processing 29 | int64_t ProcessingIdle{0}; 30 | int64_t Events{0}; 31 | 32 | // Identification of the cause of produce calls 33 | int64_t ProduceCauseTimeout{0}; 34 | } __attribute__((aligned(64))); 35 | -------------------------------------------------------------------------------- /src/modules/bifrost/geometry/BifrostConfig.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Get loki configuration from json file 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | // #undef TRC_LEVEL 16 | // #define TRC_LEVEL TRC_L_DEB 17 | 18 | namespace Caen { 19 | 20 | class BifrostConfig : public Configurations::Config { 21 | public: 22 | ///\brief default constructor (useful for unit tests) 23 | BifrostConfig(); 24 | 25 | ///\brief constructor used in EFU to load json from file 26 | BifrostConfig(const std::string &ConfigFile); 27 | 28 | ///\brief parse the loaded json object 29 | void parseConfig(); 30 | 31 | struct BifrostCfg { 32 | int MaxAmpl{std::numeric_limits::max()}; 33 | } Parms; 34 | }; 35 | 36 | } // namespace Caen 37 | -------------------------------------------------------------------------------- /src/modules/caen/generators/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial CAEN readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | #include 12 | // GCOVR_EXCL_START 13 | 14 | int main(int argc, char *argv[]) { 15 | Caen::ReadoutGenerator CaenGen; 16 | CaenGen.setReadoutDataSize(sizeof(Caen::DataParser::CaenReadout)); 17 | CaenGen.argParse(argc, argv); 18 | 19 | auto readoutTimeGenerator = 20 | std::make_unique(CaenGen.Settings.Frequency); 21 | 22 | // Move the ownership of the readout time generator to the CaenGen instance 23 | CaenGen.initialize(std::move(readoutTimeGenerator)); 24 | CaenGen.transmitLoop(); 25 | 26 | return 0; 27 | } 28 | // GCOVR_EXCL_STOP 29 | -------------------------------------------------------------------------------- /src/common/reduction/matching/OverlapMatcher.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file OverlapMatcher.h 5 | /// \brief OverlapMatcher class definition 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | /// \class OverlapMatcher OverlapMatcher.h 14 | /// \brief Matcher implementation that joins clusters into events 15 | /// if they overlap in time. 16 | 17 | class OverlapMatcher : public AbstractMatcher { 18 | public: 19 | // Inherit constructor 20 | using AbstractMatcher::AbstractMatcher; 21 | 22 | /// \brief Match queued up clusters into events. 23 | /// Clusters that overlap in time are joined into events. 24 | /// \param flush if all queued clusters should be matched regardless of 25 | /// latency considerations 26 | void match(bool flush) override; 27 | }; 28 | -------------------------------------------------------------------------------- /src/modules/nmx/generators/udpgen_smile.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial NMX readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include // Add include for std::unique_ptr 11 | // GCOVR_EXCL_START 12 | 13 | using namespace vmm3; 14 | using VMM3Data = VMM3Parser::VMM3Data; 15 | 16 | int main(int argc, char *argv[]) { 17 | 18 | Nmx::SmileReadoutGenerator NmxGen; 19 | uint8_t DataSize = sizeof(VMM3Data); 20 | NmxGen.setReadoutDataSize(DataSize); 21 | 22 | NmxGen.argParse(argc, argv); 23 | 24 | std::unique_ptr readoutTimeGenerator = 25 | std::make_unique(NmxGen.Settings.Frequency); 26 | NmxGen.initialize(std::move(readoutTimeGenerator)); 27 | 28 | NmxGen.transmitLoop(); 29 | 30 | return 0; 31 | } 32 | // GCOVR_EXCL_STOP 33 | -------------------------------------------------------------------------------- /src/modules/nmx/generators/udpgen_track.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial NMX readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include // Add include for std::unique_ptr 11 | // GCOVR_EXCL_START 12 | 13 | using namespace vmm3; 14 | using VMM3Data = VMM3Parser::VMM3Data; 15 | 16 | int main(int argc, char *argv[]) { 17 | 18 | Nmx::TrackReadoutGenerator NmxGen; 19 | uint8_t DataSize = sizeof(VMM3Data); 20 | NmxGen.setReadoutDataSize(DataSize); 21 | 22 | NmxGen.argParse(argc, argv); 23 | 24 | std::unique_ptr readoutTimeGenerator = 25 | std::make_unique(NmxGen.Settings.Frequency); 26 | NmxGen.initialize(std::move(readoutTimeGenerator)); 27 | 28 | NmxGen.transmitLoop(); 29 | 30 | return 0; 31 | } 32 | // GCOVR_EXCL_STOP 33 | -------------------------------------------------------------------------------- /src/common/reduction/reduction.md: -------------------------------------------------------------------------------- 1 | # Reduction 2 | 3 | Reduction covers clustering and coincidence matching for systems where multiple readouts make-up a single event. 4 | 5 | ## No reduction necessary 6 | 7 | Many modules don't rely on the reduction library because a single readout is a single event. These systems include: 8 | - LoKI 9 | - Bifrost 10 | - Miracles 11 | - Magic 12 | - Dream 13 | 14 | 15 | ## Separate X and Y readouts 16 | 17 | Systems where readouts for the X and Y planes arrive separate and need to be matched, we use an object of type AbstractClusterer, forming clusters in time for each plane, followed by an object of type AbstractMatcher to combine clusters into 2D events. These systems include: 18 | - NMX 19 | - Freia 20 | - Estia 21 | - Amor 22 | 23 | ## Joint X and Y readouts 24 | 25 | Systems where readouts contain both X and Y information - but don't represent single neutron events and still need reduction - we use an object of type Abstract2DClusterer, forming clusters in time, and then splitting those into clusters in space. These systems include: 26 | - Timepix3 -------------------------------------------------------------------------------- /src/modules/dream/generators/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial DREAM readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | // GCOVR_EXCL_START 14 | 15 | int main(int argc, char *argv[]) { 16 | 17 | Dream::ReadoutGenerator DreamGen; 18 | uint8_t DreamDataSize = sizeof(Dream::DataParser::CDTReadout); 19 | DreamGen.setReadoutDataSize(DreamDataSize); 20 | 21 | DreamGen.argParse(argc, argv); 22 | 23 | std::unique_ptr readoutTimeGenerator = 24 | std::make_unique(DreamGen.Settings.Frequency); 25 | DreamGen.initialize(std::move(readoutTimeGenerator)); 26 | DreamGen.transmitLoop(); 27 | 28 | return 0; 29 | } 30 | // GCOVR_EXCL_STOP 31 | -------------------------------------------------------------------------------- /src/modules/cbm/configs/cbmtest.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "CBM", 4 | 5 | "TypeSubType" : 16, 6 | 7 | "MaxPulseTimeDiffNS" : 1000000000, 8 | 9 | "MaxTOFNS" : 10000000000, 10 | 11 | "MonitorRing" : 11, 12 | 13 | "MaxFENId" : 2, 14 | 15 | "Topology" : [ 16 | { "FEN": 0, "Channel": 0, "Type": "EVENT_0D", "Source" : "cbm1", "PixelOffset": 0 }, 17 | { "FEN": 0, "Channel": 1, "Type": "EVENT_0D", "Source" : "cbm2", "PixelOffset": 1 }, 18 | { "FEN": 1, "Channel": 0, "Type": "EVENT_0D", "Source" : "cbm3", "PixelOffset": 3 }, 19 | { "FEN": 1, "Channel": 1, "Type": "IBM", "Source" : "cbm4", "MaxTofBin": 10000, "BinCount": 100 }, 20 | { "FEN": 1, "Channel": 2, "Type": "IBM", "Source" : "cbm5", "MaxTofBin": 10000, "BinCount": 100 }, 21 | { "FEN": 2, "Channel": 1, "Type": "IBM", "Source" : "cbm6", "MaxTofBin": 10000, "BinCount": 100 }, 22 | { "FEN": 2, "Channel": 0, "Type": "EVENT_2D", "Source" : "cbm7", "Width": 512, "Height": 512 }, 23 | { "FEN": 2, "Channel": 2, "Type": "EVENT_2D", "Source" : "cbm8", "Width": 512, "Height": 512 } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/modules/freia/generators/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial FREIA readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | // GCOVR_EXCL_START 10 | 11 | #include 12 | #include 13 | 14 | using namespace vmm3; 15 | using VMM3Data = VMM3Parser::VMM3Data; 16 | 17 | int main(int argc, char *argv[]) { 18 | 19 | Freia::ReadoutGenerator FreiaGen; 20 | uint8_t FreiaDataSize = sizeof(VMM3Data); 21 | FreiaGen.setReadoutDataSize(FreiaDataSize); 22 | 23 | FreiaGen.argParse(argc, argv); 24 | 25 | std::unique_ptr readoutTimeGenerator = 26 | std::make_unique(FreiaGen.Settings.Frequency); 27 | FreiaGen.initialize(std::move(readoutTimeGenerator)); 28 | 29 | FreiaGen.transmitLoop(); 30 | 31 | return 0; 32 | } 33 | // GCOVR_EXCL_STOP 34 | -------------------------------------------------------------------------------- /src/common/readout/vmm3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # ESS VMM3 Parser Tests 5 | #============================================================================= 6 | 7 | set(VMM3ParserTest_INC 8 | VMM3Parser.h 9 | test/VMM3ParserTestData.h 10 | ) 11 | set(VMM3ParserTest_SRC 12 | test/VMM3ParserTest.cpp 13 | VMM3Parser.cpp 14 | ) 15 | create_test_executable(VMM3ParserTest) 16 | 17 | 18 | set(VMM3CalibrationTest_INC 19 | VMM3Calibration.h 20 | ) 21 | set(VMM3CalibrationTest_SRC 22 | test/VMM3CalibrationTest.cpp 23 | VMM3Calibration.cpp 24 | ) 25 | create_test_executable(VMM3CalibrationTest) 26 | 27 | 28 | set(VMM3ConfigTest_INC 29 | VMM3Config.h 30 | ) 31 | set(VMM3ConfigTest_SRC 32 | test/VMM3ConfigTest.cpp 33 | VMM3Config.cpp 34 | ) 35 | create_test_executable(VMM3ConfigTest) 36 | 37 | set(HybridTest_INC 38 | Hybrid.h 39 | ) 40 | set(HybridTest_SRC 41 | test/HybridTest.cpp 42 | ) 43 | create_test_executable(HybridTest) 44 | -------------------------------------------------------------------------------- /src/modules/dream/generators/g4data/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate Dream udp stream from a dat file 7 | //===----------------------------------------------------------------------===// 8 | 9 | // GCOVR_EXCL_START 10 | 11 | #include 12 | 13 | int main(int argc, char *argv[]) { 14 | 15 | ReadoutGenerator DreamGen; 16 | uint8_t DreamDataSize = sizeof(Dream::DataParser::CDTReadout); 17 | DreamGen.setReadoutDataSize(DreamDataSize); 18 | 19 | DreamGen.argParse(argc, argv); 20 | 21 | // Create a FunctionGenerator for the readout timing 22 | std::unique_ptr readoutTimeGenerator = 23 | std::make_unique(DreamGen.Settings.Frequency); 24 | 25 | DreamGen.main(); 26 | DreamGen.initialize(std::move(readoutTimeGenerator)); 27 | DreamGen.transmitLoop(); 28 | 29 | return 0; 30 | } 31 | 32 | // GCOVR_EXCL_STOP 33 | -------------------------------------------------------------------------------- /src/common/reduction/clustering/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Classes for hit clustering 3 | #============================================================================= 4 | 5 | include_directories(.) 6 | include_directories(${ESS_MODULE_DIR}) 7 | 8 | set(clustering_obj_SRC 9 | AbstractClusterer.cpp 10 | Abstract2DClusterer.cpp 11 | Hierarchical2DClusterer.cpp 12 | GapClusterer.cpp 13 | GapClusterer2D.cpp 14 | ) 15 | 16 | set(clustering_obj_INC 17 | AbstractClusterer.h 18 | Abstract2DClusterer.h 19 | Hierarchical2DClusterer.h 20 | GapClusterer.h 21 | GapClusterer2D.h 22 | ) 23 | 24 | add_library(ClusteringLib OBJECT 25 | ${clustering_obj_SRC} 26 | ${clustering_obj_INC} 27 | ) 28 | 29 | target_link_libraries(ClusteringLib 30 | PRIVATE 31 | ${EFU_COMMON_LIBS} 32 | ) 33 | 34 | enable_coverage_flags(ClusteringLib) 35 | 36 | #============================================================================= 37 | # Tests 38 | #============================================================================= 39 | 40 | add_subdirectory(test) 41 | -------------------------------------------------------------------------------- /cmake/AddTargetFlags.cmake: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Add linker flags 3 | #============================================================================= 4 | function(add_linker_flags target flags) 5 | get_target_property(cur_link_flags ${target} LINK_FLAGS) 6 | if(NOT cur_link_flags) 7 | set(cur_link_flags "") 8 | endif() 9 | set(new_link_flags "${cur_link_flags} ${flags}") 10 | set_target_properties(${target} PROPERTIES LINK_FLAGS "${new_link_flags}") 11 | endfunction(add_linker_flags) 12 | 13 | #============================================================================= 14 | # Add compiler flags 15 | #============================================================================= 16 | function(add_compile_flags target flags) 17 | get_target_property(cur_compile_flags ${target} COMPILE_FLAGS) 18 | if(NOT cur_compile_flags) 19 | set(cur_compile_flags "") 20 | endif() 21 | set(new_compile_flags "${cur_compile_flags} ${flags}") 22 | set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${new_compile_flags}") 23 | endfunction(add_compile_flags) 24 | -------------------------------------------------------------------------------- /src/modules/loki/configs/old/Loki.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector": "loki", 4 | 5 | "StrawResolution" : 512, 6 | 7 | "PanelConfig" : [ 8 | { "Bank" : 0, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 32, "StrawOffset" : 0 }, 9 | { "Bank" : 0, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 24, "StrawOffset" : 896 }, 10 | { "Bank" : 1, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 16, "StrawOffset" : 1568 }, 11 | { "Bank" : 2, "Vertical" : true, "GroupsZ" : 4, "GroupsN" : 12, "StrawOffset" : 2016 }, 12 | { "Bank" : 3, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 16, "StrawOffset" : 2352 }, 13 | { "Bank" : 4, "Vertical" : true, "GroupsZ" : 4, "GroupsN" : 12, "StrawOffset" : 2800 }, 14 | { "Bank" : 5, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 28, "StrawOffset" : 3136 }, 15 | { "Bank" : 6, "Vertical" : true, "GroupsZ" : 4, "GroupsN" : 32, "StrawOffset" : 3920 }, 16 | { "Bank" : 7, "Vertical" : false, "GroupsZ" : 4, "GroupsN" : 20, "StrawOffset" : 4816 }, 17 | { "Bank" : 8, "Vertical" : true, "GroupsZ" : 4, "GroupsN" : 32, "StrawOffset" : 5376 } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /src/common/monitor/Monitor.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | /// \todo document functions 15 | 16 | struct Monitor { 17 | Monitor() = default; 18 | Monitor(const std::string &broker, const std::string &topic_prefix, 19 | const std::string &source_name); 20 | ~Monitor() { close(); } 21 | 22 | std::shared_ptr histograms; 23 | std::shared_ptr hit_serializer; 24 | 25 | void init_histograms(size_t max_range); 26 | 27 | void init_hits(size_t max_readouts); 28 | 29 | void close(); 30 | 31 | void produce_now(); 32 | 33 | private: 34 | std::string source_name_; 35 | std::shared_ptr producer; 36 | std::shared_ptr hist_serializer; 37 | }; 38 | -------------------------------------------------------------------------------- /src/common/monitor/HistogramSerializer.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief flatbuffer serialization 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | class HistogramSerializer { 18 | public: 19 | /// \todo document 20 | HistogramSerializer(size_t buffer_half_size, const std::string &source_name); 21 | 22 | void set_callback(ProducerCallback cb); 23 | 24 | /// \todo document 25 | size_t produce(const Hists &hists); 26 | 27 | private: 28 | ProducerCallback producer_callback; 29 | 30 | flatbuffers::FlatBufferBuilder builder; 31 | 32 | std::string SourceName; 33 | 34 | uint8_t *xtrackptr{nullptr}; 35 | uint8_t *ytrackptr{nullptr}; 36 | 37 | uint8_t *xadcptr{nullptr}; 38 | uint8_t *yadcptr{nullptr}; 39 | uint8_t *clus_adc_ptr{nullptr}; 40 | }; 41 | -------------------------------------------------------------------------------- /src/modules/loki/generators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2023 European Spallation Source, ERIC. See LICENSE file 2 | 3 | 4 | #============================================================================= 5 | # Generate artificial LoKI readouts 6 | #============================================================================= 7 | 8 | set(loki_udp_generated_INC 9 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.h 10 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.h 11 | ${ESS_MODULE_DIR}/loki/generators/ReadoutGenerator.h 12 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.h 13 | ) 14 | set(loki_udp_generated_SRC 15 | ${ESS_MODULE_DIR}/loki/generators/ReadoutGenerator.cpp 16 | ${ESS_MODULE_DIR}/loki/generators/udpgen.cpp 17 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.cpp 18 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.cpp 19 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.cpp 20 | ) 21 | create_executable(loki_udp_generated) 22 | 23 | set_target_properties(loki_udp_generated 24 | PROPERTIES 25 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators" 26 | ) 27 | -------------------------------------------------------------------------------- /src/common/reduction/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(HitTest_SRC 3 | HitTest.cpp 4 | ) 5 | create_test_executable(HitTest SKIP_MEMGRIND) 6 | 7 | set(HitVectorTest_SRC 8 | HitVectorTest.cpp 9 | ) 10 | create_test_executable(HitVectorTest) 11 | 12 | set(Hit2DVectorTest_SRC 13 | Hit2DVectorTest.cpp 14 | ) 15 | create_test_executable(Hit2DVectorTest) 16 | 17 | set(ClusterTest_SRC 18 | ClusterTest.cpp 19 | ) 20 | create_test_executable(ClusterTest) 21 | 22 | set(EventTest_SRC 23 | EventTest.cpp 24 | ) 25 | create_test_executable(EventTest) 26 | 27 | 28 | set(Cluster2DTest_INC 29 | ${ESS_COMMON_DIR}/reduction/Cluster2D.h 30 | ) 31 | set(Cluster2DTest_SRC 32 | Cluster2DTest.cpp 33 | ${ESS_COMMON_DIR}/reduction/Cluster2D.cpp 34 | ) 35 | create_test_executable(Cluster2DTest) 36 | 37 | 38 | set(ReducedEventTest_SRC 39 | ReducedEventTest.cpp 40 | ) 41 | create_test_executable(ReducedEventTest) 42 | 43 | set(ChronoMergerTest_SRC 44 | ChronoMergerTest.cpp 45 | ) 46 | create_test_executable(ChronoMergerTest) 47 | 48 | set(HitVectorBenchmark_SRC 49 | HitVectorBenchmark.cpp 50 | ) 51 | create_benchmark_executable(HitVectorBenchmark) 52 | -------------------------------------------------------------------------------- /cmake/Memcheck.cmake: -------------------------------------------------------------------------------- 1 | function(setup_memcheck results_dir) 2 | find_program(VALGRIND_CMD valgrind) 3 | mark_as_advanced(VALGRIND_CMD) 4 | if(EXISTS ${VALGRIND_CMD}) 5 | file(MAKE_DIRECTORY ${results_dir}) 6 | set(VALGRIND_RESULTS_DIR ${results_dir} PARENT_SCOPE) 7 | set(VALGRIND_ENABLED ON PARENT_SCOPE) 8 | message(STATUS "Valgrind found. Configureed memory checks. Results dir: ${results_dir}") 9 | else() 10 | set(VALGRIND_ENABLED OFF PARENT_SCOPE) 11 | message(STATUS "Valgrind not found. Unable to configure memory check.") 12 | endif() 13 | endfunction() 14 | 15 | set(vagrind_targets "" CACHE INTERNAL "All valgrind targets") 16 | 17 | function(memcheck_test test_target test_binary_dir) 18 | if(${VALGRIND_ENABLED}) 19 | add_custom_target(memcheck_${test_target} COMMAND ${VALGRIND_CMD} 20 | --tool=memcheck --leak-check=full --verbose --xml=yes 21 | --xml-file=${VALGRIND_RESULTS_DIR}/${test_target}_memcheck.valgrind 22 | ${test_binary_dir}/${test_target}) 23 | set(valgrind_targets 24 | ${valgrind_targets} memcheck_${test_target} 25 | CACHE INTERNAL "All valgrind targets") 26 | endif() 27 | endfunction() 28 | -------------------------------------------------------------------------------- /src/common/testutils/DataFuzzer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Class for fuzzing a data buffer: writing random data at random 7 | /// locations according to specifications. 8 | //===----------------------------------------------------------------------===// 9 | // GCOVR_EXCL_START 10 | 11 | #include 12 | #include 13 | 14 | void DataFuzzer::fuzz8Bits(void *Buffer, uint16_t BufferLength, 15 | uint16_t MaxRepeats) { 16 | // randomInterval(0, N) yields values from 0, N - 1. Hence the + 1 17 | uint16_t Repeats = randomInterval(0, MaxRepeats + 1); 18 | // printf("fuzz8Bits %u repeats (%u possible)\n", Repeats, MaxRepeats); 19 | for (uint16_t i = 0; i < Repeats; i++) { 20 | uint16_t Offset = randomInterval(0, BufferLength); 21 | uint8_t Value = random8(); 22 | // printf("Offset: %u, value: %u\n", Offset, Value); 23 | assert(Offset < BufferLength); 24 | *((uint8_t *)Buffer + Offset) = Value; 25 | } 26 | } 27 | 28 | // GCOVR_EXCL_STOP 29 | -------------------------------------------------------------------------------- /src/common/testutils/SaveBuffer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Save a buffer to file - only to be used in unit tests! 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | // GCOVR_EXCL_START 14 | 15 | void saveBuffer(const std::string &filename, void *buffer, uint64_t datasize) { 16 | int fd; 17 | const int flags = O_TRUNC | O_CREAT | O_RDWR; 18 | const int mode = S_IRUSR | S_IWUSR; 19 | 20 | if ((fd = open(filename.c_str(), flags, mode)) < 0) { 21 | throw std::runtime_error( 22 | fmt::format("saveBuffer: open({}) failed", filename)); 23 | } 24 | 25 | if (::write(fd, buffer, datasize) < 0) { 26 | throw std::runtime_error( 27 | fmt::format("saveBuffer: write({}) failed", filename)); 28 | } 29 | } 30 | 31 | void deleteFile(const std::string &filename) { remove(filename.c_str()); } 32 | 33 | // GCOVR_EXCL_STOP 34 | -------------------------------------------------------------------------------- /src/modules/cbm/test/cbm_base_test.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "CBM", 4 | 5 | "TypeSubType" : 16, 6 | 7 | "NumberOfMonitors" : 11, 8 | 9 | "MaxPulseTimeDiffNS" : 1000000000, 10 | 11 | "MaxTOFNS" : 1000000000, 12 | 13 | "MaxFENId" : 2, 14 | 15 | "Topology" : [ 16 | { "FEN": 0, "Channel": 0, "Type": "EVENT_0D", "Source" : "cbm1", "PixelOffset": 0 }, 17 | { "FEN": 0, "Channel": 1, "Type": "EVENT_0D", "Source" : "cbm2", "PixelOffset": 1 }, 18 | { "FEN": 1, "Channel": 0, "Type": "EVENT_0D", "Source" : "cbm3", "PixelOffset": 3 }, 19 | { "FEN": 1, "Channel": 1, "Type": "IBM", "Source" : "cbm4", "MaxTofBin": 10000, "BinCount": 100 }, 20 | { "FEN": 1, "Channel": 2, "Type": "IBM", "Source" : "cbm5", "MaxTofBin": 10000, "BinCount": 100 }, 21 | { "FEN": 2, "Channel": 1, "Type": "IBM", "Source" : "cbm6", "MaxTofBin": 10000, "BinCount": 100 }, 22 | { "FEN": 2, "Channel": 2, "Type": "EVENT_2D", "Source" : "cbm7", "Width": 512, "Height": 512 }, 23 | { "FEN": 2, "Channel": 3, "Type": "EVENT_2D", "Source" : "cbm8", "Width": 512, "Height": 512 }, 24 | { "FEN": 2, "Channel": 4, "Type": "EVENT_2D", "Source" : "cbm9", "Width": 512, "Height": 512 } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/modules/dream/geometry/DreamMantle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief CDT Mantle module abstractions 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace Dream { 15 | 16 | uint32_t DreamMantle::calcPixelId(const Config::ModuleParms &Parms, 17 | const DataParser::CDTReadout &Data) const { 18 | uint8_t MountingUnit = Parms.P1.MU; 19 | uint8_t Cassette = Parms.P2.Cassette; 20 | uint8_t Counter = (Data.Anode / WiresPerCounter) % 2; 21 | uint8_t Wire = Data.Anode % WiresPerCounter; 22 | uint8_t Strip = Data.Cathode % StripsPerCass; 23 | 24 | XTRACE(DATA, DEB, "M.U. %u, Cassette %u, Counter %u, Wire %u, Strip %u", 25 | MountingUnit, Cassette, Counter, Wire, Strip); 26 | 27 | int x = getX(Strip); 28 | int y = getY(MountingUnit, Cassette, Counter, Wire); 29 | return pixel2D(x, y); 30 | } 31 | 32 | } // namespace Dream 33 | -------------------------------------------------------------------------------- /.ci/docker/Dockerfile_entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CMD="$BINARY_PATH -b $BROKER_ADDR -t $BROKER_TOPIC --nohwcheck" 4 | 5 | if [ -n "$GRAPHITE" ]; then 6 | CMD="$CMD -g $GRAPHITE" 7 | fi 8 | 9 | if [ -z "$FILE" ]; then 10 | echo "Please specify a config file" 11 | exit 1 12 | elif [ ! -r "./config/$FILE" ]; then 13 | echo "File $FILE does not exist or is not readable" 14 | exit 1 15 | else 16 | CMD="$CMD -f ./config/$FILE" 17 | fi 18 | 19 | 20 | if [ -n "$CALIBRATION" ]; then 21 | if [ ! -r "./calib/$CALIBRATION" ]; then 22 | echo "File $CALIBRATION does not exist or is not readable" 23 | exit 1 24 | else 25 | CMD="$CMD --calibration ./calib/$CALIBRATION" 26 | fi 27 | fi 28 | 29 | if [ -n "$KAFKA_CONFIG_PATH" ]; then 30 | if [ ! -r "$KAFKA_CONFIG_PATH" ]; then 31 | echo "File $KAFKA_CONFIG_PATH does not exist or is not readable" 32 | exit 1 33 | else 34 | CMD="$CMD --kafka_config $KAFKA_CONFIG_PATH" 35 | fi 36 | fi 37 | 38 | if [ -n "$REGION" ]; then 39 | CMD="$CMD --region $REGION" 40 | fi 41 | 42 | if [ -n "$EXTRA_ARGS" ]; then 43 | CMD="$CMD $EXTRA_ARGS" 44 | fi 45 | 46 | echo "Running $CMD" 47 | 48 | exec $CMD 49 | -------------------------------------------------------------------------------- /cmake/modules/FindValgrindSdk.cmake: -------------------------------------------------------------------------------- 1 | # Finds the Valgrind source installation. 2 | # 3 | # Var VALGRIND_SDK_ROOT Where is valgrind source. 4 | # Var ValgrindSdk_FOUND Do we have the valgrind source. 5 | # Function add_valgrind_sdk() Adds compile define BUILD_SUPPORT_VALGRIND_SDK to target 6 | # and VALGRIND_SDK_ROOT to target include directories. 7 | 8 | find_path(VALGRIND_SDK_ROOT valgrind/valgrind.h 9 | /usr/include 10 | /usr/local/include 11 | /usr/local/opt/ 12 | ${VALGRIND_SDK_PREFIX}/include 13 | ) 14 | 15 | include(FindPackageHandleStandardArgs) 16 | find_package_handle_standard_args(ValgrindSdk DEFAULT_MSG 17 | VALGRIND_SDK_ROOT 18 | ) 19 | 20 | mark_as_advanced( 21 | VALGRIND_SDK_ROOT 22 | ) 23 | 24 | function(add_valgrind_sdk target_name) 25 | if(ValgrindSdk_FOUND) 26 | set_property(TARGET ${target_name} APPEND PROPERTY INCLUDE_DIRECTORIES "${VALGRIND_SDK_ROOT}") 27 | set_property(TARGET ${target_name} APPEND_STRING PROPERTY COMPILE_FLAGS "-DBUILD_SUPPORT_VALGRIND_SDK") 28 | message(STATUS "ValgrindSdk enabled for ${target_name}") 29 | else() 30 | message(STATUS "ValgrindSdk disabled for ${target_name}") 31 | endif() 32 | endfunction() -------------------------------------------------------------------------------- /src/modules/miracles/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Tests 3 | #============================================================================= 4 | 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | ## 9 | ## Pure unit tests 10 | ## 11 | 12 | set(MiraclesGeometryTest_INC 13 | ../geometry/MiraclesGeometry.h 14 | ${ESS_MODULE_DIR}/caen/geometry/Config.h 15 | ${ESS_MODULE_DIR}/caen/geometry/CDCalibration.h 16 | ${ESS_MODULE_DIR}/caen/geometry/Interval.h 17 | ${ESS_MODULE_DIR}/loki/geometry/LokiConfig.h 18 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeConfig.h 19 | ${ESS_MODULE_DIR}/bifrost/geometry/BifrostConfig.h 20 | ) 21 | set(MiraclesGeometryTest_SRC 22 | MiraclesGeometryTest.cpp 23 | ../geometry/MiraclesGeometry.cpp 24 | ${ESS_MODULE_DIR}/caen/geometry/Config.cpp 25 | ${ESS_MODULE_DIR}/caen/geometry/CDCalibration.cpp 26 | ${ESS_MODULE_DIR}/caen/geometry/Interval.cpp 27 | ${ESS_MODULE_DIR}/loki/geometry/LokiConfig.cpp 28 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeConfig.cpp 29 | ${ESS_MODULE_DIR}/bifrost/geometry/BifrostConfig.cpp 30 | ) 31 | create_test_executable(MiraclesGeometryTest) 32 | -------------------------------------------------------------------------------- /src/modules/nmx/generators/udpgen_multihit.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial NMX readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | #include // Add include for std::unique_ptr 12 | #include 13 | // GCOVR_EXCL_START 14 | 15 | using namespace vmm3; 16 | using VMM3Data = VMM3Parser::VMM3Data; 17 | 18 | int main(int argc, char *argv[]) { 19 | 20 | Nmx::MultiHitReadoutGenerator NmxGen; 21 | uint8_t DataSize = sizeof(VMM3Data); 22 | NmxGen.setReadoutDataSize(DataSize); 23 | 24 | NmxGen.argParse(argc, argv); 25 | 26 | std::unique_ptr readoutTimeGenerator = 27 | std::make_unique(NmxGen.Settings.Frequency); 28 | NmxGen.initialize(std::move(readoutTimeGenerator)); 29 | 30 | NmxGen.transmitLoop(); 31 | 32 | return 0; 33 | } 34 | // GCOVR_EXCL_STOP 35 | -------------------------------------------------------------------------------- /src/modules/nmx/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Tests 3 | #============================================================================= 4 | 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | get_filename_component(NMX_FULL "${ESS_MODULE_DIR}/nmx/configs/nmx.json" ABSOLUTE) 9 | get_filename_component(NMX_MINI "${ESS_MODULE_DIR}/nmx/configs/mininmx.json" ABSOLUTE) 10 | 11 | ## 12 | ## Pure unit tests 13 | ## 14 | 15 | set(NMXConfigTest_INC 16 | ../geometry/Config.h) 17 | set(NMXConfigTest_SRC 18 | ../geometry/Config.cpp 19 | NMXConfigTest.cpp) 20 | create_test_executable(NMXConfigTest) 21 | target_compile_definitions(NMXConfigTest PRIVATE NMX_FULL="${NMX_FULL}") 22 | 23 | 24 | set(NMXGeometryTest_INC 25 | ../geometry/NMXGeometry.h) 26 | set(NMXGeometryTest_SRC 27 | ../test/NMXGeometryTest.cpp 28 | ../geometry/NMXGeometry.cpp 29 | ../geometry/Config.cpp) 30 | create_test_executable(NMXGeometryTest) 31 | 32 | 33 | 34 | # set(NMXChannelMappingTest_INC 35 | # ../geometry/NMXChannelMapping.h) 36 | # set(NMXChannelMappingTest_SRC 37 | # ../test/NMXChannelMappingTest.cpp) 38 | # create_test_executable(NMXChannelMappingTest) 39 | -------------------------------------------------------------------------------- /src/modules/dream/geometry/HeimdalMantle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief CDT Mantle module abstractions 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace Dream { 15 | 16 | uint32_t HeimdalMantle::calcPixelId(const Config::ModuleParms &Parms, 17 | const DataParser::CDTReadout &Data) const { 18 | uint8_t MountingUnit = Parms.P1.MU; 19 | uint8_t Cassette = Parms.P2.Cassette; 20 | uint8_t Counter = (Data.Anode / WiresPerCounter) % 2; 21 | uint8_t Wire = Data.Anode % WiresPerCounter; 22 | uint8_t Strip = Data.Cathode % StripsPerCass; 23 | 24 | XTRACE(DATA, DEB, "M.U. %u, Cassette %u, Counter %u, Wire %u, Strip %u", 25 | MountingUnit, Cassette, Counter, Wire, Strip); 26 | 27 | const int y = getY(Strip, Wire); 28 | const int x = getX(MountingUnit, Cassette, Counter); 29 | return pixel2D(x, y); 30 | } 31 | 32 | } // namespace Dream 33 | -------------------------------------------------------------------------------- /src/modules/miracles/generators/DatReader.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2024 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief reader for MIRACLES data 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | class MiraclesDatReader { 16 | public: 17 | struct dat_data_t { 18 | uint8_t ring; 19 | uint8_t fen; 20 | uint16_t datalen; 21 | uint32_t tofhi; 22 | uint32_t toflow; 23 | uint8_t unused1; 24 | uint8_t tube; 25 | uint16_t unused2; 26 | uint16_t ampl_a; 27 | uint16_t ampl_b; 28 | uint32_t unused3; 29 | } __attribute__((__packed__)); 30 | static_assert(sizeof(struct dat_data_t) == 24, "wrong packing"); 31 | 32 | // 33 | MiraclesDatReader(const std::string &file, bool Verbose); 34 | 35 | // Read a CDTReadout struct, return bytes read, 0 if line is 36 | // ignored, or -1 upon error/end 37 | int readReadout(struct dat_data_t &reaout); 38 | 39 | private: 40 | std::string filename; 41 | std::ifstream *infile; 42 | uint32_t lines{0}; 43 | bool Verbose{false}; 44 | }; 45 | -------------------------------------------------------------------------------- /src/modules/caen/generators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 - 2024 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # Generate CAEN readouts 5 | #============================================================================= 6 | 7 | set(caen_udp_generated_INC 8 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.h 9 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.h 10 | ${ESS_MODULE_DIR}/caen/generators/ReadoutGenerator.h 11 | ${ESS_COMMON_DIR}/testutils/bitmaps/BitMaps.h 12 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.h 13 | ) 14 | 15 | set(caen_udp_generated_SRC 16 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.cpp 17 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.cpp 18 | ${ESS_MODULE_DIR}/caen/generators/ReadoutGenerator.cpp 19 | ${ESS_MODULE_DIR}/caen/generators/udpgen.cpp 20 | ${ESS_COMMON_DIR}/testutils/bitmaps/BitMaps.cpp 21 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.cpp 22 | ) 23 | create_executable(caen_udp_generated) 24 | 25 | set_target_properties(caen_udp_generated 26 | PROPERTIES 27 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators" 28 | ) 29 | -------------------------------------------------------------------------------- /src/modules/cspec/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Tests 3 | #============================================================================= 4 | 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | get_filename_component(CSPEC_FULL "${ESS_MODULE_DIR}/cspec/configs/cspec.json" ABSOLUTE) 9 | 10 | ## 11 | ## Pure unit tests 12 | ## 13 | 14 | set(CspecGeometryTest_INC 15 | ../geometry/CspecGeometry.h 16 | ${ESS_MODULE_DIR}/caen/geometry/Config.h 17 | ${ESS_MODULE_DIR}/caen/geometry/CDCalibration.h 18 | ${ESS_MODULE_DIR}/caen/geometry/Interval.h 19 | ${ESS_MODULE_DIR}/loki/geometry/LokiConfig.h 20 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeConfig.h 21 | ${ESS_MODULE_DIR}/bifrost/geometry/BifrostConfig.h 22 | ) 23 | set(CspecGeometryTest_SRC 24 | CspecGeometryTest.cpp 25 | ../geometry/CspecGeometry.cpp 26 | ${ESS_MODULE_DIR}/caen/geometry/Config.cpp 27 | ${ESS_MODULE_DIR}/caen/geometry/CDCalibration.cpp 28 | ${ESS_MODULE_DIR}/caen/geometry/Interval.cpp 29 | ${ESS_MODULE_DIR}/loki/geometry/LokiConfig.cpp 30 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeConfig.cpp 31 | ${ESS_MODULE_DIR}/bifrost/geometry/BifrostConfig.cpp 32 | ) 33 | create_test_executable(CspecGeometryTest) 34 | -------------------------------------------------------------------------------- /utils/efushell/EFUMetrics.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) 4 | 5 | try: 6 | from utils.efushell.SocketDriver import SimpleSocket 7 | 8 | except: 9 | from SocketDriver import SimpleSocket 10 | 11 | 12 | class Metrics: 13 | def __init__(self, ip, port): 14 | self.metrics = {} 15 | self.ip = ip 16 | self.port = port 17 | self.driver = SimpleSocket(self.ip, self.port) 18 | 19 | def _get_efu_command(self, cmd): 20 | res = self.driver.Ask(cmd) 21 | 22 | if res.find(b"Error:") != -1: 23 | print("Error getting EFU command") 24 | sys.exit(1) 25 | return res 26 | 27 | def get_number_of_stats(self): 28 | return int(self._get_efu_command('STAT_GET_COUNT').split()[1]) 29 | 30 | def get_all_metrics(self, num_metrics): 31 | for i in range(1, num_metrics + 1): 32 | res = self._get_efu_command('STAT_GET ' + str(i)).split() 33 | name = res[1].decode('utf-8') 34 | value = int(res[2]) 35 | self.metrics[name] = value 36 | 37 | def return_metric(self, name): 38 | try: 39 | return self.metrics[name] 40 | except: 41 | return -1 42 | -------------------------------------------------------------------------------- /src/modules/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | #============================================================================= 3 | # Add ESS detector modules 4 | #============================================================================= 5 | 6 | include_directories(.) 7 | 8 | add_subdirectory(bifrost) 9 | add_subdirectory(caen) 10 | add_subdirectory(timepix3) 11 | add_subdirectory(trex) 12 | add_subdirectory(cspec) 13 | add_subdirectory(dream) 14 | add_subdirectory(freia) 15 | add_subdirectory(loki) 16 | add_subdirectory(miracles) 17 | add_subdirectory(nmx) 18 | add_subdirectory(perfgen) 19 | add_subdirectory(cbm) 20 | add_subdirectory(tbl3he) 21 | 22 | 23 | #============================================================================= 24 | # Support out-of-tree build 25 | #============================================================================= 26 | # ex: cmake -DEFU_EXTERNAL_DIR="/tmp/dir1;/var/dir2" .. 27 | 28 | if(DEFINED EFU_EXTERNAL_DIR) 29 | foreach(builddir IN LISTS EFU_EXTERNAL_DIR) 30 | if(EXISTS "${builddir}") 31 | MESSAGE(STATUS "ECDC: Building out of source module \"${builddir}\"") 32 | add_subdirectory("${builddir}" "${builddir}/bin") 33 | else() 34 | MESSAGE(FATAL_ERROR "ECDC: Out of source module \"${builddir}\" doesn't exist") 35 | endif() 36 | endforeach() 37 | endif() 38 | -------------------------------------------------------------------------------- /src/common/readout/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | #============================================================================= 3 | # Add ess detector modules 4 | #============================================================================= 5 | 6 | include_directories(.) 7 | 8 | add_subdirectory(ess) 9 | add_subdirectory(vmm3) 10 | 11 | 12 | set(essreadout_obj_SRC 13 | ess/Parser.cpp 14 | vmm3/VMM3Calibration.cpp 15 | vmm3/VMM3Config.cpp 16 | vmm3/VMM3Parser.cpp 17 | ) 18 | 19 | set(essreadout_obj_INC 20 | ess/Parser.h 21 | vmm3/Hybrid.h 22 | vmm3/Readout.h 23 | vmm3/VMM3Calibration.h 24 | vmm3/VMM3Config.h 25 | vmm3/VMM3Parser.h 26 | ) 27 | 28 | add_library(EssReadoutLib OBJECT 29 | ${essreadout_obj_SRC} 30 | ${essreadout_obj_INC} 31 | ) 32 | 33 | target_link_libraries(EssReadoutLib 34 | PRIVATE 35 | ${EFU_COMMON_LIBS} 36 | ) 37 | 38 | # To be used as a dependency in the module's CMakeLists.txt 39 | # aimed to be built with UNIT_TEST macro defined 40 | add_library(EssReadoutLib-unit_test OBJECT 41 | ${essreadout_obj_SRC} 42 | ${essreadout_obj_INC} 43 | ) 44 | 45 | target_link_libraries(EssReadoutLib-unit_test 46 | PRIVATE 47 | ${EFU_COMMON_LIBS} 48 | ) 49 | 50 | target_compile_definitions(EssReadoutLib-unit_test PUBLIC -DUNIT_TEST) 51 | 52 | enable_coverage_flags(EssReadoutLib) 53 | -------------------------------------------------------------------------------- /src/common/reduction/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Classes for event reduction pipeline 3 | #============================================================================= 4 | 5 | add_subdirectory(clustering) 6 | add_subdirectory(matching) 7 | add_subdirectory(analysis) 8 | add_subdirectory(multigrid) 9 | 10 | set(reduction_obj_SRC 11 | Hit.cpp 12 | HitVector.cpp 13 | Hit2D.cpp 14 | Hit2DVector.cpp 15 | Cluster.cpp 16 | Cluster2D.cpp 17 | Event.cpp 18 | EventBuilder2D.cpp 19 | ReducedEvent.cpp 20 | NeutronEvent.cpp 21 | ChronoMerger.cpp 22 | ) 23 | 24 | set(reduction_obj_INC 25 | Hit.h 26 | HitVector.h 27 | Hit2D.h 28 | Hit2DVector.h 29 | Cluster.h 30 | Cluster2D.h 31 | Event.h 32 | EventBuilder2D.h 33 | ReducedEvent.h 34 | NeutronEvent.h 35 | ChronoMerger.h 36 | ) 37 | 38 | add_library(ReductionLib OBJECT 39 | ${reduction_obj_SRC} 40 | ${reduction_obj_INC} 41 | ) 42 | 43 | target_link_libraries(ReductionLib 44 | PRIVATE 45 | ${EFU_COMMON_LIBS} 46 | ) 47 | 48 | enable_coverage_flags(ReductionLib) 49 | 50 | #============================================================================= 51 | # Tests 52 | #============================================================================= 53 | 54 | add_subdirectory(test) 55 | -------------------------------------------------------------------------------- /src/common/reduction/ReducedEvent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file ReducedEvent.h 5 | /// \brief ReducedHit and ReducedEvent class definitions 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | 12 | uint32_t ReducedHit::center_rounded() const { 13 | return static_cast(std::round(center)); 14 | } 15 | 16 | bool ReducedHit::is_center_good() const { 17 | return std::isfinite(center) && (center >= 0); 18 | } 19 | 20 | std::string ReducedHit::to_string() const { 21 | return fmt::format("{}(lu={},uu={}) t={}(~{}) *{}", center, uncert_lower, 22 | uncert_upper, average_time, time, hits_used); 23 | } 24 | 25 | std::string ReducedEvent::to_string() const { 26 | return fmt::format("x=[{}] y=[{}] z=[{}] t={} {}", x.to_string(), 27 | y.to_string(), z.to_string(), time, 28 | (good ? "good" : "bad")); 29 | } 30 | 31 | std::string ReducedEvent::to_string_simple() const { 32 | return fmt::format("x={} y={} z=[{}] t={}", x.center, y.center, z.center, 33 | time); 34 | } 35 | -------------------------------------------------------------------------------- /src/efu/Launcher.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Implementation of the Launcher class 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include 11 | #include 12 | 13 | void Launcher::launchThreads(std::shared_ptr &detector) { 14 | auto startThreadsWithoutAffinity = [&detector, this]() { 15 | LOG(INIT, Sev::Info, "Launching threads without core affinity."); 16 | for (auto &ThreadInfo : detector->GetThreadInfo()) { 17 | 18 | LOG(INIT, Sev::Debug, "Creating new thread (id: {})", ThreadInfo.name); 19 | 20 | /// start thread with exception handling 21 | ThreadInfo.thread = std::thread([this, &ThreadInfo]() { exceptionHandlingWrapper(ThreadInfo); }); 22 | } 23 | }; 24 | 25 | startThreadsWithoutAffinity(); 26 | } 27 | 28 | void Launcher::exceptionHandlingWrapper(ThreadInfo &ThreadInfo) { 29 | try { 30 | ThreadInfo.func(); 31 | } catch (const std::exception &e) { 32 | LOG(INIT, Sev::Alert, "Initiate shutdown. Thread [{}] threw an unhandled exception! [{}]", ThreadInfo.name, e.what()); 33 | KeepRunningRef = 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/modules/cbm/generators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | 3 | #============================================================================= 4 | # Generate artificial CBM readouts - using the new data format 5 | #============================================================================= 6 | 7 | set(cbm_udp_generated_INC 8 | ReadoutGenerator.h 9 | GeneratorType.h 10 | ${ESS_COMMON_DIR}/testutils/bitmaps/BitMaps.h 11 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.h 12 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.h 13 | ${ESS_SOURCE_DIR}/generators/functiongenerators/FunctionGenerator.h 14 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.h 15 | ${ESS_SOURCE_DIR}/generators/functiongenerators/LinearGenerator.h 16 | ) 17 | set(cbm_udp_generated_SRC 18 | ReadoutGenerator.cpp 19 | udpgen.cpp 20 | ${ESS_COMMON_DIR}/testutils/bitmaps/BitMaps.cpp 21 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.cpp 22 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.cpp 23 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.cpp 24 | ) 25 | create_executable(cbm_udp_generated) 26 | 27 | set_target_properties(cbm_udp_generated 28 | PROPERTIES 29 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators" 30 | ) 31 | -------------------------------------------------------------------------------- /src/modules/nmx/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | 3 | add_subdirectory(test) 4 | add_subdirectory(generators) 5 | include_directories(.) 6 | 7 | #============================================================================= 8 | # nmx detector module and base test 9 | #============================================================================= 10 | set(nmx_common_inc 11 | NMXBase.h 12 | NMXInstrument.h 13 | geometry/Config.h 14 | geometry/NMXGeometry.h 15 | ) 16 | set(nmx_common_src 17 | NMXBase.cpp 18 | NMXInstrument.cpp 19 | geometry/Config.cpp 20 | geometry/NMXGeometry.cpp 21 | ) 22 | 23 | set(nmx_INC ${nmx_common_inc}) 24 | set(nmx_SRC 25 | ${nmx_common_src} 26 | main.cpp 27 | ) 28 | set(nmx_LIB efu_reduction efu_essreadout) 29 | create_executable(nmx) 30 | 31 | set(NMXBaseTest_INC 32 | ${nmx_common_inc} 33 | ) 34 | set(NMXBaseTest_SRC 35 | test/NMXBaseTest.cpp 36 | ${nmx_common_src} 37 | ) 38 | create_test_executable(NMXBaseTest) 39 | 40 | 41 | # NMX InstrumentTest Module integration test 42 | 43 | set(NMXInstrumentTest_INC 44 | ${nmx_common_inc} 45 | ) 46 | set(NMXInstrumentTest_SRC 47 | ${nmx_common_src} 48 | test/NMXInstrumentTest.cpp 49 | ) 50 | 51 | set(NMXInstrumentTest_LIB efu_essreadout) 52 | create_test_executable(NMXInstrumentTest) 53 | -------------------------------------------------------------------------------- /src/efu/MainProg.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// \brief Wrapper for EFU main application 6 | //===----------------------------------------------------------------------===// 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | class MainProg { 19 | public: 20 | /// \brief initialise by passing the instrument name and the arguments 21 | /// cannot return but uses exit() instead. 22 | /// constructor - roughly this is first half of the old main() function 23 | MainProg(const DetectorType &Type, int argc, char *argv[]); 24 | 25 | MainProg(const std::string &Type, int argc, char *argv[]); 26 | 27 | /// \brief setup exithandlers, launch detector - roughly equivalent to the 28 | /// second half of the old main() 29 | int run(Detector *detector); 30 | 31 | public: 32 | static constexpr uint64_t MicrosecondsPerSecond{1000000}; 33 | BaseSettings DetectorSettings; 34 | std::shared_ptr detector; 35 | Graylog graylog; 36 | HwCheck hwcheck; 37 | Timer RunTimer; 38 | EFUArgs Args; 39 | }; 40 | -------------------------------------------------------------------------------- /src/common/time/Timer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Implementation of the check timer class which uses the standard 7 | /// chrono library to provide a high resolution timer. 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include 11 | 12 | Timer::Timer(uint64_t Timeout) 13 | : TimeOutNS(Timeout) { 14 | reset(); 15 | } 16 | 17 | bool Timer::timeout() { 18 | if (timeNS() >= TimeOutNS) { 19 | reset(); 20 | return true; 21 | } 22 | 23 | return false; 24 | } 25 | 26 | void Timer::reset() { 27 | T0 = std::chrono::high_resolution_clock::now(); 28 | } 29 | 30 | uint64_t Timer::timeNS() { 31 | auto T1 = std::chrono::high_resolution_clock::now(); 32 | 33 | return std::chrono::duration_cast(T1 - T0).count(); 34 | } 35 | 36 | uint64_t Timer::timeUS() { 37 | auto T1 = std::chrono::high_resolution_clock::now(); 38 | 39 | return std::chrono::duration_cast(T1 - T0).count(); 40 | } 41 | 42 | uint64_t Timer::timeMS() { 43 | auto T1 = std::chrono::high_resolution_clock::now(); 44 | 45 | return std::chrono::duration_cast(T1 - T0).count(); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/common/monitor/DynamicHist.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016, 2017 European Spallation Source ERIC 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | std::string DynamicHist::debug() const { 8 | std::stringstream ss; 9 | for (size_t i = 0; i < hist.size(); ++i) 10 | ss << "[" << i << "]=" << hist[i]; 11 | return ss.str(); 12 | } 13 | 14 | std::string DynamicHist::visualize(bool non_empty_only) const { 15 | if (hist.empty()) 16 | return {}; 17 | 18 | size_t vmax{hist[0]}; 19 | size_t start{0}, end{0}; 20 | bool print{false}; 21 | for (uint32_t i = 0; i < hist.size(); i++) { 22 | const auto &val = hist[i]; 23 | vmax = std::max(vmax, val); 24 | if (val > 0) { 25 | end = i; 26 | if (!print) { 27 | start = i; 28 | print = true; 29 | } 30 | } 31 | } 32 | 33 | std::string largesti = fmt::format("{}", end); 34 | std::string pad = "{:<" + fmt::format("{}", largesti.size()) + "}"; 35 | 36 | /// \todo parametrize this 37 | size_t nstars{60}; 38 | 39 | std::stringstream ss; 40 | for (size_t i = start; i <= end; i++) { 41 | auto val = hist[i]; 42 | if (!non_empty_only || (val > 0)) 43 | ss << fmt::format(pad, i) << ": " 44 | << fmt::format("{:<62}", std::string((nstars * val) / vmax, '*')) 45 | << val << "\n"; 46 | } 47 | return ss.str(); 48 | } -------------------------------------------------------------------------------- /src/common/readout/vmm3/test/HybridTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Unit tests for Hybrid class 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include 11 | #include 12 | 13 | using namespace vmm3; 14 | 15 | class HybridTest : public TestBase { 16 | protected: 17 | void SetUp() override {} 18 | void TearDown() override {} 19 | }; 20 | 21 | TEST_F(HybridTest, IsAvailable) { 22 | std::vector Hybrids; 23 | Hybrid tmp; 24 | tmp.HybridId = "AAA"; 25 | Hybrids.push_back(tmp); 26 | Hybrids.push_back(tmp); 27 | ASSERT_EQ(Hybrids.size(), 2); 28 | 29 | bool res = Hybrid::isAvailable("CCC", Hybrids); 30 | ASSERT_TRUE(res); 31 | 32 | res = Hybrid::isAvailable("AAA", Hybrids); 33 | ASSERT_FALSE(res); 34 | } 35 | 36 | TEST_F(HybridTest, ADCThresholds) { 37 | std::vector Hybrids; 38 | Hybrid tmp; 39 | EXPECT_EQ(tmp.ADCThresholds.size(), 2); 40 | EXPECT_EQ(tmp.ADCThresholds[0].size(), 0); 41 | EXPECT_EQ(tmp.ADCThresholds[1].size(), 0); 42 | } 43 | 44 | int main(int argc, char **argv) { 45 | testing::InitGoogleTest(&argc, argv); 46 | return RUN_ALL_TESTS(); 47 | } 48 | -------------------------------------------------------------------------------- /utils/efushell/SocketDriver.py: -------------------------------------------------------------------------------- 1 | import string 2 | import socket 3 | import sys 4 | import time 5 | import threading 6 | 7 | 8 | class SimpleSocket: 9 | def __init__(self, hostname="localhost", port=8888, timeout=2): 10 | self.access_semaphor = threading.Semaphore(1) 11 | try: 12 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 13 | except socket.error: 14 | sys.stderr.write( 15 | "socket() [Socket connection error] Cannot connect to %s, error: %s\n" % (hostname, socket.error)) 16 | sys.exit(1) 17 | 18 | self.sock.settimeout(timeout) 19 | 20 | try: 21 | self.sock.connect((hostname, port)) 22 | except socket.error: 23 | sys.stderr.write("connect() [Socket connection error] Cannot connect to %s:%d, error: %s\n" % ( 24 | hostname, port, socket.error)) 25 | sys.exit(2) 26 | 27 | def SendCommand(self, cmd): 28 | self.access_semaphor.acquire() 29 | cmd += '\n' 30 | self.sock.send(cmd.encode('utf-8')) 31 | self.access_semaphor.release() 32 | 33 | def Ask(self, cmd): 34 | self.access_semaphor.acquire() 35 | cmd += '\n' 36 | self.sock.send(cmd.encode('utf-8')) 37 | reply = self.sock.recv(2048).strip(b'\n') 38 | self.access_semaphor.release() 39 | return reply 40 | -------------------------------------------------------------------------------- /utils/efushell/efustatus.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from EFUMetrics import Metrics 4 | import argparse 5 | 6 | parser = argparse.ArgumentParser() 7 | parser.add_argument("-i", metavar='ipaddr', help = "server ip address (default 127.0.0.1)", 8 | type = str, default = "127.0.0.1") 9 | parser.add_argument("-p", metavar='port', help = "server tcp port (default 8888)", 10 | type = int, default = 8888) 11 | args = parser.parse_args() 12 | 13 | print("") 14 | print("EFU Stats:") 15 | print("Connection info. ip address: %s, tcp port: %s" % (args.i, args.p)) 16 | metrics = Metrics(args.i, args.p) 17 | 18 | print(metrics._get_efu_command("RUNTIMESTATS")) 19 | print(metrics._get_efu_command("VERSION_GET")) 20 | print(metrics._get_efu_command("DETECTOR_INFO_GET")) 21 | print(metrics._get_efu_command("CALIB_MODE_GET")) 22 | 23 | 24 | res = metrics._get_efu_command("CMD_GET_COUNT") 25 | numcmds = int(res.split()[1]) 26 | print("Available commands: (CMD_GET 1 - %s)" % (numcmds)) 27 | for cmdnum in range(1, numcmds + 1): 28 | print(metrics._get_efu_command("CMD_GET " + str(cmdnum)).split()[1]) 29 | 30 | res = metrics._get_efu_command("STAT_GET_COUNT") 31 | numstats = int(res.split()[1]) 32 | print("Available stats: (STAT_GET 1 - %s)" % (numstats)) 33 | for statnum in range(1, numstats + 1): 34 | print(metrics._get_efu_command("STAT_GET " + str(statnum)).split()[1]) 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 - 2022, European Spallation Source 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 22 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 23 | OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /src/modules/dream/configs/hr.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector": "DREAM", 3 | 4 | "MaxPulseTimeDiffNS" : 5000000000, 5 | 6 | "Config" : [ 7 | { "Ring" : 7, "FEN": 0, "Type": "HR", "Index" : 0, "Index2" : 0}, 8 | { "Ring" : 7, "FEN": 1, "Type": "HR", "Index" : 2, "Index2" : 0}, 9 | { "Ring" : 7, "FEN": 2, "Type": "HR", "Index" : 4, "Index2" : 0}, 10 | { "Ring" : 7, "FEN": 3, "Type": "HR", "Index" : 6, "Index2" : 0}, 11 | { "Ring" : 7, "FEN": 4, "Type": "HR", "Index" : 8, "Index2" : 0}, 12 | { "Ring" : 7, "FEN": 5, "Type": "HR", "Index" : 10, "Index2" : 0}, 13 | { "Ring" : 7, "FEN": 6, "Type": "HR", "Index" : 12, "Index2" : 0}, 14 | { "Ring" : 7, "FEN": 7, "Type": "HR", "Index" : 14, "Index2" : 0}, 15 | 16 | { "Ring" : 8, "FEN": 0, "Type": "HR", "Index" : 16, "Index2" : 0}, 17 | { "Ring" : 8, "FEN": 1, "Type": "HR", "Index" : 18, "Index2" : 0}, 18 | { "Ring" : 8, "FEN": 2, "Type": "HR", "Index" : 20, "Index2" : 0}, 19 | { "Ring" : 8, "FEN": 3, "Type": "HR", "Index" : 22, "Index2" : 0}, 20 | { "Ring" : 8, "FEN": 4, "Type": "HR", "Index" : 24, "Index2" : 0}, 21 | { "Ring" : 8, "FEN": 5, "Type": "HR", "Index" : 26, "Index2" : 0}, 22 | { "Ring" : 8, "FEN": 6, "Type": "HR", "Index" : 28, "Index2" : 0}, 23 | { "Ring" : 8, "FEN": 7, "Type": "HR", "Index" : 30, "Index2" : 0}, 24 | { "Ring" : 8, "FEN": 8, "Type": "HR", "Index" : 32, "Index2" : 0} 25 | ] 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/modules/trex/Counters.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief TREX application counters (for Grafana and low level debug) 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | struct Counters { 18 | // ESSReadout parser 19 | int64_t ErrorESSHeaders{0}; 20 | // int64_t RingRx[24]; 21 | 22 | // VMM3a Readouts 23 | struct vmm3::VMM3ParserStats VMMStats; 24 | 25 | // Logical and Digital geometry incl. Calibration 26 | int64_t HybridMappingErrors{0}; 27 | int64_t TOFErrors{0}; 28 | int64_t MinADC{0}; 29 | int64_t MaxADC{0}; 30 | int64_t MappingErrors{0}; 31 | 32 | // 33 | int64_t ProcessingIdle{0}; 34 | int64_t Events{0}; 35 | int64_t ClustersNoCoincidence{0}; 36 | int64_t ClustersMatchedWireOnly{0}; 37 | int64_t ClustersMatchedGridOnly{0}; 38 | int64_t ClustersTooLargeGridSpan{0}; 39 | int64_t EventsMatchedClusters{0}; 40 | int64_t PixelErrors{0}; 41 | int64_t TimeErrors; 42 | 43 | // Identification of the cause of produce calls 44 | int64_t ProduceCauseTimeout{0}; 45 | } __attribute__((aligned(64))); 46 | -------------------------------------------------------------------------------- /src/common/debug/Hexdump.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Provide a printf based hexdump functionality 7 | /// 8 | /// From https://gist.github.com/ccbrown 9 | //===----------------------------------------------------------------------===// 10 | // GCOVR_EXCL_START 11 | 12 | #include 13 | 14 | void hexDump(const void *DataPtr, size_t DataLen) { 15 | char ascii[17]; 16 | size_t i, j; 17 | ascii[16] = '\0'; 18 | for (i = 0; i < DataLen; ++i) { 19 | printf("%02X ", ((unsigned char *)DataPtr)[i]); 20 | if (((unsigned char *)DataPtr)[i] >= ' ' && 21 | ((unsigned char *)DataPtr)[i] <= '~') { 22 | ascii[i % 16] = ((unsigned char *)DataPtr)[i]; 23 | } else { 24 | ascii[i % 16] = '.'; 25 | } 26 | if ((i + 1) % 8 == 0 || i + 1 == DataLen) { 27 | printf(" "); 28 | if ((i + 1) % 16 == 0) { 29 | printf("| %s \n", ascii); 30 | } else if (i + 1 == DataLen) { 31 | ascii[(i + 1) % 16] = '\0'; 32 | if ((i + 1) % 16 <= 8) { 33 | printf(" "); 34 | } 35 | for (j = (i + 1) % 16; j < 16; ++j) { 36 | printf(" "); 37 | } 38 | printf("| %s \n", ascii); 39 | } 40 | } 41 | } 42 | } 43 | // GCOVR_EXCL_STOP 44 | -------------------------------------------------------------------------------- /src/modules/timepix3/geometry/Config.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Get detector configuration from json file 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | // #undef TRC_LEVEL 20 | // #define TRC_LEVEL TRC_L_DEB 21 | 22 | namespace Timepix3 { 23 | 24 | class Config : public Configurations::Config { 25 | 26 | public: 27 | Config(); 28 | 29 | Config(const std::string &ConfigFile); 30 | 31 | // clang-format off 32 | std::string InstrumentName; 33 | uint16_t XResolution{0}; /// Resolution along x axis 34 | uint16_t YResolution{0}; /// Resolution along y axis 35 | uint8_t ScaleUpFactor{1}; /// Scale up factor for super resolution 36 | uint16_t ParallelThreads{1}; 37 | float FrequencyHz{14.0}; /// Frequency of the ESS proton pulse 38 | // clang-format on 39 | 40 | uint32_t MaxTimeGapNS{1}; 41 | uint32_t MinEventSizeHits{1}; 42 | uint32_t MinimumToTSum{20}; 43 | uint32_t MinEventTimeSpanNS{1}; 44 | uint16_t MaxCoordinateGap{5}; 45 | }; 46 | } // namespace Timepix3 47 | -------------------------------------------------------------------------------- /src/modules/freia/Counters.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Freia application counters (for Grafana and low level debug) 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | struct Counters { 18 | // ESSReadout parser 19 | int64_t ErrorESSHeaders; 20 | // int64_t RingRx[24]; 21 | 22 | // VMM3a Readouts 23 | struct vmm3::VMM3ParserStats VMMStats; 24 | 25 | // Logical and Digital geometry incl. Calibration 26 | int64_t MaxTOFErrors; 27 | int64_t MaxADC; 28 | int64_t ADCBelowThreshold; 29 | 30 | // 31 | int64_t ProcessingIdle; 32 | int64_t Events; 33 | int64_t EventsNoCoincidence; 34 | int64_t EventsMatchedClusters; 35 | int64_t EventsMatchedWireOnly; 36 | int64_t EventsMatchedStripOnly; 37 | int64_t EventsInvalidStripGap; 38 | int64_t EventsInvalidWireGap; 39 | struct GapMatcherStats MatcherStats; 40 | 41 | int64_t TimeErrors; 42 | // Identification of the cause of produce calls 43 | int64_t ProduceCauseTimeout; 44 | 45 | } __attribute__((aligned(64))); 46 | -------------------------------------------------------------------------------- /src/modules/bifrost/generators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | #============================================================================= 3 | # UDP generator for BIFROST 4 | #============================================================================= 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | #============================================================================= 9 | # Generate BIFROST readouts from (.dat) file 10 | #============================================================================= 11 | 12 | set(bifrost_udp_generated_INC 13 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.h 14 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.h 15 | ${ESS_MODULE_DIR}/bifrost/generators/ReadoutGenerator.h 16 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.h 17 | ) 18 | set(bifrost_udp_generated_SRC 19 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.cpp 20 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.cpp 21 | ${ESS_MODULE_DIR}/bifrost/generators/ReadoutGenerator.cpp 22 | ${ESS_MODULE_DIR}/bifrost/generators/udpgen.cpp 23 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.cpp 24 | ) 25 | create_executable(bifrost_udp_generated) 26 | 27 | set_target_properties(bifrost_udp_generated 28 | PROPERTIES 29 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators" 30 | ) 31 | -------------------------------------------------------------------------------- /src/modules/dream/generators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | #============================================================================= 3 | # UDP generator for DREAM 4 | #============================================================================= 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | add_subdirectory(g4data) 9 | 10 | #============================================================================= 11 | # Generate DREAM readouts 12 | #============================================================================= 13 | 14 | set(dream_udp_generated_INC 15 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.h 16 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.h 17 | ${ESS_MODULE_DIR}/dream/generators/ReadoutGenerator.h 18 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.h 19 | ) 20 | set(dream_udp_generated_SRC 21 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.cpp 22 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.cpp 23 | ${ESS_MODULE_DIR}/dream/generators/ReadoutGenerator.cpp 24 | ${ESS_MODULE_DIR}/dream/generators/udpgen.cpp 25 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.cpp 26 | ) 27 | create_executable(dream_udp_generated) 28 | 29 | set_target_properties(dream_udp_generated 30 | PROPERTIES 31 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators" 32 | ) 33 | -------------------------------------------------------------------------------- /src/common/reduction/analysis/EventAnalyzer.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Classes for NMX event formation 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | enum TimeAlgo { TA_center_of_mass, TA_charge2, TA_utpc, TA_utpc_weighted }; 16 | 17 | class EventAnalyzer : public AbstractAnalyzer { 18 | public: 19 | /// \param time_algorithm determines algorithm to determine position and time 20 | /// \param max_timebins maximum number of timebins to consider for upper 21 | /// uncertainty 22 | /// \param max_timedif maximum span of timebins to consider for upper 23 | /// uncertainty 24 | EventAnalyzer(const std::string &time_algorithm); 25 | 26 | /// \brief analyzes particle track in one plane 27 | ReducedHit analyze(Cluster &) const; 28 | 29 | /// \brief analyzes particle track in both planes 30 | ReducedEvent analyze(Event &) const override; 31 | 32 | /// \brief prints info for debug purposes 33 | std::string debug(const std::string &prepend) const override; 34 | 35 | private: 36 | std::string time_algorithm_ = "utpc_weighted"; 37 | TimeAlgo time_algo = TA_utpc_weighted; 38 | }; 39 | -------------------------------------------------------------------------------- /utils/efushell/efustatstocsv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from EFUMetrics import Metrics 4 | import argparse 5 | import csv 6 | 7 | parser = argparse.ArgumentParser() 8 | parser.add_argument("-i", metavar='ipaddr', help = "server ip address (default 127.0.0.1)", 9 | type = str, default = "127.0.0.1") 10 | parser.add_argument("-p", metavar='port', help = "server tcp port (default 8888)", 11 | type = int, default = 8888) 12 | parser.add_argument("-v", help = "Dump stats in format suitable for verifymetrics.py", action = 'store_true') 13 | parser.add_argument("-f", type=str, default="efustats.csv", help="Filename to save csv file under") 14 | 15 | args = parser.parse_args() 16 | 17 | print("") 18 | metrics = Metrics(args.i, args.p) 19 | 20 | res = metrics._get_efu_command("STAT_GET_COUNT") 21 | numstats = int(res.split()[1]) 22 | print("Available stats ({}):".format(numstats)) 23 | verify = "" 24 | stats_dict = {} 25 | for statnum in range(1, numstats + 1): 26 | res = metrics._get_efu_command("STAT_GET " + str(statnum)) 27 | verify = verify + str(res.split()[1]) + ":" + str(res.split()[2]) + " " 28 | stats_dict[res.split()[1].decode('utf-8')] = res.split()[2].decode('utf-8') 29 | 30 | print(stats_dict) 31 | with open(args.f, 'w') as csvfile: 32 | for key in stats_dict.keys(): 33 | csvfile.write("%s, %s\n" % (key, stats_dict[key])) 34 | 35 | if args.v: 36 | print(verify) 37 | 38 | -------------------------------------------------------------------------------- /src/modules/trex/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2021 European Spallation Source, ERIC. See LICENSE file 2 | 3 | add_subdirectory(test) 4 | add_subdirectory(generators) 5 | include_directories(.) 6 | 7 | #============================================================================= 8 | # trex detector module and base test 9 | #============================================================================= 10 | set(trex_common_inc 11 | TREXBase.h 12 | TREXInstrument.h 13 | geometry/Config.h 14 | geometry/TREXGeometry.h 15 | geometry/LETGeometry.h 16 | geometry/Geometry.h 17 | ) 18 | set(trex_common_src 19 | TREXBase.cpp 20 | TREXInstrument.cpp 21 | geometry/Config.cpp 22 | geometry/TREXGeometry.cpp 23 | geometry/LETGeometry.cpp 24 | ) 25 | 26 | set(trex_INC 27 | ${trex_common_inc} 28 | ) 29 | set(trex_SRC 30 | main.cpp 31 | ${trex_common_src} 32 | ) 33 | set(trex_LIB 34 | efu_reduction 35 | efu_essreadout 36 | ) 37 | create_executable(trex) 38 | 39 | set(TREXBaseTest_INC 40 | ${trex_common_inc} 41 | ) 42 | set(TREXBaseTest_SRC 43 | test/TREXBaseTest.cpp 44 | ${trex_common_src} 45 | ) 46 | create_test_executable(TREXBaseTest) 47 | 48 | # 49 | # TREX InstrumentTest Module integration test 50 | # 51 | set(TREXInstrumentTest_INC 52 | ${trex_common_inc} 53 | ) 54 | set(TREXInstrumentTest_SRC 55 | ${trex_common_src} 56 | test/TREXInstrumentTest.cpp 57 | ) 58 | create_test_executable(TREXInstrumentTest) 59 | -------------------------------------------------------------------------------- /cmake/modules/FindIspc.cmake: -------------------------------------------------------------------------------- 1 | # Very basic ISPC support 2 | # Enables Ispc support if Ispc is found. 3 | # 4 | # Used in the following way: 5 | # 6 | # set(myTarget_ISPC_OBJ "") 7 | # find_package(Ispc) 8 | # ispc_compile_single_file(myTarget_ISPC_OBJ SampleGen.ispc avx2) # avx2 instruction set support 9 | # add_executable(myTarget ${myTarget_SRC} ${myTarget_INC} ${myTarget_ISPC_OBJ}) 10 | # add_ispc_support(myTarget) 11 | 12 | #unset(ISPC_CMD CACHE) # test add/remove 13 | 14 | find_program(ISPC_CMD ispc) 15 | mark_as_advanced(ISPC_CMD) 16 | if(EXISTS ${ISPC_CMD}) 17 | message(STATUS "ECDC: ISPC compiler found: ${ISPC_CMD}") 18 | else() 19 | message(STATUS "ECDC: ISPC compiler not found. Fallback back to (slow) c++.") 20 | endif() 21 | 22 | function(add_ispc_support target_name) 23 | if(EXISTS ${ISPC_CMD}) 24 | set_property(TARGET ${target_name} APPEND_STRING PROPERTY COMPILE_FLAGS "-DBUILD_SUPPORT_ISPC") 25 | endif() 26 | endfunction() 27 | 28 | macro(ispc_compile_single_file target_out_obj_list ispc_source_file target_instruction_set) 29 | if(EXISTS ${ISPC_CMD}) 30 | set(out_obj_file "${ispc_source_file}.o") 31 | list(APPEND ${target_out_obj_list} ${out_obj_file}) 32 | add_custom_command(OUTPUT ${out_obj_file} 33 | COMMAND ${ISPC_CMD} --target=${target_instruction_set} ${CMAKE_CURRENT_LIST_DIR}/${ispc_source_file} -o ${out_obj_file} 34 | DEPENDS ${CMAKE_CURRENT_LIST_DIR}/${ispc_source_file}) 35 | endif() 36 | endmacro() 37 | -------------------------------------------------------------------------------- /src/modules/cbm/Counters.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief CBM application counters (for Grafana and low level debug) 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace cbm { 17 | 18 | struct Counters { 19 | // CBM Readouts 20 | struct cbm::ParserStats CbmStats; 21 | 22 | int64_t DataHeaders{0}; 23 | 24 | // Readout processing 25 | int64_t Event0DReadoutsProcessed{0}; 26 | int64_t Event2DReadoutsProcessed{0}; 27 | int64_t IBMReadoutsProcessed{0}; 28 | int64_t TypeNotConfigured{0}; 29 | 30 | // Events 31 | int64_t IBMEvents{0}; 32 | int64_t Event0DEvents{0}; 33 | int64_t Event2DEvents{0}; 34 | 35 | // Logical and Digital geometry incl. Calibration 36 | int64_t RingCfgError{0}; 37 | int64_t CbmCounts{0}; 38 | int64_t NPOSCount{0}; 39 | 40 | // Configuration errors 41 | int64_t NoSerializerCfgError{0}; 42 | 43 | // Processing time counters 44 | int64_t ProcessingIdle{0}; 45 | int64_t TimeError{0}; 46 | 47 | // Identification of the cause of produce calls 48 | int64_t ProduceCauseTimeout{0}; 49 | } __attribute__((aligned(64))); 50 | 51 | } // namespace cbm -------------------------------------------------------------------------------- /src/modules/trex/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Tests 3 | #============================================================================= 4 | 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | get_filename_component(TREX_FULL "${ESS_MODULE_DIR}/trex/configs/trex.json" ABSOLUTE) 9 | 10 | ## 11 | ## Pure unit tests 12 | ## 13 | 14 | set(TREXConfigTest_INC 15 | ../geometry/Config.h) 16 | set(TREXConfigTest_SRC 17 | ../geometry/Config.cpp 18 | ConfigTest.cpp) 19 | create_test_executable(TREXConfigTest) 20 | target_compile_definitions(TREXConfigTest PRIVATE TREX_FULL="${TREX_FULL}") 21 | 22 | 23 | 24 | 25 | set(TREXGeometryTest_INC 26 | ../geometry/TREXGeometry.h 27 | ../geometry/Geometry.h) 28 | set(TREXGeometryTest_SRC 29 | ../test/TREXGeometryTest.cpp 30 | ../geometry/TREXGeometry.cpp 31 | ../geometry/Geometry.h) 32 | create_test_executable(TREXGeometryTest) 33 | 34 | 35 | set(LETGeometryTest_INC 36 | ../geometry/LETGeometry.h 37 | ../geometry/Geometry.h) 38 | set(LETGeometryTest_SRC 39 | ../test/LETGeometryTest.cpp 40 | ../geometry/LETGeometry.cpp 41 | ../geometry/Geometry.h) 42 | create_test_executable(LETGeometryTest) 43 | 44 | 45 | # set(TREXChannelMappingTest_INC 46 | # ../geometry/TREXChannelMapping.h) 47 | # set(TREXChannelMappingTest_SRC 48 | # ../test/TREXChannelMappingTest.cpp) 49 | # create_test_executable(TREXChannelMappingTest) 50 | -------------------------------------------------------------------------------- /src/modules/dream/generators/g4data/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2024 European Spallation Source, ERIC. See LICENSE file 2 | #============================================================================= 3 | # UDP generator for DREAM from Geant4 simulations 4 | #============================================================================= 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | #============================================================================= 9 | # Generate DREAM readouts from (.dat) file 10 | #============================================================================= 11 | 12 | set(dream_udp_generated_g4_INC 13 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.h 14 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.h 15 | ${ESS_MODULE_DIR}/dream/generators/g4data/ReadoutGenerator.h 16 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.h 17 | ) 18 | set(dream_udp_generated_g4_SRC 19 | ${ESS_SOURCE_DIR}/generators/essudpgen/ReadoutGeneratorBase.cpp 20 | ${ESS_SOURCE_DIR}/generators/functiongenerators/DistributionGenerator.cpp 21 | ${ESS_MODULE_DIR}/dream/generators/g4data/ReadoutGenerator.cpp 22 | ${ESS_MODULE_DIR}/dream/generators/g4data/udpgen.cpp 23 | ${ESS_COMMON_DIR}/testutils/DataFuzzer.cpp 24 | ) 25 | create_executable(dream_udp_generated_g4) 26 | 27 | set_target_properties(dream_udp_generated_g4 28 | PROPERTIES 29 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generators" 30 | ) 31 | -------------------------------------------------------------------------------- /src/modules/caen/CaenCounters.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief CAEN application counters (for Grafana and low level debug) 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace Caen { 20 | 21 | struct CaenCounters { 22 | // Processing Counters - accessed in processing thread 23 | 24 | // System counters 25 | int64_t ProcessingIdle{0}; 26 | 27 | // ESSReadout parser 28 | int64_t ErrorESSHeaders{0}; 29 | 30 | // Caen DataParser 31 | struct DataParser::Stats Parser; 32 | 33 | // Logical and Digital geometry incl. Calibration 34 | struct CDCalibration::Stats Calibration; 35 | 36 | // Events 37 | int64_t Events{0}; 38 | int64_t TimeError{0}; 39 | int64_t EventsUdder{0}; 40 | int64_t SerializerErrors{0}; 41 | 42 | // Identification of the cause of produce calls 43 | int64_t ProduceCauseTimeout{0}; 44 | int64_t ProduceCausePulseChange{0}; 45 | int64_t ProduceCauseMaxEventsReached{0}; 46 | 47 | } __attribute__((aligned(64))); 48 | } // namespace Caen 49 | -------------------------------------------------------------------------------- /src/modules/dream/readout/DataParser.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 - 2024 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Parser for ESS readout of DREAM 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace Dream { 16 | 17 | class DataParser { 18 | public: 19 | const unsigned int MaxFiberId{23}; 20 | const unsigned int MaxFENId{12}; 21 | const unsigned int MaxReadoutsInPacket{500}; 22 | 23 | struct CDTReadout { 24 | uint8_t FiberId; 25 | uint8_t FENId; 26 | uint16_t DataLength; 27 | uint32_t TimeHigh; 28 | uint32_t TimeLow; 29 | uint8_t OM; 30 | uint8_t UnitId; 31 | uint8_t Cathode; 32 | uint8_t Anode; 33 | } __attribute__((__packed__)); 34 | 35 | static_assert(sizeof(CDTReadout) == 16, 36 | "DREAM readout header length error"); 37 | 38 | DataParser(struct Counters &counters) : Stats(counters) { 39 | Result.reserve(MaxReadoutsInPacket); 40 | }; 41 | ~DataParser(){}; 42 | 43 | // 44 | int parse(const char *buffer, unsigned int size); 45 | 46 | // To be iterated over in processing thread 47 | std::vector Result; 48 | 49 | struct Counters &Stats; 50 | }; 51 | } // namespace Dream 52 | -------------------------------------------------------------------------------- /src/efu/test/HwCheckTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 European Spallation Source 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | //===----------------------------------------------------------------------===// 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | class HwCheckTest : public TestBase { 13 | protected: 14 | HwCheck check; 15 | void SetUp() override {} 16 | void TearDown() override {} 17 | }; 18 | 19 | // Test cases below 20 | TEST_F(HwCheckTest, HwCheckFail) { 21 | std::vector MandatoryInterfaces{"if_does_not_exist"}; 22 | ASSERT_FALSE(check.checkMTU(MandatoryInterfaces, true)); 23 | } 24 | 25 | TEST_F(HwCheckTest, HwCheckNoInterfaces) { 26 | std::vector MandatoryInterfaces{}; 27 | ASSERT_TRUE(check.checkMTU(MandatoryInterfaces, true)); 28 | } 29 | 30 | 31 | TEST_F(HwCheckTest, HwCheckMacOs) { 32 | #ifdef __APPLE__ 33 | std::vector MandatoryInterfaces{"lo0"}; 34 | ASSERT_TRUE(check.checkMTU(MandatoryInterfaces, true)); 35 | #endif 36 | } 37 | 38 | TEST_F(HwCheckTest, HwCheckLinux) { 39 | #ifdef __linux__ 40 | std::vector MandatoryInterfaces{"lo"}; 41 | ASSERT_TRUE(check.checkMTU(MandatoryInterfaces, true)); 42 | #endif 43 | } 44 | 45 | 46 | 47 | int main(int argc, char **argv) { 48 | testing::InitGoogleTest(&argc, argv); 49 | 50 | return RUN_ALL_TESTS(); 51 | } 52 | -------------------------------------------------------------------------------- /test/performancetest.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tests": 3 | [ 4 | { 5 | "Module": "timepix3", 6 | "Config": "./src/modules/timepix3/configs/timepix3.json", 7 | "Generator": "udpgen_pcap -f /Users/jenniferwalker/ownCloud/DM/data/timepix3/SENJU-Jan2023/tpxCommunicationFileAcq_test06_openBeam_00001/file001.pcap", 8 | "Calib": "", 9 | "InitThrottle": 100, 10 | "KafkaTopic": "odin_detector" 11 | }, 12 | { 13 | "Module": "freia", 14 | "Config": "./src/modules/freia/configs/freia.json", 15 | "Calib": "", 16 | "Generator": "freia_udp_generated", 17 | "InitThrottle": 10, 18 | "KafkaTopic": "freia_detector" 19 | }, 20 | { 21 | "Module": "loki", 22 | "Config": "./src/modules/loki/configs/LokiFull.json", 23 | "Calib": "./src/modules/loki/configs/lokinullcalib.json", 24 | "Generator": "loki_udp_generated", 25 | "InitThrottle": 10, 26 | "KafkaTopic": "loki_detector" 27 | }, 28 | { 29 | "Module": "nmx", 30 | "Config": "./src/modules/nmx/configs/nmx.json", 31 | "Calib": "", 32 | "Generator": "nmx_udp_generated", 33 | "InitThrottle": 10, 34 | "KafkaTopic": "nmx_detector" 35 | }, 36 | { 37 | "Module": "nmx", 38 | "Config": "./src/modules/nmx/configs/nmx_split.json", 39 | "Calib": "", 40 | "Generator": "nmx_udp_generated_multihit", 41 | "InitThrottle": 10, 42 | "KafkaTopic": "nmx_detector" 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /src/modules/timepix3/test/util/gen_readouts.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2024 European Spallation Source, ERIC. See LICENSE file 2 | # ===----------------------------------------------------------------------===# 3 | # 4 | # Brief: Helper program to generate test readouts file for the Timepix3 module. 5 | # ===----------------------------------------------------------------------===# 6 | 7 | import bitstruct 8 | """ 9 | This module provides functions for generating test readouts for the Timepix3 module. 10 | 11 | Functions: 12 | - gen_pixel(): Generates a test readout for a pixel. 13 | - gen_tdc(): Generates a test readout for a TDC (Time-to-Digital Converter). 14 | 15 | Usage: 16 | - Run with python3 to generate a test readout into a file named "tpx_readouts". 17 | - Use hexdump or similar to inspect the generated file. 18 | """ 19 | 20 | 21 | def gen_pixel(): 22 | # Define the pixel format of the payload 23 | format = "u4u8u7u1u14u10u4u16" 24 | 25 | pixel_header = 0xB 26 | 27 | return bitstruct.pack(format, pixel_header, 16, 12, 1, 7937, 205, 3, 146)[::-1] 28 | 29 | 30 | def gen_tdc(): 31 | format = "u4u4u12u35u4u5" 32 | 33 | tdc_header = 0x6 34 | tdc_type = 10 35 | 36 | return bitstruct.pack(format, tdc_header, tdc_type, 4095, 34359738367, 15, 0)[::-1] 37 | 38 | 39 | if __name__ == "__main__": 40 | with open("tpx_readouts", "wb") as file: 41 | file.write(gen_tdc()) 42 | 43 | with open("tpx_readouts", "ab") as file: 44 | file.write(gen_pixel()) 45 | -------------------------------------------------------------------------------- /src/modules/dream/geometry/GeometryModule.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Common interface for DREAM geometry modules 7 | /// 8 | /// This interface allows DreamGeometry to register and manage different 9 | /// detector module types (SUMO, Mantle, Cuboid) in a unified way, only 10 | /// instantiating modules that are actually used by the configuration. 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | namespace Dream { 20 | 21 | /// \brief Abstract base class for all DREAM geometry modules 22 | /// 23 | /// Provides a common interface for calculating pixel IDs from readout data. 24 | /// Each specific module type (SUMO, Mantle, Cuboid) implements this interface. 25 | class DreamSubModule { 26 | public: 27 | virtual ~DreamSubModule() = default; 28 | 29 | /// \brief Calculate pixel ID from CDT readout data 30 | /// \param Parms Module parameters from configuration 31 | /// \param Data CDT readout data 32 | /// \return Local pixel ID (before offset), or 0 on error 33 | virtual uint32_t calcPixelId(const Config::ModuleParms &Parms, 34 | const DataParser::CDTReadout &Data) const = 0; 35 | }; 36 | 37 | } // namespace Dream 38 | -------------------------------------------------------------------------------- /src/modules/trex/geometry/Geometry.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief TREX geometry class 7 | /// 8 | /// Mapping from digital identifiers to x- and y- coordinates 9 | //===----------------------------------------------------------------------===// 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | // #undef TRC_LEVEL 20 | // #define TRC_LEVEL TRC_L_DEB 21 | 22 | namespace Trex { 23 | 24 | class Geometry { 25 | public: 26 | virtual bool isWire(uint8_t LocalHybridID) = 0; 27 | virtual bool isGrid(uint8_t LocalHybridID) = 0; 28 | virtual uint16_t xAndzCoord(uint8_t RingID, uint8_t FENID, uint8_t HybridID, 29 | uint8_t VMMID, uint8_t Channel, uint16_t XOffset, 30 | bool Rotated) = 0; 31 | virtual uint16_t yCoord(uint8_t HybridID, uint8_t VMMID, uint8_t Channel, 32 | uint16_t YOffset, bool Rotated, bool Short) = 0; 33 | virtual bool validGridMapping(uint8_t HybridID, uint8_t VMMID, 34 | uint8_t Channel, bool Short) = 0; 35 | virtual bool validWireMapping(uint8_t HybridID, uint8_t VMMID, 36 | uint8_t Channel) = 0; 37 | static constexpr uint16_t InvalidCoord = 65535; 38 | }; 39 | } // namespace Trex 40 | -------------------------------------------------------------------------------- /src/common/debug/Time.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Time related debug methods and classes 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | // Only use these if we are in debug mode 13 | // because they used in a time measurement code 14 | // for debugging purposes 15 | // #ifndef NDEBUG 16 | #include 17 | #include 18 | // #endif 19 | 20 | namespace time_debug { 21 | 22 | /// \brief Measure the runtime of a function 23 | /// \param func The function to measure 24 | /// \param args The arguments to the function 25 | /// \return The runtime of the function in microseconds 26 | /// \note This function is only active in debug mode 27 | template 28 | int inline measureRuntime(Func &&func, Args &&...args) { 29 | 30 | // #ifndef NDEBUG 31 | auto startTime = std::chrono::high_resolution_clock::now(); 32 | // #endif 33 | std::invoke(std::forward(func), std::forward(args)...); 34 | // #ifndef NDEBUG 35 | auto endTime = std::chrono::high_resolution_clock::now(); 36 | auto duration = 37 | std::chrono::duration_cast(endTime - startTime) 38 | .count(); 39 | 40 | return duration; 41 | // #else 42 | // return 0; 43 | // #endif 44 | } 45 | 46 | } // namespace time_debug -------------------------------------------------------------------------------- /src/common/kafka/test/KafkaConfigTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Unit test for KafkaConfig 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | std::string badkafkaconfigjson = R"( 15 | { 16 | "KafkaParms" : [ 17 | {"message.max.bytes" : "10000000", "garbage" : true} 18 | ] 19 | } 20 | )"; 21 | 22 | class KafkaConfigTest : public TestBase {}; 23 | 24 | TEST_F(KafkaConfigTest, Default) { 25 | KafkaConfig KafkaCfg(""); 26 | ASSERT_EQ(KafkaCfg.CfgParms.size(), 8); 27 | } 28 | 29 | TEST_F(KafkaConfigTest, LoadFileError) { 30 | ASSERT_THROW(KafkaConfig KafkaCfg("NoSuchFile"), std::runtime_error); 31 | } 32 | 33 | TEST_F(KafkaConfigTest, BadKafkaConfigJson) { 34 | ASSERT_THROW(KafkaConfig KafkaCfg("NotKafkaConfig.json"), std::runtime_error); 35 | } 36 | 37 | TEST_F(KafkaConfigTest, LoadFileOK) { KafkaConfig KafkaCfg(KAFKACONFIG_FILE); } 38 | 39 | int main(int argc, char **argv) { 40 | saveBuffer("NotKafkaConfig.json", (void *)badkafkaconfigjson.c_str(), 41 | badkafkaconfigjson.size()); 42 | testing::InitGoogleTest(&argc, argv); 43 | int res = RUN_ALL_TESTS(); 44 | deleteFile("NotKafkaConfig.json"); 45 | return res; 46 | } 47 | -------------------------------------------------------------------------------- /src/modules/dream/configs/sans.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector": "DREAM", 3 | 4 | "MaxPulseTimeDiffNS" : 5000000000, 5 | 6 | "Config" : [ 7 | { "Ring" : 9, "FEN": 0, "Type": "SANS", "Index" : 0, "Index2" : 0}, 8 | { "Ring" : 9, "FEN": 1, "Type": "SANS", "Index" : 2, "Index2" : 0}, 9 | { "Ring" : 9, "FEN": 2, "Type": "SANS", "Index" : 4, "Index2" : 0}, 10 | { "Ring" : 9, "FEN": 3, "Type": "SANS", "Index" : 6, "Index2" : 0}, 11 | { "Ring" : 9, "FEN": 4, "Type": "SANS", "Index" : 8, "Index2" : 0}, 12 | { "Ring" : 9, "FEN": 5, "Type": "SANS", "Index" : 10, "Index2" : 0}, 13 | { "Ring" : 9, "FEN": 6, "Type": "SANS", "Index" : 12, "Index2" : 0}, 14 | { "Ring" : 9, "FEN": 7, "Type": "SANS", "Index" : 14, "Index2" : 0}, 15 | { "Ring" : 9, "FEN": 8, "Type": "SANS", "Index" : 16, "Index2" : 0}, 16 | 17 | { "Ring" : 10, "FEN": 0, "Type": "SANS", "Index" : 18, "Index2" : 0}, 18 | { "Ring" : 10, "FEN": 1, "Type": "SANS", "Index" : 20, "Index2" : 0}, 19 | { "Ring" : 10, "FEN": 2, "Type": "SANS", "Index" : 22, "Index2" : 0}, 20 | { "Ring" : 10, "FEN": 3, "Type": "SANS", "Index" : 24, "Index2" : 0}, 21 | { "Ring" : 10, "FEN": 4, "Type": "SANS", "Index" : 26, "Index2" : 0}, 22 | { "Ring" : 10, "FEN": 5, "Type": "SANS", "Index" : 28, "Index2" : 0}, 23 | { "Ring" : 10, "FEN": 6, "Type": "SANS", "Index" : 30, "Index2" : 0}, 24 | { "Ring" : 10, "FEN": 7, "Type": "SANS", "Index" : 32, "Index2" : 0}, 25 | { "Ring" : 10, "FEN": 8, "Type": "SANS", "Index" : 34, "Index2" : 0} 26 | ] 27 | 28 | } 29 | -------------------------------------------------------------------------------- /CHANGELOG/changelog_2025-10-23.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | **Generated on:** 2025-10-23 09:28:23 4 | **Commit range:** `2.0.0-alpha.2` to `HEAD` 5 | **Total commits:** 8 6 | 7 | ## 🎫 JIRA Issues 8 | 9 | - [ECDC-5082](https://jira.ess.eu/browse/ECDC-5082) 10 | - [ECDC-5089](https://jira.ess.eu/browse/ECDC-5089) 11 | - [ECDC-5103](https://jira.ess.eu/browse/ECDC-5103) 12 | - [ECDC-5142](https://jira.ess.eu/browse/ECDC-5142) 13 | 14 | ## ✨ Features 15 | 16 | - **cbm beam monitor config upgrades** ([ECDC-5082](https://jira.ess.eu/browse/ECDC-5082)) - `3d9abcca` by Michael Christiansen 17 | - **ECDC-5089 Feature, add fiber id as a command line option for cbm generator** ([ECDC-5089](https://jira.ess.eu/browse/ECDC-5089)) - `12f8c331` by Michael Christiansen 18 | 19 | ## 🐛 Bug Fixes 20 | 21 | - **correct logic in tube selection and update unit tests for accuracy** ([ECDC-5103](https://jira.ess.eu/browse/ECDC-5103)) - `656fa069` by Tibor Bukovics 22 | 23 | ## 🔧 Maintenance 24 | 25 | - **add changelog for version 2.0.0-alpha.3** - `16d815c3` by Tibor Bukovics 26 | 27 | ## 📝 General Changes 28 | 29 | - **ECDC-5142: The efurates script fails for CBM EFUs** ([ECDC-5142](https://jira.ess.eu/browse/ECDC-5142)) - `2a1b128d` by Mads Ipsen 30 | - **ECDC-5142: The efurates script fails for CBM EFUs** ([ECDC-5142](https://jira.ess.eu/browse/ECDC-5142)) - `8174e2a3` by Mads Ipsen 31 | - **Revert "Merge branch 'tbu/update_changelog' into 'master'"** - `eaaf1a78` by Tibor Bukovics 32 | - **ci: upgrade Docker images** - `6cc92d89` by Milosz Nowak 33 | -------------------------------------------------------------------------------- /src/common/reduction/matching/EndMatcher.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file EndMatcher.h 5 | /// \brief EndMatcher class definition 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | 12 | #include 13 | #include 14 | 15 | /// \class EndMatcher EndMatcher.h 16 | /// \brief Matcher implementation that joins clusters into events 17 | /// if their end times are in close proximity. 18 | 19 | class EndMatcher : public AbstractMatcher { 20 | public: 21 | /// Inherit constructor 22 | using AbstractMatcher::AbstractMatcher; 23 | 24 | /// \todo document this 25 | void set_max_delta_time(uint64_t max_delta_time); 26 | 27 | /// \brief Match queued up clusters into events. 28 | /// Clusters with end times within max_delta_time are joined. 29 | /// \param flush if all queued clusters should be matched regardless of 30 | /// latency considerations 31 | void match(bool flush) override; 32 | 33 | /// \brief print configuration of EndMatcher 34 | std::string config(const std::string &prepend) const override; 35 | 36 | private: 37 | uint64_t max_delta_time_{0}; 38 | 39 | uint64_t delta_end(const Event &event, const Cluster &cluster) const; 40 | bool belongs_end(const Event &event, const Cluster &cluster) const; 41 | }; 42 | -------------------------------------------------------------------------------- /src/common/readout/vmm3/test/vmm_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Detector" : "Freia", 3 | "InstrumentGeometry" : "AMOR", 4 | 5 | "Config" : [ 6 | { "Ring" : 2, "FEN": 0, "Hybrid" : 3, "HybridId" : "a08000e4fccca0803410082006704410"}, 7 | { "Ring" : 2, "FEN": 0, "Hybrid" : 2, "HybridId" : "a08000753877a0803410082006704410"}, 8 | { "Ring" : 2, "FEN": 0, "Hybrid" : 1, "HybridId" : "a0800084049ca0803410082106704410"}, 9 | { "Ring" : 2, "FEN": 0, "Hybrid" : 0, "HybridId" : "a08000e3b432a0803410082006704410"}, 10 | { "Ring" : 1, "FEN": 0, "Hybrid" : 4, "HybridId" : "a080003b54b4a0803410082006704410"}, 11 | { "Ring" : 1, "FEN": 0, "Hybrid" : 3, "HybridId" : "a08000e0103ea0803410082106704410"}, 12 | { "Ring" : 1, "FEN": 0, "Hybrid" : 2, "HybridId" : "a0800004349aa0803410082006704410"}, 13 | { "Ring" : 1, "FEN": 0, "Hybrid" : 1, "HybridId" : "a0800075c091a0803410082006704410"}, 14 | { "Ring" : 1, "FEN": 0, "Hybrid" : 0, "HybridId" : "a08000d1448ba0803410082006704410"}, 15 | { "Ring" : 0, "FEN": 0, "Hybrid" : 4, "HybridId" : "a0800073b01ea0803410082006704410"}, 16 | { "Ring" : 0, "FEN": 0, "Hybrid" : 3, "HybridId" : "a08000a3385da0803410082006704410"}, 17 | { "Ring" : 0, "FEN": 0, "Hybrid" : 2, "HybridId" : "a08000f3bcb9a0803410082006704410"}, 18 | { "Ring" : 0, "FEN": 0, "Hybrid" : 1, "HybridId" : "a0800040c8cfa0803410082006704410"}, 19 | { "Ring" : 0, "FEN": 0, "Hybrid" : 0, "HybridId" : "a0800006b882a0803410082006704410"} 20 | ], 21 | 22 | "MaxPulseTimeNS" : 2071428570 23 | } 24 | -------------------------------------------------------------------------------- /src/common/time/Timer.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief platform independent equivalent replacement wrapper for the cheap 7 | /// and fast time stamp counter (TSC). For further details regarding the TSC 8 | /// timer, see https://tinyurl.com/mr242w8c. 9 | /// 10 | /// Uses the standard chrono library to provide a high resolution timer. 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | class Timer { 19 | 20 | public: 21 | /// \brief Create a check timer with a timeout value in nanoseconds 22 | /// \param TimeOut If a time out is not set, use this 'infinite' value 23 | Timer(uint64_t TimeOut=0xffffffffffffffff); 24 | 25 | /// \brief If a timeout has occurred, then reset timer 26 | bool timeout(); 27 | 28 | /// \brief Record current time point 29 | void reset(); 30 | 31 | /// \brief Return time in nano seconds since last time point 32 | uint64_t timeNS(); 33 | 34 | /// \return Return time in micro seconds since last time point 35 | uint64_t timeUS(); 36 | 37 | /// \return Return time in milli seconds since last time point 38 | uint64_t timeMS(); 39 | 40 | private: 41 | std::chrono::time_point T0; 43 | 44 | uint64_t TimeOutNS; 45 | }; 46 | -------------------------------------------------------------------------------- /src/modules/cbm/generators/udpgen.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 European Spallation Source ERIC 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Generate artificial CBM readouts 7 | //===----------------------------------------------------------------------===// 8 | 9 | // GCOVR_EXCL_START 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char *argv[]) { 16 | 17 | cbm::ReadoutGenerator CbmGen; 18 | uint8_t cbmReadoutDataSize = sizeof(cbm::Parser::CbmReadout); 19 | CbmGen.setReadoutDataSize(cbmReadoutDataSize); 20 | 21 | CbmGen.argParse(argc, argv); 22 | 23 | std::unique_ptr readoutTimeGenerator; 24 | if ((CbmGen.cbmSettings.monitorType == cbm::CbmType::EVENT_0D) || 25 | (CbmGen.cbmSettings.monitorType == cbm::CbmType::EVENT_2D)) { 26 | readoutTimeGenerator = 27 | std::make_unique(CbmGen.Settings.Frequency); 28 | } else if (CbmGen.cbmSettings.monitorType == cbm::CbmType::IBM) { 29 | readoutTimeGenerator = std::make_unique( 30 | CbmGen.Settings.Frequency, CbmGen.cbmSettings.NumReadouts); 31 | } else { 32 | throw std::runtime_error("Unsupported monitor type"); 33 | } 34 | 35 | CbmGen.initialize(std::move(readoutTimeGenerator)); 36 | 37 | CbmGen.transmitLoop(); 38 | return 0; 39 | } 40 | // GCOVR_EXCL_STOP 41 | -------------------------------------------------------------------------------- /src/common/reduction/analysis/AbstractAnalyzer.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file AbstractAnalyzer.h 5 | /// \brief AbstractAnalyzer class definition 6 | /// 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | /// \class AbstractAnalyzer AbstractAnalyzer.h 15 | /// \brief AbstractAnalyzer declares the interface for an event analyzer type 16 | /// that can take multi-dimensional Events and return a ReducedEvent 17 | /// summaries that provide the best estimated coordinates and time 18 | /// for a detected particle. Different strategies are to be implemented 19 | /// for various detector types, depending on the particular physics. 20 | 21 | class AbstractAnalyzer { 22 | public: 23 | AbstractAnalyzer() = default; 24 | virtual ~AbstractAnalyzer() = default; 25 | 26 | /// Assuming that only a subset of hits are used in determining particle 27 | /// position this helps keep track of how many were actually selected for 28 | /// averaging. 29 | mutable size_t stats_used_hits{0}; 30 | 31 | /// \brief analyzes cluster in both planes 32 | virtual ReducedEvent analyze(Event &) const = 0; 33 | 34 | /// \brief prints info for debug purposes 35 | virtual std::string debug(const std::string &prepend) const = 0; 36 | }; 37 | -------------------------------------------------------------------------------- /src/modules/tbl3he/configs/tbl3heconstcalib.json: -------------------------------------------------------------------------------- 1 | { 2 | "Calibration" : { 3 | "version" : 0, 4 | "date" : "2024-06-20T13:11:07.573983", 5 | "info" : "generated by generatecalib.py with type: const", 6 | 7 | "instrument" : "tbl3he", 8 | "groups" : 8, 9 | "groupsize" : 1, 10 | 11 | "Parameters" : [ 12 | { 13 | "groupindex" : 0, 14 | "intervals" : [[ 0.0, 1.0]], 15 | "polynomials" : [[-0.5, 1.0, 0.0, 0.0] ] 16 | }, 17 | { 18 | "groupindex" : 1, 19 | "intervals" : [[ 0.0, 1.0]], 20 | "polynomials" : [[-0.5, 1.0, 0.0, 0.0] ] 21 | }, 22 | { 23 | "groupindex" : 2, 24 | "intervals" : [[ 0.0, 1.0]], 25 | "polynomials" : [[-0.5, 1.0, 0.0, 0.0] ] 26 | }, 27 | { 28 | "groupindex" : 3, 29 | "intervals" : [[ 0.0, 1.0]], 30 | "polynomials" : [[-0.5, 1.0, 0.0, 0.0] ] 31 | }, 32 | { 33 | "groupindex" : 4, 34 | "intervals" : [[ 0.0, 1.0]], 35 | "polynomials" : [[-0.5, 1.0, 0.0, 0.0] ] 36 | }, 37 | { 38 | "groupindex" : 5, 39 | "intervals" : [[ 0.0, 1.0]], 40 | "polynomials" : [[-0.5, 1.0, 0.0, 0.0] ] 41 | }, 42 | { 43 | "groupindex" : 6, 44 | "intervals" : [[ 0.0, 1.0]], 45 | "polynomials" : [[-0.5, 1.0, 0.0, 0.0] ] 46 | }, 47 | { 48 | "groupindex" : 7, 49 | "intervals" : [[ 0.0, 1.0]], 50 | "polynomials" : [[-0.5, 1.0, 0.0, 0.0] ] 51 | } 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/modules/tbl3he/configs/tbl3henullcalib.json: -------------------------------------------------------------------------------- 1 | { 2 | "Calibration" : { 3 | "version" : 0, 4 | "date" : "2024-06-18T08:41:09.943857", 5 | "info" : "generated by generatecalib.py with type: null", 6 | 7 | "instrument" : "tbl3he", 8 | "groups" : 8, 9 | "groupsize" : 1, 10 | 11 | "Parameters" : [ 12 | { 13 | "groupindex" : 0, 14 | "intervals" : [[ 0.0, 1.0]], 15 | "polynomials" : [[ 0.0, 0.0, 0.0, 0.0] ] 16 | }, 17 | { 18 | "groupindex" : 1, 19 | "intervals" : [[ 0.0, 1.0]], 20 | "polynomials" : [[ 0.0, 0.0, 0.0, 0.0] ] 21 | }, 22 | { 23 | "groupindex" : 2, 24 | "intervals" : [[ 0.0, 1.0]], 25 | "polynomials" : [[ 0.0, 0.0, 0.0, 0.0] ] 26 | }, 27 | { 28 | "groupindex" : 3, 29 | "intervals" : [[ 0.0, 1.0]], 30 | "polynomials" : [[ 0.0, 0.0, 0.0, 0.0] ] 31 | }, 32 | { 33 | "groupindex" : 4, 34 | "intervals" : [[ 0.0, 1.0]], 35 | "polynomials" : [[ 0.0, 0.0, 0.0, 0.0] ] 36 | }, 37 | { 38 | "groupindex" : 5, 39 | "intervals" : [[ 0.0, 1.0]], 40 | "polynomials" : [[ 0.0, 0.0, 0.0, 0.0] ] 41 | }, 42 | { 43 | "groupindex" : 6, 44 | "intervals" : [[ 0.0, 1.0]], 45 | "polynomials" : [[ 0.0, 0.0, 0.0, 0.0] ] 46 | }, 47 | { 48 | "groupindex" : 7, 49 | "intervals" : [[ 0.0, 1.0]], 50 | "polynomials" : [[ 0.0, 0.0, 0.0, 0.0] ] 51 | } 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/modules/trex/readout/DataParser.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 - 2023 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Parser for ESS readout of TREX 7 | //===----------------------------------------------------------------------===// 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace Trex { 17 | 18 | class DataParser { 19 | public: 20 | const unsigned int MaxFiberId{23}; 21 | const unsigned int MaxFENId{23}; 22 | const unsigned int MaxReadoutsInPacket{500}; 23 | 24 | struct TREXReadout // 25 | { 26 | uint32_t TimeHigh; 27 | uint32_t TimeLow; 28 | uint8_t unused; 29 | uint8_t Group; 30 | uint16_t Unused; 31 | 32 | } __attribute__((__packed__)); 33 | 34 | static_assert(sizeof(TREXReadout) == 20, "TREX readout header length error"); 35 | 36 | DataParser(struct Counters &counters) : Stats(counters) { 37 | Result.reserve(MaxReadoutsInPacket); 38 | }; 39 | ~DataParser(){}; 40 | 41 | // 42 | int parse(const char *buffer, unsigned int size); 43 | 44 | // 45 | struct ParsedData { 46 | uint8_t FiberId; 47 | uint8_t FENId; 48 | TREXReadout Data; 49 | }; 50 | 51 | // To be iterated over in processing thread 52 | std::vector Result; 53 | 54 | struct Counters &Stats; 55 | uint32_t HeaderCounters[16][16]; // {ring,fen} counters 56 | }; 57 | } // namespace Trex 58 | -------------------------------------------------------------------------------- /src/modules/caen/geometry/Interval.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | 12 | // #undef TRC_LEVEL 13 | // #define TRC_LEVEL TRC_L_DEB 14 | 15 | namespace Caen { 16 | 17 | /// \brief Check for overlapping intervals in a list 18 | /// First put intervals into canonical order where the first element is 19 | /// smaller than the second (for calibration the reversal is ok). Then sort 20 | /// the intervals in ascending first elements. Finally, iterate through 21 | /// the list and compare the start of the iterator with the end of the 22 | /// previous interval. 23 | bool Interval::overlaps(std::vector> Intervals) { 24 | /// Put intervals into canonical order (first < second) 25 | for (auto &[i0, i1] : Intervals) { 26 | if (i1 < i0) { 27 | std::swap(i0, i1); 28 | } 29 | } 30 | 31 | // Sort intervals and check if the end point of the i'th interval is larger 32 | // than the start point of the next interval 33 | std::sort(Intervals.begin(), Intervals.end(), Compare); 34 | for (size_t i=1; i < Intervals.size(); i++) { 35 | if (Intervals[i-1].second - Intervals[i].first > -EPSILON) { 36 | return true; 37 | } 38 | } 39 | 40 | return false; 41 | } 42 | 43 | } // namespace Caen 44 | -------------------------------------------------------------------------------- /src/modules/loki/configs/LokiFull.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "Detector" : "loki", 4 | 5 | "Resolution" : 512, 6 | "GroupsZ" : 4, 7 | 8 | "ReadoutConstDelayNS" : 0, 9 | "MaxPulseTimeNS" : 357142855, 10 | 11 | "Banks" : [ 12 | {"Bank" : 0, "ID" : "bank0", "GroupsN" : 56, "YOffset" : 0}, 13 | {"Bank" : 1, "ID" : "bank1", "GroupsN" : 16, "YOffset" : 1568}, 14 | {"Bank" : 2, "ID" : "bank2", "GroupsN" : 12, "YOffset" : 2016}, 15 | {"Bank" : 3, "ID" : "bank3", "GroupsN" : 16, "YOffset" : 2352}, 16 | {"Bank" : 4, "ID" : "bank4", "GroupsN" : 12, "YOffset" : 2800}, 17 | {"Bank" : 5, "ID" : "bank5", "GroupsN" : 28, "YOffset" : 3136}, 18 | {"Bank" : 6, "ID" : "bank6", "GroupsN" : 32, "YOffset" : 3920}, 19 | {"Bank" : 7, "ID" : "bank7", "GroupsN" : 20, "YOffset" : 4816}, 20 | {"Bank" : 8, "ID" : "bank8", "GroupsN" : 32, "YOffset" : 5376} 21 | ], 22 | 23 | "Config" : [ 24 | { "Ring" : 0, "Bank" : 0, "FENs" : 16, "FENOffset" : 0}, 25 | { "Ring" : 1, "Bank" : 0, "FENs" : 12, "FENOffset" : 16}, 26 | { "Ring" : 2, "Bank" : 1, "FENs" : 8, "FENOffset" : 0}, 27 | { "Ring" : 3, "Bank" : 2, "FENs" : 6, "FENOffset" : 0}, 28 | { "Ring" : 4, "Bank" : 3, "FENs" : 8, "FENOffset" : 0}, 29 | { "Ring" : 5, "Bank" : 4, "FENs" : 6, "FENOffset" : 0}, 30 | { "Ring" : 6, "Bank" : 5, "FENs" : 14, "FENOffset" : 0}, 31 | { "Ring" : 7, "Bank" : 6, "FENs" : 16, "FENOffset" : 0}, 32 | { "Ring" : 8, "Bank" : 7, "FENs" : 10, "FENOffset" : 0}, 33 | { "Ring" : 9, "Bank" : 8, "FENs" : 16, "FENOffset" : 0} 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /src/common/kafka/test/AR51SerializerTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 European Spallation Source, ERIC. see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Unit test of AR51Serializer class 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | struct MockProducer { 18 | inline void produce(nonstd::span, int64_t) { NumberOfCalls++; } 19 | 20 | size_t NumberOfCalls{0}; 21 | }; 22 | 23 | class AR51SerializerTest : public TestBase { 24 | void SetUp() override { 25 | for (int i = 0; i < 9000; i++) { 26 | RawData[i] = i % 27 + 64; 27 | } 28 | } 29 | 30 | void TearDown() override {} 31 | 32 | protected: 33 | uint8_t RawData[9000]; 34 | AR51Serializer ar52{"nameless"}; 35 | }; 36 | 37 | 38 | TEST_F(AR51SerializerTest, Serialize) { 39 | ASSERT_TRUE(ar52.FBuffer.empty()); 40 | 41 | for (unsigned int i = 1; i <= 9000; i++) { 42 | auto buffer = ar52.serialize(RawData, i); 43 | ASSERT_TRUE(not ar52.FBuffer.empty()); 44 | ASSERT_TRUE(buffer.size_bytes() > i + 54); // imperical value 45 | ASSERT_TRUE(buffer.size_bytes() < i + 68); // imperical value 46 | } 47 | } 48 | 49 | int main(int argc, char **argv) { 50 | testing::InitGoogleTest(&argc, argv); 51 | return RUN_ALL_TESTS(); 52 | } 53 | -------------------------------------------------------------------------------- /src/common/debug/TraceGroups.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 - 2025 European Spallation Source, ERIC. See LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief Trace macros with masks and levels 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | /// Add trace groups below - must be powers of two 13 | // clang-format off 14 | const unsigned int TRC_G_INPUT = 0x00000001U; 15 | const unsigned int TRC_G_OUTPUT = 0x00000002U; 16 | const unsigned int TRC_G_PROCESS = 0x00000004U; 17 | const unsigned int TRC_G_MAIN = 0x00000008U; 18 | const unsigned int TRC_G_INIT = 0x00000010U; 19 | const unsigned int TRC_G_IPC = 0x00000020U; 20 | const unsigned int TRC_G_CMD = 0x00000040U; 21 | const unsigned int TRC_G_DATA = 0x00000080U; 22 | const unsigned int TRC_G_KAFKA = 0x00000100U; 23 | const unsigned int TRC_G_UTILS = 0x00000200U; 24 | const unsigned int TRC_G_CLUSTER = 0x00000400U; 25 | const unsigned int TRC_G_EVENT = 0x00000800U; 26 | const unsigned int TRC_G_BUILDER = 0x00001000U; 27 | 28 | /// Add trace masks below, bitwise or of groups 29 | 30 | // Do not edit below 31 | const unsigned int TRC_M_NONE = 0; 32 | const unsigned int TRC_M_ALL = 0xffffffffU; 33 | 34 | // clang-format on 35 | 36 | #ifndef TRC_MASK 37 | const unsigned int USED_TRC_MASK = TRC_M_ALL; 38 | #else 39 | const unsigned int USED_TRC_MASK = TRC_MASK; 40 | #endif 41 | 42 | #define TRC_MASK USED_TRC_MASK 43 | //#define TRC_MASK (TRC_G_IPC | TRC_G_CMD) 44 | -------------------------------------------------------------------------------- /src/modules/tbl3he/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Tests 3 | #============================================================================= 4 | 5 | include_directories(.) 6 | include_directories(..) 7 | 8 | ## 9 | ## Pure unit tests 10 | ## 11 | 12 | 13 | # Testing geometry class for tbl3he 14 | set(Tbl3HeGeometryTest_INC 15 | ${ESS_MODULE_DIR}/caen/geometry/Config.h 16 | ${ESS_MODULE_DIR}/caen/geometry/CDCalibration.h 17 | ${ESS_MODULE_DIR}/caen/geometry/Interval.h 18 | ${ESS_MODULE_DIR}/loki/geometry/LokiConfig.h 19 | ${ESS_MODULE_DIR}/bifrost/geometry/BifrostConfig.h 20 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeConfig.h 21 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeGeometry.h 22 | ) 23 | set(Tbl3HeGeometryTest_SRC 24 | ${ESS_MODULE_DIR}/caen/geometry/Config.cpp 25 | ${ESS_MODULE_DIR}/caen/geometry/CDCalibration.cpp 26 | ${ESS_MODULE_DIR}/caen/geometry/Interval.cpp 27 | ${ESS_MODULE_DIR}/loki/geometry/LokiConfig.cpp 28 | ${ESS_MODULE_DIR}/bifrost/geometry/BifrostConfig.cpp 29 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeConfig.cpp 30 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeGeometry.cpp 31 | 32 | GeometryTest.cpp 33 | ) 34 | create_test_executable(Tbl3HeGeometryTest) 35 | 36 | 37 | ## 38 | ## TBL3HE config test 39 | ## 40 | set(Tbl3HeConfigTest_INC 41 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeConfig.h 42 | ) 43 | set(Tbl3HeConfigTest_SRC 44 | Tbl3HeConfigTest.cpp 45 | ${ESS_MODULE_DIR}/tbl3he/geometry/Tbl3HeConfig.cpp 46 | 47 | ) 48 | create_test_executable(Tbl3HeConfigTest) 49 | -------------------------------------------------------------------------------- /src/modules/nmx/Counters.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 - 2025 European Spallation Source, see LICENSE file 2 | //===----------------------------------------------------------------------===// 3 | /// 4 | /// \file 5 | /// 6 | /// \brief NMX application counters (for Grafana and low level debug) 7 | /// 8 | //===----------------------------------------------------------------------===// 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | struct Counters { 19 | // ESSReadout parser 20 | int64_t ErrorESSHeaders; 21 | 22 | // VMM3a Readouts 23 | struct vmm3::VMM3ParserStats VMMStats; 24 | 25 | // Logical and Digital geometry incl. Calibration 26 | int64_t HybridMappingErrors; 27 | int64_t TOFErrors; 28 | /// \todo TREX still using this, we should decouple it from NMX Counters 29 | int64_t MinADC; 30 | int64_t MappingErrors; 31 | 32 | struct GapMatcherStats MatcherStats; 33 | // 34 | int64_t ProcessingIdle; 35 | int64_t Events; 36 | int64_t ClustersNoCoincidence; 37 | int64_t ClustersMatchedXOnly; 38 | int64_t ClustersMatchedYOnly; 39 | int64_t ClustersTooLargeSpanX; 40 | int64_t ClustersTooLargeSpanY; 41 | int64_t ClustersTooSmallSpanX; 42 | int64_t ClustersTooSmallSpanY; 43 | int64_t ClustersTooLargeTimeSpan; 44 | int64_t EventsMatchedClusters; 45 | int64_t TimeErrors; 46 | 47 | // Identification of the cause of produce calls 48 | int64_t ProduceCauseTimeout; 49 | } __attribute__((aligned(64))); 50 | --------------------------------------------------------------------------------