add ctest integration tests for musrfit maxLH/chisq validation
All checks were successful
Build and Deploy Documentation / build-and-deploy (push) Successful in 28s

Add a Python-based test script that runs musrfit -c on each example
msr-file, extracts the maxLH or chisq value, and checks it against
a reference value with a relative tolerance of 1e-4. Covers all 13
example msr-files (single histogram and asymmetry fits).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-17 18:05:24 +01:00
parent 5a2f45c083
commit c50e4a3a06
4 changed files with 96 additions and 0 deletions

View File

@@ -279,6 +279,10 @@ set(CMAKE_INSTALL_RPATH "${rpath}")
#--- propagate to the sub-directories -----------------------------------------
add_subdirectory(src)
#--- testing ------------------------------------------------------------------
enable_testing()
add_subdirectory(tests)
#--- write summary of the installation
cmake_host_system_information(RESULT PROCESSOR QUERY PROCESSOR_DESCRIPTION)

2
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,2 @@
#--- musrfit integration tests ------------------------------------------------
add_subdirectory(maxLH_check)

View File

@@ -0,0 +1,36 @@
#--- maxLH_check test (Python) ------------------------------------------------
find_package(Python3 REQUIRED COMPONENTS Interpreter)
#--- helper macro -------------------------------------------------------------
macro(add_maxLH_test test_name msr_file expected_value)
add_test(
NAME ${test_name}
COMMAND Python3::Interpreter
${CMAKE_CURRENT_SOURCE_DIR}/maxLH_check.py
$<TARGET_FILE:musrfit>
${CMAKE_SOURCE_DIR}/doc/examples/${msr_file}
${expected_value}
1e-4
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/doc/examples
)
endmacro()
#--- register ctest(s) -------------------------------------------------------
# single histogram fits (maxLH)
add_maxLH_test(test-histo-MusrRoot test-histo-MusrRoot.msr 3971.7)
add_maxLH_test(test-histo-PSI-BIN test-histo-PSI-BIN.msr 663.89)
add_maxLH_test(test-histo-ROOT-NPP test-histo-ROOT-NPP.msr 249.12)
add_maxLH_test(test-histo-HAL9500 test-histo-HAL9500.msr 1286509.8)
add_maxLH_test(test-histo-HAL9500-RRF test-histo-HAL9500-RRF.msr 22187.4)
add_maxLH_test(test-histo-muMinus test-histo-muMinus.msr 238962.6)
add_maxLH_test(test-histo-NeXus test-histo-NeXus.msr 3273.57)
add_maxLH_test(test-histo-NeXus2 test-histo-NeXus2.msr 2582.50)
# asymmetry fits (chisq)
add_maxLH_test(test-asy-PSI-BIN test-asy-PSI-BIN.msr 566.76)
add_maxLH_test(test-asy-MUD test-asy-MUD.msr 133.96)
add_maxLH_test(test-asy-NeXus2 test-asy-NeXus2.msr 796.72)
add_maxLH_test(test-asy-HAL9500-RRF test-asy-HAL9500-RRF.msr 7402.28)
add_maxLH_test(test-asy-LF-BaB6 test-asy-LF-BaB6.msr 1911.88)

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
"""
Runs musrfit -c on a given msr-file, extracts the maxLH (or chisq)
value from stdout, and compares it against an expected reference value.
Returns exit code 1 if the relative deviation exceeds the tolerance.
Usage:
maxLH_check.py <musrfit> <msr-file> <expected_value> [tolerance]
"""
import subprocess
import sys
import re
def main():
if len(sys.argv) < 4 or len(sys.argv) > 5:
print(f"usage: {sys.argv[0]} <musrfit> <msr-file> <expected> [tolerance]")
return 1
musrfit = sys.argv[1]
msr_file = sys.argv[2]
expected = float(sys.argv[3])
tol = float(sys.argv[4]) if len(sys.argv) == 5 else 1e-4
# run musrfit -c
result = subprocess.run([musrfit, "-c", msr_file],
capture_output=True, text=True)
if result.returncode != 0:
print(f"**ERROR** musrfit returned exit code {result.returncode}")
print(result.stdout + result.stderr)
return 1
# extract maxLH or chisq from stdout
match = re.search(r">>\s+(maxLH|chisq)\s*=\s*([0-9.eE+-]+)", result.stdout)
if not match:
print("**ERROR** could not extract maxLH or chisq from output:")
print(result.stdout)
return 1
label = match.group(1)
value = float(match.group(2))
rel_dev = abs((value - expected) / expected)
if rel_dev > tol:
print(f"FAIL: {label} = {value}, expected = {expected}, "
f"rel. deviation = {rel_dev:.6e} > {tol:.6e}")
return 1
print(f"PASS: {label} = {value}, expected = {expected}, "
f"rel. deviation = {rel_dev:.6e} <= {tol:.6e}")
return 0
if __name__ == "__main__":
sys.exit(main())